DevExpress / testcafe

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

RangeError: Maximum call stack size exceeded #8104

Closed volosincu closed 8 months ago

volosincu commented 9 months ago

What is your Scenario?

NPM dependencies package.json

 "@reduxjs/toolkit": "^2.0.1",
    "axios-hooks": "^5.0.2",
    "clsx": "^1.1.1",
    "mui-image": "^1.0.7",
    "npm-force-resolutions": "^0.0.10",
    "prop-types": "^15.7.2",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-redux": "^8.1.2",
    "react-world-flags": "^1.5.1",
    "redux": "^4.2.1",
    "redux-immutable-state-invariant": "^2.1.0",
    "redux-thunk": "^2.4.2"

Webpack config

 new ModuleFederationPlugin({
        name: 'myApp', 
        remotes: {
          mfeCommon: microFrontendRemoteUrl,
        },
        shared: {
          react: {
            singleton: true,
            requiredVersion: deps.react,
            eager: true,
          },
          'react-dom': {
            singleton: true,
            requiredVersion: deps['react-dom'],
            eager: true,
          },
        },
      }),
import MenuComponent from './menu/MenuComponent';
import { createRoot } from 'react-dom/client';
const Shell = React.lazy(() => import('mfeCommon/Shell'));
const ShellContextProvider = React.lazy(() =>
  import('mfeCommon/ShellContextProvider')
);
const Header = React.lazy(() =>
  import('mfeCommon/Header')
);

function MfeStudio() {
  const [shellData, setShellData] = React.useState({
    applicationSettings: {},
  } as IShellData);

  return (
    <Suspense fallback={<></>}>
      <ShellContextProvider
        value={{
          shellData,
          setShellData,
        }}
      >
        <Shell>
          <Header />
          <MenuComponent />
        </Shell>
      </ShellContextProvider>
    </Suspense>
  );
}
remoteApp/Shell  RangeError: Maximum call stack size exceeded
    at PropertyAccessorsInstrumentation._propertyGetter (hammerhead.js:20827:66)
    at get maxSize [as maxSize] (vendors-node_modules_axios-hooks_es_index_js.js:1060:17)
    at PropertyAccessorsInstrumentation._propertyGetter (hammerhead.js:20839:22)
    at get maxSize [as maxSize] (vendors-node_modules_axios-hooks_es_index_js.js:1060:17)
    at PropertyAccessorsInstrumentation._propertyGetter (hammerhead.js:20839:22)
    at get maxSize [as maxSize] (vendors-node_modules_axios-hooks_es_index_js.js:1060:17)
    at PropertyAccessorsInstrumentation._propertyGetter (hammerhead.js:20839:22)
    at get maxSize [as maxSize] (vendors-node_modules_axios-hooks_es_index_js.js:1060:17)
    at PropertyAccessorsInstrumentation._propertyGetter (hammerhead.js:20839:22)
    at get maxSize [as maxSize] (vendors-node_modules_axios-hooks_es_index_js.js:1060:17)
    Uncaught ReferenceError: Cannot access '__WEBPACK_DEFAULT_EXPORT__' before initialization
    at Module.default (vendors-node_modules_axios-hooks_es_index_js.js:16:42)
    at getter (remote.js:96:27)
    at useCacheTimestamps (src_Events_EventHandlers_ts-src_components_Icons_IconsHelper_tsx-src_components_Menu_menu_hoo-0ffb7f.js:1255:14)
    at Header (src_components_Header_Header_tsx-webpack_sharing_consume_default_clsx_clsx.js:1518:76)
    at renderWithHooks (bundle.app.js:16261:18)
    at updateFunctionComponent (bundle.app.js:19539:20)
    at mountLazyComponent (bundle.app.js:19910:17)
    at beginWork (bundle.app.js:21544:16)
    at HTMLUnknownElement.callCallback (bundle.app.js:4120:14)
    at HTMLUnknownElement.dispatchEvent (hammerhead.js:40262:56)

TestCafe-webpack-err__2023-12-14 095946

What is the Current behavior?

Scenario

The tests flows break with following errors

When rendering the 2 components from the remote microfrontend the error below appears. It happens only in the TestCafe browser window. Not sure why but I reckon that hooks from the components loaded with dynamic import in React.lazy break cause WEBPACK_DEFAULT_EXPORT is missing ( the same code works if not in TestCafe context)

What is the Expected behavior?

