Skip to content

Commit

Permalink
fix: disallow undefined xml (#757)
Browse files Browse the repository at this point in the history
* fix: disallow undefined xml

* test: add ut and require `type` to be present

* style: one import from sdr

* chore: lockfile dedupe

* test: more coverage and cases for typeguard and SC

* fix: bump SDR

---------

Co-authored-by: Cristian Dominguez <[email protected]>
  • Loading branch information
mshanemc and cristiand391 authored Sep 18, 2023
1 parent 5bfaf8d commit 42d9409
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 30 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"@salesforce/core": "^5.2.7",
"@salesforce/kit": "^3.0.9",
"@salesforce/sf-plugins-core": "^3.1.22",
"@salesforce/source-deploy-retrieve": "^9.7.13",
"@salesforce/source-deploy-retrieve": "^9.7.15",
"@salesforce/source-tracking": "^4.2.12",
"chalk": "^4.1.2",
"shelljs": "^0.8.5",
Expand Down
4 changes: 2 additions & 2 deletions src/utils/previewOutput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
import { filePathsFromMetadataComponent } from '@salesforce/source-deploy-retrieve/lib/src/utils/filePathGenerator';

import { SourceTracking } from '@salesforce/source-tracking';
import { isSourceComponent } from './types';
import { isSourceComponentWithXml } from './types';

Messages.importMessagesDirectory(__dirname);
const messages = Messages.loadMessages('@salesforce/plugin-deploy-retrieve', 'previewMessages');
Expand Down Expand Up @@ -64,7 +64,7 @@ const resolvePaths = (filenames: string[]): Array<Pick<PreviewFile, 'type' | 'fu
return undefined;
}
})
.filter(isSourceComponent)
.filter(isSourceComponentWithXml)
.map((sc) => ({ fullName: sc.fullName, type: sc.type.name, path: ensureAbsolutePath(sc.xml) }));
// dedupe by xml path
return Array.from(new Map(sourceComponents.map((sc) => [sc.path, sc])).values());
Expand Down
15 changes: 13 additions & 2 deletions src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,19 @@ export type Formatter<T> = {
};

/** validates source component with fullname, type, and xml props */
export const isSourceComponent = (sc: unknown): sc is SourceComponent & { xml: string } =>
isObject(sc) && 'fullName' in sc && 'type' in sc && 'xml' in sc;
export const isSourceComponent = (sc: unknown): sc is SourceComponent =>
isObject(sc) &&
'type' in sc &&
typeof sc.type === 'object' &&
sc.type !== null &&
'name' in sc.type &&
typeof sc.type.name === 'string' &&
'fullName' in sc &&
// (typeof sc.fullName === 'string' || typeof sc.fullName === 'function');
typeof sc.fullName === 'string';

export const isSourceComponentWithXml = (sc: unknown): sc is SourceComponent & { xml: string } =>
isSourceComponent(sc) && 'xml' in sc && typeof sc.xml === 'string';

export const isSdrFailure = (fileResponse: FileResponse): fileResponse is FileResponseFailure =>
fileResponse.state === ComponentStatus.Failed;
Expand Down
72 changes: 72 additions & 0 deletions test/utils/types.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2023, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import { expect, config } from 'chai';
import { SourceComponent, RegistryAccess } from '@salesforce/source-deploy-retrieve';
import { isSourceComponent, isSourceComponentWithXml } from '../../src/utils/types';

config.truncateThreshold = 0;

const reg = new RegistryAccess();
const type = reg.getTypeByName('ApexClass');

describe('isSourceComponent (type guard)', () => {
describe('good', () => {
it('full, correct definition', () => {
expect({ fullName: 'foo', type, xml: 'fooXml', content: 'fooContent' }).to.satisfy(isSourceComponent);
});
it('SC constructed with xml', () => {
expect(new SourceComponent({ name: 'foo', type, xml: 'classes/foo.cls' })).to.satisfy(isSourceComponent);
});
it('SC constructed with no xml', () => {
const sc = new SourceComponent({ name: 'foo', type });
// console.log(sc);
// console.log(typeof sc.fullName);
expect(sc).to.satisfy(isSourceComponent);
});
});
describe('bad', () => {
it('object is undefined', () => {
expect(undefined).to.not.satisfy(isSourceComponent);
});
it('empty object', () => {
expect({}).to.not.satisfy(isSourceComponent);
});

it('object.type is set to undefined', () => {
expect({ fullName: 'foo', type: undefined, xml: 'fooXml' }).to.not.satisfy(isSourceComponent);
});
});
});

