apextestlist 1.0.0 → 1.0.2

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/README.md CHANGED
@@ -8,7 +8,34 @@ A plugin that generates a list of tests that your, ideally, automated process sh
8
8
 
9
9
  List all files specified in the classes of a certain directory (and subfolders) and have the result be in the format for the CLI.
10
10
 
11
+ The classes should have a comment starting with `@Tests` somewhere. This is what the tool reads to return the tests. For example, the `Sample.cls` file in the `samples` folder contains a comment like this:
12
+
13
+ ```java
14
+ // @Tests: SampleTest,SuperSampleTest
15
+ public class Sample {
16
+ // ...
17
+ }
18
+ ```
19
+
20
+ In the context of this plugin, this annotation/comment on the class means that _the tests that should cover this test class are called `SampleTest` and `SuperSampleTest`_.
21
+
22
+ > Note: The tool does not check if those classes exist within your project, so make sure to keep the annotations up-to-date.
23
+
24
+ Then, assuming you want to run only the tests provided at the top level of your classes, use the command as follows:
25
+
11
26
  ```sh
12
- sf apextests list --directory samples --format sf
27
+ sf apextests list --directory force-app --format sf
13
28
  $ --tests SampleTest SuperSampleTest Sample2Test SuperSample2Test
14
29
  ```
30
+
31
+ This commnad is originally designed to be used in the context of a CI/CD pipeline. So that when your pipeline has a commnad to validate or deploy code to a Salesforce org, it will dynamically build the list of classes, like so:
32
+
33
+ ```sh
34
+ sf project deploy start $(sf apextests list)
35
+ ```
36
+
37
+ This then becomes the full command to deploy and run only the tests that you - in theory - deem to be necessary:
38
+
39
+ ```sh
40
+ sf project deploy start --tests SampleTest SuperSampleTest Sample2Test SuperSample2Test SampleTriggerTest
41
+ ```
@@ -11,6 +11,7 @@ export default class ApextestsList extends SfCommand<ApextestsListResult> {
11
11
  directory: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
12
  format: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
13
  };
14
+ protected static getConcurrencyThreshold(): number;
14
15
  private static parseTestsNames;
15
16
  private static listTestsInDirectory;
16
17
  private static formatList;
@@ -1,8 +1,11 @@
1
1
  import * as fs from 'node:fs';
2
+ import { availableParallelism } from 'node:os';
2
3
  import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
3
4
  import { Messages } from '@salesforce/core';
5
+ import { queue } from 'async';
4
6
  Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
5
7
  const messages = Messages.loadMessages('apextestlist', 'apextests.list');
8
+ const TEST_NAME_REGEX = /(@(Tests|TestSuites)).+/g;
6
9
  export default class ApextestsList extends SfCommand {
7
10
  static summary = messages.getMessage('summary');
8
11
  static description = messages.getMessage('description');
@@ -22,16 +25,24 @@ export default class ApextestsList extends SfCommand {
22
25
  }),
23
26
  // TODO: add manifest flag
24
27
  };
