vuejs / vue-jest

Jest Vue transformer
MIT License
746 stars 157 forks source link

Unable to mock $style object on a Vue 3 Options API based component using CSS Modules #533

Open schrags08 opened 1 year ago

schrags08 commented 1 year ago

Unable to mock $style on an Options API based component using CSS Modules when using vue-jest (@vue/vue3-jest@29.2.2) with experimentalCSSCompile: false.

A __cssModules object gets added to the component instance with an internal $style property as an empty object, however, the useCssModule API (and the resulting __cssModules object) should only apply when using the Composition API.

When the __cssModules object is present, vm lookups for $style resolve to __cssModules instead of the $style mock object present in the component's vm.

failing test:

import { mount } from '@vue/test-utils';
import MyFoo from '../src/foo.vue';

describe('MyFoo', () => {
    test('applies the proper module class', () => {
        const wrapper = mount(MyFoo, {
            global: {
                mocks: {
                    $style: {
                        'my-foo': 'my-foo',
                    },
                    bar: {
                        fb: 'FB',
                    },
                },
            },
        });

        expect(wrapper.vm.bar.fb).toBe('FB'); // pass
        expect(wrapper.vm.$style['my-foo']).toBe('my-foo'); // fail, undefined, tries to find 'my-foo' in MyFoo.__cssModules.$style
        expect(wrapper.classes()).toContain('my-foo'); // fail
    });
});

foo.vue:

<template>
    <div :class="$style['my-foo']">Foo</div>
</template>
<script>
    export default {
        name: 'MyFoo',
    };
</script>
<style lang="scss" module>
    @import './foo.scss';
</style>

foo.scss:

.my-foo {
    background-color: green;
    height: 200px;
    width: 200px;
}

PR #345 added support for CSS Modules in vue-jest based on Issue #268.

Perhaps adding a check for scriptSetupResult to the code modified in #345 in generate-code.js like:

if (scriptSetupResult && Array.isArray(stylesResult)) {
    const mergedStyle = {};
    // ...
}

could allow the useCssModule API to only apply when using the Composition API?