Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

next js component tests config is using framework.react instead of next which causes dev server errors for server components #21768

Closed
1 of 4 tasks
tar-aldev opened this issue Feb 10, 2024 · 4 comments · Fixed by #22170
Assignees
Labels
outdated scope: nextjs Issues related to NextJS support for Nx scope: testing tools Issues related to Cypress / Jest / Playwright / Vitest support in Nx type: bug

Comments

@tar-aldev
Copy link

tar-aldev commented Feb 10, 2024

Current Behavior

When generating cypress component test config for next using nx generate @nx/next:cypress-component-configuration
it creates the following cypress.config.ts

import { defineConfig } from 'cypress';
import { nxComponentTestingPreset } from '@nx/next/plugins/component-testing';

export default defineConfig({
  component: {
    ...nxComponentTestingPreset(__filename),
    devServer: {
      framework: 'next',
      bundler: 'webpack'
    }
  }
});

It works fine for client components, but when trying to test server components (even if they have no specific features), webpack dev server gives errors like:

webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
        - add a fallback 'resolve.fallback: { "path": require.resolve("path-browserify") }'
        - install 'path-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
        resolve.fallback: { "path": false }

Expected Behavior

Should be able to use generated cypress config to run component tests for both client and server components.
Should be able to stub next specific features (like router)

GitHub Repo

https://github.com/tar-aldev/next-nx-cypress

