控制台错误 Error: 无法解析 CSS 样式表

12

当我用 jest 运行我的测试时,遇到了以下错误。

  console.error
    Error: Could not parse CSS stylesheet
        at exports.createStylesheet ([PERSONAL_PATH]/node_modules/jsdom/lib/jsdom/living/helpers/stylesheets.js:34:21)
        at HTMLStyleElementImpl._updateAStyleBlock ([PERSONAL_PATH]/node_modules/jsdom/lib/jsdom/living/nodes/HTMLStyleElement-impl.js:68:5)
        at HTMLStyleElementImpl._childTextContentChangeSteps ([PERSONAL_PATH]/node_modules/jsdom/lib/jsdom/living/nodes/HTMLStyleElement-impl.js:36:12)
        at HTMLStyleElementImpl._insert ([PERSONAL_PATH]/node_modules/jsdom/lib/jsdom/living/nodes/Node-impl.js:832:14)
        at HTMLStyleElementImpl._preInsert ([PERSONAL_PATH]/node_modules/jsdom/lib/jsdom/living/nodes/Node-impl.js:768:10)
        at HTMLStyleElementImpl._append ([PERSONAL_PATH]/node_modules/jsdom/lib/jsdom/living/nodes/Node-impl.js:868:17)
        at HTMLStyleElementImpl.appendChild ([PERSONAL_PATH]/node_modules/jsdom/lib/jsdom/living/nodes/Node-impl.js:610:17)
        at HTMLStyleElement.appendChild ([PERSONAL_PATH]/node_modules/jsdom/lib/jsdom/living/generated/Node.js:395:60)
        at StyleSheet.insert ([PERSONAL_PATH]/node_modules/@emotion/sheet/dist/sheet.cjs.dev.js:121:11)
        at Object.insert ([PERSONAL_PATH]/node_modules/@emotion/cache/dist/cache.cjs.dev.js:168:19) {width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;}/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ[BLOB]== */

      at VirtualConsole.<anonymous> (node_modules/jsdom/lib/jsdom/virtual-console.js:29:45)
      at exports.createStylesheet (node_modules/jsdom/lib/jsdom/living/helpers/stylesheets.js:38:63)
      at HTMLStyleElementImpl._updateAStyleBlock (node_modules/jsdom/lib/jsdom/living/nodes/HTMLStyleElement-impl.js:68:5)
      at HTMLStyleElementImpl._childTextContentChangeSteps (node_modules/jsdom/lib/jsdom/living/nodes/HTMLStyleElement-impl.js:36:12)
      at HTMLStyleElementImpl._insert (node_modules/jsdom/lib/jsdom/living/nodes/Node-impl.js:832:14)
      at HTMLStyleElementImpl._preInsert (node_modules/jsdom/lib/jsdom/living/nodes/Node-impl.js:768:10)

我尝试在我的packages.json上设置了一个jsdom版本,也尝试更新了jest包,但错误并未改变。它实际上并没有导致测试失败,但会污染jest输出。
如果需要更多细节,请在评论中提问,我将编辑此问题。
这是被测试组件的Sass文件:
$spacing-medium: 2.4rem
$spacing-small: 1.6rem
$color-green: #3aa537
$color-white: #ffffff
$color-super-pale-gray: #f0f0f0
$color-pale-gray: #e6e6e6
$color-border-pale-gray: #b3b3b3
$tundora: #4d4d4d
$boulder: #757575
$electric-blue: #2251ff
$font-size-large: 1.6rem
$font-family-regular: "Arial", sans-serif
$font-family-bold: "Arial Bold", sans-serif
$[PRIVATE]-sans-regular-font-family: '[PRIVATE] Sans Regular', $font-family-regular
$[PRIVATE]-sans-medium-font-family: '[PRIVATE] Sans Medium', $font-family-bold
$font-size-medium: 1.4rem

@font-face
  font-family: [PRIVATE] Sans Medium
  src: url('https://cdn.[PRIVATE].com/assets/fonts/web/[PRIVATE]Sans-Medium.woff2') format('woff2')

@font-face
  font-family: [PRIVATE] Sans Regular
  src: url('https://cdn.[PRIVATE].com/assets/fonts/web/[PRIVATE]Sans-Regular.woff2') format('woff2')

.margin-cell
  margin-left: -12px

.active
  color: $color-green
  font-family: $[PRIVATE]-sans-medium-font-family
  margin-left: -12px

section
  margin: 1rem 0

  nav.sub-navigation
    background-color: $color-white
    padding: $spacing-medium

    a.sub-navigation-active
      display: inline-flex
      color: $electric-blue
      font-size: $font-size-large
      font-family: $[PRIVATE]-sans-medium-font-family
      text-decoration: none
      border-bottom: 4px solid $electric-blue
      padding-bottom: 1rem

  div.grid-container
    padding: $spacing-small 0 $spacing-small 0
    font-size: $font-size-medium
    background-color: $color-white
    display: grid

    .group-key
      font-family: $[PRIVATE]-sans-medium-font-family
      color: $tundora
      margin-bottom: 10px

    .input-style
      width: 100%
      font-family: $[PRIVATE]-sans-regular-font-family
      height: 30px
      padding: 0 $spacing-small
      color: $tundora
      font-size: $font-size-medium

    .group-divider
      padding: $spacing-small 10px $spacing-small 10px

    .advanced-configurations-container
      width: 100%
      font-size: $font-size-medium

    .advanced-configurations-header
      font-size: $font-size-medium
      color: $electric-blue
      width: unset

  div.info-group
    padding: 0 0 $spacing-small $spacing-medium
    font-size: 1.4rem
    background-color: $color-white
    border-top: 2px solid $color-super-pale-gray
    display: grid
    grid-template-columns: 1fr 1fr

    div.group-subsection
      display: grid
      padding: 0.8rem 0
      margin: 10px 25px 10px 0
      height: 50px
      &.variable-height
        height: unset
        min-height: 50px

    .group-key
      font-family: $[PRIVATE]-sans-medium-font-family
      color: $tundora
      margin-bottom: 10px

    .info-group-internal
      display: grid
      grid-template-columns: 1fr 1fr

  .icons-holder
    display: flex
    justify-content: center
    gap: 26px

.tab
  margin-top: $spacing-medium

.filter-wrapper
  padding: $spacing-small $spacing-medium $spacing-small $spacing-medium
  background-color: $color-white
  border-top: 1px solid $color-pale-gray

.search-input
  width: 300px
  height: 32px

.modal-form

  .form-row
    display: flex
    margin: $spacing-medium 0
    gap: $spacing-medium

    > .form-column
      flex: 1

      .input-wrapper
        height: 32px

        textarea
          //border: $color-pale-gray solid 1px
          color: $tundora
          height: 24px
          min-height: 9rem
          overflow: hidden
          padding: 10px
          resize: none

    .question-label
      color: $tundora
      font-family: $[PRIVATE]-sans-medium-font-family
      display: block
      font-weight: bold
      margin-bottom: 10px
      font-size: 1.4rem

这是我的 jest.config.js 文件:

module.exports = {
  clearMocks: true,
  collectCoverageFrom: ['src/**/*.{ts,tsx,js,jsx}'],
  coverageDirectory: 'coverage',
  coveragePathIgnorePatterns: [
    '/node_modules/',
    'src/index.tsx',
    'src/temp/',
    'src/types/',
    'src/helpers/testHelper.ts',
    'src/helpers/constants.ts',
    'src/pages/Errors/*',
  ],
  coverageThreshold: {
    global: {
      branches: 90,
      functions: 90,
      lines: 90,
      statements: 90,
    },
  },
  moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx'],
  moduleNameMapper: {
    '\\.(css|scss|sass)$': 'identity-obj-proxy',
    '\\.svg$': '<rootDir>/__mocks__/genericMock.js',
    '^@src/(.*)$': '<rootDir>/src/$1',
    '^@helpers/(.*)$': '<rootDir>/src/helpers/$1',
    '^@appConfig(.*)$': '<rootDir>/config/application/appConfigTypes.ts',
  },
  preset: 'ts-jest',
  setupFilesAfterEnv: ['./src/helpers/jestHelper.ts'],
  testEnvironment: 'jsdom',
  testMatch: ['**/*.(test|spec).(ts|tsx)'],
  transform: {
    '^.+\\.(ts|tsx)$': 'ts-jest',
  },
  transformIgnorePatterns: ['node_modules/(?!(react-native|[PRIVATE]|lodash)/)'],
};

