@probolabs/playwright 1.4.0-rc.3 โ 1.4.0-rc.5
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/bin/probo.js +5 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/cli.js +82 -6
- package/dist/cli.js.map +1 -1
- package/dist/fixtures.cjs.map +1 -1
- package/dist/fixtures.js.map +1 -1
- package/dist/index.cjs +81 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +81 -6
- package/dist/index.js.map +1 -1
- package/dist/types/cli.d.ts.map +1 -1
- package/dist/types/codegen-api.d.ts.map +1 -1
- package/dist/types/test-suite-runner.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -433,6 +433,11 @@ declare class ProboCodeGenerator {
|
|
|
433
433
|
* Get default viewport dimensions
|
|
434
434
|
*/
|
|
435
435
|
private static getDefaultViewPort;
|
|
436
|
+
/**
|
|
437
|
+
* Validate and normalize viewport dimensions
|
|
438
|
+
* Returns a valid viewport object with numeric width and height, falling back to defaults if invalid
|
|
439
|
+
*/
|
|
440
|
+
private static normalizeViewPort;
|
|
436
441
|
/**
|
|
437
442
|
* Generate code for a single scenario
|
|
438
443
|
* Fetches scenario data, converts to Interaction[], generates code
|
|
@@ -470,6 +475,7 @@ interface TestStatistics {
|
|
|
470
475
|
interface TestSuiteRunOptions {
|
|
471
476
|
outputDir?: string;
|
|
472
477
|
includeReporter?: boolean;
|
|
478
|
+
playwrightArgs?: string[];
|
|
473
479
|
onStatusUpdate?: (updates: Partial<{
|
|
474
480
|
status: string;
|
|
475
481
|
exit_code: number;
|
package/dist/index.js
CHANGED
|
@@ -1656,7 +1656,6 @@ export default defineConfig({
|
|
|
1656
1656
|
// Keep Playwright's default console output, plus HTML report${includeReporter ? ', plus Probo live progress reporter' : ''}.
|
|
1657
1657
|
reporter: ${JSON.stringify(reporters)},
|
|
1658
1658
|
use: {
|
|
1659
|
-
headless: true,
|
|
1660
1659
|
ignoreHTTPSErrors: true,
|
|
1661
1660
|
actionTimeout: 30000,
|
|
1662
1661
|
navigationTimeout: 30000,
|
|
@@ -1665,7 +1664,6 @@ export default defineConfig({
|
|
|
1665
1664
|
trace: 'on',
|
|
1666
1665
|
},
|
|
1667
1666
|
retries: 0,
|
|
1668
|
-
workers: 1,
|
|
1669
1667
|
});
|
|
1670
1668
|
`;
|
|
1671
1669
|
}
|
|
@@ -5850,6 +5848,19 @@ class ProboCodeGenerator {
|
|
|
5850
5848
|
static getDefaultViewPort() {
|
|
5851
5849
|
return { width: 1280, height: 720 };
|
|
5852
5850
|
}
|
|
5851
|
+
/**
|
|
5852
|
+
* Validate and normalize viewport dimensions
|
|
5853
|
+
* Returns a valid viewport object with numeric width and height, falling back to defaults if invalid
|
|
5854
|
+
*/
|
|
5855
|
+
static normalizeViewPort(viewPort) {
|
|
5856
|
+
const defaultViewPort = this.getDefaultViewPort();
|
|
5857
|
+
if (!viewPort) {
|
|
5858
|
+
return defaultViewPort;
|
|
5859
|
+
}
|
|
5860
|
+
const width = typeof viewPort.width === 'number' && !isNaN(viewPort.width) ? viewPort.width : defaultViewPort.width;
|
|
5861
|
+
const height = typeof viewPort.height === 'number' && !isNaN(viewPort.height) ? viewPort.height : defaultViewPort.height;
|
|
5862
|
+
return { width, height };
|
|
5863
|
+
}
|
|
5853
5864
|
/**
|
|
5854
5865
|
* Generate code for a single scenario
|
|
5855
5866
|
* Fetches scenario data, converts to Interaction[], generates code
|
|
@@ -5868,7 +5879,7 @@ class ProboCodeGenerator {
|
|
|
5868
5879
|
const interactions = this.convertBackendInteractionsToInteractionFormat(scenarioData.interactions || []);
|
|
5869
5880
|
// Get settings and viewport
|
|
5870
5881
|
const settings = (options === null || options === void 0 ? void 0 : options.recorderSettings) || this.getDefaultRecorderSettings();
|
|
5871
|
-
const viewPort = (options === null || options === void 0 ? void 0 : options.viewPort) || scenarioData.viewPort
|
|
5882
|
+
const viewPort = this.normalizeViewPort((options === null || options === void 0 ? void 0 : options.viewPort) || scenarioData.viewPort);
|
|
5872
5883
|
// Get parameter table rows
|
|
5873
5884
|
const rows = scenarioData.parameterTable || [];
|
|
5874
5885
|
// Generate code
|
|
@@ -6054,6 +6065,22 @@ class TestSuiteRunner {
|
|
|
6054
6065
|
throw new Error(`Failed to lookup test suite: ${response.status} ${errorText}`);
|
|
6055
6066
|
}
|
|
6056
6067
|
const data = await response.json();
|
|
6068
|
+
// TEMPORARY DEBUG: Output the full response
|
|
6069
|
+
console.log('๐ DEBUG: API Response URL:', url);
|
|
6070
|
+
console.log('๐ DEBUG: API Response Status:', response.status);
|
|
6071
|
+
console.log('๐ DEBUG: API Response Data:', JSON.stringify(data, null, 2));
|
|
6072
|
+
console.log('๐ DEBUG: Is Array?', Array.isArray(data));
|
|
6073
|
+
console.log('๐ DEBUG: Array length:', Array.isArray(data) ? data.length : 'N/A');
|
|
6074
|
+
console.log('๐ DEBUG: Has results?', !!data.results);
|
|
6075
|
+
console.log('๐ DEBUG: Results is Array?', Array.isArray(data.results));
|
|
6076
|
+
console.log('๐ DEBUG: Results length:', Array.isArray(data.results) ? data.results.length : 'N/A');
|
|
6077
|
+
if (Array.isArray(data) && data.length > 0) {
|
|
6078
|
+
console.log('๐ DEBUG: First item:', JSON.stringify(data[0], null, 2));
|
|
6079
|
+
}
|
|
6080
|
+
if (data.results && Array.isArray(data.results) && data.results.length > 0) {
|
|
6081
|
+
console.log('๐ DEBUG: First result:', JSON.stringify(data.results[0], null, 2));
|
|
6082
|
+
}
|
|
6083
|
+
console.log('');
|
|
6057
6084
|
if (Array.isArray(data) && data.length > 0) {
|
|
6058
6085
|
return data[0].id;
|
|
6059
6086
|
}
|
|
@@ -6072,7 +6099,52 @@ class TestSuiteRunner {
|
|
|
6072
6099
|
if (codeGenResult.scenarios.length === 0) {
|
|
6073
6100
|
throw new Error(`No scenarios found in test suite ${testSuiteId}. Cannot generate test files.`);
|
|
6074
6101
|
}
|
|
6075
|
-
//
|
|
6102
|
+
// Delete everything in the test suite directory except node_modules
|
|
6103
|
+
// This ensures a clean state while preserving dependencies for faster subsequent runs
|
|
6104
|
+
if (fs.existsSync(testSuiteDir)) {
|
|
6105
|
+
try {
|
|
6106
|
+
const nodeModulesPath = path.join(testSuiteDir, 'node_modules');
|
|
6107
|
+
const hasNodeModules = fs.existsSync(nodeModulesPath);
|
|
6108
|
+
// Temporarily move node_modules out of the way if it exists
|
|
6109
|
+
let tempNodeModulesPath = null;
|
|
6110
|
+
if (hasNodeModules) {
|
|
6111
|
+
tempNodeModulesPath = path.join(testSuiteDir, '..', `node_modules.temp.${testSuiteId}`);
|
|
6112
|
+
// Remove temp directory if it exists from a previous failed run
|
|
6113
|
+
if (fs.existsSync(tempNodeModulesPath)) {
|
|
6114
|
+
fs.rmSync(tempNodeModulesPath, { recursive: true, force: true });
|
|
6115
|
+
}
|
|
6116
|
+
fs.renameSync(nodeModulesPath, tempNodeModulesPath);
|
|
6117
|
+
console.log(`๐ฆ Preserved node_modules temporarily`);
|
|
6118
|
+
}
|
|
6119
|
+
// Delete everything in the directory
|
|
6120
|
+
const entries = fs.readdirSync(testSuiteDir, { withFileTypes: true });
|
|
6121
|
+
for (const entry of entries) {
|
|
6122
|
+
const entryPath = path.join(testSuiteDir, entry.name);
|
|
6123
|
+
try {
|
|
6124
|
+
if (entry.isDirectory()) {
|
|
6125
|
+
fs.rmSync(entryPath, { recursive: true, force: true });
|
|
6126
|
+
}
|
|
6127
|
+
else {
|
|
6128
|
+
fs.unlinkSync(entryPath);
|
|
6129
|
+
}
|
|
6130
|
+
}
|
|
6131
|
+
catch (error) {
|
|
6132
|
+
console.warn(`โ ๏ธ Failed to delete ${entry.name}:`, error);
|
|
6133
|
+
}
|
|
6134
|
+
}
|
|
6135
|
+
console.log(`๐๏ธ Cleaned test suite directory (preserved node_modules)`);
|
|
6136
|
+
// Move node_modules back
|
|
6137
|
+
if (hasNodeModules && tempNodeModulesPath) {
|
|
6138
|
+
fs.renameSync(tempNodeModulesPath, nodeModulesPath);
|
|
6139
|
+
console.log(`๐ฆ Restored node_modules`);
|
|
6140
|
+
}
|
|
6141
|
+
}
|
|
6142
|
+
catch (error) {
|
|
6143
|
+
console.warn(`โ ๏ธ Failed to clean test suite directory ${testSuiteDir}:`, error);
|
|
6144
|
+
// Continue anyway - we'll overwrite files as needed
|
|
6145
|
+
}
|
|
6146
|
+
}
|
|
6147
|
+
// Ensure directories exist (will recreate after deletion)
|
|
6076
6148
|
ensureDirectoryExists(testSuiteDir);
|
|
6077
6149
|
const testsDir = path.join(testSuiteDir, 'tests');
|
|
6078
6150
|
ensureDirectoryExists(testsDir);
|
|
@@ -6159,7 +6231,7 @@ class TestSuiteRunner {
|
|
|
6159
6231
|
* Generates files, installs dependencies, and executes tests
|
|
6160
6232
|
*/
|
|
6161
6233
|
static async runTestSuite(testSuiteId, apiToken, apiUrl, testSuiteName, runId, options = {}) {
|
|
6162
|
-
const { outputDir, includeReporter = true, onStatusUpdate, onStdout, onStderr, onReporterEvent, } = options;
|
|
6234
|
+
const { outputDir, includeReporter = true, playwrightArgs = [], onStatusUpdate, onStdout, onStderr, onReporterEvent, } = options;
|
|
6163
6235
|
const testSuiteDir = outputDir || getDefaultTestSuiteDir(testSuiteId, testSuiteName);
|
|
6164
6236
|
let currentRunId = runId;
|
|
6165
6237
|
try {
|
|
@@ -6238,6 +6310,9 @@ class TestSuiteRunner {
|
|
|
6238
6310
|
}
|
|
6239
6311
|
// Run Playwright tests with streaming output
|
|
6240
6312
|
console.log(`๐ Running Playwright tests in ${testSuiteDir}...`);
|
|
6313
|
+
if (playwrightArgs.length > 0) {
|
|
6314
|
+
console.log(`๐งช Playwright extra args: ${playwrightArgs.join(' ')}`);
|
|
6315
|
+
}
|
|
6241
6316
|
return new Promise(async (resolve) => {
|
|
6242
6317
|
var _a, _b;
|
|
6243
6318
|
let stdout = '';
|
|
@@ -6254,7 +6329,7 @@ class TestSuiteRunner {
|
|
|
6254
6329
|
let lastStepsUpdate = 0;
|
|
6255
6330
|
const collectedSteps = [];
|
|
6256
6331
|
// Use spawn for streaming output
|
|
6257
|
-
const testProcess = spawn('npx', ['playwright', 'test'], {
|
|
6332
|
+
const testProcess = spawn('npx', ['playwright', 'test', ...playwrightArgs], {
|
|
6258
6333
|
cwd: testSuiteDir,
|
|
6259
6334
|
shell: true,
|
|
6260
6335
|
stdio: ['ignore', 'pipe', 'pipe'],
|