describe('isSourceComponentWithXml (type guard)', () => {
describe('good', () => {
it('full, correct definition', () => {
expect({ fullName: 'foo', type, xml: 'fooXml', content: 'fooContent' }).to.satisfy(isSourceComponentWithXml);
});
it('SC constructed with xml', () => {
expect(new SourceComponent({ name: 'foo', type, xml: 'classes/foo.cls' })).to.satisfy(isSourceComponentWithXml);
});
});
describe('bad', () => {
it('object is undefined', () => {
expect(undefined).to.not.satisfy(isSourceComponentWithXml);
});
it('empty object', () => {
expect({}).to.not.satisfy(isSourceComponentWithXml);
});
it('object.xml is undefined', () => {
expect({ fullName: 'foo', type: 'fooType', content: 'fooContent' }).to.not.satisfy(isSourceComponentWithXml);
});
it('object.type is set to undefined', () => {
expect({ fullName: 'foo', type: undefined, xml: 'fooXml' }).to.not.satisfy(isSourceComponentWithXml);
});
it('SC constructed with no xml', () => {
expect(new SourceComponent({ name: 'foo', type })).to.not.satisfy(isSourceComponentWithXml);
});
});
});
37 changes: 12 additions & 25 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -956,15 +956,15 @@
strip-ansi "6.0.1"
ts-retry-promise "^0.7.0"

"@salesforce/core@^5.2.0", "@salesforce/core@^5.2.6", "@salesforce/core@^5.2.7":
version "5.2.9"
resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-5.2.9.tgz#812478061d766cdff28f7a0e8abefc9de562465a"
integrity sha512-ZWNxHnCPGT1pcJe1bjeRjd8VAeHELK4fftt/2WO+ZsPFHZnzmdowz2Th407v04et+uIzL0Z6+qOaRY/bZr5tLA==
"@salesforce/core@^5.2.0", "@salesforce/core@^5.2.6", "@salesforce/core@^5.2.7", "@salesforce/core@^5.2.9":
version "5.2.10"
resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-5.2.10.tgz#7f4824ddcef108b6ccec24434260c620de39012e"
integrity sha512-Xj1QRajmHWgl0ahivjKFGKJlGXwe9yFOZ3PwF91qEupGbO74XrCJ8OUM7EVlk53LKy9LlPZQFuy2ATX9MyEDKA==
dependencies:
"@salesforce/kit" "^3.0.11"
"@salesforce/schemas" "^1.6.0"
"@salesforce/ts-types" "^2.0.7"
"@types/semver" "^7.5.1"
"@types/semver" "^7.5.2"
ajv "^8.12.0"
change-case "^4.1.2"
faye "^1.4.0"
Expand Down Expand Up @@ -1121,12 +1121,12 @@
chalk "^4"
inquirer "^8.2.5"

"@salesforce/source-deploy-retrieve@^9.7.13", "@salesforce/source-deploy-retrieve@^9.7.2", "@salesforce/source-deploy-retrieve@^9.7.8":
version "9.7.13"
resolved "https://registry.yarnpkg.com/@salesforce/source-deploy-retrieve/-/source-deploy-retrieve-9.7.13.tgz#85777222e157a621eb00fcef0487c682b7e3d5f7"
integrity sha512-QRhdepll3+ED9w4clI/RvcSLtuSbTzFPZenzrvJ2R7Pg5gXRZQIJrphEkAnY7oteVBBUxPVdYgbeuQxeoi98dg==
"@salesforce/source-deploy-retrieve@^9.7.15", "@salesforce/source-deploy-retrieve@^9.7.2", "@salesforce/source-deploy-retrieve@^9.7.8":
version "9.7.15"
resolved "https://registry.yarnpkg.com/@salesforce/source-deploy-retrieve/-/source-deploy-retrieve-9.7.15.tgz#a891e95101816a7e33854bc42ba21fafbdb1728e"
integrity sha512-av9Ojd9B/uegLNJth41aVPvAVPh8N0CllzfiDG5qbtDXW7WV/bqgWjiiiGc1U6RWnJ9OmQZNL/EjaSX0UPhiLA==
dependencies:
"@salesforce/core" "^5.2.7"
"@salesforce/core" "^5.2.9"
"@salesforce/kit" "^3.0.11"
"@salesforce/ts-types" "^2.0.7"
fast-levenshtein "^3.0.0"
Expand Down Expand Up @@ -1558,12 +1558,7 @@
dependencies:
"@types/node" "*"

"@types/semver@^7.3.12":
version "7.5.0"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a"
integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==

"@types/semver@^7.5.1":
"@types/semver@^7.3.12", "@types/semver@^7.5.1", "@types/semver@^7.5.2":
version "7.5.2"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.2.tgz#31f6eec1ed7ec23f4f05608d3a2d381df041f564"
integrity sha512-7aqorHYgdNO4DM36stTiGO3DvKoex9TQRwsJU6vMaFGyqpBA1MNZkz+PG3gaNUPpTAOYhT1WR7M1JyA3fbS9Cw==
Expand Down Expand Up @@ -6607,15 +6602,7 @@ pify@^4.0.1:
resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==

pino-abstract-transport@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz#cc0d6955fffcadb91b7b49ef220a6cc111d48bb3"
integrity sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==
dependencies:
readable-stream "^4.0.0"
split2 "^4.0.0"

[email protected]:
pino-abstract-transport@^1.0.0, [email protected]:
version "1.1.0"
resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz#083d98f966262164504afb989bccd05f665937a8"
integrity sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==
Expand Down

0 comments on commit 42d9409

Please sign in to comment.