To render the 2 components from the remote microfrontend.

What is the public URL of the test page? (attach your complete example)

https://localhost:80/

What is your TestCafe test code?

fixture`Smoke Test`.page("https://localhost:80/");

test("crawl homepage test", async (t) => {
  await t.setNativeDialogHandler(() => true);

  try {
   await t
        .typeText("#username", username)
        .typeText("#password", password)
        .click(Selector("#login"));

      await t
        .expect(
          await Selector("#create-asset", { timeout: 30000 }).visible
        )
        .eql(true);

Your complete configuration file


module.exports = {
  selectorTimeout: 30000,
  pageLoadTimeout: 10000,
  ajaxRequestTimeout: 60000,
  pageRequestTimeout: 25000,
  browsers: "chrome",
  skipJsErrors: true,
  disableNativeAutomation: false,
  hostname: "localhost",
  //concurrency: 2,
  videoPath: "./output/report-video",
  videoOptions: {
    singleFile: false,
    failedOnly: true,
    pathPattern:
      "${FIXTURE}/${TEST}/${USERAGENT}/${DATE}_${TIME}/${FILE_INDEX}.mp4",
  },
  screenshots: {
    path: "./output/report-images",
    takeOnFails: true,
    fullPage: true,
    failedOnly: true,
    pathPattern:
      "${FIXTURE}/${TEST}/${USERAGENT}/${DATE}_${TIME}/${FILE_INDEX}.png",
  },
  reporter: [
    {
      name: "custom",
      output: "output-custom/report.txt",
    },
    {
      name: "html",
      output: "output/report.html",
    },
  ],
  hooks: {},
};

Your complete test report

No response

Screenshots

No response

Steps to Reproduce

  1. create a microfrontend React architecture with ModuleFederationPlugin
  2. use es6 dynamic import to load remote component in React.lazy
  3. add an axios hook in one of the remove components

TestCafe version

3.4.0

Node.js version

18.10

Command-line arguments

npx testcafe ./test_examples/test_smoke.js --config-file .testcafenight.js

Browser name(s) and version(s)

Chrome 120

Platform(s) and version(s)

Windows 11

Other

No response

PavelMor25 commented 9 months ago

Hello @volosincu,

Could you please pack all necessary files into a public repository?

volosincu commented 8 months ago

Cause

The cause is upgrade of axios-hooks to version 5.0.0 or greater. The issue is the change on default lru cache settings in axios-hooks starting with 5.0.0. If my remote (exposed from webpack-module-federation) use axios-hooks smaller than v5.0.0 then test cafe has no issue running the tests.

Solution and repo for reproduction

The solution was to disable cache when initialize axios-hooks configure({ cache: false });. To reproduce the bug I created this repo with basic setup React webpack modfed. If remote app doesn't start after npm start just run npm start in the remote directory.

See lines 4 and 5 code

The testcafe code


import { Selector } from "testcafe";

fixture`Smoke Test`.page("http://localhost:3000/");

test("crawl homepage", async (t) => {
  await t.setNativeDialogHandler(() => true);

  await t.wait(5000);
  await t.click("#btn-hello");
  await t.click("#btn-clean");
  await t.wait(5000);
  await t.wait(5000);
  await t.click("#btn-refetch");
  await t.wait(5000);
  await t.click(Selector("#id-3Gti52e4r344"));

  await t.wait(5000);
});

Error:

hammerhead.js:20803 Uncaught (in promise) Error: Cannot set property '0' of undefined
    at PropertyAccessorsInstrumentation._error (hammerhead.js:20803:16)
    at PropertyAccessorsInstrumentation._propertySetter (hammerhead.js:20856:47)
    at LRUCache.set (index.js:856:14)
    at tryStoreInCache (index.js:133:11)
    at _callee2$ (index.js:193:13)
    at tryCatch (regeneratorRuntime.js:45:16)
    at Generator.eval (regeneratorRuntime.js:133:17)
    at Generator.eval [as next] (regeneratorRuntime.js:74:21)
    at fastApply (hammerhead.js:20899:26)
    at value (hammerhead.js:20987:25)
Bayheck commented 8 months ago

Hello,

Thank you for creating an example repo.

I did not encounter any issues when running your test in Native Automation mode. Starting from version 3.0, TestCafe runs tests with the Native Automation option enabled by default. If you can reproduce the issue using native automation mode, please create a separate ticket using this template