From c8063546f4a59016a2b0d6dc1bee4de0c032674a Mon Sep 17 00:00:00 2001 From: nick2548 Date: Fri, 8 Dec 2023 15:57:26 -0500 Subject: [PATCH] fix(utils): support star matching support star matching in domain and path in regex --- .gitignore | 3 +++ .../tests/playwright/specs/http.spec.ts | 21 +++++++++++++++ packages/playwright-msw/src/utils.test.ts | 9 ++++++- packages/playwright-msw/src/utils.ts | 27 ++++++++++++++++--- 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index ace24f0..62868d7 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,7 @@ yarn-error.log # eslint .eslintcache +# ide +.idea + .env diff --git a/packages/example/tests/playwright/specs/http.spec.ts b/packages/example/tests/playwright/specs/http.spec.ts index 3df0285..2de1869 100644 --- a/packages/example/tests/playwright/specs/http.spec.ts +++ b/packages/example/tests/playwright/specs/http.spec.ts @@ -120,4 +120,25 @@ test.describe.parallel('HTTP example: users list', () => { await page.goto('/users/testmytestface'); await expect(page.locator('text="test.mc@test.face"')).toBeVisible(); }); + + test('should allow paths with route with `*` to be mocked', async ({ + page, + worker, + }) => { + await worker.use( + http.get('/a*i/us*/:userId', () => + HttpResponse.json({ + id: 'testmytestface', + firstName: 'Testy', + lastName: 'Mctestface', + dob: '1969-6-9', + email: 'test.mc@test.face', + address: '111 Testy Way', + phoneNumber: '(123) 456-7890', + }), + ), + ); + await page.goto('/users/testmytestface'); + await expect(page.locator('text="test.mc@test.face"')).toBeVisible(); + }); }); diff --git a/packages/playwright-msw/src/utils.test.ts b/packages/playwright-msw/src/utils.test.ts index 818592b..0c7f111 100644 --- a/packages/playwright-msw/src/utils.test.ts +++ b/packages/playwright-msw/src/utils.test.ts @@ -124,11 +124,18 @@ describe('utils', () => { ${'https://www.google.com.au/:potato/:eggplant/'} | ${'https://www.google.com.au/search/something/?foo=bar'} | ${true} ${'https://www.google.com.au/:potato/:eggplant?foo=bar'} | ${'https://www.google.com.au/search/something'} | ${true} ${'https://www.google.com.au/:potato/:eggplant/?foo=bar'} | ${'https://www.google.com.au/search/something/'} | ${true} + ${'https://www.google.com.au/*/?foo=bar'} | ${'https://www.google.com.au/search/something/?foo=bar'} | ${true} ${'https://www.google.com.au/search'} | ${'https://different.domain/search'} | ${false} ${'http://www.google.com.au/:something/'} | ${'http://www.google.com.au/search/?q=potato'} | ${true} - ${'*/api/users'} | ${'http://localhost:8080/api/users'} | ${true} ${'http://localhost:8080/api/users'} | ${'http://localhost:8080/api/users'} | ${true} ${'http://localhost:8081/api/users'} | ${'http://localhost:8080/api/users'} | ${false} + ${'*'} | ${'http://anything.com/will/match?q=really'} | ${true} + ${'http://api.*.foo.com/life/power'} | ${'http://api.dev.foo.com/life/power'} | ${true} + ${'http://*.foo.com/life/power'} | ${'http://api.dev.foo.com/life/power'} | ${true} + ${'http://b.co/api/*/*'} | ${'http://b.co/api/users/foo'} | ${true} + ${'http://b.co/p/https%3A%2F%2Fa.*%2F*%2Fsecond'} | ${'http://b.co/p/https%3A%2F%2Fa.co%2Ffirst%2Fsecond'} | ${true} + ${'*/api/users'} | ${'http://localhost:8080/api/users'} | ${true} + ${'*/*/users'} | ${'http://localhost:8080/api/users'} | ${true} `( '$expected: "$mswPath" should match "$playwrightUrl"', ({ mswPath, playwrightUrl, expected }) => { diff --git a/packages/playwright-msw/src/utils.ts b/packages/playwright-msw/src/utils.ts index 4f76610..70c8155 100644 --- a/packages/playwright-msw/src/utils.ts +++ b/packages/playwright-msw/src/utils.ts @@ -38,12 +38,30 @@ export const getHandlerPath = ( return (handler.info as unknown as { path: string }).path; }; +const getOriginRegex = (origin) => { + if (origin === '*') { + return '.*'; + } + return ( + (origin ?? '') + // escape dots in domains, for more exact matches + .replace(/\./, '.') + // support wildcard star matches + .replace('*', '.*') || '(\\w+://[^/]+)?' + ); +}; + export const convertMswPathToPlaywrightUrl = (path: Path): RegExp => { // If already a regex, just return straight away if (path instanceof RegExp) { return path; } + // A route that matches everything for testing + if (path === '*') { + return /.*/; + } + // Deconstruct path const { origin, pathname } = path.match( @@ -54,9 +72,12 @@ export const convertMswPathToPlaywrightUrl = (path: Path): RegExp => { return new RegExp( [ '^', - origin === '*' ? '.*' : origin ?? '(\\w+://[^/]+)?', - // Replace route parameters (`:whatever`) with multi-char wildcard - pathname.replace(/:[^/]+/g, '[^/]+'), + getOriginRegex(origin), + pathname + // support star matching + .replace(/\*/g, '.*') + // Replace route parameters (`:whatever`) with multi-char wildcard + .replace(/:[^/]+/g, '[^/]+'), // Add optional trailing slash '\\/?', // Add optional query parameters