Open Nojusle opened 2 months ago
Hey @Nojusle! I'm a bot that can help you solve bugs, answer questions, and become a contributor. I'm here to help you while waiting for a human maintainer.
To resolve the issue of the $style
attribute being undefined
when testing components that use CSS Modules in your Nuxt 3 project, you need to ensure that the @nuxt/test-utils/module
is properly loaded and configured in your nuxt.config
file.
Here are the key steps:
@nuxt/test-utils/module
is added to the modules
array in your nuxt.config
file:// nuxt.config.js
export default {
modules: [
'@nuxt/test-utils/module',
// other modules
],
// other configurations
}
startNuxtAndGetViteConfig
function to start Nuxt and get the Vite configuration, which includes the necessary setup for handling CSS Modules:import { startNuxtAndGetViteConfig } from './path/to/config';
async function setup() {
const { nuxt, viteConfig } = await startNuxtAndGetViteConfig();
// additional setup if needed
}
setup();
By ensuring that the @nuxt/test-utils/module
is properly loaded and configured, the $style
attribute should be correctly defined when testing components that use CSS Modules [1].
Additionally, you can mock the $style
attribute in your tests to avoid it being undefined
. Here is an example of how to mock a component with CSS Modules:
import { mockComponent } from '@nuxt/test-utils/runtime'
// Mock the component and its styles
mockComponent('MyComponent', {
props: {
value: String
},
setup(props) {
return {
$style: {
myClass: 'mocked-class'
}
}
}
})
// Now you can write your tests
import { mountSuspended } from '@nuxt/test-utils/runtime'
import { it, expect } from 'vitest'
import MyComponent from '~/components/MyComponent.vue'
it('renders with mocked styles', async () => {
const component = await mountSuspended(MyComponent)
expect(component.vm.$style.myClass).toBe('mocked-class')
})
In this example, the $style
attribute is mocked to return a predefined class name, ensuring that it is not undefined
during the tests [2].
To continue talking to Dosu, mention @dosu.
Well, I'm not convinced it's the proper fix solution, but you can get the correct values passed through by modifying this line from...
setup: setup ? (props: Record<string, unknown>) => wrappedSetup(props, setupContext) : undefined,
....to...
setup: setup ? (props: Record<string, unknown>) => wrappedSetup({ ...props, ...component.__cssModules }, setupContext) : undefined,
I say that I don't think its the correct fix, as this then only solve the issue for components with a setup script, but I couldn't expose this via the render context.
OK, so not a fix, but a temporary workaround for anyone else stumbling on this, a small function which wraps mountSuspended
and should work as a drop-in replacement to make for easy removal if/when the core bug is fixed.
import { mountSuspended } from '@nuxt/test-utils/runtime'
export const mountWithNuxt: typeof mountSuspended = async (component, options) => {
return mountSuspended(component, {
...options,
// @ts-expect-error Vue's TS doesn't like us specifying $style as an external prop
props: {
...options?.props,
$style: {},
},
attrs: {
...options?.attrs,
$style: undefined,
},
})
}
Great, the workaround works for me. That's all I needed, thank you!
Environment
Reproduction
https://codesandbox.io/p/devbox/nuxt-test-with-css-modules-sz2wlg?file=%2Fsandbox.config.json%3A4%2C25-4%2C37
Describe the bug
When running tests on components that uses CSS Modules, the $style attribute is consistently set to undefined, causing the tests to fail.
Additional context
There are no examples in the Nuxt test examples folder that include CSS modules. I've read the documentation for @nuxt/test-utils, and it doesn't mention how to use it with CSS modules. I tried googling it, but I couldn't find any information on how to test Vue components with CSS modules. I only found an unanswered question regarding the same issue, e.g., https://github.com/nuxt/test-utils/discussions/804. Since CSS modules work with Nuxt 'out of the box,' I believe testing components that use CSS modules should also work seamlessly.
Logs