apextestlist 1.12.4 → 1.13.0

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
@@ -5,6 +5,13 @@
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.13.0](https://github.com/renatoliveira/apex-test-list/compare/v1.12.4...v1.13.0) (2025-06-19)
9
+
10
+
11
+ ### Features
12
+
13
+ * add metadata filter option via yaml ([#234](https://github.com/renatoliveira/apex-test-list/issues/234)) ([1ccaf7b](https://github.com/renatoliveira/apex-test-list/commit/1ccaf7b445feb75c20770879289d1f3d5e1a2ae6))
14
+
8
15
  ## [1.12.4](https://github.com/renatoliveira/apex-test-list/compare/v1.12.3...v1.12.4) (2025-06-14)
9
16
 
10
17
 
package/README.md CHANGED
@@ -13,6 +13,7 @@ A plugin that generates a list of tests that your automated process should run,
13
13
  - [1. `@Tests:` (Custom Comment Annotation)](#1-tests-custom-comment-annotation)
14
14
  - [2. `@TestSuites:` (Custom Comment Annotation)](#2-testsuites-custom-comment-annotation)
15
15
  - [3. `@isTest` (Apex Annotation)](#3-istest-apex-annotation)
16
+ - [4. `.test-dependencies.yml` (Centralized Metadata Filter)](#4-test-dependenciesyml-centralized-metadata-filter)
16
17
  - [Running the Tool](#running-the-tool)
17
18
  - [Handling Missing Tests](#handling-missing-tests)
18
19
  - [Handling Missing Annotations](#handling-missing-annotations)
@@ -31,7 +32,7 @@ sf plugins install apextestlist
31
32
 
32
33
  ## Usage
33
34
 
34
- This tool identifies Apex tests using three annotations:
35
+ This tool identifies Apex tests using either 3 Apex annotations or a separate metadata filter.
35
36
 
36
37
  ### 1. `@Tests:` (Custom Comment Annotation)
37
38
 
@@ -70,6 +71,35 @@ private class SampleTest {
70
71
  }
71
72
  ```
72
73
 
74
+ ### 4. `.test-dependencies.yml` (Centralized Metadata Filter)
75
+
76
+ Instead of using the Apex annotations described previously, you can use this plugin to determine Apex tests with specific Salesforce metadata.
77
+
78
+ This approach is designed to work seamlessly with the `-x`/`--manifest` flag using a manifest file generated by the [`sfdx-git-delta`](https://github.com/scolladon/sfdx-git-delta) plugin.
79
+
80
+ 1. Create a `.test-dependencies.yml` file in the root of your project.
81
+ 2. Map test classes to metadata entries (in `MetadataType:MetadataMember` format).
82
+ 1. Use wildcards (\*) to match all children under a metadata namespace (e.g., all custom fields in an object).
83
+ 2. The plugin will fail if the entries in the YAML don't match the expected format.
84
+
85
+ ```yml
86
+ MyFooTest:
87
+ - CustomField:Account__c.field__c
88
+ - Flow:OpportunityFlowX
89
+ - ValidationRule:Account.RequiredEmail
90
+ - CustomField:Opportunity__c.*
91
+
92
+ MyBarTest:
93
+ - CustomObject:Lead__c
94
+ - Flow:LeadFlowY
95
+ ```
96
+
97
+ 3. Run this plugin's command with the `filter-by-metadata`/`-m` flag **and** the `-x`/`--manifest` flag.
98
+
99
+ ```sh
100
+ sf apextests list -x package/package.xml -m
101
+ ```
102
+
73
103
  ## Running the Tool
74
104
 
75
105
  To generate a test list, run the command in any Salesforce DX project:
@@ -96,7 +126,7 @@ The final deployment command would look like:
96
126
  sf project deploy start --tests SampleTest SuperSampleTest Sample2Test SuperSample2Test SampleTriggerTest
97
127
  ```
98
128
 
99
- If no annotations are found, the command output will be empty and will present this warning:
129
+ If no test methods are found, the command output will be empty and will present this warning:
100
130
 
101
131
  ```sh
102
132
  No test methods found
@@ -104,7 +134,7 @@ No test methods found
104
134
 
105
135
  ### Handling Missing Tests
106
136
 
107
- By default, this tool does **not** verify if the tests specified in `@Tests:` or `@TestSuites:` exist in the project. To enable warnings for missing tests, use:
137
+ By default, this tool does **not** verify if the test methods found exist in the project. To enable warnings for missing tests, use:
108
138
 
109
139
  ```sh
110
140
  sf apextests list --ignore-missing-tests
@@ -130,7 +160,7 @@ sf apextests list --no-warnings
130
160
 
131
161
  ```
132
162
  USAGE
133
- $ sf apextests list -f <value> -x <value> -s -n -d <value> [--json]
163
+ $ sf apextests list -f <value> -x <value> -s -n -d <value> -m [--json]
134
164
 
135
165
  FLAGS
136
166
  -f, --format=<value> Output format. Available options:
@@ -142,6 +172,8 @@ FLAGS
142
172
  -d, --ignore-package-directory Ignore a package directory when looking for test annotations.
143
173
  Should match how they are declared in "sfdx-project.json".
144
174
  Can be declared multiple times.
175
+ -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.
176
+
145
177
 
146
178
  GLOBAL FLAGS
147
179
  --json Format output as JSON.
@@ -10,6 +10,7 @@ export default class ApextestsList extends SfCommand<ApextestsListResult> {
10
10
  'ignore-missing-tests': import("@oclif/core/interfaces").BooleanFlag<boolean>;
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
+ 'filter-by-metadata': import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
14
  };
14
15
  run(): Promise<ApextestsListResult>;
15
16
  }
@@ -43,6 +43,13 @@ export default class ApextestsList extends SfCommand {
43
43
  required: false,
44
44
  default: false,
45
45
  }),
46
+ 'filter-by-metadata': Flags.boolean({
47
+ summary: messages.getMessage('flags.filter-by-metadata.summary'),
48
+ description: messages.getMessage('flags.filter-by-metadata.description'),
49
+ char: 'm',
50
+ required: false,
51
+ default: false,
52
+ }),
46
53
  };
47
54
  async run() {
48
55
  const { flags } = await this.parse(ApextestsList);
@@ -52,6 +59,7 @@ export default class ApextestsList extends SfCommand {
52
59
  ignoreMissingTests: flags['ignore-missing-tests'],
53
60
  ignoreDirs: flags['ignore-package-directory'],
54
61
  noWarnings: flags['no-warnings'],
62
+ filterByMetadata: flags['filter-by-metadata'],
55
63
  warn: this.warn.bind(this),
56
64
  });
57
65
  this.log(result.command);
@@ -1 +1 @@
1
- {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/apextests/list.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGpD,QAAQ,CAAC,kCAAkC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;AAEzE,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,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;YACf,OAAO,EAAE,IAAI;SACd,CAAC;QACF,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC;YACrB,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,wBAAwB,CAAC;YACtD,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,4BAA4B,CAAC;YAC9D,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,KAAK;SAChB,CAAC;QACF,sBAAsB,EAAE,KAAK,CAAC,OAAO,CAAC;YACpC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,oCAAoC,CAAC;YAClE,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,wCAAwC,CAAC;YAC1E,QAAQ,EAAE,KAAK;YACf,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,KAAK;SACf,CAAC;QACF,0BAA0B,EAAE,KAAK,CAAC,SAAS,CAAC;YAC1C,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,wCAAwC,CAAC;YACtE,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,4CAA4C,CAAC;YAC9E,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,KAAK;YACf,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC;YAC3B,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,2BAA2B,CAAC;YACzD,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,+BAA+B,CAAC;YACjE,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,KAAK;SACf,CAAC;KACH,CAAC;IAGK,KAAK,CAAC,GAAG;QACd,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAElD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC;YAC7B,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,kBAAkB,EAAE,KAAK,CAAC,sBAAsB,CAAC;YACjD,UAAU,EAAE,KAAK,CAAC,0BAA0B,CAAC;YAC7C,UAAU,EAAE,KAAK,CAAC,aAAa,CAAC;YAChC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACzB,OAAO,MAAM,CAAC;IAChB,CAAC"}
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/apextests/list.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
1
  import { ListTestsOptions, ApextestsListResult } from '../utils/types.js';
2
- export declare function listTests({ format, manifest, ignoreMissingTests, ignoreDirs, noWarnings, warn, }: ListTestsOptions): Promise<ApextestsListResult>;
2
+ export declare function listTests({ format, manifest, ignoreMissingTests, ignoreDirs, noWarnings, filterByMetadata, warn, }: ListTestsOptions): Promise<ApextestsListResult>;
@@ -1,32 +1,43 @@
1
1
  /* eslint-disable no-await-in-loop */
2
+ import { resolve } from 'node:path';
2
3
  import { getPackageDirectories } from '../utils/getPackageDirectories.js';
3
4
  import { validateTests } from '../utils/validateTests.js';
4
5
  import { extractTypeNamesFromManifestFile } from '../parsers/manifestParser.js';
5
6
  import { formatList } from '../utils/formatters.js';
6
7
  import { searchDirectoryForTestClasses } from '../readers/directorySearcher.js';
7
8
  import { searchDirectoryForTestNamesInTestSuites } from '../readers/testSuiteSearcher.js';
8
- export async function listTests({ format = 'sf', manifest, ignoreMissingTests = false, ignoreDirs = [], noWarnings = false, warn = () => { }, }) {
9
+ import { METADATA_FILTER_CONFIG } from '../utils/constants.js';
10
+ import { loadTestMetadataDependencies, selectRelevantTests } from '../parsers/metadataFilterParser.js';
11
+ export async function listTests({ format = 'sf', manifest, ignoreMissingTests = false, ignoreDirs = [], noWarnings = false, filterByMetadata = false, warn = () => { }, }) {
9
12
  let testClassesNames = null;
10
13
  const testSuitesNames = [];
11
14
  const allTestClasses = [];
12
15
  const warnings = [];
13
- const packageDirectories = await getPackageDirectories(ignoreDirs);
16
+ const { metadataPaths: packageDirectories, repoRoot } = await getPackageDirectories(ignoreDirs);
14
17
  if (manifest) {
15
18
  const manifestMetadata = await extractTypeNamesFromManifestFile(manifest);
16
19
  testClassesNames = manifestMetadata.filter((name) => !name.endsWith('testSuite-meta.xml'));
17
- }
18
- for (const directory of packageDirectories) {
19
- const searchResult = await searchDirectoryForTestClasses(directory, testClassesNames);
20
- allTestClasses.push(...searchResult.classes);
21
- testSuitesNames.push(...searchResult.testSuites);
22
- if (searchResult.warnings?.length) {
23
- warnings.push(...searchResult.warnings);
20
+ if (filterByMetadata) {
21
+ const ymlConfigPath = resolve(repoRoot, METADATA_FILTER_CONFIG);
22
+ const testMap = await loadTestMetadataDependencies(ymlConfigPath);
23
+ const testsToRun = selectRelevantTests(testMap, manifestMetadata);
24
+ allTestClasses.push(...testsToRun);
24
25
  }
25
26
  }
26
- if (testSuitesNames.length > 0) {
27
- for (const directory of packageDirectories.filter((dir) => dir.includes('testSuites'))) {
28
- const testNames = await searchDirectoryForTestNamesInTestSuites(directory, packageDirectories);
29
- allTestClasses.push(...testNames);
27
+ if (!filterByMetadata) {
28
+ for (const directory of packageDirectories) {
29
+ const searchResult = await searchDirectoryForTestClasses(directory, testClassesNames);
30
+ allTestClasses.push(...searchResult.classes);
31
+ testSuitesNames.push(...searchResult.testSuites);
32
+ if (searchResult.warnings?.length) {
33
+ warnings.push(...searchResult.warnings);
34
+ }
35
+ }
36
+ if (testSuitesNames.length > 0) {
37
+ for (const directory of packageDirectories.filter((dir) => dir.includes('testSuites'))) {
38
+ const testNames = await searchDirectoryForTestNamesInTestSuites(directory, packageDirectories);
39
+ allTestClasses.push(...testNames);
40
+ }
30
41
  }
31
42
  }
32
43
  let finalTestMethods = Array.from(new Set(allTestClasses.map((test) => test.trim())));
@@ -34,9 +45,6 @@ export async function listTests({ format = 'sf', manifest, ignoreMissingTests =
34
45
  const { validatedTests, warnings: validationWarnings } = await validateTests(finalTestMethods, packageDirectories);
35
46
  finalTestMethods = validatedTests;
36
47
  warnings.push(...validationWarnings);
37
- if (validatedTests.length === 0) {
38
- warnings.push('No test methods declared in your annotations were found in your package directories');
39
- }
40
48
  }
41
49
  if (!noWarnings && warnings.length > 0) {
42
50
  warnings.forEach(warn);
@@ -1 +1 @@
1
- {"version":3,"file":"listTests.js","sourceRoot":"","sources":["../../src/core/listTests.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,gCAAgC,EAAE,MAAM,8BAA8B,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,uCAAuC,EAAE,MAAM,iCAAiC,CAAC;AAG1F,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,IAAI,GAAG,GAAS,EAAE,GAAE,CAAC,GACJ;IACjB,IAAI,gBAAgB,GAAoB,IAAI,CAAC;IAC7C,MAAM,eAAe,GAAa,EAAE,CAAC;IACrC,MAAM,cAAc,GAAa,EAAE,CAAC;IACpC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,MAAM,kBAAkB,GAAG,MAAM,qBAAqB,CAAC,UAAU,CAAC,CAAC;IAEnE,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,gBAAgB,GAAG,MAAM,gCAAgC,CAAC,QAAQ,CAAC,CAAC;QAC1E,gBAAgB,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAC7F,CAAC;IAED,KAAK,MAAM,SAAS,IAAI,kBAAkB,EAAE,CAAC;QAC3C,MAAM,YAAY,GAAiB,MAAM,6BAA6B,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;QACpG,cAAc,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;QAC7C,eAAe,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;QACjD,IAAI,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;YAClC,QAAQ,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,KAAK,MAAM,SAAS,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;YACvF,MAAM,SAAS,GAAG,MAAM,uCAAuC,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;YAC/F,cAAc,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED,IAAI,gBAAgB,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAEtF,IAAI,kBAAkB,EAAE,CAAC;QACvB,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,kBAAkB,EAAE,GAAG,MAAM,aAAa,CAC1E,gBAAgB,EAChB,kBAAkB,CACnB,CAAC;QACF,gBAAgB,GAAG,cAAc,CAAC;QAClC,QAAQ,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,CAAC;QACrC,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,QAAQ,CAAC,IAAI,CAAC,qFAAqF,CAAC,CAAC;QACvG,CAAC;IACH,CAAC;IAED,IAAI,CAAC,UAAU,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IAED,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IAEpD,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAC9B,OAAO;YACL,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,EAAE;SACZ,CAAC;IACJ,CAAC;IAED,OAAO,UAAU,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAC9C,CAAC"}
1
+ {"version":3,"file":"listTests.js","sourceRoot":"","sources":["../../src/core/listTests.ts"],"names":[],"mappings":"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"}
@@ -18,9 +18,7 @@ export async function extractTypeNamesFromManifestFile(manifestFile) {
18
18
  const componentSet = await ComponentSet.fromManifest({ manifestPath: manifestFile });
19
19
  for (const component of componentSet) {
20
20
  const typeName = component.type.name;
21
- if (['ApexClass', 'ApexTrigger', 'ApexTestSuite'].includes(typeName)) {
22
- result.push(`${typeName}:${component.fullName}`);
23
- }
21
+ result.push(`${typeName}:${component.fullName}`);
24
22
  }
25
23
  return result.sort((a, b) => a.localeCompare(b));
26
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"manifestParser.js","sourceRoot":"","sources":["../../src/parsers/manifestParser.ts"],"names":[],"mappings":"AACA,YAAY,CAAC;AAEb,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,YAAY,EAAG,MAAM,oCAAoC,CAAC;AAEnE;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,gCAAgC,CAAC,YAAoB;IACzE,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,CAAC,YAAY,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC/C,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,YAAY,GAAiB,MAAM,YAAY,CAAC,YAAY,CAAC,EAAC,YAAY,EAAE,YAAY,EAAC,CAAC,CAAC;IACjG,KAAK,MAAM,SAAS,IAAI,YAAY,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;QACrC,IAAI,CAAC,WAAW,EAAE,aAAa,EAAE,eAAe,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACrE,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,IAAI,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC"}
1
+ {"version":3,"file":"manifestParser.js","sourceRoot":"","sources":["../../src/parsers/manifestParser.ts"],"names":[],"mappings":"AACA,YAAY,CAAC;AAEb,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,YAAY,EAAG,MAAM,oCAAoC,CAAC;AAEnE;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,gCAAgC,CAAC,YAAoB;IACzE,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,CAAC,YAAY,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC/C,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,YAAY,GAAiB,MAAM,YAAY,CAAC,YAAY,CAAC,EAAC,YAAY,EAAE,YAAY,EAAC,CAAC,CAAC;IACjG,KAAK,MAAM,SAAS,IAAI,YAAY,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,IAAI,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { TestMetadataMap } from '../utils/types.js';
2
+ /**
3
+ * Loads the test metadata filter YAML file and confirms it matches the expected structure.
4
+ */
5
+ export declare function loadTestMetadataDependencies(configPath: string): Promise<TestMetadataMap>;
6
+ /**
7
+ * Return test classes that depend on any of the changed metadata.
8
+ */
9
+ export declare function selectRelevantTests(testMap: TestMetadataMap, changedMetadata: string[]): string[];
@@ -0,0 +1,50 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { parse } from 'yaml';
3
+ /**
4
+ * Verifies structure matches the test metadata map type.
5
+ */
6
+ function isTestMetadataMap(obj) {
7
+ if (typeof obj !== 'object' || obj === null)
8
+ return false;
9
+ return Object.entries(obj).every(([key, value]) => typeof key === 'string' &&
10
+ Array.isArray(value) &&
11
+ value.every(v => typeof v === 'string'));
12
+ }
13
+ /**
14
+ * Loads the test metadata filter YAML file and confirms it matches the expected structure.
15
+ */
16
+ export async function loadTestMetadataDependencies(configPath) {
17
+ const content = await readFile(configPath, 'utf-8');
18
+ const parsed = parse(content);
19
+ if (isTestMetadataMap(parsed)) {
20
+ return parsed;
21
+ }
22
+ throw new Error('Invalid test metadata dependencies format in YAML');
23
+ }
24
+ /**
25
+ * Compare two metadata strings like "CustomField:Account__c.Name"
26
+ * against patterns with wildcards, like "CustomField:Account__c.*"
27
+ */
28
+ function matchesDependency(dependency, changed) {
29
+ if (dependency.includes('*')) {
30
+ const pattern = dependency
31
+ .replace('.', '\\.')
32
+ .replace('*', '.*');
33
+ return new RegExp(`^${pattern}$`).test(changed);
34
+ }
35
+ return dependency === changed;
36
+ }
37
+ /**
38
+ * Return test classes that depend on any of the changed metadata.
39
+ */
40
+ export function selectRelevantTests(testMap, changedMetadata) {
41
+ const selected = [];
42
+ for (const [testClass, dependencies] of Object.entries(testMap)) {
43
+ const matches = changedMetadata.some(changed => dependencies.some(dep => matchesDependency(dep, changed)));
44
+ if (matches) {
45
+ selected.push(testClass);
46
+ }
47
+ }
48
+ return selected;
49
+ }
50
+ //# sourceMappingURL=metadataFilterParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadataFilterParser.js","sourceRoot":"","sources":["../../src/parsers/metadataFilterParser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AAI7B;;GAEG;AACH,SAAS,iBAAiB,CAAC,GAAY;IACnC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAE1D,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAC9C,OAAO,GAAG,KAAK,QAAQ;QACvB,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACpB,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAC1C,CAAC;AACN,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,UAAkB;IACjE,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACpD,MAAM,MAAM,GAAY,KAAK,CAAC,OAAO,CAAC,CAAC;IAEvC,IAAI,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5B,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;AACzE,CAAC;AAED;;;GAGG;AACH,SAAS,iBAAiB,CAAC,UAAkB,EAAE,OAAe;IAC1D,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,UAAU;aACrB,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC;aACnB,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACxB,OAAO,IAAI,MAAM,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,UAAU,KAAK,OAAO,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAC/B,OAAwB,EACxB,eAAyB;IAEzB,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,KAAK,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9D,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAC3C,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAC5D,CAAC;QACF,IAAI,OAAO,EAAE,CAAC;YACV,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC7B,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AACpB,CAAC"}
@@ -3,3 +3,4 @@ export declare const SEARCHABLE_METADATA_FOLDERS: string[];
3
3
  export declare const TEST_NAME_REGEX: RegExp;
4
4
  export declare const TEST_SUITE_NAME_REGEX: RegExp;
5
5
  export declare const TEST_CLASS_ANNOTATION_REGEX: RegExp;
6
+ export declare const METADATA_FILTER_CONFIG = ".test-dependencies.yml";
@@ -4,4 +4,5 @@ export const SEARCHABLE_METADATA_FOLDERS = ['classes', 'triggers', 'testSuites']
4
4
  export const TEST_NAME_REGEX = /@tests\s*:\s*([^/\n]+)/gi;
5
5
  export const TEST_SUITE_NAME_REGEX = /@testsuites\s*:\s*([^/\n]+)/gi;
6
6
  export const TEST_CLASS_ANNOTATION_REGEX = /@istest/gi;
7
+ export const METADATA_FILTER_CONFIG = '.test-dependencies.yml';
7
8
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,MAAM,CAAC,MAAM,sBAAsB,GAAG,mBAAmB,CAAC;AAC1D,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,SAAS,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;AACjF,MAAM,CAAC,MAAM,eAAe,GAAG,0BAA0B,CAAC;AAC1D,MAAM,CAAC,MAAM,qBAAqB,GAAG,+BAA+B,CAAC;AACrE,MAAM,CAAC,MAAM,2BAA2B,GAAG,WAAW,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,MAAM,CAAC,MAAM,sBAAsB,GAAG,mBAAmB,CAAC;AAC1D,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,SAAS,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;AACjF,MAAM,CAAC,MAAM,eAAe,GAAG,0BAA0B,CAAC;AAC1D,MAAM,CAAC,MAAM,qBAAqB,GAAG,+BAA+B,CAAC;AACrE,MAAM,CAAC,MAAM,2BAA2B,GAAG,WAAW,CAAC;AACvD,MAAM,CAAC,MAAM,sBAAsB,GAAG,wBAAwB,CAAC"}
@@ -1 +1,4 @@
1
- export declare function getPackageDirectories(ignoreDirs: string[]): Promise<string[]>;
1
+ export declare function getPackageDirectories(ignoreDirs: string[]): Promise<{
2
+ metadataPaths: string[];
3
+ repoRoot: string;
4
+ }>;
@@ -15,7 +15,7 @@ export async function getPackageDirectories(ignoreDirs) {
15
15
  .map((directory) => resolve(repoRoot, directory.path))
16
16
  .filter((directory) => !ignoreDirs.includes(basename(directory)));
17
17
  const metadataPaths = (await Promise.all(packageDirectories.map((directory) => searchForSubFolders(directory, SEARCHABLE_METADATA_FOLDERS)))).flat();
18
- return metadataPaths;
18
+ return { metadataPaths, repoRoot };
19
19
  }
20
20
  async function searchForSubFolders(dxDirectory, subDirectoryNames) {
21
21
  const foundPaths = [];
@@ -1 +1 @@
1
- {"version":3,"file":"getPackageDirectories.js","sourceRoot":"","sources":["../../src/utils/getPackageDirectories.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE3D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC;AAE7D,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,UAAoB;IAC9D,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,GAAG,MAAM,WAAW,EAAE,CAAC;IAE3D,IAAI,CAAC,QAAQ,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACnF,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACxB,MAAM,cAAc,GAAW,MAAM,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;IACzE,MAAM,WAAW,GAAgB,IAAI,CAAC,KAAK,CAAC,cAAc,CAAgB,CAAC;IAC3E,MAAM,kBAAkB,GAAG,WAAW,CAAC,kBAAkB;SACtD,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;SACrD,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAEpE,MAAM,aAAa,GAAG,CACpB,MAAM,OAAO,CAAC,GAAG,CACf,kBAAkB,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,mBAAmB,CAAC,SAAS,EAAE,2BAA2B,CAAC,CAAC,CACnG,CACF,CAAC,IAAI,EAAE,CAAC;IAET,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,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,GAAG,CACvC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEnC,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,iBAAiB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5D,OAAO,CAAC,QAAQ,CAAC,CAAC;QACpB,CAAC;aAAM,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YAC/B,OAAO,mBAAmB,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;QAC1D,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC,CACH,CAAC;IAEF,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE,CAAC;QACpC,UAAU,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
1
+ {"version":3,"file":"getPackageDirectories.js","sourceRoot":"","sources":["../../src/utils/getPackageDirectories.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE3D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC;AAE7D,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,UAAoB;IAC9D,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,GAAG,MAAM,WAAW,EAAE,CAAC;IAE3D,IAAI,CAAC,QAAQ,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACnF,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACxB,MAAM,cAAc,GAAW,MAAM,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;IACzE,MAAM,WAAW,GAAgB,IAAI,CAAC,KAAK,CAAC,cAAc,CAAgB,CAAC;IAC3E,MAAM,kBAAkB,GAAG,WAAW,CAAC,kBAAkB;SACtD,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;SACrD,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAEpE,MAAM,aAAa,GAAG,CACpB,MAAM,OAAO,CAAC,GAAG,CACf,kBAAkB,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,mBAAmB,CAAC,SAAS,EAAE,2BAA2B,CAAC,CAAC,CACnG,CACF,CAAC,IAAI,EAAE,CAAC;IAET,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC;AACrC,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,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,GAAG,CACvC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEnC,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,iBAAiB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5D,OAAO,CAAC,QAAQ,CAAC,CAAC;QACpB,CAAC;aAAM,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YAC/B,OAAO,mBAAmB,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;QAC1D,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC,CACH,CAAC;IAEF,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE,CAAC;QACpC,UAAU,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -18,5 +18,7 @@ export type ListTestsOptions = {
18
18
  ignoreMissingTests?: boolean;
19
19
  ignoreDirs?: string[];
20
20
  noWarnings?: boolean;
21
+ filterByMetadata?: boolean;
21
22
  warn?: (msg: string) => void;
22
23
  };
24
+ export type TestMetadataMap = Record<string, string[]>;
@@ -46,6 +46,14 @@ Do not print warnings for each Apex file missing annotations.
46
46
 
47
47
  Do not print warnings for each Apex file missing annotations.
48
48
 
49
+ # flags.filter-by-metadata.summary
50
+
51
+ Only include tests that explicitly declare metadata dependencies matching changed metadata.
52
+
53
+ # flags.filter-by-metadata.description
54
+
55
+ When enabled with `manifest`, test selection is based on metadata changes (e.g., Flow, CustomObject) rather than Apex annotations.
56
+
49
57
  # examples
50
58
 
51
59
  - <%= config.bin %> <%= command.id %> --format csv
package/oclif.lock CHANGED
@@ -6647,15 +6647,7 @@ srcset@^5.0.0:
6647
6647
  version "5.0.1"
6648
6648
  resolved "https://registry.npmjs.org/srcset/-/srcset-5.0.1.tgz"
6649
6649
 
6650
- "string-width-cjs@npm:string-width@^4.2.0":
6651
- version "4.2.3"
6652
- resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
6653
- dependencies:
6654
- emoji-regex "^8.0.0"
6655
- is-fullwidth-code-point "^3.0.0"
6656
- strip-ansi "^6.0.1"
6657
-
6658
- string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
6650
+ "string-width-cjs@npm:string-width@^4.2.0", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
6659
6651
  version "4.2.3"
6660
6652
  resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
6661
6653
  dependencies:
@@ -6723,13 +6715,7 @@ stringify-entities@^4.0.0:
6723
6715
  character-entities-html4 "^2.0.0"
6724
6716
  character-entities-legacy "^3.0.0"
6725
6717
 
6726
- "strip-ansi-cjs@npm:strip-ansi@^6.0.1":
6727
- version "6.0.1"
6728
- resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
6729
- dependencies:
6730
- ansi-regex "^5.0.1"
6731
-
6732
- strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1:
6718
+ "strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1:
6733
6719
  version "6.0.1"
6734
6720
  resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
6735
6721
  dependencies:
@@ -7289,7 +7275,7 @@ workerpool@^6.5.1:
7289
7275
  version "6.5.1"
7290
7276
  resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz"
7291
7277
 
7292
- "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
7278
+ "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
7293
7279
  version "7.0.0"
7294
7280
  resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
7295
7281
  dependencies:
@@ -7305,14 +7291,6 @@ wrap-ansi@^6.2.0:
7305
7291
  string-width "^4.1.0"
7306
7292
  strip-ansi "^6.0.0"
7307
7293
 
7308
- wrap-ansi@^7.0.0:
7309
- version "7.0.0"
7310
- resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
7311
- dependencies:
7312
- ansi-styles "^4.0.0"
7313
- string-width "^4.1.0"
7314
- strip-ansi "^6.0.0"
7315
-
7316
7294
  wrap-ansi@^8.1.0:
7317
7295
  version "8.1.0"
7318
7296
  resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz"
@@ -7370,6 +7348,11 @@ yaml@^2.5.1, yaml@^2.7.1:
7370
7348
  resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.7.1.tgz#44a247d1b88523855679ac7fa7cda6ed7e135cf6"
7371
7349
  integrity sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==
7372
7350
 
7351
+ yaml@^2.8.0:
7352
+ version "2.8.0"
7353
+ resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.8.0.tgz#15f8c9866211bdc2d3781a0890e44d4fa1a5fff6"
7354
+ integrity sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==
7355
+
7373
7356
  yargs-parser@^18.1.2:
7374
7357
  version "18.1.3"
7375
7358
  resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz"
@@ -75,6 +75,15 @@
75
75
  "summary": "Do not print warnings for each Apex file missing annotations.",
76
76
  "allowNo": false,
77
77
  "type": "boolean"
78
+ },
79
+ "filter-by-metadata": {
80
+ "char": "m",
81
+ "description": "When enabled with `manifest`, test selection is based on metadata changes (e.g., Flow, CustomObject) rather than Apex annotations.",
82
+ "name": "filter-by-metadata",
83
+ "required": false,
84
+ "summary": "Only include tests that explicitly declare metadata dependencies matching changed metadata.",
85
+ "allowNo": false,
86
+ "type": "boolean"
78
87
  }
79
88
  },
80
89
  "hasDynamicHelp": false,
@@ -100,5 +109,5 @@
100
109
  ]
101
110
  }
102
111
  },
103
- "version": "1.12.4"
112
+ "version": "1.13.0"
104
113
  }
package/package.json CHANGED
@@ -1,14 +1,15 @@
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.12.4",
4
+ "version": "1.13.0",
5
5
  "dependencies": {
6
6
  "@oclif/core": "4.3.3",
7
7
  "@salesforce/core": "^8.8.0",
8
8
  "@salesforce/sf-plugins-core": "^11.3.12",
9
9
  "@salesforce/source-deploy-retrieve": "^12.16.5",
10
10
  "async": "^3.2.6",
11
- "xml2js": "^0.6.2"
11
+ "xml2js": "^0.6.2",
12
+ "yaml": "^2.8.0"
12
13
  },
13
14
  "devDependencies": {
14
15
  "@commitlint/cli": "^19.6.0",