vuejs / vue-jest

Jest Vue transformer
MIT License
742 stars 159 forks source link

Injecting SFC styles into the DOM using JSDom test environment #553

Open ursulean opened 9 months ago

ursulean commented 9 months ago

Reposting this question from StackOverflow as this behavior is most likely caused by vue-jest.

I want to create a Jest component test for a Vue3 single-file component where I have access to the style tag included in the .vue file. Using the JSDom Jest environment and the vue-jest transformer which supports styles tags, the component's style should be added to the DOM when mounted with the mount function from the @vue/test-utils package. But this does not happen.

I have added a minimal example in this GitHub repository for anyone who wants to reproduce this issue with my setup. When running npm test on the above repository, the following output is produced, showing that the style tag is not present in the head of the document.

> vue-jest-styles-injection@0.0.0 test
> jest

 FAIL  src/components/HelloWorld.test.ts
  HelloWorld.vue
    ✕ takes a screenshot with hello world (12 ms)

  ● HelloWorld.vue › takes a screenshot with hello world

    expect(received).toContain(expected) // indexOf

    Expected substring: "style"
    Received string:    "<html><head></head><body><div data-v-app=\"\"><h1>Hello, world!</h1><div class=\"card\"><button type=\"button\">count is 0</button><p> Edit <code>components/HelloWorld.vue</code> to test HMR </p></div><p> Check out <a href=\"https://vuejs.org/guide/quick-start.html#local\" target=\"_blank\">create-vue</a>, the official Vue + Vite starter </p><p> Install <a href=\"https://github.com/vuejs/language-tools\" target=\"_blank\">Volar</a> in your IDE for a better DX </p><p class=\"read-the-docs\">Click on the Vite and Vue logos to learn more</p></div></body></html>"

       6 |   it('takes a screenshot with hello world', async () => {
       7 |     mount(HelloWorld, { props: { msg: "Hello, world!" }, attachTo: document.body });
    >  8 |     expect(document.documentElement.outerHTML).toContain("style")
         |                                                ^
       9 |   });
      10 | });

      at Object.<anonymous> (src/components/HelloWorld.test.ts:8:48)

I tried using the Vitest testing framework instead of Jest, and I was able to mount the component and its styles to the DOM as intended. I have also included this working example on a branch in my repository.

While Vitest looks great, the real repository I want to integrate these tests into is already using Jest and has quite a complex setup which I expect will be difficult to migrate to Vitest. So I want to get this working using Jest.

Looking at the processStyles function in process.js, it looks like non-moduled CSS is ignored, and that for moduled CSS, the styles are only used for generating a class map, and not being injected into the DOM.

Is it possible to get this behavior from vue-jest?

jolting commented 7 months ago

This is currently not supported, but it would be welcome addition to model it after vitest.