Steps to Reproduce

  1. generate next.js library
  2. generate cypress component tests config nx generate @nx/next:cypress-component-configuration
  3. create test for server component
  4. run cypress component tests with nx run component-test --watch=true`

Using reproduction repo:

  1. run npx nx component-test test-lib --watch=true
  2. run the test HelloServer

Nx Report

Node   : 18.18.2
   OS     : darwin-arm64
   pnpm   : 8.7.6
   
   nx                 : 17.3.1
   @nx/js             : 17.3.1
   @nx/jest           : 17.3.1
   @nx/linter         : 17.3.1
   @nx/eslint         : 17.3.1
   @nx/workspace      : 17.3.1
   @nx/cypress        : 17.3.1
   @nx/devkit         : 17.3.1
   @nx/eslint-plugin  : 17.3.1
   @nx/express        : 17.3.1
   @nx/next           : 17.3.1
   @nx/node           : 17.3.1
   @nx/playwright     : 17.3.1
   @nx/react          : 17.3.1
   @nx/storybook      : 17.3.1
   @nrwl/tao          : 17.3.1
   @nx/web            : 17.3.1
   @nx/webpack        : 17.3.1
   typescript         : 5.3.3
   ---------------------------------------
   Community plugins:
   @ago-dev/nx-aws-cdk-v2 : 1.6.1

Failure Logs

No response

Package Manager Version

No response

Operating System

  • macOS
  • Linux
  • Windows
  • Other (Please specify)

Additional Information

Using

"@cypress/webpack-dev-server": "^3.7.2",
"@cypress/webpack-preprocessor": "6.0.1",

I tried based on this example repo https://github.com/mike-plummer/nextjs-cypress-ct-example/tree/main
If you clone that repo everything is working fine there. So it's not a cypress problem or next problem.

I can also see in cypress docs, that they set framework as next https://docs.cypress.io/guides/component-testing/react/overview#Nextjs
If I check nx source code https://github.com/nrwl/nx/blob/master/packages/next/plugins/component-testing.ts#L158 I see that framework is set to react there.
Could it be a problem?

When I try to change generate config to

import { defineConfig } from 'cypress';
import { nxComponentTestingPreset } from '@nx/next/plugins/component-testing';

export default defineConfig({
  component: {
    ...nxComponentTestingPreset(__filename),
    devServer: {
      framework: 'next',
      bundler: 'webpack'
    }
  }
});

When I run it though, it gives another error

The following error originated from your test code, not from Cypress.

  > Cannot read properties of null (reading 'parentNode')

When Cypress detects uncaught errors originating from your test code it will automatically fail the current test.

Cypress could not associate this error to any specific test.

We dynamically generated a new test to display this failure.

UPD:
The above error was caused by this import in libs/cypress/support/component.ts

import './styles.ct.css';

After removing it, the error is gone

UPD 2:
while it works for smth simple, it fails for simple things, like when importing an interface

Module parse failed: Unexpected token (4:12)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|  next three classes should be optimized when synchronization of student information with Google will be added
| */
> import type

UPD 3:

Tried using it like this

const config = nxComponentTestingPreset(__filename, {
  bundler: 'webpack',
  compiler: 'swc'
});

export default defineConfig({
  component: {
    devServer: {
      bundler: config.devServer.bundler,
      webpackConfig: config.devServer.webpackConfig,
      framework: 'next'
    }
  }
});

Unfortunately, it fails with a weird error

Module build failed (from ../../../node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/next/dist/build/webpack/loaders/next-swc-loader.js):
Error: failed to read input source map from user-provided sourcemap

Caused by:
    bad json: invalid type: string "{\"version\":3,\"sources\":[\"/Users/t-alex/projects/work/efacity/libs/frontend-next-shared/header/cypress/support/component.ts\"],\"names\":[\"mount\",\"Cypress\",\"Commands\",\"add\"],\"mappings\":\"AAAA,SAASA,KAAK,QAAQ,kBAAkB;AACxC,8DAA8D;AAC9D,qDAAqD;AACrD,+CAA+C;AAC/C,EAAE;AACF,wDAAwD;AACxD,kCAAkC;AAClC,EAAE;AACF,uDAAuD;AACvD,+CAA+C;AAC/C,sCAAsC;AACtC,EAAE;AACF,0BAA0B;AAC1B,sCAAsC;AACtC,8DAA8D;AAE9D,0CAA0C;AAC1C,OAAO,aAAa;AAapBC,QAAQC,QAAQ,CAACC,GAAG,CAAC,SAASH\"}", expected struct RawSourceMap at line 1 column 475

So it's kind of broken it seems:
when using OOTB nxComponentTestingPreset it fails when there is any server component.
when trying to extend it to specify next as framework it fails with sourcemap problems.

@tar-aldev tar-aldev changed the title Trying to component test next js server component leads to webpack < 5 used to include polyfills for node.js core modules by default error next js component tests config is using framework.react instead of next which causes dev server errors for server components Feb 10, 2024
@tar-aldev
Copy link
Author

As a workaround for now, I ended up with the following:

cypress.config.ts

import { nxComponentTestingPreset } from '@nx/next/plugins/component-testing';
import { defineConfig } from 'cypress';

export default defineConfig({
  component: nxComponentTestingPreset(__filename)
});

then the trick is to not impot anything next related in test itself.
so I put some logic into libs/<libname>/cypress/support/component.tsx

import { mount } from 'cypress/react18';
import './commands';
import { HeadManagerContext } from 'next/dist/shared/lib/head-manager-context.shared-runtime';
import { RouterContext } from 'next/dist/shared/lib/router-context.shared-runtime';
import { AppRouterContext } from 'next/dist/shared/lib/app-router-context.shared-runtime';

// add component testing only related command here, such as mount
declare global {
  // eslint-disable-next-line @typescript-eslint/no-namespace
  namespace Cypress {
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    interface Chainable<Subject> {
      mount: typeof mount;
      nextMount: any;
    }
  }
}

Cypress.Commands.add('mount', mount);

Cypress.Commands.add('nextMount', (component, options) => {
  const createRouter = (params) => ({
    route: '/',
    pathname: '/',
    query: {},
    asPath: '/',
    basePath: '',
    back: cy.stub().as('router:back'),
    forward: cy.stub().as('router:forward'),
    push: cy.stub().as('router:push'),
    reload: cy.stub().as('router:reload'),
    replace: cy.stub().as('router:replace'),
    isReady: true,
    ...params
  });
  const router = createRouter(options?.router || {});

  const createHeadManager = (params) => ({
    updateHead: cy.stub().as('head:updateHead'),
    mountedInstances: new Set(),
    updateScripts: cy.stub().as('head:updateScripts'),
    scripts: new Set(),
    getIsSsr: () => false,
    appDir: false,
    nonce: '_',
    ...params
  });

  const headManager = createHeadManager(options?.head || {});

  return mount(
    <HeadManagerContext.Provider value={headManager}>
      <AppRouterContext.Provider value={router}>{component}</AppRouterContext.Provider>
    </HeadManagerContext.Provider>,
    options
  );
});

Source from here

Finally in test

cy.nextMount(<ComponentWithUseRouter />);

I haven't tested it deep yet, but at least I am able to see component is rendered now

@AgentEnder AgentEnder added scope: testing tools Issues related to Cypress / Jest / Playwright / Vitest support in Nx scope: nextjs Issues related to NextJS support for Nx labels Feb 16, 2024
@ghost
Copy link

ghost commented Feb 20, 2024

Also experiencing the exact same issue reported by @tar-aldev using the out-of-the-box Component testing generator for NextJs. Followed the docs and Juri's video and configuration is otherwise the same.

@ndcunningham
Copy link
Contributor

Hey, thanks for reporting there are a few things to unpack here related to generating a cypress config for a library created with @nx/next.

I think we need to fix the error generated by importing the style. Everything else should be working as expected.

export default defineConfig({
  component: {
    ...nxComponentTestingPreset(__filename),
    devServer: {
      framework: 'next',
      bundler: 'webpack'
    }
  }
});

This might seem to work for your test but it creates new issues as you have completely removed the webpackConfig property. Workspace libraries/css among other things may not work with this configuration.

If you want to add the router to your library you need to ensure Cypress is configured to test it.

Copy link

github-actions bot commented Apr 5, 2024

This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 5, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
outdated scope: nextjs Issues related to NextJS support for Nx scope: testing tools Issues related to Cypress / Jest / Playwright / Vitest support in Nx type: bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants