thymikee / jest-preset-angular

Jest configuration preset for Angular projects.
https://thymikee.github.io/jest-preset-angular/
MIT License
883 stars 304 forks source link

[Bug]: Could not parse CSS stylesheet #2194

Open Trolejbus opened 8 months ago

Trolejbus commented 8 months ago

Version

13.1.4

Steps to reproduce

  1. Clone my repo: https://github.com/Trolejbus/jsdom-issue-in-jest
  2. npm install
  3. npm test

Steps which I made to prepare repo:

  1. ng new (with standalone app.component),
  2. Install PrimeNg library,
  3. Use component, which has styleUrls: [] with @layer at-rule (ex. p-inputMask).
  4. Setup jest, following manual from docs.
  5. Write tests, which are trying to create component.

Expected behavior

Should work without any errors

Actual behavior

Error is shown in console:

Error: Could not parse CSS stylesheet
        at exports.createStylesheet (C:\sources\test-jest\node_modules\jsdom\lib\jsdom\living\helpers\stylesheets.js:34:21)
        at HTMLStyleElementImpl._updateAStyleBlock (C:\sources\test-jest\node_modules\jsdom\lib\jsdom\living\nodes\HTMLStyleElement-impl.js:68:5)
        at HTMLStyleElementImpl._attach (C:\sources\test-jest\node_modules\jsdom\lib\jsdom\living\nodes\HTMLStyleElement-impl.js:19:12)
        at HTMLHeadElementImpl._insert (C:\sources\test-jest\node_modules\jsdom\lib\jsdom\living\nodes\Node-impl.js:835:14)
        at HTMLHeadElementImpl._preInsert (C:\sources\test-jest\node_modules\jsdom\lib\jsdom\living\nodes\Node-impl.js:756:10)
        at HTMLHeadElementImpl._append (C:\sources\test-jest\node_modules\jsdom\lib\jsdom\living\nodes\Node-impl.js:862:17)
        at HTMLHeadElementImpl.appendChild (C:\sources\test-jest\node_modules\jsdom\lib\jsdom\living\nodes\Node-impl.js:598:17)
        at HTMLHeadElement.appendChild (C:\sources\test-jest\node_modules\jsdom\lib\jsdom\living\generated\Node.js:411:60)
        at _SharedStylesHost.getStyleElement (C:\sources\test-jest\node_modules\@angular\platform-browser\fesm2022\platform-browser.mjs:360:18)
        at _SharedStylesHost.addStyleToHost (C:\sources\test-jest\node_modules\@angular\platform-browser\fesm2022\platform-browser.mjs:365:30)
        at _SharedStylesHost.onStyleAdded (C:\sources\test-jest\node_modules\@angular\platform-browser\fesm2022\platform-browser.mjs:307:18)
        at _SharedStylesHost.addStyles (C:\sources\test-jest\node_modules\@angular\platform-browser\fesm2022\platform-browser.mjs:270:22)
        at NoneEncapsulationDomRenderer.applyStyles (C:\sources\test-jest\node_modules\@angular\platform-browser\fesm2022\platform-browser.mjs:744:31)
        at _DomRendererFactory2.createRenderer (C:\sources\test-jest\node_modules\@angular\platform-browser\fesm2022\platform-browser.mjs:468:22)
        at addComponentLogic (C:\sources\test-jest\node_modules\@angular\core\fesm2022\core.mjs:12977:133)
        at instantiateAllDirectives (C:\sources\test-jest\node_modules\@angular\core\fesm2022\core.mjs:12768:9)
        at createDirectivesInstances (C:\sources\test-jest\node_modules\@angular\core\fesm2022\core.mjs:12193:5)
        at ɵɵelementStart (C:\sources\test-jest\node_modules\@angular\core\fesm2022\core.mjs:22068:9)
        at ɵɵelement (C:\sources\test-jest\node_modules\@angular\core\fesm2022\core.mjs:22126:5)
        at AppComponent_Template (ng:///AppComponent.js:7:21)
        at executeTemplate (C:\sources\test-jest\node_modules\@angular\core\fesm2022\core.mjs:12158:9)
        at renderView (C:\sources\test-jest\node_modules\@angular\core\fesm2022\core.mjs:15265:13)
        at renderComponent (C:\sources\test-jest\node_modules\@angular\core\fesm2022\core.mjs:15212:5)
        at renderChildComponents (C:\sources\test-jest\node_modules\@angular\core\fesm2022\core.mjs:15310:9)
        at renderView (C:\sources\test-jest\node_modules\@angular\core\fesm2022\core.mjs:15290:13)
        at ComponentFactory.create (C:\sources\test-jest\node_modules\@angular\core\fesm2022\core.mjs:15528:13)
        at initComponent (C:\sources\test-jest\node_modules\@angular\core\fesm2022\testing.mjs:1923:51)
        at _ZoneDelegate.Object.<anonymous>._ZoneDelegate.invoke (C:\sources\test-jest\node_modules\zone.js\bundles\zone.umd.js:411:30)
        at ProxyZoneSpec.Object.<anonymous>.ProxyZoneSpec.onInvoke (C:\sources\test-jest\node_modules\zone.js\bundles\zone-testing.umd.js:300:43)
        at _ZoneDelegate.Object.<anonymous>._ZoneDelegate.invoke (C:\sources\test-jest\node_modules\zone.js\bundles\zone.umd.js:410:56)
        at Object.onInvoke (C:\sources\test-jest\node_modules\@angular\core\fesm2022\core.mjs:14695:33)
        at _ZoneDelegate.Object.<anonymous>._ZoneDelegate.invoke (C:\sources\test-jest\node_modules\zone.js\bundles\zone.umd.js:410:56)
        at Zone.Object.<anonymous>.Zone.run (C:\sources\test-jest\node_modules\zone.js\bundles\zone.umd.js:165:47)
        at NgZone.run (C:\sources\test-jest\node_modules\@angular\core\fesm2022\core.mjs:14546:28)
        at _TestBedImpl.createComponent (C:\sources\test-jest\node_modules\@angular\core\fesm2022\testing.mjs:1926:41)
        at Function.createComponent (C:\sources\test-jest\node_modules\@angular\core\fesm2022\testing.mjs:1724:37)
        at C:\sources\test-jest\src\app\app.component.spec.ts:13:29
        at _ZoneDelegate.Object.<anonymous>._ZoneDelegate.invoke (C:\sources\test-jest\node_modules\zone.js\bundles\zone.umd.js:411:30)
        at ProxyZoneSpec.Object.<anonymous>.ProxyZoneSpec.onInvoke (C:\sources\test-jest\node_modules\zone.js\bundles\zone-testing.umd.js:300:43)
        at _ZoneDelegate.Object.<anonymous>._ZoneDelegate.invoke (C:\sources\test-jest\node_modules\zone.js\bundles\zone.umd.js:410:56)
        at Zone.Object.<anonymous>.Zone.run (C:\sources\test-jest\node_modules\zone.js\bundles\zone.umd.js:165:47)
        at Object.wrappedFunc (C:\sources\test-jest\node_modules\zone.js\bundles\zone-testing.umd.js:789:34)
        at Promise.then.completed (C:\sources\test-jest\node_modules\jest-circus\build\utils.js:298:28)
        at new Promise (<anonymous>)
        at callAsyncCircusFn (C:\sources\test-jest\node_modules\jest-circus\build\utils.js:231:10)
        at _callCircusTest (C:\sources\test-jest\node_modules\jest-circus\build\run.js:316:40)
        at processTicksAndRejections (node:internal/process/task_queues:95:5)
        at _runTest (C:\sources\test-jest\node_modules\jest-circus\build\run.js:252:3)
        at _runTestsForDescribeBlock (C:\sources\test-jest\node_modules\jest-circus\build\run.js:126:9)
        at _runTestsForDescribeBlock (C:\sources\test-jest\node_modules\jest-circus\build\run.js:121:9)
        at run (C:\sources\test-jest\node_modules\jest-circus\build\run.js:71:3)
        at runAndTransformResultsToJestFormat (C:\sources\test-jest\node_modules\jest-circus\build\legacy-code-todo-rewrite\jestAdapterInit.js:122:21) {
      detail: '@layer primeng{.p-inputmask-clear-icon{position:absolute;top:50%;margin-top:-.5rem;cursor:pointer}.p-inputmask-clearable{position:relative}}\n',
      type: 'css parsing'
    }

      at VirtualConsole.<anonymous> (node_modules/jest-environment-jsdom/build/index.js:63:23)
      at AppComponent_Template (ng:/AppComponent.js:7:21)
      at src/app/app.component.spec.ts:13:29

Additional context

In one of v16 releases PrimeNg has used @layer at-rule inside their css stylesheets. It looks like jsdom for some reason cannot parse css, which contains @layer {} at-rule - I found this issue reported: https://github.com/jsdom/jsdom/issues/2177.

Adding some trick to stub console.error to not show this error works, since it is not preventing tests from pass.

Environment

System:
    OS: Windows 11 10.0.22631
    CPU: (12) x64 Intel(R) Core(TM) i7-9850H CPU @ 2.60GHz
  Binaries:
    Node: 20.10.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.19 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 10.2.3 - C:\Program Files\nodejs\npm.CMD
    pnpm: 8.10.2 - ~\AppData\Roaming\npm\pnpm.CMD
  npmPackages:
    jest: ^29.7.0 => 29.7.0
Trolejbus commented 8 months ago

This bug is also reported for primeng team: https://github.com/primefaces/primeng/issues/14085

NathanLaing commented 8 months ago

Bump. Have been seeing this in my workspace and trying to get to the bottom of it

Elias-Graf commented 7 months ago

The Problem seems to be the CSS parser "cssom" that jsdom uses. I does not support @layer.

https://github.com/NV/CSSOM/issues/109#issuecomment-1398336817 https://github.com/jsdom/jsdom/issues/2026

Here is one of the pieces of code that fails for me: image

This is a copy of the comment on the PrimeNG issue: https://github.com/primefaces/primeng/issues/14085#issuecomment-1888629612

ahnpnl commented 7 months ago

I wonder if it's possible to parse CSS before JSDOM processes it. That might solve the issue

CodeBast4rd commented 6 months ago

We had the same problem in our Angular application and the source of it was as described https://github.com/primefaces/primeng/issues/14085#issuecomment-1888629612.

Our solution after trying out unsuccessfully vitetest integrating over analogjs as a replacement for jest, as suggested here, we resolved our issue with the following solution:

npm install --save-dev happy-dom npm install --save-dev @happy-dom/jest-environment And configuring the jest.config.ts with the following property: { "testEnvironment": "@happy-dom/jest-environment" }

For alternative configurations one can checkout the readme here.

This is a copy of the comment on the PrimeNG issue: https://github.com/primefaces/primeng/issues/14085#issuecomment-1941347163

AnnaVidal commented 4 months ago

We had the same problem in our Angular application and the source of it was as described primefaces/primeng#14085 (comment).

Our solution after trying out unsuccessfully vitetest integrating over analogjs as a replacement for jest, as suggested here, we resolved our issue with the following solution:

npm install --save-dev happy-dom npm install --save-dev @happy-dom/jest-environment And configuring the jest.config.ts with the following property: { "testEnvironment": "@happy-dom/jest-environment" }

For alternative configurations one can checkout the readme here.

This is a copy of the comment on the PrimeNG issue: primefaces/primeng#14085 (comment)

I was having the same issue using Primereact + Nextjs and this solution works, thank you!

pi-nathan commented 3 months ago

Switching to an alternative test environment (happy-dom, in this case as suggested above) solved this for me. Test execution speed seems similar, nothing has broken. Only thing I'd like now is to make jsdom a peer dependency rather than a dependency of this package so we can choose to opt out of it.

abhijit-chikane commented 3 months ago

put this in setup-jest.ts This should fix the issue


let consoleSpy: jest.SpyInstance;
beforeAll(() => {
    consoleSpy = jest.spyOn(global.console, 'error').mockImplementation((message) => {
        if (!message?.message?.includes('Could not parse CSS stylesheet')) {
            global.console.warn(message);
        }
    })
});

afterAll(() => consoleSpy.mockRestore());
jonelleamio commented 2 months ago

put this in setup-jest.ts This should fix the issue

let consoleSpy: jest.SpyInstance;
beforeAll(() => {
    consoleSpy = jest.spyOn(global.console, 'error').mockImplementation((message) => {
        if (!message?.message?.includes('Could not parse CSS stylesheet')) {
            global.console.warn(message);
        }
    })
});

afterAll(() => consoleSpy.mockRestore());

it's not a fix, you're just hiding the problem.

abhijit-chikane commented 2 months ago

put this in setup-jest.ts This should fix the issue

let consoleSpy: jest.SpyInstance;
beforeAll(() => {
    consoleSpy = jest.spyOn(global.console, 'error').mockImplementation((message) => {
        if (!message?.message?.includes('Could not parse CSS stylesheet')) {
            global.console.warn(message);
        }
    })
});

afterAll(() => consoleSpy.mockRestore());

it's not a fix, you're just hiding the problem.

Well that’s what I wanted as I couldn’t find the one which will solve the issue easily I have chose this approach as this is minimal and I don’t wanted my console to be flooded with these error msg

fabb commented 2 months ago

see https://github.com/jestjs/jest/issues/15106