Cypress returns Create React App 中 .scss 文件的 webpack 编译错误

Cypress returns webpack compilation error for .scss file in Create React App

我正在尝试将 Cypress 添加到一个非常基本的 CRA 中,但是 运行 正在解决 Cypress 能够理解 .scss 文件的问题。

当我运行npm run cypress到运行测试时,我收到以下错误:

Error: Webpack Compilation Error
./src/App.scss 1:0
Module parse failed: Unexpected token (1:0)
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
> .app {
|   align-items: center;
|   display: flex !important;
 @ ./src/App.jsx 28:0-21
 @ ./cypress/integration/App.spec.js
...

当 Cypress 尝试挂载组件时,似乎没有使用 sass-loader?我该如何解决这个问题?

package.json:

{
  "name": "cypress_test",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "cypress": "cypress open",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "dependencies": {
    "@cypress/react": "^5.12.4",
    "@cypress/webpack-dev-server": "^1.8.4",
    "@emotion/react": "^11.9.0",
    "@emotion/styled": "^11.8.1",
    "@fontsource/roboto": "^4.5.5",
    "@mui/icons-material": "^5.6.2",
    "@mui/material": "^5.6.3",
    "@mui/styled-engine-sc": "^5.6.1",
    "@testing-library/jest-dom": "^5.16.4",
    "@testing-library/react": "^12.1.5",
    "@testing-library/user-event": "^13.5.0",
    "cypress": "^9.6.0",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-scripts": "5.0.1",
    "sass": "^1.51.0",
    "styled-components": "^5.3.5",
    "web-vitals": "^2.1.4"
  },
  "devDependencies": {
    "@babel/core": "^7.17.9",
    "@babel/preset-env": "^7.16.11",
    "@cypress/webpack-preprocessor": "^5.11.1",
    "babel-loader": "^8.2.5",
    "eslint-plugin-cypress": "^2.12.1",
    "html-webpack-plugin": "^4.5.2",
    "webpack": "^5.72.0"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "overrides": [
    {
      "extends": [
        "plugin:cypress/recommended"
      ],
      "files": [
        "cypress/**/*.js"
      ]
    }
  ],
  "resolutions": {
    "@mui/styled-engine": "npm:@mui/styled-engine-sc@latest"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "jest": {
    "coveragePathIgnorePatterns": [
      "<rootDir>/cypress/"
    ]
  }
}

App.spec.js:

import React from 'react';
import data from '../fixtures/data.json';
import App from '../../src/App.jsx';

describe('Test search functionality', () => {
  beforeEach(() => {
    cy.mount(<App />);
  });

  it('renders new fact when search is performed', () => {
    cy.visit('http://localhost:3001')
    // Type in search input
    cy.get('input').type('Test');

    // Click on search button
    cy.get('.submit-btn').click();

    // Intercept the request and return the mock data
    cy
      .intercept({
        method: 'GET',
        url: `${process.env.REACT_APP_API_ENDPOINT}/jokes/search?query=Test`
      }, {
        fixture: data.result[1]
      })
      .as('fetchFact');

    // cy.wait(['@fetchFact']);

    cy.get('p.copy').should('contain', data.result[1].value);
  })
});

cypress/plugins/index.js:

const injectDevServer = require('@cypress/react/plugins/react-scripts');

module.exports = (on, config) => {
  injectDevServer(on, config);
  return config;
};

更新: 在尝试下面提出的修改 plugins/index.js 文件的解决方案后,我收到一个新错误:

Error: For the selected environment is no default script chunk format available:
JSONP Array push can be chosen when 'document' or 'importScripts' is available.
CommonJs exports can be chosen when 'require' or node builtins are available.
Make sure that your 'browserslist' includes only platforms that support these features or select an appropriate 'target' to allow selecting a chunk format by default. Alternatively specify the 'output.chunkFormat' directly.

更新/cypress/plugins/index.js:

const findWebpack = require('find-webpack')
const webpackPreprocessor = require('@cypress/webpack-preprocessor');
const injectDevServer = require('@cypress/react/plugins/react-scripts');

module.exports = (on, config) => {
  const webpackOptions = findWebpack.getWebpackOptions();

  if (!webpackOptions) {
    throw new Error('Could not find Webpack in this project');
  }

  const cleanOptions = { reactScripts: true };

  findWebpack.cleanForCypress(cleanOptions, webpackOptions);

  const options = {
    webpackOptions,
    watchOptions: {},
  };

  on('file:preprocessor', webpackPreprocessor(options));
  injectDevServer(on, config);
  return config;
};

我还从 package.json 中删除了 browserslist 密钥。

尝试将 CRA webpack 配置添加到 cypress 的 plugins/index 文件中:

/// <reference types="cypress" />
/// <reference types="../../../.." />
// @ts-check
const findWebpack = require('find-webpack')
const webpackPreprocessor = require('../../../..')

/**
 * @type {Cypress.PluginConfig}
 */
module.exports = (on) => {
  // find the Webpack config used by react-scripts
  const webpackOptions = findWebpack.getWebpackOptions()

  if (!webpackOptions) {
    throw new Error('Could not find Webpack in this project ')
  }

  // if we just pass webpackOptions to the preprocessor
  // it won't work - because react-scripts by default
  // includes plugins that split specs into chunks, etc.
  // https://github.com/cypress-io/cypress-webpack-preprocessor/issues/31

  // solution 1
  // blunt: delete entire optimization object
  // delete webpackOptions.optimization

  // solution 2
  // use a module that carefully removes only plugins
  // that we found to be breaking the bundling
  // https://github.com/bahmutov/find-webpack
  const cleanOptions = {
    reactScripts: true,
  }

  findWebpack.cleanForCypress(cleanOptions, webpackOptions)

  const options = {
    webpackOptions,
    watchOptions: {},
  }

  on('file:preprocessor', webpackPreprocessor(options))
}

以下是一些可能有用的链接:

Cypress Webpack 预处理器:https://github.com/cypress-io/cypress/tree/develop/npm/webpack-preprocessor#cypress-webpack-preprocessor

如何通过 react-scripts 依赖项将 Cypress 指向 Webpack 配置:https://github.com/cypress-io/cypress/tree/develop/npm/webpack-preprocessor/examples/react-app