DevExpress / testcafe

A Node.js tool to automate end-to-end web testing.
https://testcafe.io
MIT License
9.82k stars 670 forks source link

HammerHead doesn't forward the requests to the service worker #7429

Closed Roy412 closed 1 year ago

Roy412 commented 1 year ago

What is your Scenario?

I'm working on the testcafe based on NextJS framework and integrated msw library for mocking requests. Testcafe hammeread doesn't forward the some mock requests to the msw service worker and the requests fail with 404 Not Found. I debugged some hammerhead library codes and I guess this is related to the scope problem of hammerhead but not sure how I can fix this.

What is the Current behavior?

Interestingly, the mocking requests at testcafe tests work fine at the level 1 route pages(like '/', '/account', '/login', ...) and not working at deeper level sub-paths (e.g '/account/login', '/account/login/test', ...).

What is the Expected behavior?

The mocking request at testcafe should work at every sub paths. :)

What is your public website URL? (or attach your complete example)

To reproduce

What is your TestCafe test code?

https://github.com/Roy412/msw-testcafe-error/blob/main/testcafe/rest.spec.ts

Your complete configuration file

No response

Your complete test report

roy@Roys-iMac msw-testcafe-error % yarn testcafe
yarn run v1.22.19
$ NEXT_PUBLIC_IS_TESTCAFE=1 node runtestCafe.js
 Running tests in:
 - Chrome 108.0.0.0 / Ventura 13

 Rest
 ✖ should do a GET

   1) An error occurred in Selector code:

          TestingLibraryElementError: Unable to find an accessible element with the role "heading" and name "Success"

      Here are the accessible roles:

      heading:

      Name "Loading...":
      <h1 />

      --------------------------------------------------
      button:

      Name "fetch":
      <button />

      --------------------------------------------------alert:

      Name "":
      <p
      aria-live="assertive"
      id="__next-route-announcer__"
      role="alert"
      style="border: 0px; clip: rect(0px, 0px, 0px, 0px); height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px; white-space:
      nowrap; overflow-wrap: normal;"
      />

      --------------------------------------------------

      <body>
      <div
      id="__next"
      >
      <div>
        <h1>
          Loading...
        </h1>
        <button>
          fetch
        </button>
      </div>
      </div>
      <script
      src="/_next/static/chunks/react-refresh.js?ts=1671491285969"
      />
      <script
      id="__NEXT_DATA__"
      type="application/json"
      >
      {"props":{"pageProps":{}},"page":"/account/login/test","query":{},"buildId":"development","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}
      </script>
      <div
      id="__next-build-watcher"
      style="position: fixed; bottom: 10px; right: 20px; width: 0px; height: 0px; z-index: 99999;"
      />
      <next-route-announcer>
      <p
        aria-live="assertive"
        id="__next-route-announcer__"
        role="alert"
        style="border: 0px; clip: rect(0px, 0px, 0px, 0px); height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px; white-space:
      nowrap; overflow-wrap: normal;"
      />
      </next-route-announcer>
      </body>

      Browser: Chrome 108.0.0.0 / macOS 10.15.7

          9 |test("should do a GET", async (t) => {
         10 |  await t
         11 |    .expect(screen.findByRole('heading',{ name: 'Loading...' }).exists).ok('Page loaded')
         12 |    .click(screen.getByRole("button", { name: /fetch/i }))
         13 |    .wait(500)
       > 14 |    .expect(screen.getByRole("heading", { name: 'Success' }).exists).ok('Data Fetch Success')
         15 |});
         16 |// test("should do a DELETE", async (t) => {
         17 |//   await t
         18 |//     .expect(screen.findAllByRole("heading", { name: /foo|bar/ }).count)
         19 |//     .eql(2)

         at <anonymous> (/Users/roy/msw-testcafe-error/testcafe/rest.spec.ts:14:70)
         at <anonymous> (/Users/roy/msw-testcafe-error/testcafe/rest.spec.ts:8:71)
         at __awaiter (/Users/roy/msw-testcafe-error/testcafe/rest.spec.ts:4:12)
         at <anonymous> (/Users/roy/msw-testcafe-error/testcafe/rest.spec.ts:9:37)

 1/1 failed (5s)

Screenshots

Screenshot 2022-12-19 at 4 51 07 PM Screenshot 2022-12-19 at 11 41 30 PM

No response

Steps to Reproduce

To reproduce

TestCafe version

2.1.0

Node.js version

v16.16.0

Command-line arguments

NEXT_PUBLIC_IS_TESTCAFE=1 node runtestCafe.js

Browser name(s) and version(s)

No response

Platform(s) and version(s)

No response

Other

https://github.com/DevExpress/testcafe-hammerhead/blob/53f57614e829fc8f1f870b9904c3f5bdce76bfa6/src/client/worker/fetch-event.ts#L19

This check fails. parsedUrl.partAfterHost.startsWith(swFetchCheckSettings.scope)

In my case,

parsedUrl.partAfterHost: "/Kc760vbDm*hhGNZfK60/http://localhost:3000/account/login/test"
swFetchCheckSettings.scope: "/account/login/"

Not sure which one of parsedUrl.partAfterHost or swFetchCheckSettings.scope value is wrong.

felis2803 commented 1 year ago

Hi @Roy412,

Thanks for your report. I reproduced this behavior. We will inform you as soon as we have news on this issue.

miherlosev commented 1 year ago

Hi @Roy412

As a workaround, you can use the --experimental-proxyless option to run the tests. Option syntax:

// Command-line
testcafe chrome tests --experimental-proxyless

// Programmatic
const testcafe = await createTestCafe({ experimentalProxyless: true });

// Configuration file
{
   "experimentalProxyless": "true"
}    

I've run the tests with the testcafe@2.2.0-rc.1 version and the --experimental-proxyless option enabled, and the initial issue is not reproduced. There is some test error, but it looks like you need to fix the test. test-error

Roy412 commented 1 year ago

Hi @miherlosev Thanks for the reply. Enabling experimentalProxyless at testcafe@2.2.0-rc.1 resolved the proxy issue. However, as you can see, it brings another problem of testing library compatibility. Cannot call method `queryByRole` of undefined

Obviously, @testing-library/testcafe doesn't work with experimentalProxyless option. I tested with the latest version of testing-library already and this compatibility is very important for us as we use it everywhere in our project. Can you please help me with this issue and should I raise a new issue about this?

miherlosev commented 1 year ago

https://github.com/DevExpress/testcafe/issues/7429

Enabling experimentalProxyless at testcafe@2.2.0-rc.1 resolved the proxy issue.

I'm happy to hear this.

Obviously, @testing-library/testcafe doesn't work with experimentalProxyless option. I tested with the latest version of testing-library already and this compatibility is very important for us as we use it everywhere in our project. Can you please help me with this issue and should I raise a new issue about this?

Please simplify the example and create a new issue with it.

Roy412 commented 1 year ago

Please simplify the example and create a new issue with it.

@miherlosev Just raised a new issue with the simple demo project. https://github.com/DevExpress/testcafe/issues/7439

miherlosev commented 1 year ago

Thank you very much.

Roy412 commented 1 year ago

@miherlosev Can you please let me know how I can modify the proxy URL of a certain public resource(app/public/mockServiceWorker.js) to be hosted at the URL without hash?

Current serviceWorker is hosted at https://localhost:1337/fKieyJftH*vfYuf6GWj!c!utf-8/http://localhost:3000/mockServiceWorker.js I'd like to host it at https://localhost:1337/mockServiceWorker.js or https://localhost:1337/fKieyJftH*vfYuf6GWj/http://localhost:3000/mockServiceWorker.js

I'd appreciate if you locate the related hammerhead code so that I can modify it on my end. Or how can I get that KieyJftH*vfYuf6GWj!c!utf-8 value?

AlexKamaev commented 1 year ago

@Roy412 The proxied url is not supposed to be modified. However, if you want to research the issue, you can start from the following code lines:

  1. Overriding service worker registration: https://github.com/DevExpress/testcafe-hammerhead/blob/17a4b7ca22781c415004d15400cdedf261d6ab36/src/client/sandbox/node/window.ts#L723
  2. Replacing the url with the proxied url: https://github.com/DevExpress/testcafe-hammerhead/blob/17a4b7ca22781c415004d15400cdedf261d6ab36/src/client/sandbox/node/window.ts#L736
Roy412 commented 1 year ago

@AlexKamaev Thanks, it worked.

miherlosev commented 1 year ago

Hi @Roy412,

This issue is not reproduced with combination of testcafe@3.0.1 and the Google Chrome browser. Feel free to reopen this issue if you encounter it in other browsers.

ilya2010ujl commented 1 year ago

Hello I encountered the same error, which is reproduced on version 2.4.0 with experimentalProxyless turned off. If you turn it on, the page opens correctly. On version 3.1.0 - the error is reproduced both with experimentalProxyless disabled and enabled. Could you reopened the bug?

AlexKamaev commented 1 year ago

Hi @ilya2010ujl,

There is no experimentalProxyless option in the 3.1.0 version. Now it is called the Native Automation mode and it is enabled by default. If you still encounter an issue in Native Automation mode in Chromium-based browsers, please create a separate ticket using the following link: https://github.com/DevExpress/testcafe/issues/new?assignees=&labels=TYPE%3A+bug&projects=&template=bug_report.yaml.