forked from vuejs/vue-cli
/
multiPage.spec.js
205 lines (178 loc) · 7.52 KB
/
multiPage.spec.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
jest.setTimeout(80000)
const path = require('path')
const portfinder = require('portfinder')
const createServer = require('@vue/cli-test-utils/createServer')
const { defaultPreset } = require('@vue/cli/lib/options')
const create = require('@vue/cli-test-utils/createTestProject')
const serve = require('@vue/cli-test-utils/serveWithPuppeteer')
const launchPuppeteer = require('@vue/cli-test-utils/launchPuppeteer')
async function makeProjectMultiPage (project) {
await project.write('vue.config.js', `
module.exports = {
pages: {
index: { entry: 'src/main.js' },
foo: { entry: 'src/foo.js' },
bar: { entry: 'src/bar.js' },
foobar: { entry: ['src/foobar.js'] },
baz: {
entry: 'src/main.js',
template: 'public/baz.html',
filename: 'qux.html'
}
},
chainWebpack: config => {
const splitOptions = config.optimization.get('splitChunks')
config.optimization.splitChunks(Object.assign({}, splitOptions, {
minSize: 100
}))
}
}
`)
await project.write('public/baz.html', await project.read('public/index.html'))
await project.write('src/foo.js', `
import Vue from 'vue'
new Vue({
el: '#app',
render: h => h('h1', 'Foo')
})
`)
await project.write('src/bar.js', `
import Vue from 'vue'
import App from './App.vue'
new Vue({
el: '#app',
render: h => h(App)
})
`)
await project.write('src/foobar.js', `
import Vue from 'vue'
new Vue({
el: '#app',
render: h => h('h1', 'FooBar')
})
`)
const app = await project.read('src/App.vue')
await project.write('src/App.vue', app.replace(
`import HelloWorld from './components/HelloWorld.vue'`,
`const HelloWorld = () => import('./components/HelloWorld.vue')`
))
}
test('serve w/ multi page', async () => {
const project = await create('e2e-multi-page-serve', defaultPreset)
await makeProjectMultiPage(project)
await serve(
() => project.run('vue-cli-service serve'),
async ({ page, url, helpers }) => {
expect(await helpers.getText('h1')).toMatch(`Welcome to Your Vue.js App`)
await page.goto(`${url}/foo.html`)
expect(await helpers.getText('h1')).toMatch(`Foo`)
await page.goto(`${url}/bar.html`)
expect(await helpers.getText('h1')).toMatch(`Welcome to Your Vue.js App`)
await page.goto(`${url}foo`)
expect(await helpers.getText('h1')).toMatch(`Foo`)
await page.goto(`${url}bar`)
expect(await helpers.getText('h1')).toMatch(`Welcome to Your Vue.js App`)
await page.goto(`${url}foobar`)
expect(await helpers.getText('h1')).toMatch(`FooBar`)
}
)
})
let server, browser
test('build w/ multi page', async () => {
const project = await create('e2e-multi-page-build', defaultPreset)
await makeProjectMultiPage(project)
const { stdout } = await project.run('vue-cli-service build')
expect(stdout).toMatch('Build complete.')
// should generate the HTML pages
expect(project.has('dist/index.html')).toBe(true)
expect(project.has('dist/foo.html')).toBe(true)
expect(project.has('dist/bar.html')).toBe(true)
// should properly ignore the template file
expect(project.has('dist/baz.html')).toBe(false)
// should respect the `filename` field in a multi-page config
expect(project.has('dist/qux.html')).toBe(true)
const assertSharedAssets = file => {
// should split and preload vendor chunk
expect(file).toMatch(/<link [^>]*js\/chunk-vendors[^>]*\.js rel=preload as=script>/)
expect(file).toMatch(/<script [^>]*src=\/js\/chunk-vendors\.\w+\.js>/)
}
const index = await project.read('dist/index.html')
assertSharedAssets(index)
// should split and preload common js and css
expect(index).toMatch(/<link [^>]*js\/chunk-common[^>]*\.js rel=preload as=script>/)
expect(index).toMatch(/<script [^>]*src=\/js\/chunk-common\.\w+\.js>/)
expect(index).toMatch(/<link href=\/css\/chunk-common\.\w+\.css rel=stylesheet>/)
expect(index).toMatch(/<link [^>]*chunk-common[^>]*\.css rel=preload as=style>/)
// should preload correct page file
expect(index).toMatch(/<link [^>]*js\/index[^>]*\.js rel=preload as=script>/)
expect(index).not.toMatch(/<link [^>]*js\/foo[^>]*\.js rel=preload as=script>/)
expect(index).not.toMatch(/<link [^>]*js\/bar[^>]*\.js rel=preload as=script>/)
// should prefetch async chunk js and css
expect(index).toMatch(/<link [^>]*css\/chunk-\w+\.\w+\.css rel=prefetch>/)
expect(index).toMatch(/<link [^>]*js\/chunk-\w+\.\w+\.js rel=prefetch>/)
// should load correct page js
expect(index).toMatch(/<script [^>]*src=\/js\/index\.\w+\.js>/)
expect(index).not.toMatch(/<script [^>]*src=\/js\/foo\.\w+\.js>/)
expect(index).not.toMatch(/<script [^>]*src=\/js\/bar\.\w+\.js>/)
const foo = await project.read('dist/foo.html')
assertSharedAssets(foo)
// should preload correct page file
expect(foo).not.toMatch(/<link [^>]*js\/index[^>]*\.js rel=preload as=script>/)
expect(foo).toMatch(/<link [^>]*js\/foo[^>]*\.js rel=preload as=script>/)
expect(foo).not.toMatch(/<link [^>]*js\/bar[^>]*\.js rel=preload as=script>/)
// should not prefetch async chunk js and css because it's not used by
// this entry
expect(foo).not.toMatch(/<link [^>]*css\/chunk-\w+\.\w+\.css rel=prefetch>/)
expect(foo).not.toMatch(/<link [^>]*js\/chunk-\w+\.\w+\.js rel=prefetch>/)
// should load correct page js
expect(foo).not.toMatch(/<script [^>]*src=\/js\/index\.\w+\.js>/)
expect(foo).toMatch(/<script [^>]*src=\/js\/foo\.\w+\.js>/)
expect(foo).not.toMatch(/<script [^>]*src=\/js\/bar\.\w+\.js>/)
const bar = await project.read('dist/bar.html')
assertSharedAssets(bar)
// bar & index have a shared common chunk (App.vue)
expect(bar).toMatch(/<link [^>]*js\/chunk-common[^>]*\.js rel=preload as=script>/)
expect(bar).toMatch(/<script [^>]*src=\/js\/chunk-common\.\w+\.js>/)
expect(bar).toMatch(/<link href=\/css\/chunk-common\.\w+\.css rel=stylesheet>/)
expect(bar).toMatch(/<link [^>]*chunk-common[^>]*\.css rel=preload as=style>/)
// should preload correct page file
expect(bar).not.toMatch(/<link [^>]*js\/index[^>]*\.js rel=preload as=script>/)
expect(bar).not.toMatch(/<link [^>]*js\/foo[^>]*\.js rel=preload as=script>/)
expect(bar).toMatch(/<link [^>]*js\/bar[^>]*\.js rel=preload as=script>/)
// should prefetch async chunk js and css
expect(bar).toMatch(/<link [^>]*css\/chunk-\w+\.\w+\.css rel=prefetch>/)
expect(bar).toMatch(/<link [^>]*js\/chunk-\w+\.\w+\.js rel=prefetch>/)
// should load correct page js
expect(bar).not.toMatch(/<script [^>]*src=\/js\/index\.\w+\.js>/)
expect(bar).not.toMatch(/<script [^>]*src=\/js\/foo\.\w+\.js>/)
expect(bar).toMatch(/<script [^>]*src=\/js\/bar\.\w+\.js>/)
// assert pages work
const port = await portfinder.getPortPromise()
server = createServer({ root: path.join(project.dir, 'dist') })
await new Promise((resolve, reject) => {
server.listen(port, err => {
if (err) return reject(err)
resolve()
})
})
const url = `http://localhost:${port}/`
const launched = await launchPuppeteer(url)
browser = launched.browser
const page = launched.page
const getH1Text = async () => page.evaluate(() => {
return document.querySelector('h1').textContent
})
expect(await getH1Text()).toMatch('Welcome to Your Vue.js App')
await page.goto(`${url}foo.html`)
expect(await getH1Text()).toMatch('Foo')
await page.goto(`${url}bar.html`)
expect(await getH1Text()).toMatch('Welcome to Your Vue.js App')
})
afterAll(async () => {
if (browser) {
await browser.close()
}
if (server) {
server.close()
}
})