Skip to content

Commit 3ba26ce

Browse files
committed
test: add css module tests
1 parent 41af4b6 commit 3ba26ce

9 files changed

+244
-4
lines changed

Diff for: test/advanced.spec.ts

+47-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,53 @@ test('extract CSS with code spliting', async () => {
147147
expect(mfs.existsSync('/basic.test.output.css')).toBe(true)
148148
})
149149

150-
test.todo('support rules with oneOf')
150+
test('support rules with oneOf', async () => {
151+
const run = (entry: string) => {
152+
return mockBundleAndRun({
153+
entry,
154+
modify: (config: any) => {
155+
config!.module!.rules = [
156+
{ test: /\.vue$/, loader: 'vue-loader' },
157+
{
158+
test: /\.css$/,
159+
use: 'style-loader',
160+
oneOf: [
161+
{
162+
resourceQuery: /module/,
163+
use: [
164+
{
165+
loader: 'css-loader',
166+
options: {
167+
modules: {
168+
localIdentName: '[local]_[hash:base64:5]',
169+
},
170+
},
171+
},
172+
],
173+
},
174+
{
175+
use: ['css-loader'],
176+
},
177+
],
178+
},
179+
]
180+
},
181+
})
182+
}
183+
184+
const { window: window1 } = await run('basic.vue')
185+
let style = normalizeNewline(
186+
window1.document.querySelector('style')!.textContent!
187+
)
188+
expect(style).toContain('comp-a h2 {\n color: #f00;\n}')
189+
190+
const { window, instance } = await run('css-modules-simple.vue')
191+
192+
const className = instance.$style.red
193+
expect(className).toMatch(/^red_\w{5}/)
194+
style = normalizeNewline(window.document.querySelector('style')!.textContent!)
195+
expect(style).toContain('.' + className + ' {\n color: red;\n}')
196+
})
151197

152198
test.todo('should work with eslint loader')
153199

Diff for: test/edgeCases.spec.ts

+27-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,33 @@ test('normalize multiple use + options', async () => {
6060
})
6161
})
6262

63-
test.todo('should not duplicate css modules value imports')
63+
test('should not duplicate css modules value imports', async () => {
64+
const { window, exports } = await mockBundleAndRun({
65+
entry: './test/fixtures/duplicate-cssm.js',
66+
modify: (config: any) => {
67+
config!.module!.rules[1] = {
68+
test: /\.css$/,
69+
use: [
70+
'style-loader',
71+
{
72+
loader: 'css-loader',
73+
options: {
74+
modules: true,
75+
},
76+
},
77+
],
78+
}
79+
},
80+
})
81+
82+
const styles = window.document.querySelectorAll('style')
83+
expect(styles.length).toBe(2) // one for values, one for the component
84+
const style = normalizeNewline(styles[1]!.textContent!)
85+
// value should be injected
86+
expect(style).toMatch('color: red;')
87+
// exports is set as the locals imported from values.css
88+
expect(exports.color).toBe('red')
89+
})
6490

6591
// #1213
6692
test.todo('html-webpack-plugin')

Diff for: test/fixtures/css-modules-extend.vue

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<style module>
2+
.red {
3+
color: #FF0000;
4+
}
5+
</style>
6+
7+
<script>
8+
import CssModuleSimple from './css-modules-simple.vue'
9+
10+
export default {
11+
extends: CssModuleSimple
12+
}
13+
</script>
14+
15+
<template>
16+
<div :class="$style.red"></div>
17+
</template>

Diff for: test/fixtures/css-modules-simple.vue

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<style module>
2+
.red {
3+
color: red;
4+
}
5+
</style>
6+
7+
<script>
8+
export default {}
9+
</script>

Diff for: test/fixtures/css-modules.vue

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<style module="style">
2+
.red {
3+
color: red;
4+
}
5+
@keyframes fade {
6+
from { opacity: 1; } to { opacity: 0; }
7+
}
8+
.animate {
9+
animation: fade 1s;
10+
}
11+
</style>
12+
13+
<style lang="stylus" module scoped>
14+
.red
15+
color: red
16+
</style>
17+
18+
<script>
19+
export default {}
20+
</script>

