@salesforce/source-testkit 2.0.2 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/assertions.js CHANGED
@@ -16,6 +16,7 @@ const source_deploy_retrieve_1 = require("@salesforce/source-deploy-retrieve");
16
16
  const debug_1 = require("debug");
17
17
  const fileTracker_1 = require("./fileTracker");
18
18
  (0, chai_1.use)(chaiEach);
19
+ /* eslint-disable no-await-in-loop */
19
20
  /**
20
21
  * Assertions is a class that is designed to encapsulate common assertions we want to
21
22
  * make during NUT testings
@@ -147,6 +148,7 @@ class Assertions {
147
148
  /**
148
149
  * Expects files to exist in convert output directory
149
150
  */
151
+ // eslint-disable-next-line class-methods-use-this
150
152
  async filesToBeConverted(directory, globs) {
151
153
  directory = directory.split(path.sep).join('/');
152
154
  const fullGlobs = globs.map((glob) => [directory, glob].join('/'));
@@ -203,6 +205,7 @@ class Assertions {
203
205
  /**
204
206
  * Expect status to return no results
205
207
  */
208
+ // eslint-disable-next-line class-methods-use-this
206
209
  statusToBeEmpty(result) {
207
210
  (0, chai_1.expect)(result.length, 'status to have no results').to.equal(0);
208
211
  }
@@ -218,6 +221,7 @@ class Assertions {
218
221
  /**
219
222
  * Expect given file to have the given state
220
223
  */
224
+ // eslint-disable-next-line class-methods-use-this
221
225
  statusFileToHaveState(result, state, file) {
222
226
  const expectedFile = result.find((r) => r.filePath === file);
223
227
  (0, chai_1.expect)(expectedFile, `${file} to be present in json response`).to.not.be.undefined;
@@ -226,6 +230,7 @@ class Assertions {
226
230
  /**
227
231
  * Expect all given files to have the given state
228
232
  */
233
+ // eslint-disable-next-line class-methods-use-this
229
234
  statusToOnlyHaveState(result, state) {
230
235
  const allStates = result.every((r) => r.state === state);
231
236
  (0, chai_1.expect)(allStates, `all files to have ${state}`).to.be.true;
@@ -233,6 +238,7 @@ class Assertions {
233
238
  /**
234
239
  * Expect all files to have a conflict state
235
240
  */
241
+ // eslint-disable-next-line class-methods-use-this
236
242
  statusToOnlyHaveConflicts(result) {
237
243
  const allConflicts = result.every((r) => r.state.includes('Conflict'));
238
244
  (0, chai_1.expect)(allConflicts, 'all results to show conflict state').to.be.true;
@@ -240,6 +246,7 @@ class Assertions {
240
246
  /**
241
247
  * Expect json to have given error name
242
248
  */
249
+ // eslint-disable-next-line class-methods-use-this
243
250
  errorToHaveName(result, name) {
244
251
  (0, chai_1.expect)(result).to.have.property('name');
245
252
  (0, chai_1.expect)(result.name, `error name to equal ${name}`).to.equal(name);
@@ -247,6 +254,7 @@ class Assertions {
247
254
  /**
248
255
  * Expect error json to include given message
249
256
  */
257
+ // eslint-disable-next-line class-methods-use-this
250
258
  errorToHaveMessage(result, message) {
251
259
  (0, chai_1.expect)(result).to.have.property('message');
252
260
  (0, chai_1.expect)(result.message, `error name to include ${message}`).to.include(message);
@@ -277,20 +285,20 @@ class Assertions {
277
285
  const classIds = apexClasses.map((c) => c.Id);
278
286
  const executionTimestamp = this.executionLog.getLatestTimestamp(this.commands.deploy);
279
287
  const testResults = await this.retrieveApexTestResults();
280
- const testsRunAfterTimestamp = testResults.filter((r) => {
281
- return new Date(r.TestTimestamp) > executionTimestamp && classIds.includes(r.ApexClassId);
282
- });
288
+ const testsRunAfterTimestamp = testResults.filter((r) => new Date(r.TestTimestamp) > executionTimestamp && classIds.includes(r.ApexClassId));
283
289
  (0, chai_1.expect)(testsRunAfterTimestamp.length, 'tests to be run during deploy').to.be.greaterThan(0);
284
290
  }
285
291
  /**
286
292
  * Expect result to have given property
287
293
  */
294
+ // eslint-disable-next-line class-methods-use-this
288
295
  toHaveProperty(result, prop) {
289
296
  (0, chai_1.expect)(result).to.have.property(prop);
290
297
  }
291
298
  /**
292
299
  * Expect result to have given property and for that property to equal the given value
293
300
  */
301
+ // eslint-disable-next-line class-methods-use-this
294
302
  toHavePropertyAndValue(result, prop, value) {
295
303
  (0, chai_1.expect)(result).to.have.property(prop);
296
304
  (0, chai_1.expect)(result[prop], `${prop} to have value ${value.toString()}`).to.equal(value);
@@ -298,6 +306,7 @@ class Assertions {
298
306
  /**
299
307
  * Expect result to have given property and for that property to NOT equal the given value
300
308
  */
309
+ // eslint-disable-next-line class-methods-use-this
301
310
  toHavePropertyAndNotValue(result, prop, value) {
302
311
  (0, chai_1.expect)(result).to.have.property(prop);
303
312
  (0, chai_1.expect)(result[prop], `${prop} to have value that does not equal ${value.toString()}`).to.not.equal(value);
@@ -307,7 +316,7 @@ class Assertions {
307
316
  const latestSourceMembers = await this.retrieveSourceMembers(globs, ignore);
308
317
  for (const sourceMember of latestSourceMembers) {
309
318
  const assertionMessage = `expect RevisionCounter for ${sourceMember.MemberName} (${sourceMember.MemberType}) to be incremented`;
310
- const preCommandExecution = sourceMembers.find((s) => s.MemberType === sourceMember.MemberType && s.MemberName === sourceMember.MemberName) || { RevisionCounter: 0 };
319
+ const preCommandExecution = sourceMembers.find((s) => s.MemberType === sourceMember.MemberType && s.MemberName === sourceMember.MemberName) ?? { RevisionCounter: 0 };
311
320
  (0, chai_1.expect)(sourceMember.RevisionCounter, assertionMessage).to.be.greaterThan(preCommandExecution.RevisionCounter);
312
321
  }
313
322
  }
@@ -323,7 +332,7 @@ class Assertions {
323
332
  else {
324
333
  for (const sourceMember of latestSourceMembers) {
325
334
  const assertionMessage = `expect RevisionCounter for ${sourceMember.MemberName} (${sourceMember.MemberType}) to NOT be incremented`;
326
- const preCommandExecution = sourceMembers.find((s) => s.MemberType === sourceMember.MemberType && s.MemberName === sourceMember.MemberName) || { RevisionCounter: 0 };
335
+ const preCommandExecution = sourceMembers.find((s) => s.MemberType === sourceMember.MemberType && s.MemberName === sourceMember.MemberName) ?? { RevisionCounter: 0 };
327
336
  (0, chai_1.expect)(sourceMember.RevisionCounter, assertionMessage).to.equal(preCommandExecution.RevisionCounter);
328
337
  }
329
338
  }
@@ -332,7 +341,7 @@ class Assertions {
332
341
  const sourceMembers = this.executionLog.getLatest(command)?.sourceMembers || [];
333
342
  const latestSourceMembers = await this.retrieveSourceMembers(globs);
334
343
  const someAreNotUpdated = latestSourceMembers.some((sourceMember) => {
335
- const preCommandExecution = sourceMembers.find((s) => s.MemberType === sourceMember.MemberType && s.MemberName === sourceMember.MemberName) || { RevisionCounter: 0 };
344
+ const preCommandExecution = sourceMembers.find((s) => s.MemberType === sourceMember.MemberType && s.MemberName === sourceMember.MemberName) ?? { RevisionCounter: 0 };
336
345
  return sourceMember.RevisionCounter === preCommandExecution.RevisionCounter;
337
346
  });
338
347
  (0, chai_1.expect)(someAreNotUpdated, 'expect some SourceMembers to not be updated').to.be.true;
@@ -359,19 +368,17 @@ class Assertions {
359
368
  }
360
369
  }
361
370
  }
362
- return (result?.records || []).filter((sourceMember) => {
363
- return membersMap.get(sourceMember.MemberType)?.has(sourceMember.MemberName);
364
- });
371
+ return (result?.records ?? []).filter((sourceMember) => membersMap.get(sourceMember.MemberType)?.has(sourceMember.MemberName));
365
372
  }
366
373
  async retrieveApexTestResults() {
367
374
  const query = 'SELECT TestTimestamp, ApexClassId FROM ApexTestResult';
368
375
  const result = await this.connection?.tooling.query(query, { autoFetch: true, maxFetch: 50000 });
369
- return result?.records || [];
376
+ return result?.records ?? [];
370
377
  }
371
378
  async retrieveApexClasses(classNames) {
372
379
  const query = 'SELECT Name,Id FROM ApexClass';
373
380
  const result = await this.connection?.tooling.query(query, { autoFetch: true, maxFetch: 50000 });
374
- const records = result?.records || [];
381
+ const records = result?.records ?? [];
375
382
  return classNames ? records.filter((r) => classNames.includes(r.Name)) : records;
376
383
  }
377
384
  async doGlob(globs, assert = true) {
@@ -22,8 +22,8 @@ class ExecutionLog {
22
22
  * Add a command to the execution log
23
23
  */
24
24
  async add(cmd) {
25
- const baseCmd = (0, ts_types_1.ensureString)(Object.values(this.context.commands).find((c) => cmd.startsWith(c)) || cmd.split(' -')[0]);
26
- const existingEntries = this.log.get(baseCmd) || [];
25
+ const baseCmd = (0, ts_types_1.ensureString)(Object.values(this.context.commands).find((c) => cmd.startsWith(c)) ?? cmd.split(' -')[0]);
26
+ const existingEntries = this.log.get(baseCmd) ?? [];
27
27
  const sourceMembers = baseCmd.includes(this.context.commands.deploy) || baseCmd.includes(this.context.commands.push)
28
28
  ? await this.querySourceMembers()
29
29
  : [];
@@ -44,7 +44,7 @@ class ExecutionLog {
44
44
  * Return the most recent entry for a command
45
45
  */
46
46
  getLatest(cmd) {
47
- const log = this.log.get(cmd) || [];
47
+ const log = this.log.get(cmd) ?? [];
48
48
  const sorted = log.sort((a, b) => (a.timestamp < b.timestamp ? 1 : -1));
49
49
  return sorted[0];
50
50
  }
@@ -54,7 +54,7 @@ class ExecutionLog {
54
54
  autoFetch: true,
55
55
  maxFetch: 50000,
56
56
  });
57
- return result?.records || [];
57
+ return result?.records ?? [];
58
58
  }
59
59
  }
60
60
  exports.ExecutionLog = ExecutionLog;
@@ -10,6 +10,7 @@ exports.countFiles = exports.traverseForFiles = exports.FileTracker = void 0;
10
10
  const fs = require("fs");
11
11
  const path = require("path");
12
12
  const crypto = require("crypto");
13
+ /* eslint-disable no-await-in-loop */
13
14
  /**
14
15
  * This class maintains a map of tracked files. This is particularly useful
15
16
  * for determining if files have changed after a command has been executed
@@ -35,7 +36,7 @@ class FileTracker {
35
36
  * Returns tracked file's history
36
37
  */
37
38
  get(file) {
38
- return this.files.get(file) || [];
39
+ return this.files.get(file) ?? [];
39
40
  }
40
41
  /**
41
42
  * Returns latest entry for file
package/lib/testkit.d.ts CHANGED
@@ -209,14 +209,12 @@ export declare class SourceTestkit extends AsyncCreatable<SourceTestkit.Options>
209
209
  */
210
210
  execute<T>(cmd: string, options?: Partial<SourceTestkit.CommandOpts>): Promise<Nullable<Result<T>>>;
211
211
  protected init(): Promise<void>;
212
- private getExecutableName;
213
212
  private getCommandString;
214
213
  /**
215
214
  * Log error to console with helpful debugging information
216
215
  */
217
216
  private handleError;
218
217
  private createSession;
219
- private getDefaultUsername;
220
218
  private createConnection;
221
219
  private doGlob;
222
220
  }
package/lib/testkit.js CHANGED
@@ -8,6 +8,7 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.COMMANDS = exports.Executable = exports.SourceTestkit = void 0;
10
10
  /* eslint-disable no-console */
11
+ /* eslint-disable no-await-in-loop */
11
12
  const path = require("path");
12
13
  const os = require("os");
13
14
  const fs = require("fs");
@@ -43,7 +44,7 @@ class SourceTestkit extends kit_1.AsyncCreatable {
43
44
  super(options);
44
45
  this.repository = options.repository;
45
46
  this.orgless = !!options.orgless;
46
- this.scratchOrgs = options.scratchOrgs || [];
47
+ this.scratchOrgs = options.scratchOrgs ?? [];
47
48
  this.nut = path.basename(options.nut);
48
49
  this.debug = (0, debug_1.debug)(`sourceTestkit:${this.nut}`);
49
50
  }
@@ -118,6 +119,7 @@ class SourceTestkit extends kit_1.AsyncCreatable {
118
119
  * Installs a package into the scratch org. This method uses shelljs instead of testkit because
119
120
  * we can't add plugin-package as a dev plugin yet.
120
121
  */
122
+ // eslint-disable-next-line class-methods-use-this
121
123
  installPackage(id) {
122
124
  (0, shelljs_1.exec)(`sfdx force:package:install --noprompt --package ${id} --wait 5 --json 2> /dev/null`, { silent: true });
123
125
  }
@@ -127,7 +129,7 @@ class SourceTestkit extends kit_1.AsyncCreatable {
127
129
  * @param options
128
130
  */
129
131
  async assignPermissionSet(options = {}) {
130
- return await this.execute('force:user:permset:assign', options);
132
+ return this.execute('force:user:permset:assign', options);
131
133
  }
132
134
  /**
133
135
  * Adds given files to FileTracker for tracking
@@ -181,6 +183,7 @@ class SourceTestkit extends kit_1.AsyncCreatable {
181
183
  /**
182
184
  * Write file
183
185
  */
186
+ // eslint-disable-next-line class-methods-use-this
184
187
  async writeFile(filename, contents) {
185
188
  return fs.promises.writeFile(filename, contents);
186
189
  }
@@ -317,6 +320,7 @@ class SourceTestkit extends kit_1.AsyncCreatable {
317
320
  * in the same location as toolbelt so we have to find it within the output
318
321
  * dir, move it, and delete the generated dir.
319
322
  */
323
+ // eslint-disable-next-line class-methods-use-this
320
324
  findAndMoveManifest(dir) {
321
325
  const manifest = (0, shelljs_1.find)(dir).filter((file) => file.endsWith('package.xml'));
322
326
  if (!manifest?.length) {
@@ -365,7 +369,7 @@ class SourceTestkit extends kit_1.AsyncCreatable {
365
369
  (0, ts_types_1.ensureString)(SourceTestkit.Env.getString('TESTKIT_HUB_INSTANCE'));
366
370
  }
367
371
  try {
368
- this.executableName = await this.getExecutableName();
372
+ this.executableName = await getExecutableName();
369
373
  this.commands = exports.COMMANDS[this.executableName];
370
374
  this.metadataResolver = new source_deploy_retrieve_1.MetadataResolver();
371
375
  this.session = await this.createSession();
@@ -375,7 +379,7 @@ class SourceTestkit extends kit_1.AsyncCreatable {
375
379
  this.packageNames = this.packages.map((p) => p.name);
376
380
  this.packagePaths = this.packages.map((p) => p.fullPath);
377
381
  this.packageGlobs = this.packages.map((p) => `${p.path}/**/*`);
378
- this.username = await this.getDefaultUsername();
382
+ this.username = await getDefaultUsername();
379
383
  this.connection = await this.createConnection();
380
384
  const context = {
381
385
  connection: this.connection,
@@ -396,11 +400,6 @@ class SourceTestkit extends kit_1.AsyncCreatable {
396
400
  await this.handleError(error, true);
397
401
  }
398
402
  }
399
- async getExecutableName() {
400
- const pkgJsonPath = path.join(process.cwd(), 'package.json');
401
- const pkgJson = (0, kit_1.parseJsonMap)(await fs.promises.readFile(pkgJsonPath, 'utf8'));
402
- return pkgJson.oclif.bin;
403
- }
404
403
  getCommandString(cmdKey) {
405
404
  const cmd = this.commands[cmdKey];
406
405
  if (cmd) {
@@ -430,22 +429,13 @@ class SourceTestkit extends kit_1.AsyncCreatable {
430
429
  const scratchOrgs = this.orgless
431
430
  ? []
432
431
  : [{ executable: 'sf', duration: 1, setDefault: true, config: path.join('config', 'project-scratch-def.json') }];
433
- return await cli_plugins_testkit_1.TestSession.create({
432
+ return cli_plugins_testkit_1.TestSession.create({
434
433
  project: { gitClone: this.repository },
435
434
  devhubAuthStrategy: 'AUTO',
436
435
  scratchOrgs: [...scratchOrgs, ...this.scratchOrgs],
437
436
  retries: 2,
438
437
  });
439
438
  }
440
- async getDefaultUsername() {
441
- const configVar = 'target-org';
442
- const configResult = (0, cli_plugins_testkit_1.execCmd)(`config:get ${configVar} --json`).jsonOutput?.result;
443
- // depending on which version of config:get the user has available, there may be a name or key
444
- // eventually, drop the `key` option and the deprecated SfdxPropertyKeys
445
- const possibleKeys = [configVar, core_1.SfdxPropertyKeys.DEFAULT_USERNAME];
446
- const username = configResult?.find((r) => (r.key && possibleKeys.includes(r.key)) || (r.name && possibleKeys.includes(r.name)))?.value;
447
- return username;
448
- }
449
439
  async createConnection() {
450
440
  if (this.orgless)
451
441
  return;
@@ -498,4 +488,19 @@ exports.COMMANDS = {
498
488
  retrieve: 'retrieve metadata',
499
489
  },
500
490
  };
491
+ const getDefaultUsername = async () => {
492
+ const configVar = 'target-org';
493
+ const configResult = (0, cli_plugins_testkit_1.execCmd)(`config:get ${configVar} --json`)
494
+ .jsonOutput?.result;
495
+ // depending on which version of config:get the user has available, there may be a name or key
496
+ // eventually, drop the `key` option and the deprecated SfdxPropertyKeys
497
+ const possibleKeys = [configVar, core_1.SfdxPropertyKeys.DEFAULT_USERNAME];
498
+ const username = configResult?.find((r) => (r.key && possibleKeys.includes(r.key)) || (r.name && possibleKeys.includes(r.name)))?.value;
499
+ return username;
500
+ };
501
+ const getExecutableName = async () => {
502
+ const pkgJsonPath = path.join(process.cwd(), 'package.json');
503
+ const pkgJson = (0, kit_1.parseJsonMap)(await fs.promises.readFile(pkgJsonPath, 'utf8'));
504
+ return pkgJson.oclif.bin;
505
+ };
501
506
  //# sourceMappingURL=testkit.js.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@salesforce/source-testkit",
3
3
  "description": "testkit for running NUTs for source related commands",
4
- "version": "2.0.2",
4
+ "version": "2.0.3",
5
5
  "author": "Salesforce",
6
6
  "license": "BSD-3-Clause",
7
7
  "main": "lib/index.js",
@@ -31,7 +31,7 @@
31
31
  ],
32
32
  "dependencies": {
33
33
  "@salesforce/cli-plugins-testkit": "^3.0.2",
34
- "@salesforce/core": "^3.30.2",
34
+ "@salesforce/core": "^3.30.11",
35
35
  "@salesforce/kit": "^1.5.42",
36
36
  "@salesforce/source-deploy-retrieve": "^6.8.2",
37
37
  "@salesforce/ts-types": "^1.5.21",
@@ -44,40 +44,34 @@
44
44
  },
45
45
  "devDependencies": {
46
46
  "@salesforce/dev-config": "^3.0.0",
47
- "@salesforce/dev-scripts": "^2.0.2",
47
+ "@salesforce/dev-scripts": "^3.1.0",
48
48
  "@salesforce/prettier-config": "^0.0.2",
49
49
  "@salesforce/ts-sinon": "^1.4.0",
50
50
  "@types/archiver": "^5.1.0",
51
51
  "@types/debug": "^4.1.5",
52
52
  "@types/shelljs": "^0.8.11",
53
- "@typescript-eslint/eslint-plugin": "^4.15.2",
54
- "@typescript-eslint/parser": "^4.15.2",
53
+ "@typescript-eslint/eslint-plugin": "^5.33.0",
54
+ "@typescript-eslint/parser": "^5.39.0",
55
55
  "chai": "^4.3.0",
56
56
  "copyfiles": "^2.4.1",
57
- "cz-conventional-changelog": "^3.3.0",
58
- "eslint": "^7.27.0",
59
- "eslint-config-prettier": "^8.1.0",
60
- "eslint-config-salesforce": "^0.1.6",
57
+ "eslint": "^8.21.0",
58
+ "eslint-config-prettier": "^8.5.0",
59
+ "eslint-config-salesforce": "^1.1.0",
61
60
  "eslint-config-salesforce-license": "^0.1.6",
62
- "eslint-config-salesforce-typescript": "^0.2.8",
61
+ "eslint-config-salesforce-typescript": "^1.1.1",
63
62
  "eslint-plugin-header": "^3.1.1",
64
63
  "eslint-plugin-import": "2.26.0",
65
- "eslint-plugin-jsdoc": "^35.1.2",
66
- "eslint-plugin-prettier": "^3.3.1",
64
+ "eslint-plugin-jsdoc": "^39.3.6",
67
65
  "husky": "^7.0.4",
68
66
  "mocha": "^9.1.3",
69
67
  "nyc": "^15.1.0",
70
- "prettier": "^2.0.5",
68
+ "prettier": "^2.7.1",
71
69
  "pretty-quick": "^3.1.0",
72
70
  "sinon": "^10.0.0",
73
71
  "ts-node": "^10.0.0",
74
72
  "typescript": "^4.8.4"
75
73
  },
76
- "config": {
77
- "commitizen": {
78
- "path": "cz-conventional-changelog"
79
- }
80
- },
74
+ "config": {},
81
75
  "publishConfig": {
82
76
  "access": "public"
83
77
  }