Repository: mswjs/msw
Pull request #2491: chore(setup): fixed `test:browser`
Author: login: Andarist
Created: 2025-05-06T08:43:24Z | Merged: 2025-05-06T11:24:06Z



Diff:
diff --git a/package.json b/package.json
index 2f510d21b..fccbd0979 100644
--- a/package.json
+++ b/package.json
@@ -288,6 +288,7 @@
     "json-bigint": "^1.0.0",
     "knip": "^5.51.1",
     "lint-staged": "^15.2.10",
+    "msw": "workspace:*",
     "page-with": "^0.6.1",
     "prettier": "^3.4.2",
     "publint": "^0.3.12",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1d1ae0f0d..cf26d0935 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -156,6 +156,9 @@ importers:
       lint-staged:
         specifier: ^15.2.10
         version: 15.2.10
+      msw:
+        specifier: workspace:*
+        version: 'link:'
       page-with:
         specifier: ^0.6.1
         version: 0.6.1(@swc/core@1.9.3)(esbuild@0.25.3)
@@ -188,10 +191,10 @@ importers:
         version: 4.1.1(webpack@5.96.1(@swc/core@1.9.3)(esbuild@0.25.3))
       vitest:
         specifier: ^3.1.3
-        version: 3.1.3(@types/debug@4.1.12)(@types/node@18.19.28)(jsdom@25.0.1)(terser@5.30.1)
+        version: 3.1.3(@types/debug@4.1.12)(@types/node@18.19.28)(jsdom@25.0.1)(msw@)(terser@5.30.1)
       vitest-environment-miniflare:
         specifier: ^2.14.4
-        version: 2.14.4(vitest@3.1.3(@types/debug@4.1.12)(@types/node@18.19.28)(jsdom@25.0.1)(terser@5.30.1))
+        version: 2.14.4(vitest@3.1.3(@types/debug@4.1.12)(@types/node@18.19.28)(jsdom@25.0.1)(msw@)(terser@5.30.1))
       webpack:
         specifier: ^5.95.0
         version: 5.96.1(@swc/core@1.9.3)(esbuild@0.25.3)
@@ -6536,12 +6539,13 @@ snapshots:
       chai: 5.2.0
       tinyrainbow: 2.0.0
 
-  '@vitest/mocker@3.1.3(vite@5.2.7(@types/node@18.19.28)(terser@5.30.1))':
+  '@vitest/mocker@3.1.3(msw@)(vite@5.2.7(@types/node@18.19.28)(terser@5.30.1))':
     dependencies:
       '@vitest/spy': 3.1.3
       estree-walker: 3.0.3
       magic-string: 0.30.17
     optionalDependencies:
+      msw: 'link:'
       vite: 5.2.7(@types/node@18.19.28)(terser@5.30.1)
 
   '@vitest/pretty-format@3.1.3':
@@ -10397,22 +10401,22 @@ snapshots:
       fsevents: 2.3.3
       terser: 5.30.1
 
-  vitest-environment-miniflare@2.14.4(vitest@3.1.3(@types/debug@4.1.12)(@types/node@18.19.28)(jsdom@25.0.1)(terser@5.30.1)):
+  vitest-environment-miniflare@2.14.4(vitest@3.1.3(@types/debug@4.1.12)(@types/node@18.19.28)(jsdom@25.0.1)(msw@)(terser@5.30.1)):
     dependencies:
       '@miniflare/queues': 2.14.4
       '@miniflare/runner-vm': 2.14.4
       '@miniflare/shared': 2.14.4
       '@miniflare/shared-test-environment': 2.14.4
       undici: 5.28.4
-      vitest: 3.1.3(@types/debug@4.1.12)(@types/node@18.19.28)(jsdom@25.0.1)(terser@5.30.1)
+      vitest: 3.1.3(@types/debug@4.1.12)(@types/node@18.19.28)(jsdom@25.0.1)(msw@)(terser@5.30.1)
     transitivePeerDependencies:
       - bufferutil
       - utf-8-validate
 
-  vitest@3.1.3(@types/debug@4.1.12)(@types/node@18.19.28)(jsdom@25.0.1)(terser@5.30.1):
+  vitest@3.1.3(@types/debug@4.1.12)(@types/node@18.19.28)(jsdom@25.0.1)(msw@)(terser@5.30.1):
     dependencies:
       '@vitest/expect': 3.1.3