更新

我已经开始从组件中分离出我正在测试的东西,最终只剩下一个单一的组件。所以我发现来自第三方库的日期选择器引起了问题。我克隆了它,运行了它们的测试,并注意到他们在测试中使用了另一个库来渲染该组件。 我发现他们还使用了testing-library/react,创建了另一个使用它进行渲染的测试,但没有成功复现错误。有人有什么建议吗?我已经没有更多的想法了。


“无法解析 CSS 样式表”通常意味着您的 CSS 中存在某种错误。如果没有这个 CSS,我们就无法告诉您问题所在。 - Ouroborus
我使用 npx sass <StyleFile.sass> 编译了被测试组件所使用的样式表,输出结果没有错误。 - wviana
@Ouroborus 只需添加主要的Sass文件。感谢您的帮助。 - wviana
刚试图从两个Sass文件中删除文件内容。即使是干净的文件也出现了相同的错误。 - wviana
2
@wviana 你最终解决了这个问题吗? - liamlows
2
@wviana 你找到解决方案了吗?如果是这样,你能不能成为英雄并回答你的问题呢? - Cezar Cobuz
4个回答

11

在此处有一个与之相关的问题:https://github.com/jsdom/jsdom/issues/2230,建议您更改jsdom配置为:

const jsdom = require('jsdom');
const { JSDOM } = jsdom;
const virtualConsole = new jsdom.VirtualConsole();
virtualConsole.on("error", () => {
  // No-op to skip console errors.
});
const dom = new JSDOM(``, { virtualConsole });

这个相同的答案也可以在这里找到:JSDOM: Could not parse CSS stylesheet

还有另一个问题在这里提到,https://github.com/styled-components/styled-components/issues/1931,似乎将多行注释改为单行注释对一些人解决了该问题。

我认为 jsdom 对 CSS 的支持并不是很好,或者说它似乎在尝试解析 CSS 时会出现奇怪的错误。

然而,我不认为解决方案是继续解析 CSS,你应该使用 jest 转换或 moduleNameMapper 来模拟 css 并导入一个空对象,没有理由测试样式。

根据 jest 文档,https://jestjs.io/docs/webpack#mocking-css-modules,您可以使用 moduleNameMapper:

"moduleNameMapper": {
  "\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js",
  "\\.(gif|ttf|eot|svg)$": "<rootDir>/__mocks__/fileMock.js"
}

然后在fileMock.js文件中,您只需要导出一个空对象。

您还可以使用transform:

"transform": {
  "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/fileTransformer.js"
}

然后在 fileTransformer.js 文件中,你也可以只导出一个空对象。


你好,感谢你的帮助。我已经检查了modulesNameMapper,我已经有了这个配置 '\\.(css|scss|sass)$': 'identity-obj-proxy'。关于jsdom配置,我应该把它放在哪里?我唯一带有jsdom字符串的是在jest.config.js中,如下所示:testEnvironment: 'jsdom' - wviana
删除 identity-obj-project 并卸载它,你只需要一个空的 mock.js 文件,它所要做的就是 module.exports = {}, 然后在 moduleNameMapper 中使用该文件,即 \\.css$: <rootDir>/tests/mock.js,这样你就可以将任何 css 导入映射到一个空对象导入。 - user16435030

1
我使用了vitest并且在PrimeVue上遇到了同样的问题。 stackoverflow上的答案帮助了我。
import { useConfirm } from 'primevue/useconfirm';
import PrimeVue from 'primevue/config';
import ConfirmationService from 'primevue/confirmationservice';

const wrapper = shallowMount(MyComponent, {
  props: { aProp },
  global: {
    components: { useConfirm },
    plugins: [PrimeVue, ConfirmationService],
  },
});

1

出现错误信息...

由于样式表使用了(合法的)特性,[jsdom] CSS解析器不支持。 在GitHub问题评论中的源评论

在同一线程中,有一个解决方案对我有效。我稍微修改了它:

// in setupTests.js
const originalConsoleError = console.error
console.error = function (msg) {
  if (msg.startsWith('Error: Could not parse CSS stylesheet')) return
  originalConsoleError(msg)
}

0

我已经在我的 jest.config.js 文件中添加了它,我已将其添加到我的问题中。 - wviana

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接