cypress-io / cypress

Fast, easy and reliable testing for anything that runs in a browser.
https://cypress.io
MIT License
47.06k stars 3.19k forks source link

Cypress 10 | SASS Global Style File Imports Within Next.js - Unable To Run Cypress Component Test #22525

Closed Sayvai closed 2 years ago

Sayvai commented 2 years ago

Current behavior

After launching Cypress Component Test application for the Next.js project, and importing multiple SASS (.scss) files from within the cypress/component.ts file, then i am unable to run a defined component test within the file news-aggregator-article.cy.tsx (link to file on repo). On the test rendering panel, only the text Cannot GET /__cypress/src/index.html is rendered out.

See the highlighted screenshot below: cypress-10_import-scss_unable-to-run-component-test

Is it not currently possible to import / support SASS style files for component testing? Or am i missing a step? 🤔

If SASS imports are currently not supported, are you able to advise or recommend how I may be able to render the styles within the component test?

Warning - The component test will successfully run (without SASS styles) if the imported SASS (.scss) files are removed from within the cypress/component.ts file.

Note - This is a Next.js project that was initially scaffolded via npx create-next-app, and then configured to use SASS afterwards (npm install --save-dev sass).

Desired behavior

The component test should run within the Cypress Component Test application window, as well as successfully importing and rendering the styles defined within the SASS files (.scss)

Test code to reproduce

You may reproduce the issue by cloning the project from the repo; nextjs-playground, and then checkout the branch; cypress-integration

The relevant code files are listed below.

file: component.ts:

...
import '../../styles/globals.scss'
import '../../styles/Index.module.scss'
import '../../components/news-aggregator/news-aggregator-article.module.scss'
...

file: news-aggregator-article.cy.tsx (component test):

import NewsAggregatorArticle from "./news-aggregator-article"

describe('news-aggregator-article.tsx', () => {
  it('should render with article data', () => {
    // given
    const article = {
      id: 15547,
      title: 'InSight teams push for more science in lander’s final months, Curiosity continues trek around Gale Crater',
      url: 'https://www.nasaspaceflight.com/2022/06/insight-curiosity-june-2022/',
      imageUrl: 'https://www.nasaspaceflight.com/wp-content/uploads/2022/06/jpegPIA25287-1170x702.jpeg',
      summary: 'In May 2022, members of NASA’s InSight Mars lander team announced that power levels on the lander were diminishing and that they expected the lander to become inoperative by December 2022. However, InSight’s teams want to push the lander to do as much as possible in its final months and have chosen to operate the lander’s seismometer for longer than previously planned.',
      publishedAt: '2022-06-25T16:42:33.000Z',
      updatedAt: '2022-06-25T19:27:56.825Z',
      newsSite: 'Space Fight News',
      featured: false,
      launches: [
        {
            id: 'df8d4fdb-9add-4ce9-9f0e-aae1c61df212',
            provider: 'Launch Library 2'
        },
        {
            id: '3b633f7e-fad9-480e-9011-f38d1bb2f932',
            provider: 'Launch Library 2'
        }
      ],
      events: [],
  }

    cy.mount(<NewsAggregatorArticle article={article} />)
  })
})

Cypress Version

10.2.0

Other

No response

lmiller1990 commented 2 years ago

Import scss definitely works, I do it in some projects. We also have tests with Next.js that do it, eg: https://github.com/cypress-io/cypress/tree/develop/system-tests/project-fixtures/next (there is Home.module.scss). We use your webpack config (or for Next.js, we go find there webpack config) so it should all "just work". Seems like a bug.

I will look into this. Thanks for sharing a reproduction, that's really useful. I will try to get to this in the next few days.

fazo96 commented 2 years ago

We are having what I think is the same issue. Same error message inside cypress, and the terminal output shows this:

ERROR in ./app/components/AnimBox.module.css
No template for dependency: ModuleHotAcceptDependency

Repeated for every component that is loaded. We don't use SASS, but we have a couple global css imports in the style of import './file.css' plus Next.js CSS modules.

Currently we are using Cypress 9 and @cypress/react version 5 which are working correctly. Upgrading to Cypress 10 and @cypress/react 6 is causing this issue. Next.js version is 12.1.5, I tried upgrading to Next.js 12.2.0 but no change.

fazo96 commented 2 years ago

Not sure what I did, but now all of a sudden it works again

lmiller1990 commented 2 years ago

Having a look now, I ran the reproduction and got:

$ npx cypress open --component                              cypress-integration
[45804:0711/110922.230761:WARNING:bluez_dbus_manager.cc(248)] Floss manager not present, cannot set Floss enable/disable.
[45958:0711/110922.277430:ERROR:sandbox_linux.cc(377)] InitializeSandbox() called with multiple threads in process gpu-process.
[45958:0711/110922.305290:ERROR:gpu_memory_buffer_support_x11.cc(44)] dri3 extension not supported.
Missing baseUrl in compilerOptions. tsconfig-paths will be skipped
[@cypress/webpack-dev-server]: removing HotModuleReplacementPlugin from configuration.
<i> [webpack-dev-server] Project is running at:
<i> [webpack-dev-server] Loopback: http://127.0.0.1:8080/
<i> [webpack-dev-server] Content not from webpack is served from '/home/lachlan/code/dump/nextjs-playground/public' directory
15 assets
90 modules

ERROR in ./styles/globals.scss
Module Error (from ./node_modules/next/dist/build/webpack/loaders/error-loader.js):
Global CSS cannot be imported from files other than your Custom <App>. Due to the Global nature of stylesheets, and to avoid conflicts, Please move all first-party global CSS imports to pages/_app.js. Or convert the import to Component-Level CSS (CSS Modules).
Read more: https://nextjs.org/docs/messages/css-global
Location: cypress/support/component.ts