Diff for: test/fixtures/duplicate-cssm.css

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@value color: red;

Diff for: test/fixtures/duplicate-cssm.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import values from './duplicate-cssm.css'
2+
import Comp from './duplicate-cssm.vue'
3+
4+
export { values }
5+
export default Comp
6+
7+
window.exports = values

Diff for: test/fixtures/duplicate-cssm.vue

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<template>
2+
<h1 :class="$style.red">hi</h1>
3+
</template>
4+
5+
<style module>
6+
@value color from './duplicate-cssm.css';
7+
8+
.red {
9+
color: color;
10+
}
11+
</style>

Diff for: test/style.spec.ts

+105-2
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,111 @@ test('postcss', async () => {
8686
expect(style).toContain(`h1[${id}] {\n color: red;\n font-size: 14px\n}`)
8787
})
8888

89-
test.todo('CSS Modules')
89+
test('CSS Modules', async () => {
90+
const testWithIdent = async (
91+
localIdentName: string | undefined,
92+
regexToMatch: RegExp
93+
) => {
94+
const baseLoaders = [
95+
'style-loader',
96+
{
97+
loader: 'css-loader',
98+
options: {
99+
modules: {
100+
localIdentName,
101+
},
102+
},
103+
},
104+
]
105+
106+
const { window, instance } = await mockBundleAndRun({
107+
entry: 'css-modules.vue',
108+
modify: (config: any) => {
109+
config!.module!.rules = [
110+
{
111+
test: /\.vue$/,
112+
loader: 'vue-loader',
113+
},
114+
{
115+
test: /\.css$/,
116+
use: baseLoaders,
117+
},
118+
{
119+
test: /\.stylus$/,
120+
use: [...baseLoaders, 'stylus-loader'],
121+
},
122+
]
123+
},
124+
})
125+
126+
// get local class name
127+
const className = instance.$style.red
128+
expect(className).toMatch(regexToMatch)
129+
130+
// class name in style
131+
let style = [].slice
132+
.call(window.document.querySelectorAll('style'))
133+
.map((style: any) => {
134+
return style!.textContent
135+
})
136+
.join('\n')
137+
style = normalizeNewline(style)
138+
expect(style).toContain('.' + className + ' {\n color: red;\n}')
139+
140+
// animation name
141+
const match = style.match(/@keyframes\s+(\S+)\s+{/)
142+
expect(match).toHaveLength(2)
143+
const animationName = match[1]
144+
expect(animationName).not.toBe('fade')
145+
expect(style).toContain('animation: ' + animationName + ' 1s;')
146+
147+
// default module + pre-processor + scoped
148+
const anotherClassName = instance.$style.red
149+
expect(anotherClassName).toMatch(regexToMatch)
150+
const id = 'data-v-' + genId('css-modules.vue')
151+
expect(style).toContain('.' + anotherClassName + '[' + id + ']')
152+
}
153+
154+
// default ident
155+
await testWithIdent(undefined, /^\w{21,}/)
156+
157+
// custom ident
158+
await testWithIdent(
159+
'[path][name]---[local]---[hash:base64:5]',
160+
/css-modules---red---\w{5}/
161+
)
162+
})
90163

91-
test.todo('CSS Modules Extend')
164+
test('CSS Modules Extend', async () => {
165+
const baseLoaders = [
166+
'style-loader',
167+
{
168+
loader: 'css-loader',
169+
options: {
170+
modules: true,
171+
},
172+
},
173+
]
174+
175+
const { window, instance } = await mockBundleAndRun({
176+
entry: 'css-modules-extend.vue',
177+
modify: (config: any) => {
178+
config!.module!.rules = [
179+
{
180+
test: /\.vue$/,
181+
loader: 'vue-loader',
182+
},
183+
{
184+
test: /\.css$/,
185+
use: baseLoaders,
186+
},
187+
]
188+
},
189+
})
190+
191+
expect(instance.$el.className).toBe(instance.$style.red)
192+
const style = window.document.querySelectorAll('style')![1]!.textContent
193+
expect(style).toContain(`.${instance.$style.red} {\n color: #FF0000;\n}`)
194+
})
92195

93196
test.todo('experimental <style vars>')

0 commit comments

Comments
 (0)