testchimp-runner-core 0.1.21 → 0.1.22
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/dist/execution-service.d.ts.map +1 -1
- package/dist/execution-service.js +166 -77
- package/dist/execution-service.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/pom-denormalizer.d.ts +44 -0
- package/dist/utils/pom-denormalizer.d.ts.map +1 -0
- package/dist/utils/pom-denormalizer.js +754 -0
- package/dist/utils/pom-denormalizer.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution-service.d.ts","sourceRoot":"","sources":["../src/execution-service.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAE3B,sBAAsB,EACtB,uBAAuB,EAKvB,wBAAwB,EACxB,yBAAyB,EAG1B,MAAM,SAAS,CAAC;AAKjB,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"execution-service.d.ts","sourceRoot":"","sources":["../src/execution-service.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAE3B,sBAAsB,EACtB,uBAAuB,EAKvB,wBAAwB,EACxB,yBAAyB,EAG1B,MAAM,SAAS,CAAC;AAKjB,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAY3C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAA+C,MAAM,qBAAqB,CAAC;AAmbpG;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,gBAAgB,CAAC,CAAmB;IAC5C,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,uBAAuB,CAAS;IACxC,OAAO,CAAC,gBAAgB,CAAgC;IACxD,OAAO,CAAC,MAAM,CAAC,CAA8D;IAC7E,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,cAAc,CAAkB;IAExC;;OAEG;IACH,aAAa;gBAKX,UAAU,CAAC,EAAE,UAAU,EACvB,UAAU,CAAC,EAAE,MAAM,EACnB,uBAAuB,GAAE,MAAW,EACpC,WAAW,CAAC,EAAE,WAAW,EACzB,gBAAgB,CAAC,EAAE,gBAAgB;IA8BrC;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,MAAM,KAAK,IAAI,GAAG,IAAI;IAKpF;;OAEG;IACH,OAAO,CAAC,GAAG;IASX,OAAO,CAAC,WAAW;IAanB;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC;;;OAGG;IACH,aAAa,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI;IAQ3C;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAkBtF;;;;;;;;;;OAUG;IACG,cAAc,CAClB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,GAAG,EACT,OAAO,CAAC,EAAE,GAAG,EACb,cAAc,CAAC,EAAE,GAAG,EACpB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAuBhB;;OAEG;YACW,qBAAqB;IAmBnC;;OAEG;IACG,gBAAgB,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,2BAA2B,CAAC;IAgCjG;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAsC7B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B;;OAEG;IACH,OAAO,IAAI,OAAO;IAIlB;;;;OAIG;YACW,+BAA+B;IAm2B7C;;;OAGG;YACW,iBAAiB;YAiGjB,UAAU;YAoMV,eAAe;YAsKf,oBAAoB;YAiBpB,eAAe;IAuC7B,OAAO,CAAC,qBAAqB;IAK7B;;OAEG;YACW,iBAAiB;IAI/B;;;;OAIG;IACG,WAAW,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAsxBxF;;;;;OAKG;YACW,WAAW;CAoI1B"}
|
|
@@ -51,6 +51,7 @@ const import_utils_1 = require("./utils/import-utils");
|
|
|
51
51
|
const initialization_code_utils_1 = require("./utils/initialization-code-utils");
|
|
52
52
|
const script_parser_utils_1 = require("./utils/script-parser-utils");
|
|
53
53
|
const script_generator_utils_1 = require("./utils/script-generator-utils");
|
|
54
|
+
const pom_denormalizer_1 = require("./utils/pom-denormalizer");
|
|
54
55
|
const progress_reporter_1 = require("./progress-reporter");
|
|
55
56
|
const backend_proxy_llm_provider_1 = require("./providers/backend-proxy-llm-provider");
|
|
56
57
|
const build_info_1 = require("./build-info");
|
|
@@ -645,12 +646,71 @@ class ExecutionService {
|
|
|
645
646
|
* Variables persist across steps without re-execution
|
|
646
647
|
*/
|
|
647
648
|
async executeStepsInPersistentContext(steps, page, browser, browserContext, options, sharedContext) {
|
|
648
|
-
this.log(`[executeStepsInPersistentContext] Called with ${steps.length} steps, mode=${options.mode}, originalScript=${!!options.originalScript}, tempDir=${!!options.tempDir}, sharedContext=${!!sharedContext}`);
|
|
649
|
+
this.log(`[executeStepsInPersistentContext] Called with ${steps.length} steps, mode=${options.mode}, originalScript=${!!options.originalScript}, tempDir=${!!options.tempDir}, sharedContext=${!!sharedContext}, runPomDenormalized=${!!options.runPomDenormalized}`);
|
|
649
650
|
const { expect, test } = require('@playwright/test');
|
|
650
651
|
const { ai } = require('ai-wright');
|
|
651
652
|
// Use shared context if provided, otherwise create new context
|
|
652
653
|
const persistentContext = sharedContext || new PersistentExecutionContext(page, expect, test, ai, browser, browserContext, options.tempDir);
|
|
653
654
|
const isSharedContext = !!sharedContext;
|
|
655
|
+
const resolvedTestFileDir = (() => {
|
|
656
|
+
if (!options.tempDir) {
|
|
657
|
+
return undefined;
|
|
658
|
+
}
|
|
659
|
+
if (options.testFolderPath && options.testFolderPath.length > 0) {
|
|
660
|
+
return path.join(options.tempDir, ...options.testFolderPath);
|
|
661
|
+
}
|
|
662
|
+
const defaultDir = path.join(options.tempDir, 'tests');
|
|
663
|
+
try {
|
|
664
|
+
const testsDir = defaultDir;
|
|
665
|
+
const fs = require('fs');
|
|
666
|
+
if (!fs.existsSync(testsDir)) {
|
|
667
|
+
this.log(`Tests directory ${testsDir} does not exist, using default for module resolution`, 'warn');
|
|
668
|
+
return defaultDir;
|
|
669
|
+
}
|
|
670
|
+
const findTestFile = (dir, depth = 0, maxDepth = 10) => {
|
|
671
|
+
if (depth > maxDepth) {
|
|
672
|
+
return null;
|
|
673
|
+
}
|
|
674
|
+
try {
|
|
675
|
+
const files = fs.readdirSync(dir);
|
|
676
|
+
for (const file of files) {
|
|
677
|
+
const fullPath = path.join(dir, file);
|
|
678
|
+
try {
|
|
679
|
+
const stat = fs.statSync(fullPath);
|
|
680
|
+
if (stat.isDirectory()) {
|
|
681
|
+
const found = findTestFile(fullPath, depth + 1, maxDepth);
|
|
682
|
+
if (found)
|
|
683
|
+
return found;
|
|
684
|
+
}
|
|
685
|
+
else if (file.endsWith('.spec.ts') || file.endsWith('.spec.js') ||
|
|
686
|
+
file.endsWith('.test.ts') || file.endsWith('.test.js')) {
|
|
687
|
+
return fullPath;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
catch (statError) {
|
|
691
|
+
continue;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
catch (e) {
|
|
696
|
+
return null;
|
|
697
|
+
}
|
|
698
|
+
return null;
|
|
699
|
+
};
|
|
700
|
+
const testFilePath = findTestFile(testsDir);
|
|
701
|
+
if (testFilePath) {
|
|
702
|
+
const testFileDir = path.dirname(testFilePath);
|
|
703
|
+
this.log(`Found test file at ${testFilePath}, using directory ${testFileDir} for module resolution`);
|
|
704
|
+
return testFileDir;
|
|
705
|
+
}
|
|
706
|
+
this.log(`No test file found in ${testsDir}, using tests directory for module resolution`, 'warn');
|
|
707
|
+
return testsDir;
|
|
708
|
+
}
|
|
709
|
+
catch (searchError) {
|
|
710
|
+
this.log(`Could not search for test file: ${searchError.message}, using tests directory for module resolution`, 'warn');
|
|
711
|
+
return defaultDir;
|
|
712
|
+
}
|
|
713
|
+
})();
|
|
654
714
|
// Extract and execute imports from original script if provided
|
|
655
715
|
this.log(`[executeStepsInPersistentContext] Checking imports: originalScript=${!!options.originalScript}, tempDir=${!!options.tempDir}`);
|
|
656
716
|
if (options.originalScript && options.tempDir) {
|
|
@@ -664,60 +724,7 @@ class ExecutionService {
|
|
|
664
724
|
// Execute imports with proper context - find the actual test file path
|
|
665
725
|
// All tests are within the tests folder
|
|
666
726
|
// We search for test files in tempDir/tests directory tree
|
|
667
|
-
|
|
668
|
-
try {
|
|
669
|
-
const fs = require('fs');
|
|
670
|
-
const testsDir = path.join(options.tempDir, 'tests');
|
|
671
|
-
// Check if tests directory exists
|
|
672
|
-
if (!fs.existsSync(testsDir)) {
|
|
673
|
-
this.log(`Tests directory ${testsDir} does not exist, using default for module resolution`, 'warn');
|
|
674
|
-
}
|
|
675
|
-
else {
|
|
676
|
-
// Recursive search with depth limit to prevent infinite loops
|
|
677
|
-
const findTestFile = (dir, depth = 0, maxDepth = 10) => {
|
|
678
|
-
if (depth > maxDepth) {
|
|
679
|
-
return null; // Prevent infinite recursion
|
|
680
|
-
}
|
|
681
|
-
try {
|
|
682
|
-
const files = fs.readdirSync(dir);
|
|
683
|
-
for (const file of files) {
|
|
684
|
-
const fullPath = path.join(dir, file);
|
|
685
|
-
try {
|
|
686
|
-
const stat = fs.statSync(fullPath);
|
|
687
|
-
if (stat.isDirectory()) {
|
|
688
|
-
const found = findTestFile(fullPath, depth + 1, maxDepth);
|
|
689
|
-
if (found)
|
|
690
|
-
return found;
|
|
691
|
-
}
|
|
692
|
-
else if (file.endsWith('.spec.ts') || file.endsWith('.spec.js') ||
|
|
693
|
-
file.endsWith('.test.ts') || file.endsWith('.test.js')) {
|
|
694
|
-
return fullPath; // Found a test file
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
catch (statError) {
|
|
698
|
-
// Skip files we can't stat
|
|
699
|
-
continue;
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
catch (e) {
|
|
704
|
-
// Continue searching in other directories
|
|
705
|
-
}
|
|
706
|
-
return null;
|
|
707
|
-
};
|
|
708
|
-
const testFilePath = findTestFile(testsDir);
|
|
709
|
-
if (testFilePath) {
|
|
710
|
-
testFileDir = path.dirname(testFilePath);
|
|
711
|
-
this.log(`Found test file at ${testFilePath}, using directory ${testFileDir} for module resolution`);
|
|
712
|
-
}
|
|
713
|
-
else {
|
|
714
|
-
this.log(`No test file found in ${testsDir}, using tests directory for module resolution`, 'warn');
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
catch (searchError) {
|
|
719
|
-
this.log(`Could not search for test file: ${searchError.message}, using tests directory for module resolution`, 'warn');
|
|
720
|
-
}
|
|
727
|
+
const testFileDir = resolvedTestFileDir || path.join(options.tempDir, 'tests');
|
|
721
728
|
// Store test file directory in context for module resolution
|
|
722
729
|
persistentContext.setTestFileDir(testFileDir);
|
|
723
730
|
this.log(`Module resolution context: testFileDir=${testFileDir}, tempDir=${options.tempDir}`);
|
|
@@ -963,6 +970,78 @@ class ExecutionService {
|
|
|
963
970
|
}
|
|
964
971
|
return { success: false, error: 'No script or steps provided for execution' };
|
|
965
972
|
}
|
|
973
|
+
if (options.runPomDenormalized && options.originalScript) {
|
|
974
|
+
const originalCount = allStatements.length;
|
|
975
|
+
const originalStepIds = allStatements
|
|
976
|
+
.map((stmt, idx) => ({ idx, stepId: stmt.stepId, code: stmt.code.substring(0, 50) }))
|
|
977
|
+
.filter(s => s.stepId);
|
|
978
|
+
this.log(`[executeStepsInPersistentContext] Starting POM denormalization: ${originalCount} original statements, ` +
|
|
979
|
+
`${originalStepIds.length} with stepIds`);
|
|
980
|
+
// Convert to ScriptStep[] for denormalization
|
|
981
|
+
const scriptSteps = allStatements.map(stmt => ({
|
|
982
|
+
code: stmt.code,
|
|
983
|
+
description: stmt.intentComment || '',
|
|
984
|
+
id: stmt.stepId, // stepId may not exist for InitializationCodeUtils results
|
|
985
|
+
isVariableDeclaration: stmt.isVariableDeclaration
|
|
986
|
+
}));
|
|
987
|
+
// Denormalize POM calls
|
|
988
|
+
const denormalizedSteps = pom_denormalizer_1.PomDenormalizer.denormalizePomSteps(scriptSteps, {
|
|
989
|
+
originalScript: options.originalScript,
|
|
990
|
+
tempDir: options.tempDir || '',
|
|
991
|
+
testFileDir: resolvedTestFileDir,
|
|
992
|
+
logger: (msg, level) => this.log(msg, level)
|
|
993
|
+
});
|
|
994
|
+
const denormalizedCount = denormalizedSteps.length;
|
|
995
|
+
const denormalizedStepIds = denormalizedSteps
|
|
996
|
+
.map((step, idx) => ({ idx, stepId: step.id, isVar: step.isVariableDeclaration, code: step.code.substring(0, 50) }))
|
|
997
|
+
.filter(s => s.stepId && !s.isVar);
|
|
998
|
+
this.log(`[executeStepsInPersistentContext] Denormalization complete: ${originalCount} -> ${denormalizedCount} statements ` +
|
|
999
|
+
`(${denormalizedCount - originalCount > 0 ? '+' : ''}${denormalizedCount - originalCount}), ` +
|
|
1000
|
+
`${denormalizedStepIds.length} non-variable steps with stepIds`);
|
|
1001
|
+
if (denormalizedStepIds.length > 0 && this.log) {
|
|
1002
|
+
const stepIdPreview = denormalizedStepIds.slice(0, 5).map(s => `idx=${s.idx} stepId=${s.stepId?.substring(0, 16)}...`).join(', ');
|
|
1003
|
+
this.log(`[executeStepsInPersistentContext] Sample denormalized stepIds: ${stepIdPreview}${denormalizedStepIds.length > 5 ? '...' : ''}`);
|
|
1004
|
+
}
|
|
1005
|
+
// Convert back to inline type format
|
|
1006
|
+
allStatements = denormalizedSteps.map(step => ({
|
|
1007
|
+
code: step.code,
|
|
1008
|
+
isVariableDeclaration: step.isVariableDeclaration || false,
|
|
1009
|
+
intentComment: step.description !== step.code ? step.description : undefined,
|
|
1010
|
+
screenStateAnnotation: undefined,
|
|
1011
|
+
stepId: step.id
|
|
1012
|
+
}));
|
|
1013
|
+
// Verify stepId preservation
|
|
1014
|
+
const preservedStepIds = allStatements
|
|
1015
|
+
.map((stmt, idx) => ({ idx, stepId: stmt.stepId, isVar: stmt.isVariableDeclaration }))
|
|
1016
|
+
.filter(s => s.stepId && !s.isVar);
|
|
1017
|
+
this.log(`[executeStepsInPersistentContext] StepId preservation: ${preservedStepIds.length} non-variable statements have stepIds ` +
|
|
1018
|
+
`(expected: ${denormalizedStepIds.length})`);
|
|
1019
|
+
// Verify stepId matching between denormalized and preserved
|
|
1020
|
+
if (preservedStepIds.length !== denormalizedStepIds.length) {
|
|
1021
|
+
this.log(`[executeStepsInPersistentContext] WARNING: StepId count mismatch! ` +
|
|
1022
|
+
`Denormalized: ${denormalizedStepIds.length}, Preserved: ${preservedStepIds.length}`, 'warn');
|
|
1023
|
+
}
|
|
1024
|
+
else {
|
|
1025
|
+
// Check if stepIds match
|
|
1026
|
+
let matchCount = 0;
|
|
1027
|
+
for (let i = 0; i < Math.min(denormalizedStepIds.length, preservedStepIds.length); i++) {
|
|
1028
|
+
const denorm = denormalizedStepIds[i];
|
|
1029
|
+
const preserved = preservedStepIds.find(p => p.idx === denorm.idx);
|
|
1030
|
+
if (preserved && preserved.stepId === denorm.stepId) {
|
|
1031
|
+
matchCount++;
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
this.log(`[executeStepsInPersistentContext] StepId matching: ${matchCount}/${Math.min(denormalizedStepIds.length, preservedStepIds.length)} stepIds match`);
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
else {
|
|
1038
|
+
if (!options.runPomDenormalized) {
|
|
1039
|
+
this.log(`[executeStepsInPersistentContext] POM denormalization skipped: runPomDenormalized=false`);
|
|
1040
|
+
}
|
|
1041
|
+
else if (!options.originalScript) {
|
|
1042
|
+
this.log(`[executeStepsInPersistentContext] POM denormalization skipped: originalScript not provided`);
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
966
1045
|
// Build stepId -> statement index map before execution
|
|
967
1046
|
const statementIndexByStepId = new Map();
|
|
968
1047
|
for (let idx = 0; idx < allStatements.length; idx++) {
|
|
@@ -1079,14 +1158,6 @@ class ExecutionService {
|
|
|
1079
1158
|
let shouldSkipStep = false;
|
|
1080
1159
|
if (this.progressReporter?.beforeStepStart && options.jobId) {
|
|
1081
1160
|
const { description, baseStepId, stepId, runNumber } = stepMeta;
|
|
1082
|
-
// Log stepId usage for debugging
|
|
1083
|
-
if (stmt.stepId) {
|
|
1084
|
-
const stepIdPreview = stmt.stepId.length > 16 ? `${stmt.stepId.substring(0, 16)}...` : stmt.stepId;
|
|
1085
|
-
this.log(`[stepId] beforeStepStart: Using hash-based stepId: ${stepIdPreview} (stepNumber: ${stepNumber}, run: ${runNumber})`);
|
|
1086
|
-
}
|
|
1087
|
-
else {
|
|
1088
|
-
this.log(`[stepId] beforeStepStart: WARNING: No hash-based stepId, using fallback: ${baseStepId} (stepNumber: ${stepNumber}, run: ${runNumber})`);
|
|
1089
|
-
}
|
|
1090
1161
|
const beforeStepResult = await this.progressReporter.beforeStepStart({
|
|
1091
1162
|
stepId,
|
|
1092
1163
|
stepNumber,
|
|
@@ -1401,12 +1472,18 @@ class ExecutionService {
|
|
|
1401
1472
|
}
|
|
1402
1473
|
// Execute script in persistent context (STOP on first error)
|
|
1403
1474
|
// Pre-parsed steps from consumer (if any) will be ignored - AST extracts from script
|
|
1475
|
+
this.log(`[runExactly] Calling executeStepsInPersistentContext (existing browser): ` +
|
|
1476
|
+
`runPomDenormalized=${request.runPomDenormalized}, ` +
|
|
1477
|
+
`originalScript=${!!request.script} (length: ${request.script?.length || 0}), ` +
|
|
1478
|
+
`tempDir=${!!request.tempDir}`);
|
|
1404
1479
|
const result = await this.executeStepsInPersistentContext(request.steps || [], // Pre-parsed steps (optional, for backward compatibility)
|
|
1405
1480
|
page, browser, context, {
|
|
1406
1481
|
mode: 'RUN_EXACTLY',
|
|
1407
1482
|
jobId: request.jobId,
|
|
1408
1483
|
tempDir: request.tempDir,
|
|
1409
|
-
originalScript: request.script // AST will extract statements from this
|
|
1484
|
+
originalScript: request.script, // AST will extract statements from this
|
|
1485
|
+
testFolderPath: request.testFolderPath,
|
|
1486
|
+
runPomDenormalized: request.runPomDenormalized
|
|
1410
1487
|
});
|
|
1411
1488
|
// LIFECYCLE: afterEndTest
|
|
1412
1489
|
if (this.progressReporter?.afterEndTest) {
|
|
@@ -1454,12 +1531,18 @@ class ExecutionService {
|
|
|
1454
1531
|
}
|
|
1455
1532
|
// Execute script in persistent context (STOP on first error)
|
|
1456
1533
|
// Pre-parsed steps from consumer (if any) will be ignored - AST extracts from script
|
|
1534
|
+
this.log(`[runExactly] Calling executeStepsInPersistentContext (new browser, attempt ${attempt}): ` +
|
|
1535
|
+
`runPomDenormalized=${request.runPomDenormalized}, ` +
|
|
1536
|
+
`originalScript=${!!request.script} (length: ${request.script?.length || 0}), ` +
|
|
1537
|
+
`tempDir=${!!request.tempDir}`);
|
|
1457
1538
|
const result = await this.executeStepsInPersistentContext(request.steps || [], // Pre-parsed steps (optional, for backward compatibility)
|
|
1458
1539
|
page, browser, context, {
|
|
1459
1540
|
mode: 'RUN_EXACTLY',
|
|
1460
1541
|
jobId: request.jobId,
|
|
1461
1542
|
tempDir: request.tempDir,
|
|
1462
|
-
originalScript: request.script // AST will extract statements from this
|
|
1543
|
+
originalScript: request.script, // AST will extract statements from this
|
|
1544
|
+
testFolderPath: request.testFolderPath,
|
|
1545
|
+
runPomDenormalized: request.runPomDenormalized
|
|
1463
1546
|
});
|
|
1464
1547
|
// LIFECYCLE: afterEndTest
|
|
1465
1548
|
if (this.progressReporter?.afterEndTest) {
|
|
@@ -1575,7 +1658,9 @@ class ExecutionService {
|
|
|
1575
1658
|
jobId: request.jobId,
|
|
1576
1659
|
model,
|
|
1577
1660
|
tempDir: request.tempDir,
|
|
1578
|
-
originalScript: request.script // Pass original script for import extraction
|
|
1661
|
+
originalScript: request.script, // Pass original script for import extraction
|
|
1662
|
+
testFolderPath: request.testFolderPath,
|
|
1663
|
+
runPomDenormalized: request.runPomDenormalized
|
|
1579
1664
|
});
|
|
1580
1665
|
const updatedSteps = result.updatedSteps || steps;
|
|
1581
1666
|
const allStepsSuccessful = result.success;
|
|
@@ -1886,7 +1971,7 @@ class ExecutionService {
|
|
|
1886
1971
|
this.log(`Executing ${flattened.fileLevelHooks.beforeAll.length} file-level beforeAll hook(s)...`);
|
|
1887
1972
|
try {
|
|
1888
1973
|
for (const hook of flattened.fileLevelHooks.beforeAll) {
|
|
1889
|
-
await this.executeHook(hook.code, page, context, browser, request.tempDir, originalScript, fileLevelContext || undefined, hook);
|
|
1974
|
+
await this.executeHook(hook.code, page, context, browser, request.tempDir, originalScript, request.testFolderPath, request.runPomDenormalized, fileLevelContext || undefined, hook);
|
|
1890
1975
|
}
|
|
1891
1976
|
this.log('File-level beforeAll hooks executed successfully');
|
|
1892
1977
|
}
|
|
@@ -1957,7 +2042,7 @@ class ExecutionService {
|
|
|
1957
2042
|
// Get or create suite context (includes file variables + suite variables)
|
|
1958
2043
|
const suiteContext = await getOrCreateSuiteContext(suitePath, suite.suiteVariables, flattened.fileVariables);
|
|
1959
2044
|
for (const hook of suite.beforeAll) {
|
|
1960
|
-
await this.executeHook(hook.code, page, context, browser, request.tempDir, originalScript, suiteContext, hook);
|
|
2045
|
+
await this.executeHook(hook.code, page, context, browser, request.tempDir, originalScript, request.testFolderPath, request.runPomDenormalized, suiteContext, hook);
|
|
1961
2046
|
}
|
|
1962
2047
|
suiteBeforeAllExecuted.add(suiteKey);
|
|
1963
2048
|
this.log(`Suite-level beforeAll hooks executed for suite: ${suiteDisplayName}`);
|
|
@@ -1982,7 +2067,7 @@ class ExecutionService {
|
|
|
1982
2067
|
this.log(`Executing ${flattened.fileLevelHooks.beforeEach.length} file-level beforeEach hook(s) for test: ${test.fullName}`);
|
|
1983
2068
|
try {
|
|
1984
2069
|
for (const hook of flattened.fileLevelHooks.beforeEach) {
|
|
1985
|
-
const stepsExecuted = await this.executeHook(hook.code, page, context, browser, request.tempDir, originalScript, fileLevelContext || undefined, hook, jobId, testStepCounter);
|
|
2070
|
+
const stepsExecuted = await this.executeHook(hook.code, page, context, browser, request.tempDir, originalScript, request.testFolderPath, request.runPomDenormalized, fileLevelContext || undefined, hook, jobId, testStepCounter);
|
|
1986
2071
|
testStepCounter += stepsExecuted;
|
|
1987
2072
|
}
|
|
1988
2073
|
}
|
|
@@ -2000,7 +2085,7 @@ class ExecutionService {
|
|
|
2000
2085
|
// Get or create suite context for this test's suite
|
|
2001
2086
|
const suiteContext = await getOrCreateSuiteContext(testData.suitePath, testData.suiteVariables, flattened.fileVariables);
|
|
2002
2087
|
for (const hook of testData.suiteBeforeEachHooks) {
|
|
2003
|
-
const stepsExecuted = await this.executeHook(hook.code, page, context, browser, request.tempDir, originalScript, suiteContext, hook, jobId, testStepCounter);
|
|
2088
|
+
const stepsExecuted = await this.executeHook(hook.code, page, context, browser, request.tempDir, originalScript, request.testFolderPath, request.runPomDenormalized, suiteContext, hook, jobId, testStepCounter);
|
|
2004
2089
|
testStepCounter += stepsExecuted;
|
|
2005
2090
|
}
|
|
2006
2091
|
}
|
|
@@ -2061,7 +2146,9 @@ class ExecutionService {
|
|
|
2061
2146
|
jobId: jobId,
|
|
2062
2147
|
tempDir: request.tempDir,
|
|
2063
2148
|
originalScript: testScript, // For module resolution (imports)
|
|
2064
|
-
model: request.model
|
|
2149
|
+
model: request.model,
|
|
2150
|
+
testFolderPath: request.testFolderPath,
|
|
2151
|
+
runPomDenormalized: request.runPomDenormalized
|
|
2065
2152
|
}, suiteContext // Pass shared context
|
|
2066
2153
|
);
|
|
2067
2154
|
if (!result.success) {
|
|
@@ -2110,7 +2197,7 @@ class ExecutionService {
|
|
|
2110
2197
|
// Get or create suite context for this test's suite
|
|
2111
2198
|
const suiteContext = await getOrCreateSuiteContext(testData.suitePath, testData.suiteVariables, flattened.fileVariables);
|
|
2112
2199
|
for (const hook of testData.suiteAfterEachHooks) {
|
|
2113
|
-
const stepsExecuted = await this.executeHook(hook.code, page, context, browser, request.tempDir, originalScript, suiteContext, hook, jobId, testStepCounter);
|
|
2200
|
+
const stepsExecuted = await this.executeHook(hook.code, page, context, browser, request.tempDir, originalScript, request.testFolderPath, request.runPomDenormalized, suiteContext, hook, jobId, testStepCounter);
|
|
2114
2201
|
testStepCounter += stepsExecuted;
|
|
2115
2202
|
}
|
|
2116
2203
|
}
|
|
@@ -2125,7 +2212,7 @@ class ExecutionService {
|
|
|
2125
2212
|
this.log(`Executing ${flattened.fileLevelHooks.afterEach.length} file-level afterEach hook(s) for test: ${test.fullName}`);
|
|
2126
2213
|
try {
|
|
2127
2214
|
for (const hook of flattened.fileLevelHooks.afterEach) {
|
|
2128
|
-
const stepsExecuted = await this.executeHook(hook.code, page, context, browser, request.tempDir, originalScript, fileLevelContext || undefined, hook, jobId, testStepCounter);
|
|
2215
|
+
const stepsExecuted = await this.executeHook(hook.code, page, context, browser, request.tempDir, originalScript, request.testFolderPath, request.runPomDenormalized, fileLevelContext || undefined, hook, jobId, testStepCounter);
|
|
2129
2216
|
testStepCounter += stepsExecuted;
|
|
2130
2217
|
}
|
|
2131
2218
|
}
|
|
@@ -2164,7 +2251,7 @@ class ExecutionService {
|
|
|
2164
2251
|
// Get or create suite context (should already exist, but safe to call)
|
|
2165
2252
|
const suiteContext = await getOrCreateSuiteContext(suitePath, suite.suiteVariables, flattened.fileVariables);
|
|
2166
2253
|
for (const hook of suite.afterAll) {
|
|
2167
|
-
await this.executeHook(hook.code, page, context, browser, request.tempDir, originalScript, suiteContext, hook);
|
|
2254
|
+
await this.executeHook(hook.code, page, context, browser, request.tempDir, originalScript, request.testFolderPath, request.runPomDenormalized, suiteContext, hook);
|
|
2168
2255
|
}
|
|
2169
2256
|
this.log(`Suite-level afterAll hooks executed for suite: ${suiteDisplayName}`);
|
|
2170
2257
|
}
|
|
@@ -2229,7 +2316,7 @@ class ExecutionService {
|
|
|
2229
2316
|
this.log(`Executing ${flattened.fileLevelHooks.afterAll.length} file-level afterAll hook(s)...`);
|
|
2230
2317
|
try {
|
|
2231
2318
|
for (const hook of flattened.fileLevelHooks.afterAll) {
|
|
2232
|
-
await this.executeHook(hook.code, page, context, browser, request.tempDir, originalScript, fileLevelContext || undefined, hook);
|
|
2319
|
+
await this.executeHook(hook.code, page, context, browser, request.tempDir, originalScript, request.testFolderPath, request.runPomDenormalized, fileLevelContext || undefined, hook);
|
|
2233
2320
|
}
|
|
2234
2321
|
this.log('File-level afterAll hooks executed successfully');
|
|
2235
2322
|
}
|
|
@@ -2295,7 +2382,7 @@ class ExecutionService {
|
|
|
2295
2382
|
* If jobId is provided, executes step-wise with callbacks for step reporting
|
|
2296
2383
|
* @returns Number of non-variable steps executed (for step counter tracking)
|
|
2297
2384
|
*/
|
|
2298
|
-
async executeHook(hookCode, page, context, browser, tempDir, originalScript, sharedContext, hook, jobId, stepIdOffset = 0) {
|
|
2385
|
+
async executeHook(hookCode, page, context, browser, tempDir, originalScript, testFolderPath, runPomDenormalized, sharedContext, hook, jobId, stepIdOffset = 0) {
|
|
2299
2386
|
const { expect, test } = require('@playwright/test');
|
|
2300
2387
|
const { ai } = require('ai-wright');
|
|
2301
2388
|
// Construct hook script with imports from original script (for module resolution)
|
|
@@ -2334,7 +2421,9 @@ class ExecutionService {
|
|
|
2334
2421
|
mode: types_1.ExecutionMode.RUN_EXACTLY,
|
|
2335
2422
|
jobId: jobId,
|
|
2336
2423
|
tempDir: tempDir,
|
|
2337
|
-
originalScript: hookScript
|
|
2424
|
+
originalScript: hookScript,
|
|
2425
|
+
testFolderPath: testFolderPath,
|
|
2426
|
+
runPomDenormalized: runPomDenormalized
|
|
2338
2427
|
}, hookContext // Pass shared context
|
|
2339
2428
|
);
|
|
2340
2429
|
if (!result.success) {
|