-      '@vitest/mocker': 3.1.3(vite@5.2.7(@types/node@18.19.28)(terser@5.30.1))
+      '@vitest/mocker': 3.1.3(msw@)(vite@5.2.7(@types/node@18.19.28)(terser@5.30.1))
       '@vitest/pretty-format': 3.1.3
       '@vitest/runner': 3.1.3
       '@vitest/snapshot': 3.1.3
diff --git a/test/browser/msw-api/distribution/iife.test.ts b/test/browser/msw-api/distribution/iife.test.ts
index e4b6f509c..d6cb47936 100644
--- a/test/browser/msw-api/distribution/iife.test.ts
+++ b/test/browser/msw-api/distribution/iife.test.ts
@@ -13,7 +13,7 @@ test('supports the usage of the iife bundle in a <script> tag', async ({
       compilation.use((router) => {
         router.get('/iife/index.js', (_, res) => {
           fs.createReadStream(
-            require.resolve('../../../../lib/iife/index.js'),
+            new URL('../../../../lib/iife/index.js', import.meta.url),
           ).pipe(res)
 
           return res
diff --git a/test/browser/msw-api/integrity-check.test.ts b/test/browser/msw-api/integrity-check.test.ts
index 429a439b0..8916272e3 100644
--- a/test/browser/msw-api/integrity-check.test.ts
+++ b/test/browser/msw-api/integrity-check.test.ts
@@ -1,5 +1,4 @@
 import fs from 'node:fs'
-import path from 'node:path'
 import { test, expect } from '../playwright.extend'
 import copyServiceWorker from '../../../config/copyServiceWorker'
 import packageJson from '../../../package.json' assert { type: 'json' }
@@ -33,10 +32,10 @@ test('errors when activating the worker with an outdated integrity', async ({
   fetch,
   waitFor,
 }) => {
-  const TEMP_SERVICE_WORKER_PATH = path.resolve(
-    __dirname,
+  const TEMP_SERVICE_WORKER_PATH = new URL(
     '../../tmp/mockServiceWorker-outdated.js',
-  )
+    import.meta.url,
+  ).pathname
 
   // Manually create a Service Worker file with invalid integrity
   await copyServiceWorker(
diff --git a/test/browser/msw-api/setup-worker/fallback-mode/fallback-mode.test.ts b/test/browser/msw-api/setup-worker/fallback-mode/fallback-mode.test.ts
index c694e42a3..2bd88a03e 100644
--- a/test/browser/msw-api/setup-worker/fallback-mode/fallback-mode.test.ts
+++ b/test/browser/msw-api/setup-worker/fallback-mode/fallback-mode.test.ts
@@ -63,7 +63,7 @@ test.beforeAll(async () => {
 
 test.beforeEach(async ({ webpackServer }, testInfo) => {
   const compilation = await webpackServer.compile([
-    new URL('./fallback-mode.mocks.ts', import.meta.url),
+    new URL('./fallback-mode.mocks.ts', import.meta.url).pathname,
   ])
   const bundleUrl = new URL('./main.js', compilation.previewUrl)
   await fsMock.create({
diff --git a/test/browser/msw-api/setup-worker/response-logging.test.ts b/test/browser/msw-api/setup-worker/response-logging.test.ts
index aa9ac4a83..0e62324b2 100644
--- a/test/browser/msw-api/setup-worker/response-logging.test.ts
+++ b/test/browser/msw-api/setup-worker/response-logging.test.ts
@@ -12,7 +12,7 @@ test('prints the response info to the console', async ({
   fetch,
   waitFor,
 }) => {
-  await loadExample(require.resolve('../../rest-api/basic.mocks.ts'))
+  await loadExample(new URL('../../rest-api/basic.mocks.ts', import.meta.url))
   const consoleSpy = spyOnConsole()
 
   const waitForResponseLog = async (exp: RegExp) => {
diff --git a/test/browser/msw-api/setup-worker/scenarios/iframe-isolated-response/iframe-isolated-response.test.ts b/test/browser/msw-api/setup-worker/scenarios/iframe-isolated-response/iframe-isolated-response.test.ts
index e52972d17..0c5f62bb3 100644
--- a/test/browser/msw-api/setup-worker/scenarios/iframe-isolated-response/iframe-isolated-response.test.ts
+++ b/test/browser/msw-api/setup-worker/scenarios/iframe-isolated-response/iframe-isolated-response.test.ts
@@ -1,10 +1,9 @@
-import path from 'node:path'
 import * as express from 'express'
 import type { Frame, Page } from '@playwright/test'
 import { test, expect } from '../../../../playwright.extend'
 
 const staticMiddleware = (router: express.Router) => {
-  router.use(express.static(__dirname))
+  router.use(express.static(new URL('./', import.meta.url).pathname))
 }
 
 export function getFrameById(id: string, page: Page): Frame {
@@ -27,7 +26,7 @@ test('responds with different responses for the same request based on request re
   await loadExample(
     new URL('./iframe-isolated-response.mocks.ts', import.meta.url),
     {
-      markup: path.resolve(__dirname, 'app.html'),
+      markup: new URL('app.html', import.meta.url).pathname,
       beforeNavigation(compilation) {
         compilation.use(staticMiddleware)
       },
diff --git a/test/browser/msw-api/setup-worker/scenarios/iframe/iframe.test.ts b/test/browser/msw-api/setup-worker/scenarios/iframe/iframe.test.ts
index e85a0eab3..fd08d44fc 100644
--- a/test/browser/msw-api/setup-worker/scenarios/iframe/iframe.test.ts
+++ b/test/browser/msw-api/setup-worker/scenarios/iframe/iframe.test.ts
@@ -1,4 +1,3 @@
-import path from 'node:path'
 import { Frame } from '@playwright/test'
 import * as express from 'express'
 import { test, expect } from '../../../../playwright.extend'
@@ -14,7 +13,7 @@ function findFrame(frame: Frame) {
 }
 
 const staticMiddleware = (router: express.Router) => {
-  router.use(express.static(__dirname))
+  router.use(express.static(new URL('./', import.meta.url).pathname))
 }
 
 test('intercepts a request from an iframe (nested client)', async ({
@@ -22,7 +21,7 @@ test('intercepts a request from an iframe (nested client)', async ({
   page,
 }) => {
   await loadExample(new URL('./iframe.mocks.ts', import.meta.url), {
-    markup: path.resolve(__dirname, 'page-in-iframe.html'),
+    markup: new URL('page-in-iframe.html', import.meta.url).pathname,
     beforeNavigation(compilation) {
       compilation.use(staticMiddleware)
     },
@@ -42,7 +41,7 @@ test('intercepts a request from a deeply nested iframe', async ({
   page,
 }) => {
   await loadExample(new URL('./iframe.mocks.ts', import.meta.url), {
-    markup: path.resolve(__dirname, 'page-in-nested-iframe.html'),
+    markup: new URL('page-in-nested-iframe.html', import.meta.url).pathname,
     beforeNavigation(compilation) {
       compilation.use(staticMiddleware)
     },
@@ -68,7 +67,7 @@ test('intercepts a request from a deeply nested iframe given MSW is registered i
   page,
 }) => {
   await loadExample(new URL('./iframe.mocks.ts', import.meta.url), {
-    markup: path.resolve(__dirname, 'page-in-iframe.html'),
+    markup: new URL('page-in-iframe.html', import.meta.url).pathname,
     beforeNavigation(compilation) {
       compilation.use(staticMiddleware)
     },
@@ -100,7 +99,7 @@ test('intercepts a request from an iframe given MSW is registered in a sibling i
   // A request-issuing frame. Here lives the `window.fetch` call.
   const requestPage = await context.newPage()
   const requestCompilation = await webpackServer.compile([], {
-    markup: path.resolve(__dirname, 'page-in-iframe.html'),
+    markup: new URL('page-in-iframe.html', import.meta.url).pathname,
   })
   requestCompilation.use(staticMiddleware)
   await requestPage.goto(requestCompilation.previewUrl)
diff --git a/test/browser/msw-api/setup-worker/scenarios/iframe/multiple-workers/iframe-multiple-workers.test.ts b/test/browser/msw-api/setup-worker/scenarios/iframe/multiple-workers/iframe-multiple-workers.test.ts
index c4b78078d..3c4480a86 100644
--- a/test/browser/msw-api/setup-worker/scenarios/iframe/multiple-workers/iframe-multiple-workers.test.ts
+++ b/test/browser/msw-api/setup-worker/scenarios/iframe/multiple-workers/iframe-multiple-workers.test.ts
@@ -5,10 +5,10 @@ test('intercepts a request issued by child frame when both child and parent have
   page,
 }) => {
   const parentCompilation = await webpackServer.compile([
-    new URL('./parent.mocks.ts', import.meta.url),
+    new URL('./parent.mocks.ts', import.meta.url).pathname,
   ])
   const childCompilation = await webpackServer.compile([
-    new URL('./child.mocks.ts', import.meta.url),
+    new URL('./child.mocks.ts', import.meta.url).pathname,
   ])
 
   await page.goto(parentCompilation.previewUrl, { waitUntil: 'networkidle' })
diff --git a/test/browser/msw-api/setup-worker/scenarios/shared-worker/shared-worker.test.ts b/test/browser/msw-api/setup-worker/scenarios/shared-worker/shared-worker.test.ts
index f5f806786..e5c2cfdcc 100644
--- a/test/browser/msw-api/setup-worker/scenarios/shared-worker/shared-worker.test.ts
+++ b/test/browser/msw-api/setup-worker/scenarios/shared-worker/shared-worker.test.ts
@@ -14,7 +14,7 @@ test('does not interfere with a shared worker', async ({
   await loadExample(new URL('./shared-worker.mocks.ts', import.meta.url), {
     beforeNavigation(compilation) {
       compilation.use((router) => {
-        router.use(express.static(__dirname))
+        router.use(express.static(new URL('./', import.meta.url).pathname))
       })
     },
   })
diff --git a/test/browser/msw-api/setup-worker/start/options-sw-scope.test.ts b/test/browser/msw-api/setup-worker/start/options-sw-scope.test.ts
index 413d89807..0f64c21cf 100644
--- a/test/browser/msw-api/setup-worker/start/options-sw-scope.test.ts
+++ b/test/browser/msw-api/setup-worker/start/options-sw-scope.test.ts
@@ -1,4 +1,3 @@
-import path from 'node:path'
 import { test, expect } from '../../../playwright.extend'
 
 test('respects a custom "scope" Service Worker option', async ({
@@ -7,7 +6,7 @@ test('respects a custom "scope" Service Worker option', async ({
   fetch,
 }) => {
   const consoleSpy = spyOnConsole()
-  await loadExample(path.resolve(__dirname, 'options-sw-scope.mocks.ts'))
+  await loadExample(new URL('options-sw-scope.mocks.ts', import.meta.url))
 
   expect(consoleSpy.get('startGroupCollapsed')).toEqual(
     expect.arrayContaining([expect.stringContaining('[MSW] Mocking enabled.')]),
diff --git a/test/browser/msw-api/setup-worker/start/start.test.ts b/test/browser/msw-api/setup-worker/start/start.test.ts
index 12b464e97..2c9d194d1 100644
--- a/test/browser/msw-api/setup-worker/start/start.test.ts
+++ b/test/browser/msw-api/setup-worker/start/start.test.ts
@@ -1,4 +1,3 @@
-import path from 'node:path'
 import { SetupWorkerApi } from 'msw/browser'
 import { TestFixtures, test, expect } from '../../../playwright.extend'
 
@@ -15,7 +14,7 @@ const exampleOptions: Parameters<TestFixtures['loadExample']> = [
     beforeNavigation(compilation) {
       compilation.use((router) => {
         router.get('/worker.js', (_, res) => {
-          res.sendFile(path.resolve(__dirname, 'worker.delayed.js'))
+          res.sendFile(new URL('worker.delayed.js', import.meta.url).pathname)
         })
       })
     },
diff --git a/test/browser/rest-api/response/body/body-binary.test.ts b/test/browser/rest-api/response/body/body-binary.test.ts
index ef35204f3..a500a1128 100644
--- a/test/browser/rest-api/response/body/body-binary.test.ts
+++ b/test/browser/rest-api/response/body/body-binary.test.ts
@@ -1,5 +1,4 @@
 import fs from 'node:fs'
-import path from 'node:path'
 import { test, expect } from '../../../playwright.extend'
 
 test('responds with a given binary body', async ({ loadExample, fetch }) => {
@@ -10,7 +9,7 @@ test('responds with a given binary body', async ({ loadExample, fetch }) => {
   const body = await res.body()
 
   const expectedBuffer = fs.readFileSync(
-    path.resolve(__dirname, '../../../../fixtures/image.jpg'),
+    new URL('../../../../fixtures/image.jpg', import.meta.url),
   )
 
   expect(status).toBe(200)
diff --git a/test/browser/setup/webpackHttpServer.ts b/test/browser/setup/webpackHttpServer.ts
index 5738160ae..49753e008 100644
--- a/test/browser/setup/webpackHttpServer.ts
+++ b/test/browser/setup/webpackHttpServer.ts
@@ -1,5 +1,4 @@
 import fs from 'node:fs'
-import url from 'node:url'
 import { WebpackHttpServer } from 'webpack-http-server'
 import { getWorkerScriptPatch } from './workerConsole'
 // @ts-expect-error Importing a JavaScript module.
@@ -62,12 +61,11 @@ async function startWebpackServer(): Promise<WebpackHttpServer> {
       },
       resolve: {
         alias: {
-          'msw/browser': url.fileURLToPath(
-            new URL('../../../lib/browser/index.mjs', import.meta.url),
-          ),
-          msw: url.fileURLToPath(
-            new URL('../../../lib/core/index.mjs', import.meta.url),
-          ),
+          'msw/browser': new URL(
+            '../../../lib/browser/index.mjs',
+            import.meta.url,
+          ).pathname,
+          msw: new URL('../../../lib/core/index.mjs', import.meta.url).pathname,
         },
         extensions: ['.ts', '.js', '.mjs', '.cjs'],
       },
diff --git a/test/tsconfig.json b/test/tsconfig.json
index 4699426f3..62ac2ae0f 100644
--- a/test/tsconfig.json
+++ b/test/tsconfig.json
@@ -13,11 +13,6 @@
     "esModuleInterop": true,
     "declaration": false,
     "noEmit": true,
-    "baseUrl": ".",
-    "paths": {
-      "msw": ["../"],
-      "msw/*": ["../*"]
-    },
     "types": ["node", "vitest/globals"]
   },
   "include": ["**/*.ts"]


Reviews:
user: login: Andarist
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T08:43:56Z
user: login: Andarist
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T08:44:55Z
user: login: Andarist
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T08:46:18Z
user: login: Andarist
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T08:49:53Z
user: login: kettanaito
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-06T10:32:17Z
user: login: kettanaito
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-06T10:34:20Z
user: login: Andarist
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T10:41:36Z
user: login: kettanaito
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-06T10:49:05Z
user: login: kettanaito
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-06T10:51:55Z
user: login: Andarist
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T11:20:00Z

Review comments:
diff_hunk: @@ -13,11 +13,6 @@
     "esModuleInterop": true,
     "declaration": false,
     "noEmit": true,
-    "baseUrl": ".",
-    "paths": {
-      "msw": ["../"],
-      "msw/*": ["../*"]
-    },
path: test/tsconfig.json
user: login: Andarist
body: This prevents `package.json#exports` lookup, see: https://github.com/microsoft/playwright/blob/a84ba4db691e7d2a51ff5b2460c9946d406edfc0/packages/playwright/src/util.ts#L365-L375
created_at: 2025-05-06T08:43:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -13,11 +13,6 @@
     "esModuleInterop": true,
     "declaration": false,
     "noEmit": true,
-    "baseUrl": ".",
-    "paths": {
-      "msw": ["../"],
-      "msw/*": ["../*"]
-    },
path: test/tsconfig.json
user: login: Andarist
body: You might have to *build* before you run your tests now. If this is a problem let's figure out the solution to this once we make everything functional
created_at: 2025-05-06T08:44:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -13,11 +13,6 @@
     "esModuleInterop": true,
     "declaration": false,
     "noEmit": true,
-    "baseUrl": ".",
-    "paths": {
-      "msw": ["../"],
-      "msw/*": ["../*"]
-    },
path: test/tsconfig.json
user: login: Andarist
body: Oh, and I'd really just encourage you to get rid of the other `tsconfig.json#paths` you have. My rule of thumb when it comes to `tsconfig.json#paths` is simple: "just don't". I don't think it's worthwhile to save yourself from a few relative paths - especially in the context of a *library*
created_at: 2025-05-06T08:46:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -288,6 +288,7 @@
     "json-bigint": "^1.0.0",
     "knip": "^5.51.1",
     "lint-staged": "^15.2.10",
+    "msw": "workspace:*",
path: package.json
user: login: Andarist
body: this is a funny thing, normally "self resolve" would just work with a modern resolution algorithm (as in - importig/requiring msw from within the msw package). But that only works if your closest `package.json` has a matching `.name`.

But you are introducing a new `package.json` scope to override the module's type here:
https://github.com/mswjs/msw/blob/faed5c016c91e2f84f491d34c9ede92d43dc53e8/test/package.json

and that breaks the node's lookup algorithm for the self-resolve. So to work around this, I have just added an explicit self-devDependency so a normal node_modules lookup can find this.

Question: why are you trying to have the root as commonjs and then override specific directories with module type? I'd probably try the opposite - just make the root a module and then override with commonjs if needed anywhere or just use .cjs if needed
created_at: 2025-05-06T08:49:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -288,6 +288,7 @@
     "json-bigint": "^1.0.0",
     "knip": "^5.51.1",
     "lint-staged": "^15.2.10",
+    "msw": "workspace:*",
path: package.json
user: login: kettanaito
body: > Question: why are you trying to have the root as commonjs and then override specific directories with module type?

Because changing from no `type` (which is implied as CJS) to `type: module` is a breaking change that makes MSW ESM-first. It will break consumers requiring MSW in their apps. I don't want to do that right now. 

I am adding explicit `type: commonjs` simply to be explicit and keep the current behavior. The package must remains CJS-first. What I'm pursuing with this change is to make all of internals ESM. 
created_at: 2025-05-06T10:32:17Z
author_association: MEMBER
diff_hunk: @@ -13,11 +13,6 @@
     "esModuleInterop": true,
     "declaration": false,
     "noEmit": true,
-    "baseUrl": ".",
-    "paths": {
-      "msw": ["../"],
-      "msw/*": ["../*"]
-    },
path: test/tsconfig.json
user: login: kettanaito
body: > You might have to build before you run your tests now.

That was always the case for browser tests. I believe it wasn't the case for node tests but that's a small price to pay for having aliases working. 
created_at: 2025-05-06T10:34:20Z
author_association: MEMBER
diff_hunk: @@ -288,6 +288,7 @@
     "json-bigint": "^1.0.0",
     "knip": "^5.51.1",
     "lint-staged": "^15.2.10",
+    "msw": "workspace:*",
path: package.json
user: login: Andarist
body: > Because changing from no type (which is implied as CJS) to type: module is a breaking change that makes MSW ESM-first. It will break consumers requiring MSW in their apps. I don't want to do that right now.

I don't fully see this argument. The `package.json#type` is just a default value that you can "override". If you override all places then your CJS consumers won't notice a thing. The same rule applies to the opposite situation, the one that you are trying to achieve here. You have a CJS-first repo, but you provide ESM entrypoints so your consumers won't even know that it's configured as CJS. 

created_at: 2025-05-06T10:41:36Z
author_association: CONTRIBUTOR
diff_hunk: @@ -288,6 +288,7 @@
     "json-bigint": "^1.0.0",
     "knip": "^5.51.1",
     "lint-staged": "^15.2.10",
+    "msw": "workspace:*",
path: package.json
user: login: kettanaito
body: Perhaps you're right. I simply fear the cases where people do `require('msw')`. I don't want those to start failing out of a sudden because the root-level `type` has been set to `module`. 

Keep in mind that we are also talking about _really old_ tools. Tools that don't know what `exports` is. I know for a fact there are MSW consumers that rely on those tools. Changing the module `type` in that case is a breaking change in every sense of the word. 
created_at: 2025-05-06T10:49:05Z
author_association: MEMBER
diff_hunk: @@ -288,6 +288,7 @@
     "json-bigint": "^1.0.0",
     "knip": "^5.51.1",
     "lint-staged": "^15.2.10",
+    "msw": "workspace:*",
path: package.json
user: login: kettanaito
body: I suppose we do have module operability tests to keep us somewhat safe and validate if what you're proposing won't break CJS consumers. I can try that. 
created_at: 2025-05-06T10:51:55Z
author_association: MEMBER
diff_hunk: @@ -288,6 +288,7 @@
     "json-bigint": "^1.0.0",
     "knip": "^5.51.1",
     "lint-staged": "^15.2.10",
+    "msw": "workspace:*",
path: package.json
user: login: Andarist
body: > Perhaps you're right. I simply fear the cases where people do require('msw'). I don't want those to start failing out of a sudden because the root-level type has been set to module.

Whatever tool that respects `package.json#type` should also respect `package.json#exports`. In that situation, those tools will resolve through `exports` first and they will just find relevant `require` conditions there (or `module-sync`).

> Keep in mind that we are also talking about really old tools. Tools that don't know what exports is. I

For those just keep `package.json#main` pointing to the CJS build. If they are unaware of `package.json#exports` they are surely also not aware of `package.json#type`
created_at: 2025-05-06T11:20:00Z
author_association: CONTRIBUTOR

PR comments:
user: login: kettanaito
created_at: 2025-05-06T10:33:38Z
body: Thank you so much, @Andarist 🙏 From what I can see, the current `test:browser` failures are related to CJS leftovers. I will cherry-pick the changes from another PR, I've already solve these. Excited to see how this goes. 
author_association: MEMBER
user: login: kettanaito
created_at: 2025-05-06T10:43:48Z
body: Looks like `msw` imports are still broken in tests:

```
> msw@2.7.6 test:browser /Users/kettanaito/Documents/web/mswjs/msw
> playwright test -c ./test/browser/playwright.config.ts

(node:47745) ExperimentalWarning: Importing JSON modules is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
Error: Cannot find package 'msw' imported from /Users/kettanaito/Documents/web/mswjs/msw/test/browser/rest-api/response-patching.test.ts
```

This _might_ be a TS-only issue. TS fails to resolve types for `msw` imports at all.

I'm getting this on Node.js v18.20.4 and TypeScript 5.5.2, if that makes any difference.  

_Edit:_ I don't quite understand how come the CI tests are not having this error. Changing to `type: module` has no effect on this error. 
author_association: MEMBER
user: login: Andarist
created_at: 2025-05-06T11:09:14Z
body: > Looks like msw imports are still broken in tests:

This is unexpected. `msw` resolved fine when running `test:browser` for me before I pushed this. The job run on my commit suggests the same (240 tests passed): https://github.com/mswjs/msw/actions/runs/14855375796/job/41707378564

> I'm getting this on Node.js v18.20.4 and TypeScript 5.5.2, if that makes any difference.

`pnpm test:browser test/browser/rest-api/response-patching.test.ts` runs just OK for me on node v18.20.3. But overall, ye - Playwright is using node itself (with customizations) to resolve and load those modules. So the results could be specific to a node version (I doubt the `0.0.1` difference is at fault here though)

---

Either way, I'll take a look at the current state of things a little bit later :p
author_association: CONTRIBUTOR
user: login: kettanaito
created_at: 2025-05-06T11:13:05Z
body: > I doubt the 0.0.1 difference is at fault here though

Hah! 0.0.1 _did_ make a difference. Now I have the tests running on v18.20.8. 

I think your changes fixed the browser tests! 🎉 I will wrap this up and merge it. 
author_association: MEMBER
user: login: Andarist
created_at: 2025-05-06T11:14:55Z
body: <img src="https://media1.giphy.com/media/v1.Y2lkPTc5MGI3NjExdTByY2FrZ2h1cmlkbXI4YWhjOHVtcWVxcHl3cmt4MHJxOXMwaDI3dCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/4ls9MvzG21kem11N1N/giphy.gif" />

I was running on an older one that yours though. That's not a great sign :/
author_association: CONTRIBUTOR
user: login: kettanaito
created_at: 2025-05-06T11:15:37Z
body: Regressions happen. We should be running on the latest of any major anyway. I don't treat this as an issue. 
author_association: MEMBER
user: login: Andarist
created_at: 2025-05-06T11:17:05Z
body: Ah, so it works on one that is even newer. I agree, that's fine 👍 
author_association: CONTRIBUTOR
user: login: kettanaito
created_at: 2025-05-06T11:24:22Z
body: @Andarist, you, sir, are a wizard once again. Thank you so much! 
author_association: MEMBER