diff --git a/.github/workflows/test-matrix.yml b/.github/workflows/test-matrix.yml new file mode 100644 index 00000000..cca040cd --- /dev/null +++ b/.github/workflows/test-matrix.yml @@ -0,0 +1,23 @@ +name: Test matrix +'on': pull_request + +jobs: + url_matrix: + runs-on: ubuntu-20.04 + strategy: + matrix: + url: + ['https://github.com', 'https://google.com', 'https://wikipedia.org'] + steps: + - name: Checkout repo + uses: actions/checkout@v2 + + - uses: actions/setup-node@v3 + with: + node-version: 18.0.0 + + - run: echo ${{ matrix.url }} + + - run: npm i + + - run: BASE_URL=${{ matrix.url }} npx @puppeteer/replay ./test/resources/replay.json diff --git a/README.md b/README.md index 95007756..f81ba2c3 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,12 @@ PUPPETEER_HEADLESS=false npx @puppeteer/replay recording.json # runs in headful PUPPETEER_HEADLESS=chrome npx @puppeteer/replay recording.json # runs in the new experimental headless mode. ``` +Set the `BASE_URL` environment variable to replace your base URL in your recordings. For example, + +``` +BASE_URL=localhost:3001 npx @puppeteer/replay recording.json # It will run your recording.json by replacing the base URLs of your URLs with the BASE_URL you provided +``` + Using [the replay lib API](/examples/replay-from-file-using-puppeteer/main.js): ```js diff --git a/src/PuppeteerRunnerExtension.ts b/src/PuppeteerRunnerExtension.ts index eccaffc7..fa6f87db 100644 --- a/src/PuppeteerRunnerExtension.ts +++ b/src/PuppeteerRunnerExtension.ts @@ -256,7 +256,26 @@ export class PuppeteerRunnerExtension extends RunnerExtension { } case 'navigate': { startWaitingForEvents(); - await localFrame.goto(step.url); + let url = step.url; + + if (process.env.BASE_URL) { + try { + const baseURL = new URL(process.env.BASE_URL); + const givenURL = new URL(step.url); + const targetURL = new URL( + givenURL.pathname + + (givenURL.search || '') + + (givenURL.hash || ''), + baseURL.origin + ); + + url = targetURL.href; + } catch (error) { + throw new Error(`invalid URL BASE_URL: ${process.env.BASE_URL}`); + } + } + + await localFrame.goto(url); break; } case 'waitForElement': { diff --git a/src/Schema.ts b/src/Schema.ts index f4a3c792..b20f09bc 100644 --- a/src/Schema.ts +++ b/src/Schema.ts @@ -244,7 +244,7 @@ export type Step = UserStep | AssertionStep; export interface UserFlow { /** - * Human-readble title describing the recorder user flow. + * Human-readable title describing the recorder user flow. */ title: string; /** diff --git a/test/runner_test.ts b/test/runner_test.ts index 75798793..11c46f77 100644 --- a/test/runner_test.ts +++ b/test/runner_test.ts @@ -103,6 +103,60 @@ describe('Runner', () => { assert.strictEqual(page.url(), `${HTTP_PREFIX}/empty.html`); }); + it('should navigate to URL with BASE_URL', async () => { + process.env.BASE_URL = 'https://'; + + const runner = await createRunner( + { + title: 'test', + steps: [ + { + type: 'navigate', + url: `${HTTP_PREFIX}/empty.html`, + }, + ], + }, + new PuppeteerRunnerExtension(browser, page) + ); + + try { + await runner.run(); + } catch (error) { + assert.instanceOf( + error, + Error, + `invalid URL BASE_URL: ${process.env.BASE_URL}` + ); + } + + delete process.env.BASE_URL; + }); + + it('should navigate to URL with BASE_URL', async () => { + process.env.BASE_URL = 'https://developer.chrome.com'; + + const runner = await createRunner( + { + title: 'test', + steps: [ + { + type: 'navigate', + url: `${HTTP_PREFIX}/docs/devtools/recorder/#open`, + }, + ], + }, + new PuppeteerRunnerExtension(browser, page) + ); + + await runner.run(); + assert.strictEqual( + page.url(), + `https://developer.chrome.com/docs/devtools/recorder/#open` + ); + + delete process.env.BASE_URL; + }); + it('should be able to replay mouse click steps', async () => { const runner = await createRunner( {