From d467dca3a944f5e31505efa74bbc42a4e0ccf593 Mon Sep 17 00:00:00 2001 From: Alex Plischke Date: Mon, 16 Oct 2023 17:07:26 -0700 Subject: [PATCH 1/3] feat: add global default timeout --- src/runner.mts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/runner.mts b/src/runner.mts index a76b7c2..f6a3943 100644 --- a/src/runner.mts +++ b/src/runner.mts @@ -25,6 +25,7 @@ type LogEntry = { type Suite = { name: string; recording: string; + timeout?: number; }; type RunConfig = { @@ -135,9 +136,25 @@ export async function replay(runCfgPath: string, suiteName: string) { throw new Error(`Could not find suite named '${suiteName}'`); } + // saucectl suite.timeout is in nanoseconds, convert to seconds + const timeout = (suite.timeout || 0) / 1_000_000_000 || 30 * 60; // 30min default + + const timeoutPromise = new Promise((resolve) => { + setTimeout(() => { + console.error(`Job timed out after ${timeout} seconds`); + resolve(false); + }, timeout * 1000); + }); + // Validate & parse the file. const recording = parseRecording(suite.recording); + const replayPromise = runReplay(recording); + + return Promise.race([timeoutPromise, replayPromise]); +} + +async function runReplay(recording: UserFlow) { const browser = await puppeteer.launch({ headless: false, product: process.env.BROWSER_NAME as Product, From 01b111c6321ba2d356983ef4d46047670a42d6e9 Mon Sep 17 00:00:00 2001 From: Alex Plischke Date: Mon, 16 Oct 2023 17:23:11 -0700 Subject: [PATCH 2/3] refactor: return at last --- src/runner.mts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runner.mts b/src/runner.mts index f6a3943..b653cb1 100644 --- a/src/runner.mts +++ b/src/runner.mts @@ -167,5 +167,5 @@ async function runReplay(recording: UserFlow) { const runner = await createRunner(recording, new Extension(browser, page)); await runner.run(); - await browser.close(); + return browser.close(); } From 4f9e28b1134a7f12c7d3c458a12c4420c38c8691 Mon Sep 17 00:00:00 2001 From: Alex Plischke Date: Tue, 17 Oct 2023 09:37:32 -0700 Subject: [PATCH 3/3] refactor: harden error handling --- .gitignore | 2 ++ src/index.mts | 11 ++++++++++- src/runner.mts | 31 ++++++++++++++++++------------- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 0e220f6..d6a1458 100644 --- a/.gitignore +++ b/.gitignore @@ -105,3 +105,5 @@ dist # TernJS port file .tern-port + +__assets__ diff --git a/src/index.mts b/src/index.mts index f8d695d..8d09f63 100644 --- a/src/index.mts +++ b/src/index.mts @@ -11,7 +11,16 @@ import { replay } from './runner.mjs'; // noop }, async (argv) => { - await replay(argv.runCfgPath as string, argv.suiteName as string); + try { + const passed = await replay( + argv.runCfgPath as string, + argv.suiteName as string + ); + process.exit(passed ? 0 : 1); + } catch (err) { + console.error(err); + process.exit(1); + } } ) .option('runCfgPath', { diff --git a/src/runner.mts b/src/runner.mts index b653cb1..74c2010 100644 --- a/src/runner.mts +++ b/src/runner.mts @@ -149,23 +149,28 @@ export async function replay(runCfgPath: string, suiteName: string) { // Validate & parse the file. const recording = parseRecording(suite.recording); - const replayPromise = runReplay(recording); - - return Promise.race([timeoutPromise, replayPromise]); + return Promise.race([timeoutPromise, runReplay(recording)]); } async function runReplay(recording: UserFlow) { - const browser = await puppeteer.launch({ - headless: false, - product: process.env.BROWSER_NAME as Product, - executablePath: process.env.BROWSER_PATH, - }); + try { + const browser = await puppeteer.launch({ + headless: false, + product: process.env.BROWSER_NAME as Product, + executablePath: process.env.BROWSER_PATH, + }); - const page = await browser.newPage(); + const page = await browser.newPage(); - // Create a runner and execute the script. - const runner = await createRunner(recording, new Extension(browser, page)); + // Create a runner and execute the script. + const runner = await createRunner(recording, new Extension(browser, page)); - await runner.run(); - return browser.close(); + await runner.run(); + await browser.close(); + + return true; + } catch (e) { + console.error('Error running replay:', e.message); + return false; + } }