apextestlist 1.14.4 → 1.15.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 +14 -0
- package/README.md +50 -6
- package/lib/commands/apextests/list.d.ts +1 -0
- package/lib/commands/apextests/list.js +11 -1
- package/lib/commands/apextests/list.js.map +1 -1
- package/lib/core/listTests.js +4 -1
- package/lib/core/listTests.js.map +1 -1
- package/lib/utils/formatters.d.ts +1 -1
- package/lib/utils/formatters.js +4 -1
- package/lib/utils/formatters.js.map +1 -1
- package/lib/utils/types.d.ts +1 -0
- package/messages/apextests.list.md +13 -0
- package/oclif.manifest.json +12 -2
- package/package.json +11 -11
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,20 @@
|
|
|
5
5
|
|
|
6
6
|
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.
|
|
7
7
|
|
|
8
|
+
## [1.15.1](https://github.com/wisefoxme/apex-test-list/compare/v1.15.0...v1.15.1) (2026-09-28)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **deps:** bump @salesforce/core in the dependencies group ([#426](https://github.com/wisefoxme/apex-test-list/issues/426)) ([f98d484](https://github.com/wisefoxme/apex-test-list/commit/f98d48450fa7d2f54e8b6ec8cb075c5709e39144))
|
|
14
|
+
|
|
15
|
+
## [1.15.0](https://github.com/wisefoxme/apex-test-list/compare/v1.14.4...v1.15.0) (2026-09-16)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* add manifest-aware --fail-on-empty flag ([#420](https://github.com/wisefoxme/apex-test-list/issues/420)) ([8fef2b5](https://github.com/wisefoxme/apex-test-list/commit/8fef2b54d169e4b474a340ea97b44642c9bd6815))
|
|
21
|
+
|
|
8
22
|
## [1.14.4](https://github.com/wisefoxme/apex-test-list/compare/v1.14.3...v1.14.4) (2026-09-13)
|
|
9
23
|
|
|
10
24
|
|
package/README.md
CHANGED
|
@@ -20,8 +20,10 @@ A plugin that generates a list of tests that your automated process should run,
|
|
|
20
20
|
- [3. `@isTest` (Apex Annotation)](#3-istest-apex-annotation)
|
|
21
21
|
- [4. `.test-dependencies.yml` (Centralized Metadata Filter)](#4-test-dependenciesyml-centralized-metadata-filter)
|
|
22
22
|
- [Running the Tool](#running-the-tool)
|
|
23
|
+
- [Explicit Test Level for Deploy and Validate](#explicit-test-level-for-deploy-and-validate)
|
|
23
24
|
- [Handling Missing Tests](#handling-missing-tests)
|
|
24
25
|
- [Handling Missing Annotations](#handling-missing-annotations)
|
|
26
|
+
- [Failing When No Tests Are Found](#failing-when-no-tests-are-found)
|
|
25
27
|
- [GitHub Action](#github-action)
|
|
26
28
|
- [Command Reference](#command-reference)
|
|
27
29
|
- [Issues](#issues)
|
|
@@ -123,13 +125,29 @@ Example output:
|
|
|
123
125
|
This command is useful in CI/CD pipelines, dynamically generating the test list for deployments:
|
|
124
126
|
|
|
125
127
|
```sh
|
|
126
|
-
sf project deploy start $(sf apextests list)
|
|
128
|
+
sf project deploy start --test-level RunSpecifiedTests $(sf apextests list)
|
|
127
129
|
```
|
|
128
130
|
|
|
129
131
|
The final deployment command would look like:
|
|
130
132
|
|
|
131
133
|
```sh
|
|
132
|
-
sf project deploy start --tests SampleTest SuperSampleTest Sample2Test SuperSample2Test SampleTriggerTest
|
|
134
|
+
sf project deploy start --test-level RunSpecifiedTests --tests SampleTest SuperSampleTest Sample2Test SuperSample2Test SampleTriggerTest
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Explicit Test Level for Deploy and Validate
|
|
138
|
+
|
|
139
|
+
When you append `sf apextests list` output (or the GitHub Action `command` output) to `sf project deploy start` or `sf project deploy validate`, explicitly pass `--test-level RunSpecifiedTests`. Without it, the deploy or validation can fail immediately with:
|
|
140
|
+
|
|
141
|
+
```text
|
|
142
|
+
Error (1): INVALID_OPERATION: runTests can only be used with a testLevel of RunSpecifiedTests
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Salesforce CLI documentation suggests that providing `--tests` should infer `RunSpecifiedTests`, but behavior differs between deploy subcommands. In practice, `sf project deploy validate` does not set the level implicitly (a fix is tracked in [salesforcecli/plugin-deploy-retrieve#1650](https://github.com/salesforcecli/plugin-deploy-retrieve/pull/1650)). Using an explicit test level works for both start and validate.
|
|
146
|
+
|
|
147
|
+
With a manifest:
|
|
148
|
+
|
|
149
|
+
```sh
|
|
150
|
+
sf project deploy start -x package/package.xml --test-level RunSpecifiedTests $(sf apextests list -x package/package.xml)
|
|
133
151
|
```
|
|
134
152
|
|
|
135
153
|
If no test methods are found, the command output will be empty and will present this warning:
|
|
@@ -162,6 +180,28 @@ To remove these warnings from the terminal, use:
|
|
|
162
180
|
sf apextests list --no-warnings
|
|
163
181
|
```
|
|
164
182
|
|
|
183
|
+
### Failing When No Tests Are Found
|
|
184
|
+
|
|
185
|
+
By default, the command exits with code `0` even when no test methods are found — it just prints an empty result and a warning. To have it fail the run instead, use:
|
|
186
|
+
|
|
187
|
+
```sh
|
|
188
|
+
sf apextests list --fail-on-empty
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Combined with `-x`/`--manifest`, this is manifest-aware: it only fails when the manifest actually declares `ApexClass`/`ApexTrigger` members but no tests could be resolved for them. If the manifest contains no Apex at all (e.g., a delta package with only non-Apex metadata), the command still exits `0`, since there's nothing to test.
|
|
192
|
+
|
|
193
|
+
```sh
|
|
194
|
+
# Exits 0: package.xml has no ApexClass/ApexTrigger members, nothing to check
|
|
195
|
+
sf apextests list --manifest package.xml --fail-on-empty
|
|
196
|
+
|
|
197
|
+
# Exits 1: package.xml declares Apex, but no tests were found for it
|
|
198
|
+
sf apextests list --manifest package.xml --fail-on-empty
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
This is useful as a CI guardrail: skip the deploy/validate step cleanly when a manifest has no Apex changes, but fail loudly when Apex changed and no tests cover it.
|
|
202
|
+
|
|
203
|
+
The GitHub Action's `fail-on-empty` input behaves the same way — see [Inputs](#inputs).
|
|
204
|
+
|
|
165
205
|
## GitHub Action
|
|
166
206
|
|
|
167
207
|
For GitHub Actions, this is also available as a native Action — no `sf` CLI or plugin install required:
|
|
@@ -175,7 +215,7 @@ For GitHub Actions, this is also available as a native Action — no `sf` CLI or
|
|
|
175
215
|
ignore-missing-tests: 'true'
|
|
176
216
|
|
|
177
217
|
- name: Deploy with the specified tests
|
|
178
|
-
run: sf project deploy start -x package.xml ${{ steps.list.outputs.command }}
|
|
218
|
+
run: sf project deploy start -x package.xml --test-level RunSpecifiedTests ${{ steps.list.outputs.command }}
|
|
179
219
|
```
|
|
180
220
|
|
|
181
221
|
### Inputs
|
|
@@ -188,7 +228,7 @@ For GitHub Actions, this is also available as a native Action — no `sf` CLI or
|
|
|
188
228
|
| `ignore-package-directory` | Directory to ignore when searching for test annotations, one per line. | No | |
|
|
189
229
|
| `no-warnings` | Do not print warnings for each Apex file missing annotations. | No | `false` |
|
|
190
230
|
| `filter-by-metadata` | Only include tests that explicitly declare metadata dependencies matching changed metadata. Requires `manifest`. | No | `false` |
|
|
191
|
-
| `fail-on-empty` | Fail the action if no test methods are found.
|
|
231
|
+
| `fail-on-empty` | Fail the action if no test methods are found. Manifest-aware when `manifest` is set — see [Failing When No Tests Are Found](#failing-when-no-tests-are-found). | No | `false` |
|
|
192
232
|
|
|
193
233
|
### Outputs
|
|
194
234
|
|
|
@@ -203,7 +243,7 @@ For GitHub Actions, this is also available as a native Action — no `sf` CLI or
|
|
|
203
243
|
|
|
204
244
|
```
|
|
205
245
|
USAGE
|
|
206
|
-
$ sf apextests list -f <value> -x <value> -s -n -d <value> -m [--json]
|
|
246
|
+
$ sf apextests list -f <value> -x <value> -s -n -d <value> -m -e [--json]
|
|
207
247
|
|
|
208
248
|
FLAGS
|
|
209
249
|
-f, --format=<value> Output format. Available options:
|
|
@@ -216,7 +256,7 @@ FLAGS
|
|
|
216
256
|
Should match how they are declared in "sfdx-project.json".
|
|
217
257
|
Can be declared multiple times.
|
|
218
258
|
-m, --filter-by-metadata [default: false] When enabled with `manifest`, test selection is based on metadata changes (e.g., Flow, CustomObject) rather than Apex annotations.
|
|
219
|
-
|
|
259
|
+
-e, --fail-on-empty [default: false] Exit with code 1 if no test methods are found. With `--manifest`, exits 0 instead when the manifest has no ApexClass/ApexTrigger members.
|
|
220
260
|
|
|
221
261
|
GLOBAL FLAGS
|
|
222
262
|
--json Format output as JSON.
|
|
@@ -242,6 +282,10 @@ EXAMPLES
|
|
|
242
282
|
|
|
243
283
|
$ sf apextests list -d "force-app"
|
|
244
284
|
|
|
285
|
+
Fail with exit code 1 if a manifest declares Apex but no tests are found for it (exit 0 if the manifest has no Apex at all):
|
|
286
|
+
|
|
287
|
+
$ sf apextests list --format sf --manifest package.xml --fail-on-empty
|
|
288
|
+
|
|
245
289
|
List test annotations without printing warnings for each file missing annotations:
|
|
246
290
|
|
|
247
291
|
$ sf apextests list -n
|
|
@@ -11,6 +11,7 @@ export default class ApextestsList extends SfCommand<ApextestsListResult> {
|
|
|
11
11
|
'ignore-package-directory': import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
12
|
'no-warnings': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
13
|
'filter-by-metadata': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
|
+
'fail-on-empty': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
15
|
};
|
|
15
16
|
run(): Promise<ApextestsListResult>;
|
|
16
17
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
import { Messages } from '@salesforce/core';
|
|
2
|
+
import { Messages, SfError } from '@salesforce/core';
|
|
3
3
|
import { Flags, SfCommand } from '@salesforce/sf-plugins-core';
|
|
4
4
|
import { listTests } from '../../core/listTests.js';
|
|
5
5
|
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
@@ -50,6 +50,13 @@ export default class ApextestsList extends SfCommand {
|
|
|
50
50
|
required: false,
|
|
51
51
|
default: false,
|
|
52
52
|
}),
|
|
53
|
+
'fail-on-empty': Flags.boolean({
|
|
54
|
+
summary: messages.getMessage('flags.fail-on-empty.summary'),
|
|
55
|
+
description: messages.getMessage('flags.fail-on-empty.description'),
|
|
56
|
+
char: 'e',
|
|
57
|
+
required: false,
|
|
58
|
+
default: false,
|
|
59
|
+
}),
|
|
53
60
|
};
|
|
54
61
|
async run() {
|
|
55
62
|
const { flags } = await this.parse(ApextestsList);
|
|
@@ -62,6 +69,9 @@ export default class ApextestsList extends SfCommand {
|
|
|
62
69
|
filterByMetadata: flags['filter-by-metadata'],
|
|
63
70
|
warn: this.warn.bind(this),
|
|
64
71
|
});
|
|
72
|
+
if (flags['fail-on-empty'] && result.tests.length === 0 && (!flags.manifest || result.manifestHasApex)) {
|
|
73
|
+
throw new SfError(messages.getMessage('errors.noTestsFound'));
|
|
74
|
+
}
|
|
65
75
|
this.log(result.command);
|
|
66
76
|
return result;
|
|
67
77
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/apextests/list.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/apextests/list.ts"],"names":[],"mappings":"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"}
|
package/lib/core/listTests.js
CHANGED
|
@@ -14,9 +14,11 @@ export async function listTests({ format = 'sf', manifest, ignoreMissingTests =
|
|
|
14
14
|
const testSuitesNames = [];
|
|
15
15
|
const allTestClasses = [];
|
|
16
16
|
const warnings = [];
|
|
17
|
+
let manifestHasApex = false;
|
|
17
18
|
const { metadataPaths: packageDirectories, repoRoot } = await getPackageDirectories(ignoreDirs);
|
|
18
19
|
if (manifest) {
|
|
19
20
|
const manifestMetadata = await extractTypeNamesFromManifestFile(manifest);
|
|
21
|
+
manifestHasApex = manifestMetadata.some((name) => name.startsWith('ApexClass:') || name.startsWith('ApexTrigger:'));
|
|
20
22
|
testClassesNames = manifestMetadata.filter((name) => !name.endsWith('testSuite-meta.xml'));
|
|
21
23
|
if (filterByMetadata) {
|
|
22
24
|
const ymlConfigPath = resolve(repoRoot, METADATA_FILTER_CONFIG);
|
|
@@ -57,8 +59,9 @@ export async function listTests({ format = 'sf', manifest, ignoreMissingTests =
|
|
|
57
59
|
return {
|
|
58
60
|
tests: [],
|
|
59
61
|
command: '',
|
|
62
|
+
manifestHasApex,
|
|
60
63
|
};
|
|
61
64
|
}
|
|
62
|
-
return formatList(format, finalTestMethods);
|
|
65
|
+
return formatList(format, finalTestMethods, manifestHasApex);
|
|
63
66
|
}
|
|
64
67
|
//# sourceMappingURL=listTests.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listTests.js","sourceRoot":"","sources":["../../src/core/listTests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gCAAgC,EAAE,MAAM,8BAA8B,CAAC;AAChF,OAAO,EAAE,4BAA4B,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACvG,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,uCAAuC,EAAE,MAAM,iCAAiC,CAAC;AAC1F,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAE1E,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE1D,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,EAC9B,MAAM,GAAG,IAAI,EACb,QAAQ,EACR,kBAAkB,GAAG,KAAK,EAC1B,UAAU,GAAG,EAAE,EACf,UAAU,GAAG,KAAK,EAClB,gBAAgB,GAAG,KAAK,EACxB,IAAI,GAAG,GAAS,EAAE;IAChB,gBAAgB;AAClB,CAAC,GACgB;IACjB,IAAI,gBAAgB,GAAoB,IAAI,CAAC;IAC7C,MAAM,eAAe,GAAa,EAAE,CAAC;IACrC,MAAM,cAAc,GAAa,EAAE,CAAC;IACpC,MAAM,QAAQ,GAAa,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"listTests.js","sourceRoot":"","sources":["../../src/core/listTests.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { ApextestsListResult } from '../utils/types.js';
|
|
2
|
-
export declare function formatList(format: string, tests: string[]): Promise<ApextestsListResult>;
|
|
2
|
+
export declare function formatList(format: string, tests: string[], manifestHasApex?: boolean): Promise<ApextestsListResult>;
|
package/lib/utils/formatters.js
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
const TESTS_FLAG = '--tests ';
|
|
3
|
-
export async function formatList(format, tests) {
|
|
3
|
+
export async function formatList(format, tests, manifestHasApex = false) {
|
|
4
4
|
switch (format) {
|
|
5
5
|
case 'sf':
|
|
6
6
|
return Promise.resolve({
|
|
7
7
|
tests,
|
|
8
8
|
command: TESTS_FLAG + tests.join(` ${TESTS_FLAG}`),
|
|
9
|
+
manifestHasApex,
|
|
9
10
|
});
|
|
10
11
|
case 'sfdx':
|
|
11
12
|
return Promise.resolve({
|
|
12
13
|
tests,
|
|
13
14
|
command: TESTS_FLAG + tests.join(' '),
|
|
15
|
+
manifestHasApex,
|
|
14
16
|
});
|
|
15
17
|
case 'csv':
|
|
16
18
|
return Promise.resolve({
|
|
17
19
|
tests,
|
|
18
20
|
command: tests.join(','),
|
|
21
|
+
manifestHasApex,
|
|
19
22
|
});
|
|
20
23
|
default:
|
|
21
24
|
throw new Error('Invalid format.');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatters.js","sourceRoot":"","sources":["../../src/utils/formatters.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAGb,MAAM,UAAU,GAAG,UAAU,CAAC;AAE9B,MAAM,CAAC,KAAK,UAAU,UAAU,
|
|
1
|
+
{"version":3,"file":"formatters.js","sourceRoot":"","sources":["../../src/utils/formatters.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAGb,MAAM,UAAU,GAAG,UAAU,CAAC;AAE9B,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAc,EACd,KAAe,EACf,eAAe,GAAG,KAAK;IAEvB,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,IAAI;YACP,OAAO,OAAO,CAAC,OAAO,CAAC;gBACrB,KAAK;gBACL,OAAO,EAAE,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,EAAE,CAAC;gBAClD,eAAe;aAChB,CAAC,CAAC;QACL,KAAK,MAAM;YACT,OAAO,OAAO,CAAC,OAAO,CAAC;gBACrB,KAAK;gBACL,OAAO,EAAE,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;gBACrC,eAAe;aAChB,CAAC,CAAC;QACL,KAAK,KAAK;YACR,OAAO,OAAO,CAAC,OAAO,CAAC;gBACrB,KAAK;gBACL,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;gBACxB,eAAe;aAChB,CAAC,CAAC;QACL;YACE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACvC,CAAC;AACH,CAAC"}
|
package/lib/utils/types.d.ts
CHANGED
|
@@ -54,6 +54,18 @@ Only include tests that explicitly declare metadata dependencies matching change
|
|
|
54
54
|
|
|
55
55
|
When enabled with `manifest`, test selection is based on metadata changes (e.g., Flow, CustomObject) rather than Apex annotations.
|
|
56
56
|
|
|
57
|
+
# flags.fail-on-empty.summary
|
|
58
|
+
|
|
59
|
+
Fail with exit code 1 if no test methods are found.
|
|
60
|
+
|
|
61
|
+
# flags.fail-on-empty.description
|
|
62
|
+
|
|
63
|
+
If provided, the command exits with code 1 when no test methods are found. When combined with `--manifest`, the command still exits with code 0 if the manifest contains no `ApexClass` or `ApexTrigger` members, since there is nothing to test in that case.
|
|
64
|
+
|
|
65
|
+
# errors.noTestsFound
|
|
66
|
+
|
|
67
|
+
No test methods found.
|
|
68
|
+
|
|
57
69
|
# examples
|
|
58
70
|
|
|
59
71
|
- <%= config.bin %> <%= command.id %> --format csv
|
|
@@ -61,3 +73,4 @@ When enabled with `manifest`, test selection is based on metadata changes (e.g.,
|
|
|
61
73
|
- <%= config.bin %> <%= command.id %> --format sf --manifest package.xml
|
|
62
74
|
- <%= config.bin %> <%= command.id %> --format sf --manifest package.xml --ignore-missing-tests
|
|
63
75
|
- <%= config.bin %> <%= command.id %> --format sf --manifest package.xml -d "force-app"
|
|
76
|
+
- <%= config.bin %> <%= command.id %> --format sf --manifest package.xml --fail-on-empty
|
package/oclif.manifest.json
CHANGED
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"<%= config.bin %> <%= command.id %> --format sf",
|
|
10
10
|
"<%= config.bin %> <%= command.id %> --format sf --manifest package.xml",
|
|
11
11
|
"<%= config.bin %> <%= command.id %> --format sf --manifest package.xml --ignore-missing-tests",
|
|
12
|
-
"<%= config.bin %> <%= command.id %> --format sf --manifest package.xml -d \"force-app\""
|
|
12
|
+
"<%= config.bin %> <%= command.id %> --format sf --manifest package.xml -d \"force-app\"",
|
|
13
|
+
"<%= config.bin %> <%= command.id %> --format sf --manifest package.xml --fail-on-empty"
|
|
13
14
|
],
|
|
14
15
|
"flags": {
|
|
15
16
|
"json": {
|
|
@@ -84,6 +85,15 @@
|
|
|
84
85
|
"summary": "Only include tests that explicitly declare metadata dependencies matching changed metadata.",
|
|
85
86
|
"allowNo": false,
|
|
86
87
|
"type": "boolean"
|
|
88
|
+
},
|
|
89
|
+
"fail-on-empty": {
|
|
90
|
+
"char": "e",
|
|
91
|
+
"description": "If provided, the command exits with code 1 when no test methods are found. When combined with `--manifest`, the command still exits with code 0 if the manifest contains no `ApexClass` or `ApexTrigger` members, since there is nothing to test in that case.",
|
|
92
|
+
"name": "fail-on-empty",
|
|
93
|
+
"required": false,
|
|
94
|
+
"summary": "Fail with exit code 1 if no test methods are found.",
|
|
95
|
+
"allowNo": false,
|
|
96
|
+
"type": "boolean"
|
|
87
97
|
}
|
|
88
98
|
},
|
|
89
99
|
"hasDynamicHelp": false,
|
|
@@ -109,5 +119,5 @@
|
|
|
109
119
|
]
|
|
110
120
|
}
|
|
111
121
|
},
|
|
112
|
-
"version": "1.
|
|
122
|
+
"version": "1.15.1"
|
|
113
123
|
}
|
package/package.json
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apextestlist",
|
|
3
3
|
"description": "A plugin that generates a list of apex test and test suite names for use in CI/CD pipelines.",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.15.1",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@oclif/core": "5.0.0",
|
|
7
|
-
"@salesforce/core": "9.
|
|
7
|
+
"@salesforce/core": "9.2.0",
|
|
8
8
|
"@salesforce/sf-plugins-core": "13.0.4"
|
|
9
9
|
},
|
|
10
10
|
"devDependencies": {
|
|
11
11
|
"@actions/core": "3.0.1",
|
|
12
|
-
"@biomejs/biome": "2.5.
|
|
13
|
-
"@commitlint/cli": "21.2.
|
|
14
|
-
"@commitlint/config-conventional": "21.2.
|
|
12
|
+
"@biomejs/biome": "2.5.14",
|
|
13
|
+
"@commitlint/cli": "21.2.3",
|
|
14
|
+
"@commitlint/config-conventional": "21.2.3",
|
|
15
15
|
"@salesforce/cli-plugins-testkit": "5.3.66",
|
|
16
16
|
"@salesforce/dev-config": "4.3.3",
|
|
17
17
|
"@stryker-mutator/core": "10.0.0",
|
|
18
18
|
"@stryker-mutator/vitest-runner": "10.0.0",
|
|
19
|
-
"@types/node": "26.
|
|
20
|
-
"@vitest/coverage-v8": "5.0.
|
|
19
|
+
"@types/node": "26.6.2",
|
|
20
|
+
"@vitest/coverage-v8": "5.0.1",
|
|
21
21
|
"esbuild": "0.28.2",
|
|
22
22
|
"husky": "9.1.7",
|
|
23
|
-
"knip": "6.
|
|
24
|
-
"lint-staged": "17.5.
|
|
23
|
+
"knip": "6.38.0",
|
|
24
|
+
"lint-staged": "17.5.1",
|
|
25
25
|
"ls-engines": "0.10.1",
|
|
26
|
-
"oclif": "
|
|
26
|
+
"oclif": "6.0.1",
|
|
27
27
|
"shx": "0.4.0",
|
|
28
28
|
"typescript": "7.0.2",
|
|
29
|
-
"vitest": "5.0.
|
|
29
|
+
"vitest": "5.0.1",
|
|
30
30
|
"wireit": "0.14.13"
|
|
31
31
|
},
|
|
32
32
|
"engines": {
|