@jterrats/smart-deployment 1.0.5 → 1.1.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/README.md +3 -2
- package/lib/ai/wave-validation-prompt.d.ts +2 -0
- package/lib/ai/wave-validation-prompt.js +56 -0
- package/lib/ai/wave-validation-prompt.js.map +1 -0
- package/lib/ai/wave-validation-report.d.ts +2 -0
- package/lib/ai/wave-validation-report.js +96 -0
- package/lib/ai/wave-validation-report.js.map +1 -0
- package/lib/ai/wave-validation-response-parser.d.ts +8 -0
- package/lib/ai/wave-validation-response-parser.js +112 -0
- package/lib/ai/wave-validation-response-parser.js.map +1 -0
- package/lib/ai/wave-validation-result-synthesis.d.ts +6 -0
- package/lib/ai/wave-validation-result-synthesis.js +49 -0
- package/lib/ai/wave-validation-result-synthesis.js.map +1 -0
- package/lib/ai/wave-validation-service.d.ts +1 -55
- package/lib/ai/wave-validation-service.js +11 -359
- package/lib/ai/wave-validation-service.js.map +1 -1
- package/lib/ai/wave-validation-transport.d.ts +7 -0
- package/lib/ai/wave-validation-transport.js +10 -0
- package/lib/ai/wave-validation-transport.js.map +1 -0
- package/lib/analysis/analysis-reporter.d.ts +29 -0
- package/lib/analysis/analysis-reporter.js +84 -1
- package/lib/analysis/analysis-reporter.js.map +1 -1
- package/lib/analysis/analyze-context-service.d.ts +1 -1
- package/lib/analysis/analyze-context-service.js +2 -0
- package/lib/analysis/analyze-context-service.js.map +1 -1
- package/lib/analysis/project-analysis-service.d.ts +2 -0
- package/lib/analysis/project-analysis-service.js +2 -0
- package/lib/analysis/project-analysis-service.js.map +1 -1
- package/lib/commands/start.d.ts +1 -0
- package/lib/commands/start.js +14 -1
- package/lib/commands/start.js.map +1 -1
- package/lib/commands/status.d.ts +2 -0
- package/lib/commands/status.js +1 -0
- package/lib/commands/status.js.map +1 -1
- package/lib/commands/validate.d.ts +3 -3
- package/lib/commands/validate.js +4 -4
- package/lib/commands/validate.js.map +1 -1
- package/lib/constants/api-version.d.ts +2 -2
- package/lib/constants/api-version.js +2 -2
- package/lib/constants/deployment-order.js +11 -8
- package/lib/constants/deployment-order.js.map +1 -1
- package/lib/dependencies/circular-dependency-detector.d.ts +1 -31
- package/lib/dependencies/circular-dependency-detector.js +7 -156
- package/lib/dependencies/circular-dependency-detector.js.map +1 -1
- package/lib/dependencies/cycle-break-suggestions.d.ts +3 -0
- package/lib/dependencies/cycle-break-suggestions.js +63 -0
- package/lib/dependencies/cycle-break-suggestions.js.map +1 -0
- package/lib/dependencies/cycle-discovery.d.ts +16 -0
- package/lib/dependencies/cycle-discovery.js +70 -0
- package/lib/dependencies/cycle-discovery.js.map +1 -0
- package/lib/dependencies/dependency-graph-builder.d.ts +0 -65
- package/lib/dependencies/dependency-graph-builder.js +19 -233
- package/lib/dependencies/dependency-graph-builder.js.map +1 -1
- package/lib/dependencies/dependency-graph-intake.d.ts +17 -0
- package/lib/dependencies/dependency-graph-intake.js +20 -0
- package/lib/dependencies/dependency-graph-intake.js.map +1 -0
- package/lib/dependencies/dependency-graph-stats.d.ts +4 -0
- package/lib/dependencies/dependency-graph-stats.js +82 -0
- package/lib/dependencies/dependency-graph-stats.js.map +1 -0
- package/lib/dependencies/dependency-graph-validation.d.ts +16 -0
- package/lib/dependencies/dependency-graph-validation.js +78 -0
- package/lib/dependencies/dependency-graph-validation.js.map +1 -0
- package/lib/dependencies/dependency-impact-analyzer.d.ts +1 -22
- package/lib/dependencies/dependency-impact-analyzer.js +12 -110
- package/lib/dependencies/dependency-impact-analyzer.js.map +1 -1
- package/lib/dependencies/dependency-impact-scoring.d.ts +5 -0
- package/lib/dependencies/dependency-impact-scoring.js +24 -0
- package/lib/dependencies/dependency-impact-scoring.js.map +1 -0
- package/lib/dependencies/dependency-impact-traversal.d.ts +18 -0
- package/lib/dependencies/dependency-impact-traversal.js +74 -0
- package/lib/dependencies/dependency-impact-traversal.js.map +1 -0
- package/lib/dependencies/dependency-resolution-classifier.d.ts +19 -0
- package/lib/dependencies/dependency-resolution-classifier.js +67 -0
- package/lib/dependencies/dependency-resolution-classifier.js.map +1 -0
- package/lib/dependencies/dependency-resolver.d.ts +1 -48
- package/lib/dependencies/dependency-resolver.js +12 -181
- package/lib/dependencies/dependency-resolver.js.map +1 -1
- package/lib/dependencies/dynamic-query-dependency-references.d.ts +3 -0
- package/lib/dependencies/dynamic-query-dependency-references.js +41 -0
- package/lib/dependencies/dynamic-query-dependency-references.js.map +1 -0
- package/lib/dependencies/topological-dependency-sorter.d.ts +10 -0
- package/lib/dependencies/topological-dependency-sorter.js +84 -0
- package/lib/dependencies/topological-dependency-sorter.js.map +1 -0
- package/lib/deployment/cycle-remediation-runner.d.ts +1 -0
- package/lib/deployment/cycle-remediation-runner.js +5 -1
- package/lib/deployment/cycle-remediation-runner.js.map +1 -1
- package/lib/deployment/deployment-runner.d.ts +3 -1
- package/lib/deployment/deployment-runner.js +6 -1
- package/lib/deployment/deployment-runner.js.map +1 -1
- package/lib/deployment/deployment-status-service.d.ts +2 -0
- package/lib/deployment/deployment-status-service.js +2 -0
- package/lib/deployment/deployment-status-service.js.map +1 -1
- package/lib/deployment/deployment-validation-service.js +1 -1
- package/lib/deployment/deployment-validation-service.js.map +1 -1
- package/lib/deployment/dynamic-query-target-validator.d.ts +24 -0
- package/lib/deployment/dynamic-query-target-validator.js +65 -0
- package/lib/deployment/dynamic-query-target-validator.js.map +1 -0
- package/lib/deployment/sf-cli-integration.d.ts +1 -0
- package/lib/deployment/sf-cli-integration.js +1 -1
- package/lib/deployment/sf-cli-integration.js.map +1 -1
- package/lib/deployment/sf-cli-metadata-lookup.d.ts +4 -0
- package/lib/deployment/sf-cli-metadata-lookup.js +26 -0
- package/lib/deployment/sf-cli-metadata-lookup.js.map +1 -0
- package/lib/deployment/start-execution-service.d.ts +5 -0
- package/lib/deployment/start-execution-service.js +26 -6
- package/lib/deployment/start-execution-service.js.map +1 -1
- package/lib/deployment/wave-graph-state.d.ts +6 -0
- package/lib/deployment/wave-graph-state.js +89 -0
- package/lib/deployment/wave-graph-state.js.map +1 -0
- package/lib/deployment/wave-manifest-service.d.ts +1 -0
- package/lib/deployment/wave-manifest-service.js +1 -1
- package/lib/deployment/wave-manifest-service.js.map +1 -1
- package/lib/errors/deployment-error.js +1 -1
- package/lib/errors/deployment-error.js.map +1 -1
- package/lib/parsers/apex-class-dependencies.d.ts +4 -0
- package/lib/parsers/apex-class-dependencies.js +122 -0
- package/lib/parsers/apex-class-dependencies.js.map +1 -0
- package/lib/parsers/apex-class-lexical.d.ts +3 -0
- package/lib/parsers/apex-class-lexical.js +101 -0
- package/lib/parsers/apex-class-lexical.js.map +1 -0
- package/lib/parsers/apex-class-names.d.ts +18 -0
- package/lib/parsers/apex-class-names.js +93 -0
- package/lib/parsers/apex-class-names.js.map +1 -0
- package/lib/parsers/apex-class-parser-model.d.ts +59 -0
- package/lib/parsers/apex-class-parser-model.js +2 -0
- package/lib/parsers/apex-class-parser-model.js.map +1 -0
- package/lib/parsers/apex-class-parser.d.ts +3 -29
- package/lib/parsers/apex-class-parser.js +10 -395
- package/lib/parsers/apex-class-parser.js.map +1 -1
- package/lib/parsers/apex-class-symbols.d.ts +2 -0
- package/lib/parsers/apex-class-symbols.js +61 -0
- package/lib/parsers/apex-class-symbols.js.map +1 -0
- package/lib/parsers/apex-dynamic-query-analysis.d.ts +2 -0
- package/lib/parsers/apex-dynamic-query-analysis.js +150 -0
- package/lib/parsers/apex-dynamic-query-analysis.js.map +1 -0
- package/lib/parsers/custom-metadata-dynamic-query-analysis.d.ts +2 -0
- package/lib/parsers/custom-metadata-dynamic-query-analysis.js +50 -0
- package/lib/parsers/custom-metadata-dynamic-query-analysis.js.map +1 -0
- package/lib/parsers/custom-metadata-parser.d.ts +2 -0
- package/lib/parsers/custom-metadata-parser.js +3 -0
- package/lib/parsers/custom-metadata-parser.js.map +1 -1
- package/lib/parsers/custom-object-dependency-builder.d.ts +3 -0
- package/lib/parsers/custom-object-dependency-builder.js +103 -0
- package/lib/parsers/custom-object-dependency-builder.js.map +1 -0
- package/lib/parsers/custom-object-parser.js +1 -208
- package/lib/parsers/custom-object-parser.js.map +1 -1
- package/lib/parsers/custom-object-reference-helpers.d.ts +4 -0
- package/lib/parsers/custom-object-reference-helpers.js +92 -0
- package/lib/parsers/custom-object-reference-helpers.js.map +1 -0
- package/lib/parsers/dynamic-query-reference.d.ts +16 -0
- package/lib/parsers/dynamic-query-reference.js +65 -0
- package/lib/parsers/dynamic-query-reference.js.map +1 -0
- package/lib/parsers/layout-action-analysis.d.ts +6 -0
- package/lib/parsers/layout-action-analysis.js +36 -0
- package/lib/parsers/layout-action-analysis.js.map +1 -0
- package/lib/parsers/layout-parser.js +4 -272
- package/lib/parsers/layout-parser.js.map +1 -1
- package/lib/parsers/layout-reference-analysis.d.ts +9 -0
- package/lib/parsers/layout-reference-analysis.js +70 -0
- package/lib/parsers/layout-reference-analysis.js.map +1 -0
- package/lib/parsers/layout-result-assembly.d.ts +5 -0
- package/lib/parsers/layout-result-assembly.js +35 -0
- package/lib/parsers/layout-result-assembly.js.map +1 -0
- package/lib/parsers/layout-section-analysis.d.ts +7 -0
- package/lib/parsers/layout-section-analysis.js +9 -0
- package/lib/parsers/layout-section-analysis.js.map +1 -0
- package/lib/parsers/lwc-code-analysis.d.ts +10 -0
- package/lib/parsers/lwc-code-analysis.js +161 -0
- package/lib/parsers/lwc-code-analysis.js.map +1 -0
- package/lib/parsers/lwc-metadata-analysis.d.ts +6 -0
- package/lib/parsers/lwc-metadata-analysis.js +112 -0
- package/lib/parsers/lwc-metadata-analysis.js.map +1 -0
- package/lib/parsers/lwc-parser.d.ts +3 -27
- package/lib/parsers/lwc-parser.js +6 -377
- package/lib/parsers/lwc-parser.js.map +1 -1
- package/lib/parsers/lwc-result-assembly.d.ts +4 -0
- package/lib/parsers/lwc-result-assembly.js +47 -0
- package/lib/parsers/lwc-result-assembly.js.map +1 -0
- package/lib/presentation/status-command-presenter.d.ts +1 -0
- package/lib/presentation/status-command-presenter.js +20 -0
- package/lib/presentation/status-command-presenter.js.map +1 -1
- package/lib/scanner/forceignore-parser.d.ts +1 -0
- package/lib/scanner/forceignore-parser.js +14 -3
- package/lib/scanner/forceignore-parser.js.map +1 -1
- package/lib/scanner/structure-validator.js +1 -1
- package/lib/services/metadata-scanner-service.d.ts +2 -0
- package/lib/services/metadata-scanner-service.js +9 -2
- package/lib/services/metadata-scanner-service.js.map +1 -1
- package/lib/services/scanners/additional-metadata-scanner.d.ts +2 -0
- package/lib/services/scanners/additional-metadata-scanner.js +183 -0
- package/lib/services/scanners/additional-metadata-scanner.js.map +1 -0
- package/lib/services/scanners/automation-ai-metadata-scanner.d.ts +1 -0
- package/lib/services/scanners/automation-ai-metadata-scanner.js +11 -0
- package/lib/services/scanners/automation-ai-metadata-scanner.js.map +1 -1
- package/lib/services/scanners/code-metadata-scanner.js +14 -1
- package/lib/services/scanners/code-metadata-scanner.js.map +1 -1
- package/lib/services/scanners/data-metadata-scanner.js +24 -8
- package/lib/services/scanners/data-metadata-scanner.js.map +1 -1
- package/lib/types/metadata.d.ts +1 -1
- package/lib/utils/cache-entry-serializer.d.ts +7 -0
- package/lib/utils/cache-entry-serializer.js +15 -0
- package/lib/utils/cache-entry-serializer.js.map +1 -0
- package/lib/utils/cache-expiry-policy.d.ts +7 -0
- package/lib/utils/cache-expiry-policy.js +34 -0
- package/lib/utils/cache-expiry-policy.js.map +1 -0
- package/lib/utils/cache-key-derivation.d.ts +11 -0
- package/lib/utils/cache-key-derivation.js +28 -0
- package/lib/utils/cache-key-derivation.js.map +1 -0
- package/lib/utils/cache-lock-lifecycle.d.ts +15 -0
- package/lib/utils/cache-lock-lifecycle.js +84 -0
- package/lib/utils/cache-lock-lifecycle.js.map +1 -0
- package/lib/utils/cache-logger.d.ts +8 -0
- package/lib/utils/cache-logger.js +19 -0
- package/lib/utils/cache-logger.js.map +1 -0
- package/lib/utils/cache-manager.d.ts +1 -2
- package/lib/utils/cache-manager.js +7 -253
- package/lib/utils/cache-manager.js.map +1 -1
- package/lib/utils/cache-storage.d.ts +20 -0
- package/lib/utils/cache-storage.js +83 -0
- package/lib/utils/cache-storage.js.map +1 -0
- package/lib/validators/xml-metadata-validator.js +1 -1
- package/lib/waves/priority-wave-generator.js +8 -2
- package/lib/waves/priority-wave-generator.js.map +1 -1
- package/lib/waves/test-optimizer-discovery.d.ts +12 -0
- package/lib/waves/test-optimizer-discovery.js +46 -0
- package/lib/waves/test-optimizer-discovery.js.map +1 -0
- package/lib/waves/test-optimizer-matching.d.ts +6 -0
- package/lib/waves/test-optimizer-matching.js +43 -0
- package/lib/waves/test-optimizer-matching.js.map +1 -0
- package/lib/waves/test-optimizer-model.d.ts +92 -0
- package/lib/waves/test-optimizer-model.js +2 -0
- package/lib/waves/test-optimizer-model.js.map +1 -0
- package/lib/waves/test-optimizer-scoring.d.ts +11 -0
- package/lib/waves/test-optimizer-scoring.js +53 -0
- package/lib/waves/test-optimizer-scoring.js.map +1 -0
- package/lib/waves/test-optimizer.d.ts +2 -102
- package/lib/waves/test-optimizer.js +9 -154
- package/lib/waves/test-optimizer.js.map +1 -1
- package/lib/waves/wave-builder.d.ts +0 -11
- package/lib/waves/wave-builder.js +19 -193
- package/lib/waves/wave-builder.js.map +1 -1
- package/lib/waves/wave-graph.d.ts +25 -0
- package/lib/waves/wave-graph.js +138 -0
- package/lib/waves/wave-graph.js.map +1 -0
- package/lib/waves/wave-metadata.d.ts +4 -0
- package/lib/waves/wave-metadata.js +36 -0
- package/lib/waves/wave-metadata.js.map +1 -0
- package/lib/waves/wave-priority-policy.d.ts +5 -0
- package/lib/waves/wave-priority-policy.js +83 -0
- package/lib/waves/wave-priority-policy.js.map +1 -0
- package/lib/waves/wave-topology.d.ts +28 -0
- package/lib/waves/wave-topology.js +65 -0
- package/lib/waves/wave-topology.js.map +1 -0
- package/messages/start.json +5 -5
- package/messages/validate.json +1 -1
- package/npm-shrinkwrap.json +342 -751
- package/oclif.lock +83 -262
- package/oclif.manifest.json +7 -7
- package/package.json +6 -2
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if component is a test class
|
|
3
|
+
*/
|
|
4
|
+
export function isTestClass(component) {
|
|
5
|
+
return (component.startsWith('ApexClass:') &&
|
|
6
|
+
(component.toLowerCase().includes('test') || component.toLowerCase().endsWith('_test')));
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Collect all test classes from all waves
|
|
10
|
+
*/
|
|
11
|
+
export function collectAllTestClasses(waves) {
|
|
12
|
+
const testClasses = new Set();
|
|
13
|
+
for (const wave of waves) {
|
|
14
|
+
for (const component of wave.components) {
|
|
15
|
+
if (isTestClass(component)) {
|
|
16
|
+
testClasses.add(component);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return Array.from(testClasses);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get code classes (non-test Apex classes)
|
|
24
|
+
*/
|
|
25
|
+
function getCodeClasses(wave) {
|
|
26
|
+
return wave.components.filter((component) => component.startsWith('ApexClass:') && !isTestClass(component));
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* @ac US-040-AC-4: Ensure trigger tests are included
|
|
30
|
+
*/
|
|
31
|
+
function getTriggers(wave) {
|
|
32
|
+
return wave.components.filter((component) => component.startsWith('ApexTrigger:'));
|
|
33
|
+
}
|
|
34
|
+
export function analyzeWave(wave) {
|
|
35
|
+
const codeClasses = getCodeClasses(wave);
|
|
36
|
+
const triggers = getTriggers(wave);
|
|
37
|
+
return {
|
|
38
|
+
waveNumber: wave.number,
|
|
39
|
+
waveComponents: wave.components,
|
|
40
|
+
waveMetadata: wave.metadata,
|
|
41
|
+
codeClasses,
|
|
42
|
+
triggers,
|
|
43
|
+
needsTests: codeClasses.length > 0 || triggers.length > 0,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=test-optimizer-discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-optimizer-discovery.js","sourceRoot":"","sources":["../../src/waves/test-optimizer-discovery.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,SAAiB;IAC3C,OAAO,CACL,SAAS,CAAC,UAAU,CAAC,YAAY,CAAC;QAClC,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CACxF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAsB;IAC1D,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IAEtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACxC,IAAI,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC3B,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,IAAU;IAChC,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC;AAC9G,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,IAAU;IAC7B,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC;AACrF,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAU;IACpC,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAEnC,OAAO;QACL,UAAU,EAAE,IAAI,CAAC,MAAM;QACvB,cAAc,EAAE,IAAI,CAAC,UAAU;QAC/B,YAAY,EAAE,IAAI,CAAC,QAAQ;QAC3B,WAAW;QACX,QAAQ;QACR,UAAU,EAAE,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;KAC1D,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { NodeId } from '../types/dependency.js';
|
|
2
|
+
import type { OptimizerPolicy, WaveTestContext } from './test-optimizer-model.js';
|
|
3
|
+
/**
|
|
4
|
+
* Sync test classes with production classes
|
|
5
|
+
*/
|
|
6
|
+
export declare function matchTestClasses(context: WaveTestContext, allTestClasses: readonly NodeId[], policy: OptimizerPolicy): NodeId[];
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
function getComponentName(component) {
|
|
2
|
+
return component.split(':')[1];
|
|
3
|
+
}
|
|
4
|
+
function matchesCodeClass(testClass, codeClass) {
|
|
5
|
+
const testName = getComponentName(testClass).toLowerCase();
|
|
6
|
+
const codeName = getComponentName(codeClass).toLowerCase();
|
|
7
|
+
return testName.includes(codeName) || codeName.includes(testName.replace('test', ''));
|
|
8
|
+
}
|
|
9
|
+
function matchesTrigger(testClass, trigger) {
|
|
10
|
+
const testName = getComponentName(testClass).toLowerCase();
|
|
11
|
+
const triggerName = getComponentName(trigger).toLowerCase();
|
|
12
|
+
return testName.includes(triggerName) || testName.includes('trigger');
|
|
13
|
+
}
|
|
14
|
+
function addRelatedTestSubset(matchedTests, allTestClasses) {
|
|
15
|
+
for (let index = 0; index < Math.min(10, allTestClasses.length); index++) {
|
|
16
|
+
matchedTests.add(allTestClasses[index]);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Sync test classes with production classes
|
|
21
|
+
*/
|
|
22
|
+
export function matchTestClasses(context, allTestClasses, policy) {
|
|
23
|
+
const matchedTests = new Set();
|
|
24
|
+
for (const codeClass of context.codeClasses) {
|
|
25
|
+
for (const testClass of allTestClasses) {
|
|
26
|
+
if (matchesCodeClass(testClass, codeClass)) {
|
|
27
|
+
matchedTests.add(testClass);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
for (const trigger of context.triggers) {
|
|
32
|
+
for (const testClass of allTestClasses) {
|
|
33
|
+
if (matchesTrigger(testClass, trigger)) {
|
|
34
|
+
matchedTests.add(testClass);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (matchedTests.size === 0 && policy.includeRelatedTests) {
|
|
39
|
+
addRelatedTestSubset(matchedTests, allTestClasses);
|
|
40
|
+
}
|
|
41
|
+
return Array.from(matchedTests);
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=test-optimizer-matching.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-optimizer-matching.js","sourceRoot":"","sources":["../../src/waves/test-optimizer-matching.ts"],"names":[],"mappings":"AAGA,SAAS,gBAAgB,CAAC,SAAiB;IACzC,OAAO,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,gBAAgB,CAAC,SAAiB,EAAE,SAAiB;IAC5D,MAAM,QAAQ,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;IAC3D,MAAM,QAAQ,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;IAE3D,OAAO,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;AACxF,CAAC;AAED,SAAS,cAAc,CAAC,SAAiB,EAAE,OAAe;IACxD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;IAC3D,MAAM,WAAW,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;IAE5D,OAAO,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AACxE,CAAC;AAED,SAAS,oBAAoB,CAAC,YAAyB,EAAE,cAAiC;IACxF,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,cAAc,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QACzE,YAAY,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1C,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAAwB,EACxB,cAAiC,EACjC,MAAuB;IAEvB,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IAEvC,KAAK,MAAM,SAAS,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;QAC5C,KAAK,MAAM,SAAS,IAAI,cAAc,EAAE,CAAC;YACvC,IAAI,gBAAgB,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC;gBAC3C,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACvC,KAAK,MAAM,SAAS,IAAI,cAAc,EAAE,CAAC;YACvC,IAAI,cAAc,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC;gBACvC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,YAAY,CAAC,IAAI,KAAK,CAAC,IAAI,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAC1D,oBAAoB,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { NodeId } from '../types/dependency.js';
|
|
2
|
+
import type { Wave } from './wave-builder.js';
|
|
3
|
+
export type OptimizerPolicy = {
|
|
4
|
+
alwaysRunAllTests: boolean;
|
|
5
|
+
minCoverageRequired: number;
|
|
6
|
+
includeRelatedTests: boolean;
|
|
7
|
+
};
|
|
8
|
+
export type WaveTestContext = {
|
|
9
|
+
waveNumber: number;
|
|
10
|
+
waveComponents: NodeId[];
|
|
11
|
+
waveMetadata: Wave['metadata'];
|
|
12
|
+
codeClasses: NodeId[];
|
|
13
|
+
triggers: NodeId[];
|
|
14
|
+
needsTests: boolean;
|
|
15
|
+
};
|
|
16
|
+
export type WaveTestPlan = {
|
|
17
|
+
testClasses: NodeId[];
|
|
18
|
+
estimatedCoverage: number;
|
|
19
|
+
decision: OptimizationDecision;
|
|
20
|
+
};
|
|
21
|
+
export type OptimizationPlanningState = {
|
|
22
|
+
allTestClasses: NodeId[];
|
|
23
|
+
waveContexts: WaveTestContext[];
|
|
24
|
+
wavePlans: WaveTestPlan[];
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Test optimization result
|
|
28
|
+
*/
|
|
29
|
+
export type TestOptimizationResult = {
|
|
30
|
+
/** Original waves */
|
|
31
|
+
originalWaves: Wave[];
|
|
32
|
+
/** Optimized waves with test classes */
|
|
33
|
+
optimizedWaves: OptimizedWave[];
|
|
34
|
+
/** Optimization decisions */
|
|
35
|
+
decisions: OptimizationDecision[];
|
|
36
|
+
/** Statistics */
|
|
37
|
+
stats: OptimizationStats;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Optimized wave with test information
|
|
41
|
+
*/
|
|
42
|
+
export type OptimizedWave = Wave & {
|
|
43
|
+
/** Test classes included in this wave */
|
|
44
|
+
testClasses: NodeId[];
|
|
45
|
+
/** Code classes in this wave */
|
|
46
|
+
codeClasses: NodeId[];
|
|
47
|
+
/** Triggers in this wave */
|
|
48
|
+
triggers: NodeId[];
|
|
49
|
+
/** Needs test execution */
|
|
50
|
+
needsTests: boolean;
|
|
51
|
+
/** Estimated test coverage % */
|
|
52
|
+
estimatedCoverage: number;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Optimization decision
|
|
56
|
+
*/
|
|
57
|
+
export type OptimizationDecision = {
|
|
58
|
+
/** Wave number */
|
|
59
|
+
waveNumber: number;
|
|
60
|
+
/** Decision type */
|
|
61
|
+
type: 'include-tests' | 'skip-tests' | 'sync-tests';
|
|
62
|
+
/** Reason for decision */
|
|
63
|
+
reason: string;
|
|
64
|
+
/** Tests affected */
|
|
65
|
+
testsAffected: number;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Optimization statistics
|
|
69
|
+
*/
|
|
70
|
+
export type OptimizationStats = {
|
|
71
|
+
/** Total waves */
|
|
72
|
+
totalWaves: number;
|
|
73
|
+
/** Waves with tests */
|
|
74
|
+
wavesWithTests: number;
|
|
75
|
+
/** Waves without tests */
|
|
76
|
+
wavesWithoutTests: number;
|
|
77
|
+
/** Total test classes added */
|
|
78
|
+
totalTestsAdded: number;
|
|
79
|
+
/** Estimated time saved (seconds) */
|
|
80
|
+
timeSaved: number;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Optimizer options
|
|
84
|
+
*/
|
|
85
|
+
export type OptimizerOptions = {
|
|
86
|
+
/** Always run all tests (disable optimization) */
|
|
87
|
+
alwaysRunAllTests?: boolean;
|
|
88
|
+
/** Minimum test coverage required (0-100) */
|
|
89
|
+
minCoverageRequired?: number;
|
|
90
|
+
/** Include related tests (not just direct) */
|
|
91
|
+
includeRelatedTests?: boolean;
|
|
92
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-optimizer-model.js","sourceRoot":"","sources":["../../src/waves/test-optimizer-model.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { NodeId } from '../types/dependency.js';
|
|
2
|
+
import type { OptimizationStats, OptimizedWave, WaveTestContext, WaveTestPlan } from './test-optimizer-model.js';
|
|
3
|
+
/**
|
|
4
|
+
* @ac US-040-AC-5: Calculate test coverage per wave
|
|
5
|
+
*/
|
|
6
|
+
export declare function scoreEstimatedCoverage(context: WaveTestContext, testClasses: readonly NodeId[]): number;
|
|
7
|
+
export declare function collectOptimizationDecisions(wavePlans: readonly WaveTestPlan[]): Array<WaveTestPlan['decision']>;
|
|
8
|
+
/**
|
|
9
|
+
* Calculate optimization statistics
|
|
10
|
+
*/
|
|
11
|
+
export declare function calculateStats(optimizedWaves: readonly OptimizedWave[], totalAvailableTests: number): OptimizationStats;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ac US-040-AC-5: Calculate test coverage per wave
|
|
3
|
+
*/
|
|
4
|
+
export function scoreEstimatedCoverage(context, testClasses) {
|
|
5
|
+
const codeClassCount = context.codeClasses.length;
|
|
6
|
+
const testClassCount = testClasses.length;
|
|
7
|
+
if (codeClassCount === 0)
|
|
8
|
+
return 100;
|
|
9
|
+
if (testClassCount === 0)
|
|
10
|
+
return 0;
|
|
11
|
+
const coverage = Math.min(100, (testClassCount / codeClassCount) * 75);
|
|
12
|
+
return Math.round(coverage);
|
|
13
|
+
}
|
|
14
|
+
export function collectOptimizationDecisions(wavePlans) {
|
|
15
|
+
return wavePlans.map((plan) => plan.decision);
|
|
16
|
+
}
|
|
17
|
+
function collectWaveTestTotals(optimizedWaves) {
|
|
18
|
+
let wavesWithTests = 0;
|
|
19
|
+
let wavesWithoutTests = 0;
|
|
20
|
+
let totalTestsAdded = 0;
|
|
21
|
+
for (const wave of optimizedWaves) {
|
|
22
|
+
if (wave.testClasses.length > 0) {
|
|
23
|
+
wavesWithTests++;
|
|
24
|
+
totalTestsAdded += wave.testClasses.length;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
wavesWithoutTests++;
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
wavesWithTests,
|
|
31
|
+
wavesWithoutTests,
|
|
32
|
+
totalTestsAdded,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function calculateTimeSaved(totalWaves, totalAvailableTests, totalTestsAdded) {
|
|
36
|
+
const testsSkipped = totalWaves * totalAvailableTests - totalTestsAdded;
|
|
37
|
+
return testsSkipped * 5;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Calculate optimization statistics
|
|
41
|
+
*/
|
|
42
|
+
export function calculateStats(optimizedWaves, totalAvailableTests) {
|
|
43
|
+
const totals = collectWaveTestTotals(optimizedWaves);
|
|
44
|
+
const timeSaved = calculateTimeSaved(optimizedWaves.length, totalAvailableTests, totals.totalTestsAdded);
|
|
45
|
+
return {
|
|
46
|
+
totalWaves: optimizedWaves.length,
|
|
47
|
+
wavesWithTests: totals.wavesWithTests,
|
|
48
|
+
wavesWithoutTests: totals.wavesWithoutTests,
|
|
49
|
+
totalTestsAdded: totals.totalTestsAdded,
|
|
50
|
+
timeSaved,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=test-optimizer-scoring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-optimizer-scoring.js","sourceRoot":"","sources":["../../src/waves/test-optimizer-scoring.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAwB,EAAE,WAA8B;IAC7F,MAAM,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC;IAClD,MAAM,cAAc,GAAG,WAAW,CAAC,MAAM,CAAC;IAE1C,IAAI,cAAc,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IACrC,IAAI,cAAc,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAEnC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,cAAc,GAAG,cAAc,CAAC,GAAG,EAAE,CAAC,CAAC;IACvE,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,SAAkC;IAC7E,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,qBAAqB,CAAC,cAAwC;IAKrE,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,IAAI,iBAAiB,GAAG,CAAC,CAAC;IAC1B,IAAI,eAAe,GAAG,CAAC,CAAC;IAExB,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE,CAAC;QAClC,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,cAAc,EAAE,CAAC;YACjB,eAAe,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;YAC3C,SAAS;QACX,CAAC;QAED,iBAAiB,EAAE,CAAC;IACtB,CAAC;IAED,OAAO;QACL,cAAc;QACd,iBAAiB;QACjB,eAAe;KAChB,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,UAAkB,EAAE,mBAA2B,EAAE,eAAuB;IAClG,MAAM,YAAY,GAAG,UAAU,GAAG,mBAAmB,GAAG,eAAe,CAAC;IACxE,OAAO,YAAY,GAAG,CAAC,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAC5B,cAAwC,EACxC,mBAA2B;IAE3B,MAAM,MAAM,GAAG,qBAAqB,CAAC,cAAc,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,kBAAkB,CAAC,cAAc,CAAC,MAAM,EAAE,mBAAmB,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;IAEzG,OAAO;QACL,UAAU,EAAE,cAAc,CAAC,MAAM;QACjC,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;QAC3C,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,SAAS;KACV,CAAC;AACJ,CAAC"}
|
|
@@ -11,75 +11,9 @@
|
|
|
11
11
|
*
|
|
12
12
|
* @issue #40
|
|
13
13
|
*/
|
|
14
|
-
import type { NodeId } from '../types/dependency.js';
|
|
15
14
|
import type { Wave } from './wave-builder.js';
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
*/
|
|
19
|
-
export type TestOptimizationResult = {
|
|
20
|
-
/** Original waves */
|
|
21
|
-
originalWaves: Wave[];
|
|
22
|
-
/** Optimized waves with test classes */
|
|
23
|
-
optimizedWaves: OptimizedWave[];
|
|
24
|
-
/** Optimization decisions */
|
|
25
|
-
decisions: OptimizationDecision[];
|
|
26
|
-
/** Statistics */
|
|
27
|
-
stats: OptimizationStats;
|
|
28
|
-
};
|
|
29
|
-
/**
|
|
30
|
-
* Optimized wave with test information
|
|
31
|
-
*/
|
|
32
|
-
export type OptimizedWave = Wave & {
|
|
33
|
-
/** Test classes included in this wave */
|
|
34
|
-
testClasses: NodeId[];
|
|
35
|
-
/** Code classes in this wave */
|
|
36
|
-
codeClasses: NodeId[];
|
|
37
|
-
/** Triggers in this wave */
|
|
38
|
-
triggers: NodeId[];
|
|
39
|
-
/** Needs test execution */
|
|
40
|
-
needsTests: boolean;
|
|
41
|
-
/** Estimated test coverage % */
|
|
42
|
-
estimatedCoverage: number;
|
|
43
|
-
};
|
|
44
|
-
/**
|
|
45
|
-
* Optimization decision
|
|
46
|
-
*/
|
|
47
|
-
export type OptimizationDecision = {
|
|
48
|
-
/** Wave number */
|
|
49
|
-
waveNumber: number;
|
|
50
|
-
/** Decision type */
|
|
51
|
-
type: 'include-tests' | 'skip-tests' | 'sync-tests';
|
|
52
|
-
/** Reason for decision */
|
|
53
|
-
reason: string;
|
|
54
|
-
/** Tests affected */
|
|
55
|
-
testsAffected: number;
|
|
56
|
-
};
|
|
57
|
-
/**
|
|
58
|
-
* Optimization statistics
|
|
59
|
-
*/
|
|
60
|
-
export type OptimizationStats = {
|
|
61
|
-
/** Total waves */
|
|
62
|
-
totalWaves: number;
|
|
63
|
-
/** Waves with tests */
|
|
64
|
-
wavesWithTests: number;
|
|
65
|
-
/** Waves without tests */
|
|
66
|
-
wavesWithoutTests: number;
|
|
67
|
-
/** Total test classes added */
|
|
68
|
-
totalTestsAdded: number;
|
|
69
|
-
/** Estimated time saved (seconds) */
|
|
70
|
-
timeSaved: number;
|
|
71
|
-
};
|
|
72
|
-
/**
|
|
73
|
-
* Optimizer options
|
|
74
|
-
*/
|
|
75
|
-
export type OptimizerOptions = {
|
|
76
|
-
/** Always run all tests (disable optimization) */
|
|
77
|
-
alwaysRunAllTests?: boolean;
|
|
78
|
-
/** Minimum test coverage required (0-100) */
|
|
79
|
-
minCoverageRequired?: number;
|
|
80
|
-
/** Include related tests (not just direct) */
|
|
81
|
-
includeRelatedTests?: boolean;
|
|
82
|
-
};
|
|
15
|
+
import type { OptimizerOptions, OptimizedWave, TestOptimizationResult } from './test-optimizer-model.js';
|
|
16
|
+
export type { OptimizerOptions, OptimizationDecision, OptimizationStats, OptimizedWave, TestOptimizationResult, } from './test-optimizer-model.js';
|
|
83
17
|
/**
|
|
84
18
|
* Test Optimizer
|
|
85
19
|
*
|
|
@@ -114,42 +48,8 @@ export declare class TestOptimizer {
|
|
|
114
48
|
optimizeTests(waves: Wave[]): TestOptimizationResult;
|
|
115
49
|
private getPolicy;
|
|
116
50
|
private createOptimizationPlanningState;
|
|
117
|
-
private analyzeWave;
|
|
118
51
|
private createWaveTestPlan;
|
|
119
52
|
private createOptimizedWave;
|
|
120
|
-
private collectOptimizationDecisions;
|
|
121
|
-
/**
|
|
122
|
-
* Collect all test classes from all waves
|
|
123
|
-
*/
|
|
124
|
-
private collectAllTestClasses;
|
|
125
|
-
/**
|
|
126
|
-
* Get code classes (non-test Apex classes)
|
|
127
|
-
*/
|
|
128
|
-
private getCodeClasses;
|
|
129
|
-
/**
|
|
130
|
-
* @ac US-040-AC-4: Ensure trigger tests are included
|
|
131
|
-
*/
|
|
132
|
-
private getTriggers;
|
|
133
|
-
/**
|
|
134
|
-
* Check if component is a test class
|
|
135
|
-
*/
|
|
136
|
-
private isTestClass;
|
|
137
|
-
/**
|
|
138
|
-
* Sync test classes with production classes
|
|
139
|
-
*/
|
|
140
|
-
private syncTestClasses;
|
|
141
|
-
private matchTestClasses;
|
|
142
|
-
/**
|
|
143
|
-
* @ac US-040-AC-5: Calculate test coverage per wave
|
|
144
|
-
*/
|
|
145
|
-
private estimateCoverage;
|
|
146
|
-
private scoreEstimatedCoverage;
|
|
147
|
-
/**
|
|
148
|
-
* Calculate optimization statistics
|
|
149
|
-
*/
|
|
150
|
-
private calculateStats;
|
|
151
|
-
private collectWaveTestTotals;
|
|
152
|
-
private calculateTimeSaved;
|
|
153
53
|
/**
|
|
154
54
|
* @ac US-040-AC-6: Report test optimization savings
|
|
155
55
|
*/
|
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
* @issue #40
|
|
13
13
|
*/
|
|
14
14
|
import { getLogger } from '../utils/logger.js';
|
|
15
|
+
import { analyzeWave, collectAllTestClasses } from './test-optimizer-discovery.js';
|
|
16
|
+
import { matchTestClasses } from './test-optimizer-matching.js';
|
|
17
|
+
import { calculateStats, collectOptimizationDecisions, scoreEstimatedCoverage } from './test-optimizer-scoring.js';
|
|
15
18
|
const logger = getLogger('TestOptimizer');
|
|
16
19
|
/**
|
|
17
20
|
* Test Optimizer
|
|
@@ -58,8 +61,8 @@ export class TestOptimizer {
|
|
|
58
61
|
const startTime = Date.now();
|
|
59
62
|
const planningState = this.createOptimizationPlanningState(waves);
|
|
60
63
|
const optimizedWaves = planningState.waveContexts.map((context, index) => this.createOptimizedWave(context, planningState.wavePlans[index]));
|
|
61
|
-
const decisions =
|
|
62
|
-
const stats =
|
|
64
|
+
const decisions = collectOptimizationDecisions(planningState.wavePlans);
|
|
65
|
+
const stats = calculateStats(optimizedWaves, planningState.allTestClasses.length);
|
|
63
66
|
const duration = Date.now() - startTime;
|
|
64
67
|
logger.info('Test optimization completed', {
|
|
65
68
|
totalWaves: stats.totalWaves,
|
|
@@ -84,8 +87,8 @@ export class TestOptimizer {
|
|
|
84
87
|
}
|
|
85
88
|
createOptimizationPlanningState(waves) {
|
|
86
89
|
const policy = this.getPolicy();
|
|
87
|
-
const allTestClasses =
|
|
88
|
-
const waveContexts = waves.map((wave) =>
|
|
90
|
+
const allTestClasses = collectAllTestClasses(waves);
|
|
91
|
+
const waveContexts = waves.map((wave) => analyzeWave(wave));
|
|
89
92
|
const wavePlans = waveContexts.map((context) => this.createWaveTestPlan(context, allTestClasses, policy));
|
|
90
93
|
return {
|
|
91
94
|
allTestClasses,
|
|
@@ -93,18 +96,6 @@ export class TestOptimizer {
|
|
|
93
96
|
wavePlans,
|
|
94
97
|
};
|
|
95
98
|
}
|
|
96
|
-
analyzeWave(wave) {
|
|
97
|
-
const codeClasses = this.getCodeClasses(wave);
|
|
98
|
-
const triggers = this.getTriggers(wave);
|
|
99
|
-
return {
|
|
100
|
-
waveNumber: wave.number,
|
|
101
|
-
waveComponents: wave.components,
|
|
102
|
-
waveMetadata: wave.metadata,
|
|
103
|
-
codeClasses,
|
|
104
|
-
triggers,
|
|
105
|
-
needsTests: codeClasses.length > 0 || triggers.length > 0,
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
99
|
createWaveTestPlan(context, allTestClasses, policy) {
|
|
109
100
|
if (policy.alwaysRunAllTests) {
|
|
110
101
|
return {
|
|
@@ -130,10 +121,10 @@ export class TestOptimizer {
|
|
|
130
121
|
},
|
|
131
122
|
};
|
|
132
123
|
}
|
|
133
|
-
const testClasses =
|
|
124
|
+
const testClasses = matchTestClasses(context, allTestClasses, policy);
|
|
134
125
|
return {
|
|
135
126
|
testClasses,
|
|
136
|
-
estimatedCoverage:
|
|
127
|
+
estimatedCoverage: scoreEstimatedCoverage(context, testClasses),
|
|
137
128
|
decision: {
|
|
138
129
|
waveNumber: context.waveNumber,
|
|
139
130
|
type: 'sync-tests',
|
|
@@ -154,142 +145,6 @@ export class TestOptimizer {
|
|
|
154
145
|
estimatedCoverage: plan.estimatedCoverage,
|
|
155
146
|
};
|
|
156
147
|
}
|
|
157
|
-
collectOptimizationDecisions(wavePlans) {
|
|
158
|
-
return wavePlans.map((plan) => plan.decision);
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Collect all test classes from all waves
|
|
162
|
-
*/
|
|
163
|
-
collectAllTestClasses(waves) {
|
|
164
|
-
const testClasses = new Set();
|
|
165
|
-
for (const wave of waves) {
|
|
166
|
-
for (const component of wave.components) {
|
|
167
|
-
if (this.isTestClass(component)) {
|
|
168
|
-
testClasses.add(component);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
return Array.from(testClasses);
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* Get code classes (non-test Apex classes)
|
|
176
|
-
*/
|
|
177
|
-
getCodeClasses(wave) {
|
|
178
|
-
return wave.components.filter((c) => c.startsWith('ApexClass:') && !this.isTestClass(c));
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* @ac US-040-AC-4: Ensure trigger tests are included
|
|
182
|
-
*/
|
|
183
|
-
getTriggers(wave) {
|
|
184
|
-
return wave.components.filter((c) => c.startsWith('ApexTrigger:'));
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Check if component is a test class
|
|
188
|
-
*/
|
|
189
|
-
isTestClass(component) {
|
|
190
|
-
return (component.startsWith('ApexClass:') &&
|
|
191
|
-
(component.toLowerCase().includes('test') || component.toLowerCase().endsWith('_test')));
|
|
192
|
-
}
|
|
193
|
-
/**
|
|
194
|
-
* Sync test classes with production classes
|
|
195
|
-
*/
|
|
196
|
-
syncTestClasses(codeClasses, triggers, allTestClasses) {
|
|
197
|
-
const matchedTests = new Set();
|
|
198
|
-
// Match tests to code classes
|
|
199
|
-
for (const codeClass of codeClasses) {
|
|
200
|
-
const className = codeClass.split(':')[1];
|
|
201
|
-
for (const testClass of allTestClasses) {
|
|
202
|
-
const testName = testClass.split(':')[1].toLowerCase();
|
|
203
|
-
const codeName = className.toLowerCase();
|
|
204
|
-
// Match patterns:
|
|
205
|
-
// - AccountService → AccountServiceTest
|
|
206
|
-
// - AccountService → TestAccountService
|
|
207
|
-
// - AccountService → AccountService_Test
|
|
208
|
-
if (testName.includes(codeName) || codeName.includes(testName.replace('test', ''))) {
|
|
209
|
-
matchedTests.add(testClass);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
// Match tests to triggers
|
|
214
|
-
for (const trigger of triggers) {
|
|
215
|
-
const triggerName = trigger.split(':')[1];
|
|
216
|
-
for (const testClass of allTestClasses) {
|
|
217
|
-
const testName = testClass.split(':')[1].toLowerCase();
|
|
218
|
-
const trgName = triggerName.toLowerCase();
|
|
219
|
-
// Match patterns:
|
|
220
|
-
// - AccountTrigger → AccountTriggerTest
|
|
221
|
-
// - AccountTrigger → TestAccountTrigger
|
|
222
|
-
if (testName.includes(trgName) || testName.includes('trigger')) {
|
|
223
|
-
matchedTests.add(testClass);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
// If no tests matched and we have code, include related tests
|
|
228
|
-
if (matchedTests.size === 0 && this.options.includeRelatedTests) {
|
|
229
|
-
// Include a reasonable subset (e.g., first 10 test classes)
|
|
230
|
-
for (let i = 0; i < Math.min(10, allTestClasses.length); i++) {
|
|
231
|
-
matchedTests.add(allTestClasses[i]);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
return Array.from(matchedTests);
|
|
235
|
-
}
|
|
236
|
-
matchTestClasses(context, allTestClasses, policy) {
|
|
237
|
-
if (policy.includeRelatedTests !== this.options.includeRelatedTests) {
|
|
238
|
-
return this.syncTestClasses(context.codeClasses, context.triggers, allTestClasses);
|
|
239
|
-
}
|
|
240
|
-
return this.syncTestClasses(context.codeClasses, context.triggers, allTestClasses);
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* @ac US-040-AC-5: Calculate test coverage per wave
|
|
244
|
-
*/
|
|
245
|
-
estimateCoverage(codeClassCount, testClassCount) {
|
|
246
|
-
if (codeClassCount === 0)
|
|
247
|
-
return 100;
|
|
248
|
-
if (testClassCount === 0)
|
|
249
|
-
return 0;
|
|
250
|
-
// Simple heuristic: assume each test class covers ~75% of one class
|
|
251
|
-
const coverage = Math.min(100, (testClassCount / codeClassCount) * 75);
|
|
252
|
-
return Math.round(coverage);
|
|
253
|
-
}
|
|
254
|
-
scoreEstimatedCoverage(context, testClasses) {
|
|
255
|
-
return this.estimateCoverage(context.codeClasses.length, testClasses.length);
|
|
256
|
-
}
|
|
257
|
-
/**
|
|
258
|
-
* Calculate optimization statistics
|
|
259
|
-
*/
|
|
260
|
-
calculateStats(optimizedWaves, totalAvailableTests) {
|
|
261
|
-
const totals = this.collectWaveTestTotals(optimizedWaves);
|
|
262
|
-
const timeSaved = this.calculateTimeSaved(optimizedWaves.length, totalAvailableTests, totals.totalTestsAdded);
|
|
263
|
-
return {
|
|
264
|
-
totalWaves: optimizedWaves.length,
|
|
265
|
-
wavesWithTests: totals.wavesWithTests,
|
|
266
|
-
wavesWithoutTests: totals.wavesWithoutTests,
|
|
267
|
-
totalTestsAdded: totals.totalTestsAdded,
|
|
268
|
-
timeSaved,
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
collectWaveTestTotals(optimizedWaves) {
|
|
272
|
-
let wavesWithTests = 0;
|
|
273
|
-
let wavesWithoutTests = 0;
|
|
274
|
-
let totalTestsAdded = 0;
|
|
275
|
-
for (const wave of optimizedWaves) {
|
|
276
|
-
if (wave.testClasses.length > 0) {
|
|
277
|
-
wavesWithTests++;
|
|
278
|
-
totalTestsAdded += wave.testClasses.length;
|
|
279
|
-
continue;
|
|
280
|
-
}
|
|
281
|
-
wavesWithoutTests++;
|
|
282
|
-
}
|
|
283
|
-
return {
|
|
284
|
-
wavesWithTests,
|
|
285
|
-
wavesWithoutTests,
|
|
286
|
-
totalTestsAdded,
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
calculateTimeSaved(totalWaves, totalAvailableTests, totalTestsAdded) {
|
|
290
|
-
const testsSkipped = totalWaves * totalAvailableTests - totalTestsAdded;
|
|
291
|
-
return testsSkipped * 5;
|
|
292
|
-
}
|
|
293
148
|
/**
|
|
294
149
|
* @ac US-040-AC-6: Report test optimization savings
|
|
295
150
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-optimizer.js","sourceRoot":"","sources":["../../src/waves/test-optimizer.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"test-optimizer.js","sourceRoot":"","sources":["../../src/waves/test-optimizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -117,21 +117,10 @@ export declare class WaveBuilder {
|
|
|
117
117
|
generateWaves(graph: DependencyGraph): WaveResult;
|
|
118
118
|
private createPlacementState;
|
|
119
119
|
private getPlacementPolicy;
|
|
120
|
-
private selectWaveCandidates;
|
|
121
|
-
private planTopologyStage;
|
|
122
|
-
private createWaveChunks;
|
|
123
120
|
private createWave;
|
|
124
121
|
private markProcessed;
|
|
125
|
-
private updateInDegreeForPlacedCandidates;
|
|
126
122
|
private resolveCircularWave;
|
|
127
123
|
private compareWavePriority;
|
|
128
|
-
private createWavePriorityProfile;
|
|
129
|
-
private getDependencyRiskProfile;
|
|
130
|
-
private assembleWaveMetadata;
|
|
131
|
-
/**
|
|
132
|
-
* Calculate wave statistics
|
|
133
|
-
*/
|
|
134
|
-
private calculateStats;
|
|
135
124
|
/**
|
|
136
125
|
* Get wave by number
|
|
137
126
|
*/
|