apextestlist 1.1.0 → 1.3.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/README.md +3 -3
- package/lib/commands/apextests/list.d.ts +1 -1
- package/lib/commands/apextests/list.js +44 -22
- package/lib/commands/apextests/list.js.map +1 -1
- package/lib/helpers/constants.d.ts +1 -0
- package/lib/helpers/constants.js +3 -0
- package/lib/helpers/constants.js.map +1 -0
- package/lib/helpers/getPackageDirectories.d.ts +1 -0
- package/lib/helpers/getPackageDirectories.js +45 -0
- package/lib/helpers/getPackageDirectories.js.map +1 -0
- package/lib/helpers/getRepoRoot.d.ts +1 -0
- package/lib/helpers/getRepoRoot.js +12 -0
- package/lib/helpers/getRepoRoot.js.map +1 -0
- package/lib/helpers/types.d.ts +5 -0
- package/lib/helpers/types.js +3 -0
- package/lib/helpers/types.js.map +1 -0
- package/lib/helpers/validateTests.d.ts +5 -0
- package/lib/helpers/validateTests.js +48 -0
- package/lib/helpers/validateTests.js.map +1 -0
- package/messages/apextests.list.md +12 -11
- package/oclif.lock +10385 -7392
- package/oclif.manifest.json +15 -15
- package/package.json +15 -9
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ A plugin that generates a list of tests that your, ideally, automated process sh
|
|
|
6
6
|
|
|
7
7
|
## Usage
|
|
8
8
|
|
|
9
|
-
List all files specified in the classes
|
|
9
|
+
List all files specified in the classes in your package directories and have the result be in the format for the CLI.
|
|
10
10
|
|
|
11
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
12
|
|
|
@@ -19,12 +19,12 @@ public class Sample {
|
|
|
19
19
|
|
|
20
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
21
|
|
|
22
|
-
> Note:
|
|
22
|
+
> Note: By default, this tool does not check if those classes exist within your project, so make sure to keep the annotations up-to-date. If you want to check that test annotations are found in your package directories, provide the optional `--ignore-missing-tests` Boolean flag. When the flag is provided, a warning will be printed for each test annotation it is unable to find in any of your package directories and will not add those missing annotations to the final output.
|
|
23
23
|
|
|
24
24
|
Then, assuming you want to run only the tests provided at the top level of your classes, use the command as follows:
|
|
25
25
|
|
|
26
26
|
```sh
|
|
27
|
-
sf apextests list --
|
|
27
|
+
sf apextests list --format sf
|
|
28
28
|
$ --tests SampleTest SuperSampleTest Sample2Test SuperSample2Test
|
|
29
29
|
```
|
|
30
30
|
|
|
@@ -8,9 +8,9 @@ export default class ApextestsList extends SfCommand<ApextestsListResult> {
|
|
|
8
8
|
static readonly description: string;
|
|
9
9
|
static readonly examples: string[];
|
|
10
10
|
static readonly flags: {
|
|
11
|
-
directory: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
11
|
format: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
12
|
manifest: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
'ignore-missing-tests': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
14
|
};
|
|
15
15
|
protected static getConcurrencyThreshold(): number;
|
|
16
16
|
private static parseTestsNames;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/* eslint-disable no-await-in-loop */
|
|
1
3
|
import * as fs from 'node:fs';
|
|
2
4
|
import { availableParallelism } from 'node:os';
|
|
3
5
|
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
|
|
4
6
|
import { Messages } from '@salesforce/core';
|
|
5
7
|
import { queue } from 'async';
|
|
6
8
|
import { Parser } from 'xml2js';
|
|
9
|
+
import { getPackageDirectories } from '../../helpers/getPackageDirectories.js';
|
|
10
|
+
import { validateTests } from '../../helpers/validateTests.js';
|
|
7
11
|
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
8
12
|
const messages = Messages.loadMessages('apextestlist', 'apextests.list');
|
|
9
13
|
const TEST_NAME_REGEX = /(@(Tests|TestSuites)).+/g;
|
|
@@ -12,12 +16,6 @@ export default class ApextestsList extends SfCommand {
|
|
|
12
16
|
static description = messages.getMessage('description');
|
|
13
17
|
static examples = messages.getMessages('examples');
|
|
14
18
|
static flags = {
|
|
15
|
-
directory: Flags.string({
|
|
16
|
-
summary: messages.getMessage('flags.directory.summary'),
|
|
17
|
-
description: messages.getMessage('flags.directory.description'),
|
|
18
|
-
char: 'd',
|
|
19
|
-
required: false,
|
|
20
|
-
}),
|
|
21
19
|
format: Flags.string({
|
|
22
20
|
summary: messages.getMessage('flags.format.summary'),
|
|
23
21
|
description: messages.getMessage('flags.format.description'),
|
|
@@ -30,6 +28,13 @@ export default class ApextestsList extends SfCommand {
|
|
|
30
28
|
char: 'x',
|
|
31
29
|
required: false,
|
|
32
30
|
}),
|
|
31
|
+
'ignore-missing-tests': Flags.boolean({
|
|
32
|
+
summary: messages.getMessage('flags.ignore-missing-tests.summary'),
|
|
33
|
+
description: messages.getMessage('flags.ignore-missing-tests.description'),
|
|
34
|
+
required: false,
|
|
35
|
+
char: 's',
|
|
36
|
+
default: false,
|
|
37
|
+
}),
|
|
33
38
|
};
|
|
34
39
|
static getConcurrencyThreshold() {
|
|
35
40
|
const AVAILABLE_PARALLELISM = availableParallelism ? availableParallelism() : Infinity;
|
|
@@ -49,10 +54,6 @@ export default class ApextestsList extends SfCommand {
|
|
|
49
54
|
}
|
|
50
55
|
static async searchTestClasses(directory, names) {
|
|
51
56
|
const testMethodsNames = [];
|
|
52
|
-
// check if the provided directory exists
|
|
53
|
-
if (!directory) {
|
|
54
|
-
throw new Error('Invalid directory.');
|
|
55
|
-
}
|
|
56
57
|
let readDir;
|
|
57
58
|
try {
|
|
58
59
|
readDir = fs.readdirSync(directory, { recursive: true });
|
|
@@ -62,7 +63,7 @@ export default class ApextestsList extends SfCommand {
|
|
|
62
63
|
}
|
|
63
64
|
const localFiles = readDir.filter((file) => {
|
|
64
65
|
if (!file.endsWith('.cls') && !file.endsWith('.trigger')) {
|
|
65
|
-
return;
|
|
66
|
+
return false;
|
|
66
67
|
}
|
|
67
68
|
const fileFullName = file.split('/').pop()?.split('.');
|
|
68
69
|
if (!names) {
|
|
@@ -125,28 +126,49 @@ export default class ApextestsList extends SfCommand {
|
|
|
125
126
|
.catch((error) => {
|
|
126
127
|
throw error;
|
|
127
128
|
});
|
|
128
|
-
return result;
|
|
129
|
+
return result.sort((a, b) => a.localeCompare(b));
|
|
129
130
|
}
|
|
130
131
|
async run() {
|
|
131
132
|
const { flags } = await this.parse(ApextestsList);
|
|
132
|
-
const directory = flags.directory ?? '.';
|
|
133
133
|
const format = flags.format ?? 'sf';
|
|
134
134
|
const manifest = flags.manifest ?? undefined;
|
|
135
|
-
|
|
136
|
-
throw new Error('Directory must be provided.');
|
|
137
|
-
}
|
|
135
|
+
const ignoreMissingTests = flags['ignore-missing-tests'] ?? false;
|
|
138
136
|
let result = null;
|
|
139
137
|
let testClassesNames = null;
|
|
138
|
+
// Get package directories
|
|
139
|
+
const packageDirectories = await getPackageDirectories();
|
|
140
140
|
if (manifest) {
|
|
141
|
-
// If a manifest file was provided, we read the name of the test classes
|
|
142
|
-
// from it and then we try to find those in the provided directory.
|
|
143
141
|
testClassesNames = await ApextestsList.extractClassNamesFromManifestFile(manifest);
|
|
144
142
|
}
|
|
145
|
-
|
|
146
|
-
|
|
143
|
+
const allTestMethods = [];
|
|
144
|
+
// Loop through each directory and search for test classes
|
|
145
|
+
for (const directory of packageDirectories) {
|
|
146
|
+
const testMethodsInDir = await ApextestsList.searchTestClasses(directory, testClassesNames);
|
|
147
|
+
allTestMethods.push(...testMethodsInDir);
|
|
148
|
+
}
|
|
149
|
+
let finalTestMethods = allTestMethods; // default to allTestMethods
|
|
150
|
+
// If ignore-missing-tests is true, validate the test methods
|
|
151
|
+
if (ignoreMissingTests) {
|
|
152
|
+
const { validatedTests, warnings } = await validateTests(allTestMethods, packageDirectories);
|
|
153
|
+
if (validatedTests.length > 0) {
|
|
154
|
+
finalTestMethods = validatedTests;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
throw new Error('No test methods declared in your annotations were found in your package directories.');
|
|
158
|
+
}
|
|
159
|
+
// Log any warnings
|
|
160
|
+
if (warnings.length > 0) {
|
|
161
|
+
warnings.forEach((warning) => {
|
|
162
|
+
this.warn(warning);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
finalTestMethods.sort((a, b) => a.localeCompare(b));
|
|
167
|
+
if (finalTestMethods.length > 0) {
|
|
168
|
+
result = ApextestsList.formatList(format, finalTestMethods);
|
|
147
169
|
}
|
|
148
|
-
|
|
149
|
-
throw new Error('No
|
|
170
|
+
else {
|
|
171
|
+
throw new Error('No test methods found');
|
|
150
172
|
}
|
|
151
173
|
this.log((await result).command);
|
|
152
174
|
return result;
|
|
@@ -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,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,QAAQ,CAAC,kCAAkC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;AACzE,MAAM,eAAe,GAAG,0BAA0B,CAAC;AAQnD,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,
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/apextests/list.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const SFDX_PROJECT_FILE_NAME = "sfdx-project.json";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/helpers/constants.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,MAAM,CAAC,MAAM,sBAAsB,GAAG,mBAAmB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getPackageDirectories(): Promise<string[]>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/* eslint-disable no-await-in-loop */
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
4
|
+
import { resolve, join } from 'node:path';
|
|
5
|
+
import { readFile, readdir, stat } from 'node:fs/promises';
|
|
6
|
+
import { SFDX_PROJECT_FILE_NAME } from './constants.js';
|
|
7
|
+
import { getRepoRoot } from './getRepoRoot.js';
|
|
8
|
+
export async function getPackageDirectories() {
|
|
9
|
+
const repoRoot = await getRepoRoot();
|
|
10
|
+
process.chdir(repoRoot);
|
|
11
|
+
const dxConfigPath = resolve(repoRoot, SFDX_PROJECT_FILE_NAME);
|
|
12
|
+
if (!existsSync(dxConfigPath)) {
|
|
13
|
+
throw Error(`Salesforce DX Config File does not exist in this path: ${dxConfigPath}`);
|
|
14
|
+
}
|
|
15
|
+
const sfdxProjectRaw = await readFile(dxConfigPath, 'utf-8');
|
|
16
|
+
const sfdxProject = JSON.parse(sfdxProjectRaw);
|
|
17
|
+
const packageDirectories = sfdxProject.packageDirectories.map((directory) => resolve(repoRoot, directory.path));
|
|
18
|
+
const metadataPaths = [];
|
|
19
|
+
for (const directory of packageDirectories) {
|
|
20
|
+
const classesPath = await searchForSubFolders(directory, ['classes', 'triggers']);
|
|
21
|
+
if (classesPath.length > 0) {
|
|
22
|
+
metadataPaths.push(...classesPath);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return metadataPaths;
|
|
26
|
+
}
|
|
27
|
+
async function searchForSubFolders(dxDirectory, subDirectoryNames) {
|
|
28
|
+
const foundPaths = [];
|
|
29
|
+
const files = await readdir(dxDirectory);
|
|
30
|
+
for (const file of files) {
|
|
31
|
+
const filePath = join(dxDirectory, file);
|
|
32
|
+
const stats = await stat(filePath);
|
|
33
|
+
// Check if current directory is one of the desired sub-folders
|
|
34
|
+
if (stats.isDirectory() && subDirectoryNames.includes(file)) {
|
|
35
|
+
foundPaths.push(filePath);
|
|
36
|
+
}
|
|
37
|
+
// Recursively search sub-directories that aren't the target folders
|
|
38
|
+
else if (stats.isDirectory()) {
|
|
39
|
+
const result = await searchForSubFolders(filePath, subDirectoryNames);
|
|
40
|
+
foundPaths.push(...result);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return foundPaths;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=getPackageDirectories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getPackageDirectories.js","sourceRoot":"","sources":["../../src/helpers/getPackageDirectories.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,qCAAqC;AAErC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAC;IACrC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACxB,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,EAAE,sBAAsB,CAAC,CAAC;IAC/D,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,MAAM,KAAK,CAAC,0DAA0D,YAAY,EAAE,CAAC,CAAC;IACxF,CAAC;IAED,MAAM,cAAc,GAAW,MAAM,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACrE,MAAM,WAAW,GAAgB,IAAI,CAAC,KAAK,CAAC,cAAc,CAAgB,CAAC;IAC3E,MAAM,kBAAkB,GAAG,WAAW,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAChH,MAAM,aAAa,GAAa,EAAE,CAAC;IACnC,KAAK,MAAM,SAAS,IAAI,kBAAkB,EAAE,CAAC;QAC3C,MAAM,WAAW,GAAG,MAAM,mBAAmB,CAAC,SAAS,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;QAClF,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,aAAa,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,WAAmB,EAAE,iBAA2B;IACjF,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;IAEzC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEnC,+DAA+D;QAC/D,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,iBAAiB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5D,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5B,CAAC;QACD,oEAAoE;aAC/D,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;YACtE,UAAU,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getRepoRoot(): Promise<string>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
import { promises as fsPromises, readFile, stat, readdir } from 'node:fs';
|
|
3
|
+
import git from 'isomorphic-git';
|
|
4
|
+
export async function getRepoRoot() {
|
|
5
|
+
const fs = { promises: fsPromises, readFile, stat, readdir };
|
|
6
|
+
const repoRoot = await git.findRoot({
|
|
7
|
+
fs,
|
|
8
|
+
filepath: process.cwd(),
|
|
9
|
+
});
|
|
10
|
+
return repoRoot;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=getRepoRoot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getRepoRoot.js","sourceRoot":"","sources":["../../src/helpers/getRepoRoot.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,OAAO,EAAE,QAAQ,IAAI,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,GAAG,MAAM,gBAAgB,CAAC;AAEjC,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAC7D,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC;QAClC,EAAE;QACF,QAAQ,EAAE,OAAO,CAAC,GAAG,EAAE;KACxB,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/helpers/types.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function validateTests(unvalidatedTests: string[], packageDirectories: string[]): Promise<{
|
|
2
|
+
validatedTests: string[];
|
|
3
|
+
warnings: string[];
|
|
4
|
+
}>;
|
|
5
|
+
export declare function findFilePath(fileName: string, packageDirectories: string[]): Promise<string | undefined>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/* eslint-disable no-await-in-loop */
|
|
3
|
+
import { readdir, stat } from 'node:fs/promises';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
export async function validateTests(unvalidatedTests, packageDirectories) {
|
|
6
|
+
const warnings = [];
|
|
7
|
+
const validatedTests = [];
|
|
8
|
+
for (const unvalidatedTest of unvalidatedTests) {
|
|
9
|
+
// Pass the test method with the ".cls" extension
|
|
10
|
+
const testPath = await findFilePath(`${unvalidatedTest}.cls`, packageDirectories);
|
|
11
|
+
if (testPath === undefined) {
|
|
12
|
+
warnings.push(`The test method ${unvalidatedTest}.cls was not found in any package directory.`);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
validatedTests.push(unvalidatedTest);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return { validatedTests, warnings };
|
|
19
|
+
}
|
|
20
|
+
export async function findFilePath(fileName, packageDirectories) {
|
|
21
|
+
let relativeFilePath;
|
|
22
|
+
for (const directory of packageDirectories) {
|
|
23
|
+
relativeFilePath = await searchRecursively(fileName, directory);
|
|
24
|
+
if (relativeFilePath !== undefined) {
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return relativeFilePath;
|
|
29
|
+
}
|
|
30
|
+
async function searchRecursively(fileName, dxDirectory) {
|
|
31
|
+
const files = await readdir(dxDirectory);
|
|
32
|
+
for (const file of files) {
|
|
33
|
+
const filePath = join(dxDirectory, file);
|
|
34
|
+
const stats = await stat(filePath);
|
|
35
|
+
if (stats.isDirectory()) {
|
|
36
|
+
// Recursively search inside subdirectories
|
|
37
|
+
const result = await searchRecursively(fileName, filePath);
|
|
38
|
+
if (result) {
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
else if (file === fileName) {
|
|
43
|
+
return filePath;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=validateTests.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateTests.js","sourceRoot":"","sources":["../../src/helpers/validateTests.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,qCAAqC;AAErC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,gBAA0B,EAC1B,kBAA4B;IAE5B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,cAAc,GAAa,EAAE,CAAC;IAEpC,KAAK,MAAM,eAAe,IAAI,gBAAgB,EAAE,CAAC;QAC/C,iDAAiD;QACjD,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,GAAG,eAAe,MAAM,EAAE,kBAAkB,CAAC,CAAC;QAClF,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,QAAQ,CAAC,IAAI,CAAC,mBAAmB,eAAe,8CAA8C,CAAC,CAAC;QAClG,CAAC;aAAM,CAAC;YACN,cAAc,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IACD,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,QAAgB,EAChB,kBAA4B;IAE5B,IAAI,gBAAoC,CAAC;IACzC,KAAK,MAAM,SAAS,IAAI,kBAAkB,EAAE,CAAC;QAC3C,gBAAgB,GAAG,MAAM,iBAAiB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAChE,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM;QACR,CAAC;IACH,CAAC;IACD,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,QAAgB,EAAE,WAAmB;IACpE,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;IACzC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,2CAA2C;YAC3C,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAC3D,IAAI,MAAM,EAAE,CAAC;gBACX,OAAO,MAAM,CAAC;YAChB,CAAC;QACH,CAAC;aAAM,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,OAAO,QAAQ,CAAC;QAClB,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -4,15 +4,7 @@ List
|
|
|
4
4
|
|
|
5
5
|
# description
|
|
6
6
|
|
|
7
|
-
Lists tests in a package.xml file or from
|
|
8
|
-
|
|
9
|
-
# flags.directory.summary
|
|
10
|
-
|
|
11
|
-
Directory name. Defaults to the current working directory.
|
|
12
|
-
|
|
13
|
-
# flags.directory.description
|
|
14
|
-
|
|
15
|
-
Usually, if you run this command at the root of your Salesforce DX project, it means that the directory points to the original "force-app" folder (even if you have renamed it to something else). If you wish to limit the usage to a specific module, specify the folder with this flag.
|
|
7
|
+
Lists tests in a package.xml file or from your package directories.
|
|
16
8
|
|
|
17
9
|
# flags.format.summary
|
|
18
10
|
|
|
@@ -28,10 +20,19 @@ Manifest XML file.
|
|
|
28
20
|
|
|
29
21
|
# flags.manifest.description
|
|
30
22
|
|
|
31
|
-
When you specify a manifest file, the plugin will not search directories for all classes with annotations, but instead will read the manifest file and search for those classes within
|
|
23
|
+
When you specify a manifest file, the plugin will not search directories for all classes with annotations, but instead will read the manifest file and search for those classes within your package directories.
|
|
24
|
+
|
|
25
|
+
# flags.ignore-missing-tests.summary
|
|
26
|
+
|
|
27
|
+
Ignore missing test methods.
|
|
28
|
+
|
|
29
|
+
# flags.ignore-missing-tests.description
|
|
30
|
+
|
|
31
|
+
If provided, ignore test methods that are not found in any of the package directories.
|
|
32
32
|
|
|
33
33
|
# examples
|
|
34
34
|
|
|
35
35
|
- <%= config.bin %> <%= command.id %> --format csv
|
|
36
|
-
- <%= config.bin %> <%= command.id %> --format sf
|
|
36
|
+
- <%= config.bin %> <%= command.id %> --format sf
|
|
37
37
|
- <%= config.bin %> <%= command.id %> --format sf --manifest package.xml
|
|
38
|
+
- <%= config.bin %> <%= command.id %> --format sf --manifest package.xml --ignore-missing-tests
|