mswjs / msw

Industry standard API mocking for JavaScript.
https://mswjs.io
MIT License
15.97k stars 519 forks source link

Always 404 / Not Intercepted on homepage set CRA #2274

Open chiahao opened 2 months ago

chiahao commented 2 months ago

Prerequisites

Environment check

Browsers

Firefox, Safari

Reproduction repository

https://github.com/chiahao/mymswtestapp.git

Reproduction steps

Describe the bug

create-react-app with homepage setted causes MSW not to mock

Environment

react: "^18.3.1" msw: "^2.4.4" nodejs: 21.1.0

To Reproduce

  1. npx create-react-app mytestapp
  2. npm install msw@latest --save-dev
  3. npx msw init public --save
  4. mymswtestapp/src/mocks/browser.js
import { setupWorker } from "msw/browser";
import { handlers } from "./handler";

export const worker = setupWorker(...handlers);
  1. mymswtestapp/src/mocks/handler.js
import { http, HttpResponse } from 'msw';

export const handlers = [
    http.post("api/code/NAT/:code", () => {
        return HttpResponse.json({
            "data": [
                {"CODE": "11", "DESCR": "UNIT1"},
                {"CODE": "22", "DESCR": "UNIT2"}
            ]
        });
    }),

]
  1. mymswtestapp/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

async function enableMocking() {
    if (process.env.NODE_ENV !== 'development') {
        return;
    }

    const { worker } = await import("./mocks/browser");

    let workerService = worker.start();
    console.log(worker.listHandlers());
    return workerService;
}

enableMocking().then(() => {

    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(
      <React.StrictMode>
        <App />
      </React.StrictMode>
    );
});
  1. in firefox, send request http://localhost:3000/api/code/NAT/1 can be succefully intercepted.

  2. Add "homepage": "myPage", to package.json.

  3. Modify mytestapp/index.js:

async function enableMocking() {
    if (process.env.NODE_ENV !== 'development') {
        return;
    }

    const packageJson = await import("../package.json");
    const { worker } = await import("./mocks/browser");

    // `worker.start()` returns a Promise that resolves
    // once the Service Worker is up and ready to intercept requests.
    let workerService = worker.start({
        serviceWorker: {
            // Provide a custom worker script URL, taking
            // the "homepage" into account.
            url: `${packageJson.homepage}/mockServiceWorker.js`,
        },
    });
}

enableMocking().then(() => {

const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(
      <React.StrictMode>
        <App />
      </React.StrictMode>
    );
});
  1. Now npm start still can start server, and show [MSW] Mocking enabled..
    But requests won't intercepted.

Current behavior

Firefox get this:
Cannot POST /myPage/api/code/NAT/1

Expected behavior

"data": [ {"CODE": "11", "DESCR": "UNIT1"}, {"CODE": "22", "DESCR": "UNIT2"} ]

kettanaito commented 2 months ago

Hi, @chiahao. Thanks for reporting this.

Can you please follow the Debugging runbook and let me know how far you got?

chiahao commented 2 months ago

Hi, @kettanaito . Thanks for so fast response.

Modified browser.js:

import { setupWorker } from "msw/browser";
import { handlers } from "./handler";

export const worker = setupWorker(...handlers);
worker.events.on('request:start', async ({ request }) => {
  // Read the request body as text for every request
  // that occurs in your application.
  const payload = await request.clone().text()
});

worker.events.on('request:start', ({ request }) => {
  console.log('Outgoing:', request.method, request.url)
});

Test the version where the homepage is not set. The request is intercepted and shown in the console:

without_homepage_setting

But still, once homepage is set, the request is not intercepted:

with_homepage_setting
chiahao commented 2 months ago

Hi, @kettanaito , does this test right?

kettanaito commented 2 months ago

Can you please await the worker.start() promise? That doesn't look right.

chiahao commented 2 months ago

Hi, @kettanaito ,

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

async function enableMocking() {
    if (process.env.NODE_ENV !== 'development') {
        return;
    }

    const packageJson = await import("../package.json");
    const { worker } = await import("./mocks/browser");

    // `worker.start()` returns a Promise that resolves
    // once the Service Worker is up and ready to intercept requests.
    await worker.start({
        serviceWorker: {
            // Provide a custom worker script URL, taking
            // the "homepage" into account.
            url: `${packageJson.homepage}/mockServiceWorker.js`,
        },
    });
    console.log(worker.listHandlers());
}

enableMocking().then(() => {
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(
        <React.StrictMode>
            <App />
        </React.StrictMode>
    );
});

still no luck with await. But there is a warning:

截圖 2024-09-20 清晨7 44 59

Does this mean MSW not support custom project path? Thanks for any helping.