ERROR in ./styles/globals.scss
Module build failed: Error: Final loader (./node_modules/next/dist/build/webpack/loaders/error-loader.js) didn't return a Buffer or String
    at processResult (/home/lachlan/code/dump/nextjs-playground/node_modules/next/dist/compiled/webpack/bundle5.js:49230:17)
    at /home/lachlan/code/dump/nextjs-playground/node_modules/next/dist/compiled/webpack/bundle5.js:49316:5
    at /home/lachlan/code/dump/nextjs-playground/node_modules/next/dist/compiled/webpack/bundle5.js:139505:3
    at iterateNormalLoaders (/home/lachlan/code/dump/nextjs-playground/node_modules/next/dist/compiled/webpack/bundle5.js:139331:10)
    at iterateNormalLoaders (/home/lachlan/code/dump/nextjs-playground/node_modules/next/dist/compiled/webpack/bundle5.js:139338:10)
    at /home/lachlan/code/dump/nextjs-playground/node_modules/next/dist/compiled/webpack/bundle5.js:139353:3
    at runSyncOrAsync (/home/lachlan/code/dump/nextjs-playground/node_modules/next/dist/compiled/webpack/bundle5.js:139236:12)
    at iterateNormalLoaders (/home/lachlan/code/dump/nextjs-playground/node_modules/next/dist/compiled/webpack/bundle5.js:139349:2)
    at /home/lachlan/code/dump/nextjs-playground/node_modules/next/dist/compiled/webpack/bundle5.js:139322:4
    at /home/lachlan/code/dump/nextjs-playground/node_modules/next/dist/compiled/webpack/bundle5.js:49290:15
    at eval (eval at create (/home/lachlan/code/dump/nextjs-playground/node_modules/next/dist/compiled/webpack/bundle5.js:140346:10), <anonymous>:14:1)
    at Array.<anonymous> (/home/lachlan/code/dump/nextjs-playground/node_modules/next/build/webpack/plugins/profiling-plugin.ts:154:15)
    at runCallbacks (/home/lachlan/code/dump/nextjs-playground/node_modules/next/dist/compiled/webpack/bundle5.js:134035:15)
    at /home/lachlan/code/dump/nextjs-playground/node_modules/next/dist/compiled/webpack/bundle5.js:134208:4
    at /home/lachlan/code/dump/nextjs-playground/node_modules/next/dist/compiled/webpack/bundle5.js:14502:16
    at /home/lachlan/.cache/Cypress/10.2.0/Cypress/resources/app/node_modules/graceful-fs/graceful-fs.js:123:16
    at /home/lachlan/.cache/Cypress/10.2.0/Cypress/resources/app/node_modules/graceful-fs/graceful-fs.js:123:16
    at FSReqCallback.readFileAfterClose [as oncomplete] (node:internal/fs/read_file_context:68:3)

I guess Next.js has something buried in the webpack config that stops this. Cannot proceed:

image

Bizarrely, I commented out import '../../styles/globals.scss' in component.ts, saved, commented back in, and it works!

image

Either way, I think we probably should do some "under the hood" magic to make this a more seamless experience for Next.js users. We can modify the webpack config on the fly like suggested here.

I'll mark this as an enhancement. Adding this should be simple, we do similar on the fly mods in the Next.js handler, see here: https://github.com/cypress-io/cypress/blob/develop/npm/webpack-dev-server/src/helpers/nextHandler.ts#L64-L98

Sayvai commented 2 years ago

Interesting, and thanks for looking into this @lmiller1990

So based on the article you had linked, it seems like from my understanding that Next.js only allows for the global CSS files to be imported from within the main <App> component, which would explain why Cypress failed to run in the test in this instance, as i am now also importing the global CSS from within the Cypress component.ts file too.

Hopefully the enhancement work will allow for imports of global CSS within component.ts without any hacky workarounds, to make the configuration experience as seamless as possible 🙏

Note - I've updated the cypress-integration branch to upgrade the initial Next.js version from 12.1.0 to 12.2.2, and also refactored the Cypress component test file; news-aggregator-article.cy.tsx, and added a test, as well as further enriching the component test UI as close to style parity as possible, just without global CSS styles applied, for now.

A git rebase action was performed for the above update. So i suggest when you next pull the branch, you'd either hard reset your local branch with git fetch && git reset --hard origin/cypress-integration if you don't mind losing any existing changes, or you may be able to get away with git pull --rebase and keep any localised commits.

lmiller1990 commented 2 years ago

@Sayvai no problem - we will need to do a hack, but it'll be in the Cypress code base, so you don't need to.

I'm pretty swamped, I am not sure if I can do this during the next week or two, but I marked this as "ready for work" so someone at Cypress (or external, if someone is keen) wants to pick it up.

If anyone outside Cypress wants to take a stab, ping me and I can point you in the right direction.

ZachJW34 commented 2 years ago

I have an open PR to remove the global style restrictions that Next enforces.

There are some binaries you can install from the PR to test it out locally to see if the fix works for you!

Sayvai commented 2 years ago

@ZachJW34 - Thank you very much for applying the underlying configuration enhancement 🙌

I hope to test your changes at some point tomorrow, and will report back the status of your changes here 🤞

cypress-bot[bot] commented 2 years ago

The code for this is done in cypress-io/cypress#22769, but has yet to be released. We'll update this issue and reference the changelog when it's released.