25
- static parseTestsNames(data) {
28
+ static getConcurrencyThreshold() {
29
+ const AVAILABLE_PARALLELISM = availableParallelism ? availableParallelism() : Infinity;
30
+ return Math.min(AVAILABLE_PARALLELISM, 6);
31
+ }
32
+ static parseTestsNames(testNames) {
33
+ if (!testNames || testNames.length === 0) {
34
+ return [];
35
+ }
26
36
  // remove the prefix @Tests or @TestSuites
27
- return data
37
+ return testNames
38
+ .join(',')
28
39
  .split(',')
29
- .map((line) => line.replace(/(@Tests|@TestSuites)/, ''))
30
- .map((line) => line.replace(':', ''))
40
+ .map((line) => line.replace(/(@Tests|@TestSuites):/, ''))
31
41
  .map((line) => line.trim())
32
- .filter((line) => line.trim().length > 0);
42
+ .filter((line) => line);
33
43
  }
34
- static listTestsInDirectory(directory) {
44
+ static async listTestsInDirectory(directory) {
45
+ const testMethodsNames = [];
35
46
  // check if the provided directory exists
36
47
  if (!directory) {
37
48
  throw new Error('Invalid directory.');
@@ -43,21 +54,24 @@ export default class ApextestsList extends SfCommand {
43
54
  catch (error) {
44
55
  throw new Error('Invalid directory.');
45
56
  }
46
- const files = readDir.filter((file) => file.endsWith('.cls') || file.endsWith('.trigger'));
47
- const testMethodsNames = [];
48
- // read each file and check for the test methods at the top
49
- files.map((file) => {
50
- const data = fs.readFileSync(`${directory}/${file}`, 'utf8');
51
- // try to find, with a RegEx, the test methods listed at the top of the
52
- // file with @Tests or @TestSuites
53
- const testMethods = data.match(/(@(Tests|TestSuites)).+/g);
54
- // for each entry, parse the names
55
- // const testMethodsNames = testMethods ? ApextestsList.parseTestsNames(testMethods.join(',')) : [];
56
- testMethodsNames.push(...(testMethods ? ApextestsList.parseTestsNames(testMethods.join(',')) : []));
57
- });
58
- return testMethodsNames;
57
+ const localFiles = readDir.filter((file) => file.endsWith('.cls') || file.endsWith('.trigger'));
58
+ const handler = (fileName) => {
59
+ const path = `${directory}/${fileName}`;
60
+ const data = fs.readFileSync(path, 'utf-8');
61
+ const testMethods = data.match(TEST_NAME_REGEX);
62
+ testMethodsNames.push(...ApextestsList.parseTestsNames(testMethods));
63
+ };
64
+ const processor = queue((f, cb) => {
65
+ handler(f);
66
+ cb();
67
+ }, this.getConcurrencyThreshold());
68
+ await processor.push(localFiles);
69
+ if (processor.length() > 0) {
70
+ await processor.drain();
71
+ }
72
+ return testMethodsNames.sort();
59
73
  }
60
- static async formatList(format, tests) {
74
+ static formatList(format, tests) {
61
75
  switch (format) {
62
76
  case 'sf':
63
77
  return Promise.resolve({
@@ -82,7 +96,7 @@ export default class ApextestsList extends SfCommand {
82
96
  }
83
97
  let result = null;
84
98
  if (directory) {
85
- result = ApextestsList.formatList(format, ApextestsList.listTestsInDirectory(directory));
99
+ result = ApextestsList.formatList(format, await ApextestsList.listTestsInDirectory(directory));
86
100
  }
87
101
  if (!result) {
88
102
  throw new Error('No directory or manifest provided');
@@ -1 +1 @@
1
- {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/apextests/list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,QAAQ,CAAC,kCAAkC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;AAQzE,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,SAA8B;IAChE,MAAM,CAAU,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACzD,MAAM,CAAU,WAAW,GAAG,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IACjE,MAAM,CAAU,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAE5D,MAAM,CAAU,KAAK,GAAG;QAC7B,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC;YACtB,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,yBAAyB,CAAC;YACvD,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,6BAA6B,CAAC;YAC/D,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,KAAK;SAChB,CAAC;QACF,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;YACnB,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,sBAAsB,CAAC;YACpD,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,0BAA0B,CAAC;YAC5D,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,KAAK;SAChB,CAAC;QACF,0BAA0B;KAC3B,CAAC;IAEM,MAAM,CAAC,eAAe,CAAC,IAAY;QACzC,0CAA0C;QAC1C,OAAO,IAAI;aACR,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,sBAAsB,EAAE,EAAE,CAAC,CAAC;aACvD,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;aACpC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;aAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC9C,CAAC;IAEO,MAAM,CAAC,oBAAoB,CAAC,SAAiB;QACnD,yCAAyC;QACzC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QAED,IAAI,OAAO,CAAC;QAEZ,IAAI,CAAC;YACH,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAa,CAAC;QACvE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QAED,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;QAC3F,MAAM,gBAAgB,GAAa,EAAE,CAAC;QAEtC,2DAA2D;QAC3D,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACjB,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,SAAS,IAAI,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC;YAE7D,uEAAuE;YACvE,kCAAkC;YAClC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;YAC3D,kCAAkC;YAClC,oGAAoG;YACpG,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC,eAAe,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACtG,CAAC,CAAC,CAAC;QAEH,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAEO,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAc,EAAE,KAAe;QAC7D,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,IAAI;gBACP,OAAO,OAAO,CAAC,OAAO,CAAC;oBACrB,KAAK;oBACL,OAAO,EAAE,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;iBACtC,CAAC,CAAC;YACL,KAAK,KAAK;gBACR,OAAO,OAAO,CAAC,OAAO,CAAC;oBACrB,KAAK;oBACL,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;iBACzB,CAAC,CAAC;YACL;gBACE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,GAAG;QACd,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAElD,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,GAAG,CAAC;QACzC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC;QAEpC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjD,CAAC;QAED,IAAI,MAAM,GAAwC,IAAI,CAAC;QAEvD,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,GAAG,aAAa,CAAC,UAAU,CAAC,MAAM,EAAE,aAAa,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC,CAAC;QAC3F,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACvD,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC;QAEjC,OAAO,MAAM,CAAC;IAChB,CAAC"}
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/apextests/list.ts"],"names":[],"mappings":"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"}