@salesforce/source-testkit 0.0.17 → 1.0.1

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/CHANGELOG.md CHANGED
@@ -2,6 +2,24 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [1.0.1](https://github.com/salesforcecli/source-testkit/compare/v1.0.0...v1.0.1) (2022-05-31)
6
+
7
+ ### Bug Fixes
8
+
9
+ - support multiple plugin-config versions ([#78](https://github.com/salesforcecli/source-testkit/issues/78)) ([365831f](https://github.com/salesforcecli/source-testkit/commit/365831f5de5f489d2f2065230e8847de1ecf4f0b))
10
+
11
+ ## [1.0.0](https://github.com/salesforcecli/source-testkit/compare/v0.0.18...v1.0.0) (2022-05-31)
12
+
13
+ ### Features
14
+
15
+ - use parking-orbit newer core/sdr ([#77](https://github.com/salesforcecli/source-testkit/issues/77)) ([d9ed642](https://github.com/salesforcecli/source-testkit/commit/d9ed642003bb85407a7b17ffa7b64764eb81b488))
16
+
17
+ ### [0.0.18](https://github.com/salesforcecli/source-testkit/compare/v0.0.17...v0.0.18) (2022-03-08)
18
+
19
+ ### Features
20
+
21
+ - make type changes to make testing sf easier ([#59](https://github.com/salesforcecli/source-testkit/issues/59)) ([7752ed6](https://github.com/salesforcecli/source-testkit/commit/7752ed66eff3be11c9fa6921223f277427334fab))
22
+
5
23
  ### [0.0.17](https://github.com/salesforcecli/source-testkit/compare/v0.0.16...v0.0.17) (2022-02-12)
6
24
 
7
25
  ### [0.0.16](https://github.com/salesforcecli/source-testkit/compare/v0.0.15...v0.0.16) (2021-10-13)
package/lib/assertions.js CHANGED
@@ -1,21 +1,21 @@
1
1
  "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Assertions = void 0;
2
4
  /*
3
5
  * Copyright (c) 2021, salesforce.com, inc.
4
6
  * All rights reserved.
5
7
  * Licensed under the BSD 3-Clause license.
6
8
  * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
7
9
  */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.Assertions = void 0;
10
+ const fs = require("fs");
10
11
  const path = require("path");
11
12
  const chai_1 = require("chai");
12
13
  const chaiEach = require("chai-each");
13
14
  const fg = require("fast-glob");
14
- const core_1 = require("@salesforce/core");
15
15
  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
- chai_1.use(chaiEach);
18
+ (0, chai_1.use)(chaiEach);
19
19
  /**
20
20
  * Assertions is a class that is designed to encapsulate common assertions we want to
21
21
  * make during NUT testings
@@ -31,7 +31,7 @@ class Assertions {
31
31
  this.projectDir = context.projectDir;
32
32
  this.connection = context.connection;
33
33
  this.commands = context.commands;
34
- this.debug = debug_1.debug(`assertions:${context.nut}`);
34
+ this.debug = (0, debug_1.debug)(`assertions:${context.nut}`);
35
35
  this.metadataResolver = new source_deploy_retrieve_1.MetadataResolver();
36
36
  }
37
37
  /**
@@ -39,14 +39,14 @@ class Assertions {
39
39
  */
40
40
  fileToBeChanged(file) {
41
41
  const fileHistory = this.fileTracker.getLatest(file);
42
- chai_1.expect(fileHistory === null || fileHistory === void 0 ? void 0 : fileHistory.changedFromPrevious, 'File to be changed').to.be.true;
42
+ (0, chai_1.expect)(fileHistory === null || fileHistory === void 0 ? void 0 : fileHistory.changedFromPrevious, 'File to be changed').to.be.true;
43
43
  }
44
44
  /**
45
45
  * Expect given file to NOT be changed according to the file history provided by FileTracker
46
46
  */
47
47
  fileToNotBeChanged(file) {
48
48
  const fileHistory = this.fileTracker.getLatest(file);
49
- chai_1.expect(fileHistory === null || fileHistory === void 0 ? void 0 : fileHistory.changedFromPrevious, 'File to NOT be changed').to.be.false;
49
+ (0, chai_1.expect)(fileHistory === null || fileHistory === void 0 ? void 0 : fileHistory.changedFromPrevious, 'File to NOT be changed').to.be.false;
50
50
  }
51
51
  /**
52
52
  * Expect all files found by globs to be changed according to the file history provided by FileTracker
@@ -62,9 +62,9 @@ class Assertions {
62
62
  .filter((f) => !f.endsWith('.resource'))
63
63
  .map((f) => this.fileTracker.getLatest(path.normalize(f)))
64
64
  .filter((f) => !!f);
65
- chai_1.expect(fileHistories, 'file history to exist for tracked files').length.to.be.greaterThan(0);
65
+ (0, chai_1.expect)(fileHistories, 'file history to exist for tracked files').length.to.be.greaterThan(0);
66
66
  const allChanged = fileHistories.every((f) => f === null || f === void 0 ? void 0 : f.changedFromPrevious);
67
- chai_1.expect(allChanged, 'all files to be changed').to.be.true;
67
+ (0, chai_1.expect)(allChanged, 'all files to be changed').to.be.true;
68
68
  }
69
69
  /**
70
70
  * Expect all files found by globs to NOT be changed according to the file history provided by FileTracker
@@ -77,9 +77,9 @@ class Assertions {
77
77
  .filter((f) => !f.endsWith('.resource-meta.xml'))
78
78
  .map((f) => this.fileTracker.getLatest(f))
79
79
  .filter((f) => !!f);
80
- chai_1.expect(fileHistories, 'file history to exist for tracked files').length.to.be.greaterThan(0);
80
+ (0, chai_1.expect)(fileHistories, 'file history to exist for tracked files').length.to.be.greaterThan(0);
81
81
  const allChanged = fileHistories.every((f) => f === null || f === void 0 ? void 0 : f.changedFromPrevious);
82
- chai_1.expect(allChanged, 'all files to NOT be changed').to.be.false;
82
+ (0, chai_1.expect)(allChanged, 'all files to NOT be changed').to.be.false;
83
83
  }
84
84
  /**
85
85
  * Finds all files in project based on the provided globs and expects them to be updated on the server
@@ -102,7 +102,7 @@ class Assertions {
102
102
  // glob will return files with '/' as separators, this won't work on Windows
103
103
  const toTrack = all.filter((file) => !ignoreFiles.includes(file)).map((file) => file.replace(/\//g, path.sep));
104
104
  result.map((source) => {
105
- chai_1.expect(toTrack, `toTrack: ${toTrack.join('\n')}, missing file : ${source.filePath}`).to.include(source.filePath);
105
+ (0, chai_1.expect)(toTrack, `toTrack: ${toTrack.join('\n')}, missing file : ${source.filePath}`).to.include(source.filePath);
106
106
  });
107
107
  }
108
108
  /**
@@ -123,8 +123,8 @@ class Assertions {
123
123
  */
124
124
  async fileToExist(file) {
125
125
  const fullPath = file.startsWith(this.projectDir) ? file : path.join(this.projectDir, file);
126
- const fileExists = await core_1.fs.fileExists(fullPath);
127
- chai_1.expect(fileExists, `${fullPath} to exist`).to.be.true;
126
+ const fileExists = fs.existsSync(fullPath);
127
+ (0, chai_1.expect)(fileExists, `${fullPath} to exist`).to.be.true;
128
128
  }
129
129
  /**
130
130
  * Expects given globs to return files
@@ -132,7 +132,7 @@ class Assertions {
132
132
  async filesToExist(globs) {
133
133
  for (const glob of globs) {
134
134
  const results = await this.doGlob([glob]);
135
- chai_1.expect(results.length, `expect files to be found by glob: ${glob}`).to.be.greaterThan(0);
135
+ (0, chai_1.expect)(results.length, `expect files to be found by glob: ${glob}`).to.be.greaterThan(0);
136
136
  }
137
137
  }
138
138
  /**
@@ -141,7 +141,7 @@ class Assertions {
141
141
  async filesToNotExist(globs) {
142
142
  for (const glob of globs) {
143
143
  const results = await this.doGlob([glob], false);
144
- chai_1.expect(results.length, `expect no files to be found by glob: ${glob}`).to.equal(0);
144
+ (0, chai_1.expect)(results.length, `expect no files to be found by glob: ${glob}`).to.equal(0);
145
145
  }
146
146
  }
147
147
  /**
@@ -151,7 +151,7 @@ class Assertions {
151
151
  directory = directory.split(path.sep).join('/');
152
152
  const fullGlobs = globs.map((glob) => [directory, glob].join('/'));
153
153
  const convertedFiles = await fg(fullGlobs);
154
- chai_1.expect(convertedFiles.length, 'files to be converted').to.be.greaterThan(0);
154
+ (0, chai_1.expect)(convertedFiles.length, 'files to be converted').to.be.greaterThan(0);
155
155
  }
156
156
  /**
157
157
  * Expects files found by glob to not contain any of the provided strings
@@ -159,9 +159,9 @@ class Assertions {
159
159
  async filesToNotContainString(glob, ...strings) {
160
160
  const files = await this.doGlob([glob]);
161
161
  for (const file of files) {
162
- const contents = await core_1.fs.readFile(file, 'UTF-8');
162
+ const contents = await fs.promises.readFile(file, 'utf-8');
163
163
  for (const str of strings) {
164
- chai_1.expect(contents, `expect ${file} to not include ${str}`).to.not.include(str);
164
+ (0, chai_1.expect)(contents, `expect ${file} to not include ${str}`).to.not.include(str);
165
165
  }
166
166
  }
167
167
  }
@@ -171,9 +171,9 @@ class Assertions {
171
171
  async filesToContainString(glob, ...strings) {
172
172
  const files = await this.doGlob([glob]);
173
173
  for (const file of files) {
174
- const contents = await core_1.fs.readFile(file, 'UTF-8');
174
+ const contents = await fs.promises.readFile(file, 'utf-8');
175
175
  for (const str of strings) {
176
- chai_1.expect(contents, `expect ${file} to not include ${str}`).to.include(str);
176
+ (0, chai_1.expect)(contents, `expect ${file} to not include ${str}`).to.include(str);
177
177
  }
178
178
  }
179
179
  }
@@ -197,14 +197,14 @@ class Assertions {
197
197
  */
198
198
  async directoryToHaveSomeFiles(directory) {
199
199
  const fullPath = directory.startsWith(this.projectDir) ? directory : path.join(this.projectDir, directory);
200
- const fileCount = await fileTracker_1.countFiles([fullPath]);
201
- chai_1.expect(fileCount, `at least 1 file found in ${directory}`).to.be.greaterThan(0);
200
+ const fileCount = await (0, fileTracker_1.countFiles)([fullPath]);
201
+ (0, chai_1.expect)(fileCount, `at least 1 file found in ${directory}`).to.be.greaterThan(0);
202
202
  }
203
203
  /**
204
204
  * Expect status to return no results
205
205
  */
206
206
  statusToBeEmpty(result) {
207
- chai_1.expect(result.length, 'status to have no results').to.equal(0);
207
+ (0, chai_1.expect)(result.length, 'status to have no results').to.equal(0);
208
208
  }
209
209
  /**
210
210
  * Expect all given files to have the given state
@@ -213,36 +213,36 @@ class Assertions {
213
213
  for (const file of files) {
214
214
  this.statusFileToHaveState(result, state, file);
215
215
  }
216
- chai_1.expect(result.length, 'all files to be present in json response').to.equal(files.length);
216
+ (0, chai_1.expect)(result.length, 'all files to be present in json response').to.equal(files.length);
217
217
  }
218
218
  /**
219
219
  * Expect given file to have the given state
220
220
  */
221
221
  statusFileToHaveState(result, state, file) {
222
222
  const expectedFile = result.find((r) => r.filePath === file);
223
- chai_1.expect(expectedFile, `${file} to be present in json response`).to.not.be.undefined;
224
- chai_1.expect(expectedFile === null || expectedFile === void 0 ? void 0 : expectedFile.state, `${file} to have state ${state}`).to.equal(state);
223
+ (0, chai_1.expect)(expectedFile, `${file} to be present in json response`).to.not.be.undefined;
224
+ (0, chai_1.expect)(expectedFile === null || expectedFile === void 0 ? void 0 : expectedFile.state, `${file} to have state ${state}`).to.equal(state);
225
225
  }
226
226
  /**
227
227
  * Expect all given files to have the given state
228
228
  */
229
229
  statusToOnlyHaveState(result, state) {
230
230
  const allStates = result.every((r) => r.state === state);
231
- chai_1.expect(allStates, `all files to have ${state}`).to.be.true;
231
+ (0, chai_1.expect)(allStates, `all files to have ${state}`).to.be.true;
232
232
  }
233
233
  /**
234
234
  * Expect all files to have a conflict state
235
235
  */
236
236
  statusToOnlyHaveConflicts(result) {
237
237
  const allConflicts = result.every((r) => r.state.includes('Conflict'));
238
- chai_1.expect(allConflicts, 'all results to show conflict state').to.be.true;
238
+ (0, chai_1.expect)(allConflicts, 'all results to show conflict state').to.be.true;
239
239
  }
240
240
  /**
241
241
  * Expect json to have given error name
242
242
  */
243
243
  errorToHaveName(result, name) {
244
- chai_1.expect(result).to.have.property('name');
245
- chai_1.expect(result.name, `error name to equal ${name}`).to.equal(name);
244
+ (0, chai_1.expect)(result).to.have.property('name');
245
+ (0, chai_1.expect)(result.name, `error name to equal ${name}`).to.equal(name);
246
246
  }
247
247
  /**
248
248
  * Expect no apex tests to be run
@@ -251,7 +251,7 @@ class Assertions {
251
251
  const executionTimestamp = this.executionLog.getLatestTimestamp(this.commands.deploy);
252
252
  const testResults = await this.retrieveApexTestResults();
253
253
  const testsRunAfterTimestamp = testResults.filter((r) => new Date(r.TestTimestamp) > executionTimestamp);
254
- chai_1.expect(testsRunAfterTimestamp.length, 'no tests to be run during deploy').to.equal(0);
254
+ (0, chai_1.expect)(testsRunAfterTimestamp.length, 'no tests to be run during deploy').to.equal(0);
255
255
  }
256
256
  /**
257
257
  * Expect some apex tests to be run
@@ -260,7 +260,7 @@ class Assertions {
260
260
  const executionTimestamp = this.executionLog.getLatestTimestamp(this.commands.deploy);
261
261
  const testResults = await this.retrieveApexTestResults();
262
262
  const testsRunAfterTimestamp = testResults.filter((r) => new Date(r.TestTimestamp) > executionTimestamp);
263
- chai_1.expect(testsRunAfterTimestamp.length, 'tests to be run during deploy').to.be.greaterThan(0);
263
+ (0, chai_1.expect)(testsRunAfterTimestamp.length, 'tests to be run during deploy').to.be.greaterThan(0);
264
264
  }
265
265
  /**
266
266
  * Expect apex tests owned by the provided classes to be run
@@ -273,27 +273,27 @@ class Assertions {
273
273
  const testsRunAfterTimestamp = testResults.filter((r) => {
274
274
  return new Date(r.TestTimestamp) > executionTimestamp && classIds.includes(r.ApexClassId);
275
275
  });
276
- chai_1.expect(testsRunAfterTimestamp.length, 'tests to be run during deploy').to.be.greaterThan(0);
276
+ (0, chai_1.expect)(testsRunAfterTimestamp.length, 'tests to be run during deploy').to.be.greaterThan(0);
277
277
  }
278
278
  /**
279
279
  * Expect result to have given property
280
280
  */
281
281
  toHaveProperty(result, prop) {
282
- chai_1.expect(result).to.have.property(prop);
282
+ (0, chai_1.expect)(result).to.have.property(prop);
283
283
  }
284
284
  /**
285
285
  * Expect result to have given property and for that property to equal the given value
286
286
  */
287
287
  toHavePropertyAndValue(result, prop, value) {
288
- chai_1.expect(result).to.have.property(prop);
289
- chai_1.expect(result[prop], `${prop} to have value ${value.toString()}`).to.equal(value);
288
+ (0, chai_1.expect)(result).to.have.property(prop);
289
+ (0, chai_1.expect)(result[prop], `${prop} to have value ${value.toString()}`).to.equal(value);
290
290
  }
291
291
  /**
292
292
  * Expect result to have given property and for that property to NOT equal the given value
293
293
  */
294
294
  toHavePropertyAndNotValue(result, prop, value) {
295
- chai_1.expect(result).to.have.property(prop);
296
- chai_1.expect(result[prop], `${prop} to have value that does not equal ${value.toString()}`).to.not.equal(value);
295
+ (0, chai_1.expect)(result).to.have.property(prop);
296
+ (0, chai_1.expect)(result[prop], `${prop} to have value that does not equal ${value.toString()}`).to.not.equal(value);
297
297
  }
298
298
  async filesToBeUpdated(globs, ignore = [], command) {
299
299
  var _a;
@@ -302,7 +302,7 @@ class Assertions {
302
302
  for (const sourceMember of latestSourceMembers) {
303
303
  const assertionMessage = `expect RevisionCounter for ${sourceMember.MemberName} (${sourceMember.MemberType}) to be incremented`;
304
304
  const preCommandExecution = sourceMembers.find((s) => s.MemberType === sourceMember.MemberType && s.MemberName === sourceMember.MemberName) || { RevisionCounter: 0 };
305
- chai_1.expect(sourceMember.RevisionCounter, assertionMessage).to.be.greaterThan(preCommandExecution.RevisionCounter);
305
+ (0, chai_1.expect)(sourceMember.RevisionCounter, assertionMessage).to.be.greaterThan(preCommandExecution.RevisionCounter);
306
306
  }
307
307
  }
308
308
  async filesToNotBeUpdated(globs, ignore = [], command) {
@@ -313,13 +313,13 @@ class Assertions {
313
313
  // Not finding any source members based on the globs means that there is no SourceMember for those files
314
314
  // which we're assuming means that it hasn't been deployed to the org yet.
315
315
  // That's acceptable for this test since we're testing that metadata hasn't been deployed.
316
- chai_1.expect(latestSourceMembers.length).to.equal(0);
316
+ (0, chai_1.expect)(latestSourceMembers.length).to.equal(0);
317
317
  }
318
318
  else {
319
319
  for (const sourceMember of latestSourceMembers) {
320
320
  const assertionMessage = `expect RevisionCounter for ${sourceMember.MemberName} (${sourceMember.MemberType}) to NOT be incremented`;
321
321
  const preCommandExecution = sourceMembers.find((s) => s.MemberType === sourceMember.MemberType && s.MemberName === sourceMember.MemberName) || { RevisionCounter: 0 };
322
- chai_1.expect(sourceMember.RevisionCounter, assertionMessage).to.equal(preCommandExecution.RevisionCounter);
322
+ (0, chai_1.expect)(sourceMember.RevisionCounter, assertionMessage).to.equal(preCommandExecution.RevisionCounter);
323
323
  }
324
324
  }
325
325
  }
@@ -331,7 +331,7 @@ class Assertions {
331
331
  const preCommandExecution = sourceMembers.find((s) => s.MemberType === sourceMember.MemberType && s.MemberName === sourceMember.MemberName) || { RevisionCounter: 0 };
332
332
  return sourceMember.RevisionCounter === preCommandExecution.RevisionCounter;
333
333
  });
334
- chai_1.expect(someAreNotUpdated, 'expect some SourceMembers to not be updated').to.be.true;
334
+ (0, chai_1.expect)(someAreNotUpdated, 'expect some SourceMembers to not be updated').to.be.true;
335
335
  }
336
336
  async retrieveSourceMembers(globs, ignore = []) {
337
337
  var _a;
@@ -395,7 +395,7 @@ class Assertions {
395
395
  files.push(...globResults);
396
396
  }
397
397
  if (assert)
398
- chai_1.expect(files.length, 'globs to return files').to.be.greaterThan(0);
398
+ (0, chai_1.expect)(files.length, 'globs to return files').to.be.greaterThan(0);
399
399
  return files;
400
400
  }
401
401
  }
@@ -22,7 +22,7 @@ class ExecutionLog {
22
22
  * Add a command to the execution log
23
23
  */
24
24
  async add(cmd) {
25
- const baseCmd = ts_types_1.ensureString(Object.values(this.context.commands).find((c) => cmd.startsWith(c)) || cmd.split(' -')[0]);
25
+ const baseCmd = (0, ts_types_1.ensureString)(Object.values(this.context.commands).find((c) => cmd.startsWith(c)) || cmd.split(' -')[0]);
26
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()
@@ -1,14 +1,15 @@
1
1
  "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.countFiles = exports.traverseForFiles = exports.FileTracker = void 0;
2
4
  /*
3
5
  * Copyright (c) 2021, salesforce.com, inc.
4
6
  * All rights reserved.
5
7
  * Licensed under the BSD 3-Clause license.
6
8
  * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
7
9
  */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.countFiles = exports.traverseForFiles = exports.FileTracker = void 0;
10
+ const fs = require("fs");
10
11
  const path = require("path");
11
- const core_1 = require("@salesforce/core");
12
+ const crypto = require("crypto");
12
13
  /**
13
14
  * This class maintains a map of tracked files. This is particularly useful
14
15
  * for determining if files have changed after a command has been executed
@@ -76,10 +77,12 @@ class FileTracker {
76
77
  async getContentHash(file) {
77
78
  const filePath = this.getFullPath(file);
78
79
  try {
79
- const filestat = await core_1.fs.stat(filePath);
80
+ const filestat = await fs.promises.stat(filePath);
80
81
  const isDirectory = filestat.isDirectory();
81
- const contents = isDirectory ? (await core_1.fs.readdir(filePath)).toString() : await core_1.fs.readFile(filePath);
82
- return core_1.fs.getContentHash(contents);
82
+ const contents = isDirectory
83
+ ? (await fs.promises.readdir(filePath)).toString()
84
+ : await fs.promises.readFile(filePath);
85
+ return crypto.createHash('sha1').update(contents).digest('hex');
83
86
  }
84
87
  catch {
85
88
  return null;
@@ -94,10 +97,10 @@ exports.FileTracker = FileTracker;
94
97
  * Returns all files in directory that match the filter
95
98
  */
96
99
  async function traverseForFiles(dirPath, regexFilter = /./, allFiles = []) {
97
- const files = await core_1.fs.readdir(dirPath);
100
+ const files = await fs.promises.readdir(dirPath);
98
101
  for (const file of files) {
99
102
  const filePath = path.join(dirPath, file);
100
- if (core_1.fs.statSync(filePath).isDirectory()) {
103
+ if (fs.statSync(filePath).isDirectory()) {
101
104
  allFiles = await traverseForFiles(filePath, regexFilter, allFiles);
102
105
  }
103
106
  else if (regexFilter.test(file)) {
package/lib/testkit.d.ts CHANGED
@@ -58,9 +58,9 @@ export declare class SourceTestkit extends AsyncCreatable<SourceTestkit.Options>
58
58
  /**
59
59
  * Executes force:source:deploy
60
60
  */
61
- deploy(options?: Partial<SourceTestkit.CommandOpts>): Promise<Result<{
61
+ deploy<T = {
62
62
  id: string;
63
- }>>;
63
+ }>(options?: Partial<SourceTestkit.CommandOpts>): Promise<Result<T>>;
64
64
  /**
65
65
  * Executes force:source:deploy:report
66
66
  */
@@ -199,7 +199,7 @@ export declare class SourceTestkit extends AsyncCreatable<SourceTestkit.Options>
199
199
  */
200
200
  spoofRemoteChange(globs: string[]): Promise<void>;
201
201
  /**
202
- * Returns true if the executable being used belongs to a local pacakage
202
+ * Returns true if the executable being used belongs to a local package
203
203
  */
204
204
  isLocalExecutable(): boolean;
205
205
  /**
package/lib/testkit.js CHANGED
@@ -10,6 +10,7 @@ exports.COMMANDS = exports.Executable = exports.SourceTestkit = void 0;
10
10
  /* eslint-disable no-console */
11
11
  const path = require("path");
12
12
  const os = require("os");
13
+ const fs = require("fs");
13
14
  const fg = require("fast-glob");
14
15
  const shelljs_1 = require("shelljs");
15
16
  const cli_plugins_testkit_1 = require("@salesforce/cli-plugins-testkit");
@@ -39,13 +40,14 @@ const fileTracker_1 = require("./fileTracker");
39
40
  */
40
41
  class SourceTestkit extends kit_1.AsyncCreatable {
41
42
  constructor(options) {
43
+ var _a, _b, _c;
42
44
  super(options);
43
- this.executable = options.executable || shelljs_1.which('sfdx').stdout;
45
+ this.executable = (_c = (_a = options.executable) !== null && _a !== void 0 ? _a : (_b = (0, shelljs_1.which)('sfdx')) === null || _b === void 0 ? void 0 : _b.stdout) !== null && _c !== void 0 ? _c : 'sfdx';
44
46
  this.repository = options.repository;
45
47
  this.orgless = !!options.orgless;
46
48
  this.setupCommands = options.setupCommands || [];
47
49
  this.nut = path.basename(options.nut);
48
- this.debug = debug_1.debug(`sourceTestkit:${this.nut}`);
50
+ this.debug = (0, debug_1.debug)(`sourceTestkit:${this.nut}`);
49
51
  }
50
52
  /**
51
53
  * Cleans the test session
@@ -120,7 +122,7 @@ class SourceTestkit extends kit_1.AsyncCreatable {
120
122
  * we can't add plugin-package as a dev plugin yet.
121
123
  */
122
124
  installPackage(id) {
123
- shelljs_1.exec(`sfdx force:package:install --noprompt --package ${id} --wait 5 --json 2> /dev/null`, { silent: true });
125
+ (0, shelljs_1.exec)(`sfdx force:package:install --noprompt --package ${id} --wait 5 --json 2> /dev/null`, { silent: true });
124
126
  }
125
127
  /**
126
128
  * Runs the permset:assign command with the passed in options
@@ -154,7 +156,7 @@ class SourceTestkit extends kit_1.AsyncCreatable {
154
156
  const files = await this.doGlob(globs);
155
157
  const returnValue = {};
156
158
  for (const file of files) {
157
- returnValue[file] = await core_1.fs.readFile(file, 'UTF-8');
159
+ returnValue[file] = await fs.promises.readFile(file, 'utf8');
158
160
  }
159
161
  return returnValue;
160
162
  }
@@ -163,27 +165,27 @@ class SourceTestkit extends kit_1.AsyncCreatable {
163
165
  */
164
166
  async readSourcePathInfos() {
165
167
  const sourcePathInfosPath = path.join(this.projectDir, '.sfdx', 'orgs', this.username, 'sourcePathInfos.json');
166
- return core_1.fs.readJson(sourcePathInfosPath);
168
+ return JSON.parse(await fs.promises.readFile(sourcePathInfosPath, 'utf8'));
167
169
  }
168
170
  /**
169
171
  * Read the org's maxRevision.json
170
172
  */
171
173
  async readMaxRevision() {
172
174
  const maxRevisionPath = path.join(this.projectDir, '.sfdx', 'orgs', this.username, 'maxRevision.json');
173
- return core_1.fs.readJson(maxRevisionPath);
175
+ return JSON.parse(await fs.promises.readFile(maxRevisionPath, 'utf8'));
174
176
  }
175
177
  /**
176
178
  * Write the org's maxRevision.json
177
179
  */
178
180
  async writeMaxRevision(contents) {
179
181
  const maxRevisionPath = path.join(this.projectDir, '.sfdx', 'orgs', this.username, 'maxRevision.json');
180
- return core_1.fs.writeJson(maxRevisionPath, contents);
182
+ return fs.promises.writeFile(maxRevisionPath, JSON.stringify(contents));
181
183
  }
182
184
  /**
183
185
  * Write file
184
186
  */
185
187
  async writeFile(filename, contents) {
186
- return core_1.fs.writeFile(filename, contents);
188
+ return fs.promises.writeFile(filename, contents);
187
189
  }
188
190
  /**
189
191
  * Create a package.xml
@@ -196,7 +198,7 @@ class SourceTestkit extends kit_1.AsyncCreatable {
196
198
  </Package>
197
199
  `;
198
200
  const packageXmlPath = path.join(this.projectDir, 'package.xml');
199
- await core_1.fs.writeFile(packageXmlPath, packageXml);
201
+ await fs.promises.writeFile(packageXmlPath, packageXml);
200
202
  return packageXmlPath;
201
203
  }
202
204
  /**
@@ -204,14 +206,14 @@ class SourceTestkit extends kit_1.AsyncCreatable {
204
206
  */
205
207
  async deleteSourcePathInfos() {
206
208
  const sourcePathInfosPath = path.join(this.projectDir, '.sfdx', 'orgs', this.username, 'sourcePathInfos.json');
207
- return core_1.fs.unlink(sourcePathInfosPath);
209
+ return fs.promises.unlink(sourcePathInfosPath);
208
210
  }
209
211
  /**
210
212
  * Delete the org's maxRevision.json
211
213
  */
212
214
  async deleteMaxRevision() {
213
215
  const maxRevisionPath = path.join(this.projectDir, '.sfdx', 'orgs', this.username, 'maxRevision.json');
214
- return core_1.fs.unlink(maxRevisionPath);
216
+ return fs.promises.unlink(maxRevisionPath);
215
217
  }
216
218
  /**
217
219
  * Delete the files found by the given globs
@@ -219,7 +221,7 @@ class SourceTestkit extends kit_1.AsyncCreatable {
219
221
  async deleteGlobs(globs) {
220
222
  const files = await this.doGlob(globs);
221
223
  for (const file of files) {
222
- await core_1.fs.unlink(file);
224
+ await fs.promises.unlink(file);
223
225
  }
224
226
  }
225
227
  /**
@@ -227,8 +229,8 @@ class SourceTestkit extends kit_1.AsyncCreatable {
227
229
  */
228
230
  async deleteAllSourceFiles() {
229
231
  for (const pkg of this.packagePaths) {
230
- await core_1.fs.rmdir(pkg, { recursive: true });
231
- await core_1.fs.mkdirp(pkg);
232
+ await fs.promises.rm(pkg, { recursive: true });
233
+ await fs.promises.mkdir(pkg, { recursive: true });
232
234
  }
233
235
  }
234
236
  /**
@@ -245,9 +247,9 @@ class SourceTestkit extends kit_1.AsyncCreatable {
245
247
  */
246
248
  async modifyLocalFile(file, append = os.EOL) {
247
249
  const fullPath = file.startsWith(this.projectDir) ? file : path.join(this.projectDir, file);
248
- let contents = await core_1.fs.readFile(fullPath, 'UTF-8');
250
+ let contents = await fs.promises.readFile(fullPath, 'utf-8');
249
251
  contents += append;
250
- await core_1.fs.writeFile(fullPath, contents);
252
+ await fs.promises.writeFile(fullPath, contents);
251
253
  await this.fileTracker.update(fullPath, 'modified file');
252
254
  }
253
255
  /**
@@ -276,11 +278,11 @@ class SourceTestkit extends kit_1.AsyncCreatable {
276
278
  const src = path.join(this.testMetadataFolder, file);
277
279
  this.debug(`addTestFiles: ${src} -> ${dest}`);
278
280
  try {
279
- core_1.fs.copyFileSync(src, dest);
281
+ fs.copyFileSync(src, dest);
280
282
  }
281
283
  catch {
282
- await core_1.fs.mkdirp(path.dirname(dest));
283
- core_1.fs.copyFileSync(src, dest);
284
+ await fs.promises.mkdir(path.dirname(dest), { recursive: true });
285
+ fs.copyFileSync(src, dest);
284
286
  }
285
287
  }
286
288
  await this.trackFiles(this.testMetadataFiles);
@@ -300,19 +302,19 @@ class SourceTestkit extends kit_1.AsyncCreatable {
300
302
  const name = component.name;
301
303
  if (!type.includes('CustomLabel')) {
302
304
  const maxRevisionKey = parent ? `${type}__${parent}.${name}` : `${type}__${name}`;
303
- kit_1.set(maxRevision.sourceMembers, `${maxRevisionKey}.lastRetrievedFromServer`, null);
305
+ (0, kit_1.set)(maxRevision.sourceMembers, `${maxRevisionKey}.lastRetrievedFromServer`, null);
304
306
  }
305
307
  else {
306
308
  const labels = Object.keys(maxRevision.sourceMembers).filter((k) => k.startsWith('CustomLabel'));
307
309
  labels.forEach((label) => {
308
- kit_1.set(maxRevision.sourceMembers, `${label}.lastRetrievedFromServer`, null);
310
+ (0, kit_1.set)(maxRevision.sourceMembers, `${label}.lastRetrievedFromServer`, null);
309
311
  });
310
312
  }
311
313
  }
312
314
  await this.writeMaxRevision(maxRevision);
313
315
  }
314
316
  /**
315
- * Returns true if the executable being used belongs to a local pacakage
317
+ * Returns true if the executable being used belongs to a local package
316
318
  */
317
319
  isLocalExecutable() {
318
320
  return (this.executable.endsWith(SourceTestkit.LocalDevPath) || this.executable.endsWith(SourceTestkit.LocalProdPath));
@@ -325,12 +327,12 @@ class SourceTestkit extends kit_1.AsyncCreatable {
325
327
  * dir, move it, and delete the generated dir.
326
328
  */
327
329
  findAndMoveManifest(dir) {
328
- const manifest = shelljs_1.find(dir).filter((file) => file.endsWith('package.xml'));
330
+ const manifest = (0, shelljs_1.find)(dir).filter((file) => file.endsWith('package.xml'));
329
331
  if (!(manifest === null || manifest === void 0 ? void 0 : manifest.length)) {
330
332
  throw Error(`Did not find package.xml within ${dir}`);
331
333
  }
332
- shelljs_1.mv(manifest[0], path.join(process.cwd()));
333
- shelljs_1.rm('-rf', dir);
334
+ (0, shelljs_1.mv)(manifest[0], path.join(process.cwd()));
335
+ (0, shelljs_1.rm)('-rf', dir);
334
336
  }
335
337
  /**
336
338
  * Execute a command using testkit. Adds --json to every command to ensure json output.
@@ -343,10 +345,10 @@ class SourceTestkit extends kit_1.AsyncCreatable {
343
345
  await this.fileTracker.updateAll(`PRE: ${command}`);
344
346
  await this.executionLog.add(command);
345
347
  const result = this.executableName === Executable.SF
346
- ? cli_plugins_testkit_1.execCmd(command, { ensureExitCode: exitCode, cli: 'sf' })
347
- : cli_plugins_testkit_1.execCmd(command, { ensureExitCode: exitCode, cli: 'sfdx' });
348
+ ? (0, cli_plugins_testkit_1.execCmd)(command, { ensureExitCode: exitCode, cli: 'sf' })
349
+ : (0, cli_plugins_testkit_1.execCmd)(command, { ensureExitCode: exitCode, cli: 'sfdx' });
348
350
  await this.fileTracker.updateAll(`POST: ${command}`);
349
- if (json && this.executableName === Executable.SFDX) {
351
+ if (json) {
350
352
  const jsonOutput = result.jsonOutput;
351
353
  this.debug('%O', jsonOutput);
352
354
  if (!jsonOutput) {
@@ -361,15 +363,6 @@ class SourceTestkit extends kit_1.AsyncCreatable {
361
363
  }
362
364
  return jsonOutput;
363
365
  }
364
- if (json && this.executableName === Executable.SF) {
365
- const jsonOutput = result.jsonOutput;
366
- this.debug('%O', jsonOutput);
367
- if (!jsonOutput) {
368
- console.error(`${command} returned null jsonOutput`);
369
- console.error(result);
370
- }
371
- return jsonOutput;
372
- }
373
366
  }
374
367
  catch (err) {
375
368
  const error = err;
@@ -378,9 +371,9 @@ class SourceTestkit extends kit_1.AsyncCreatable {
378
371
  }
379
372
  async init() {
380
373
  if (!SourceTestkit.Env.getString('TESTKIT_HUB_USERNAME') && !SourceTestkit.Env.getString('TESTKIT_AUTH_URL')) {
381
- ts_types_1.ensureString(SourceTestkit.Env.getString('TESTKIT_JWT_KEY'));
382
- ts_types_1.ensureString(SourceTestkit.Env.getString('TESTKIT_JWT_CLIENT_ID'));
383
- ts_types_1.ensureString(SourceTestkit.Env.getString('TESTKIT_HUB_INSTANCE'));
374
+ (0, ts_types_1.ensureString)(SourceTestkit.Env.getString('TESTKIT_JWT_KEY'));
375
+ (0, ts_types_1.ensureString)(SourceTestkit.Env.getString('TESTKIT_JWT_CLIENT_ID'));
376
+ (0, ts_types_1.ensureString)(SourceTestkit.Env.getString('TESTKIT_HUB_INSTANCE'));
384
377
  }
385
378
  SourceTestkit.Env.setString('TESTKIT_EXECUTABLE_PATH', this.executable);
386
379
  try {
@@ -406,7 +399,7 @@ class SourceTestkit extends kit_1.AsyncCreatable {
406
399
  this.executionLog = new executionLog_1.ExecutionLog(context);
407
400
  this.expect = new assertions_1.Assertions(context, this.executionLog, this.fileTracker);
408
401
  this.testMetadataFolder = path.join(__dirname, 'metadata');
409
- this.testMetadataFiles = (await fileTracker_1.traverseForFiles(this.testMetadataFolder))
402
+ this.testMetadataFiles = (await (0, fileTracker_1.traverseForFiles)(this.testMetadataFolder))
410
403
  .filter((f) => !f.endsWith('.DS_Store'))
411
404
  .map((f) => f.replace(`${this.testMetadataFolder}${path.sep}`, ''));
412
405
  }
@@ -421,7 +414,7 @@ class SourceTestkit extends kit_1.AsyncCreatable {
421
414
  .replace(SourceTestkit.LocalProdPath, '')
422
415
  .replace(SourceTestkit.LocalDevPath, '');
423
416
  const pkgJsonPath = path.join(npmPackagePath, 'package.json');
424
- const pkgJson = (await core_1.fs.readJsonMap(pkgJsonPath));
417
+ const pkgJson = (0, kit_1.parseJsonMap)(await fs.promises.readFile(pkgJsonPath, 'utf8'));
425
418
  return pkgJson.oclif.bin;
426
419
  }
427
420
  else {
@@ -468,10 +461,13 @@ class SourceTestkit extends kit_1.AsyncCreatable {
468
461
  });
469
462
  }
470
463
  async getDefaultUsername() {
471
- const configVar = this.executableName === Executable.SF ? 'target-org' : core_1.Config.DEFAULT_USERNAME;
472
- const configResult = cli_plugins_testkit_1.execCmd(`config:get ${configVar} --json`).jsonOutput;
473
- const results = ts_types_1.get(configResult, 'result', configResult);
474
- const username = results.find((r) => r.key === configVar || r.name === configVar).value;
464
+ var _a, _b;
465
+ const configVar = 'target-org';
466
+ const configResult = (_a = (0, cli_plugins_testkit_1.execCmd)(`config:get ${configVar} --json`).jsonOutput) === null || _a === void 0 ? void 0 : _a.result;
467
+ // depending on which version of config:get the user has available, there may be a name or key
468
+ // eventually, drop the `key` option and the deprecated SfdxPropertyKeys
469
+ const possibleKeys = [configVar, core_1.SfdxPropertyKeys.DEFAULT_USERNAME];
470
+ const username = (_b = configResult === null || configResult === void 0 ? void 0 : configResult.find((r) => (r.key && possibleKeys.includes(r.key)) || (r.name && possibleKeys.includes(r.name)))) === null || _b === void 0 ? void 0 : _b.value;
475
471
  return username;
476
472
  }
477
473
  async createConnection() {
package/lib/types.d.ts CHANGED
@@ -1,11 +1,9 @@
1
1
  import { Connection } from '@salesforce/core';
2
2
  import { JsonCollection, JsonMap, Nullable } from '@salesforce/ts-types';
3
- export declare type SfdxResult<T = JsonMap> = Nullable<JsonMap & {
3
+ export declare type Result<T = JsonCollection> = Nullable<JsonMap & {
4
4
  status: number;
5
5
  result: T;
6
6
  }>;
7
- export declare type SfResult<T = JsonCollection> = Nullable<T>;
8
- export declare type Result<T = JsonCollection> = SfdxResult<T> | SfResult<T>;
9
7
  export declare type Context = {
10
8
  projectDir: string;
11
9
  connection: Nullable<Connection>;
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": "0.0.17",
4
+ "version": "1.0.1",
5
5
  "author": "Salesforce",
6
6
  "license": "BSD-3-Clause",
7
7
  "main": "lib/index.js",
@@ -30,26 +30,26 @@
30
30
  "!lib/**/*.map"
31
31
  ],
32
32
  "dependencies": {
33
- "@salesforce/cli-plugins-testkit": "^1.2.0",
34
- "@salesforce/core": "^2.20.11",
33
+ "@salesforce/cli-plugins-testkit": "^2.0.0",
34
+ "@salesforce/core": "^3.19.1",
35
35
  "@salesforce/kit": "^1.4.5",
36
- "@salesforce/source-deploy-retrieve": "^4.0.2",
36
+ "@salesforce/source-deploy-retrieve": "^6.0.2",
37
37
  "@salesforce/ts-types": "^1.5.5",
38
38
  "archiver": "^5.2.0",
39
39
  "chai-each": "^0.0.1",
40
40
  "debug": "^4.3.1",
41
41
  "shelljs": "^0.8.4",
42
42
  "sinon": "^10.0.0",
43
- "strip-ansi": "^6.0.0"
43
+ "strip-ansi": "^7.0.1"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@salesforce/dev-config": "^3.0.0",
47
- "@salesforce/dev-scripts": "^2.0.0",
47
+ "@salesforce/dev-scripts": "^2.0.2",
48
48
  "@salesforce/prettier-config": "^0.0.2",
49
49
  "@salesforce/ts-sinon": "^1.3.5",
50
50
  "@types/archiver": "^5.1.0",
51
51
  "@types/debug": "^4.1.5",
52
- "@types/shelljs": "^0.8.8",
52
+ "@types/shelljs": "^0.8.11",
53
53
  "@typescript-eslint/eslint-plugin": "^4.15.2",
54
54
  "@typescript-eslint/parser": "^4.15.2",
55
55
  "chai": "^4.3.0",
@@ -59,7 +59,7 @@
59
59
  "eslint-config-prettier": "^8.1.0",
60
60
  "eslint-config-salesforce": "^0.1.6",
61
61
  "eslint-config-salesforce-license": "^0.1.6",
62
- "eslint-config-salesforce-typescript": "^0.2.7",
62
+ "eslint-config-salesforce-typescript": "^0.2.8",
63
63
  "eslint-plugin-header": "^3.1.1",
64
64
  "eslint-plugin-import": "^2.22.1",
65
65
  "eslint-plugin-jsdoc": "^32.2.0",
@@ -69,9 +69,9 @@
69
69
  "nyc": "^15.1.0",
70
70
  "prettier": "^2.0.5",
71
71
  "pretty-quick": "^3.1.0",
72
- "sinon": "10.0.0",
72
+ "sinon": "^10.0.0",
73
73
  "ts-node": "^10.0.0",
74
- "typescript": "^4.1.3"
74
+ "typescript": "^4.7.2"
75
75
  },
76
76
  "config": {
77
77
  "commitizen": {