UNPKG

12.3 kBJavaScriptView Raw
1import path from 'path'
2import chai from 'chai'
3
4import fs from 'fs'
5
6import isomorpher from '../source/index'
7import isomorpher_plugin from '../source/plugin/plugin'
8
9import { extend } from './../source/helpers'
10
11import Log from '../source/tools/log'
12
13chai.should()
14
15// logging
16const log = new Log('testing', { debug: true })
17
18const webpack_assets_path = path.resolve(__dirname, 'webpack-assets.json')
19
20const webpack_assets =
21{
22 "javascript":
23 {
24 "main": "/assets/main.6c2b37c0fc8c0592e2d3.js"
25 },
26 "styles":
27 {
28 "main": "/assets/main.6c2b37c0fc8c0592e2d3.css"
29 },
30 "assets":
31 {
32 "./assets/husky.jpg": "/assets/9059f094ddb49c2b0fa6a254a6ebf2ad.jpg",
33 "./assets/style.scss": "body {} .child { background: url(/assets/test.jpg) } head {}",
34 "./assets/child.scss": ".child { background: url(/assets/test.jpg) }",
35 "./assets/test.text_parser_test": "text parser test",
36 "./assets/test.object_parser_test.extra": { one: 1 },
37 "./~/whatever.jpg": 1,
38 "./~/aliased_module_name/test.jpg": true
39 }
40}
41
42const webpack_configuration =
43{
44 context: __dirname,
45
46 output:
47 {
48 publicPath: '/assets/'
49 },
50
51 module:
52 {
53 loaders: []
54 }
55}
56
57const isomorpher_settings = () =>
58({
59 // debug: true,
60
61 webpack_assets_file_path: webpack_assets_path,
62
63 assets:
64 {
65 javascript:
66 {
67 extension: 'js'
68 },
69 styles:
70 {
71 extension: 'scss'
72 },
73 images_and_fonts:
74 {
75 extensions:
76 [
77 'png',
78 'jpg',
79 'ico',
80 'woff',
81 'woff2',
82 'eot',
83 'ttf',
84 'svg'
85 ]
86 },
87 text_parser_test:
88 {
89 extension: 'text_parser_test',
90 parser: module => 'text parser test'
91 },
92 object_parser_test:
93 {
94 extension: 'object_parser_test',
95 path: module => module.name + '.extra',
96 parser: module => ({ one: 1 })
97 }
98 }
99})
100
101// deletes webpack-assets.json if it exists
102function cleanup_webpack_assets()
103{
104 // clear require() cache
105 delete require.cache[webpack_assets_path]
106
107 // delete webpack-assets.json if it exists
108 if (fs.existsSync(webpack_assets_path))
109 {
110 // delete it
111 fs.unlinkSync(webpack_assets_path)
112
113 // ensure webpack-assets.json was deleted
114 if (fs.existsSync(webpack_assets_path))
115 {
116 throw new Error('Failed to delete webpack-assets.json')
117 }
118 }
119}
120
121// writes webpack-assets.json
122function create_assets_file(data = webpack_assets)
123{
124 fs.writeFileSync(webpack_assets_path, JSON.stringify(data))
125}
126
127describe('plugin', function()
128{
129 beforeEach(function()
130 {
131 cleanup_webpack_assets()
132 })
133
134 afterEach(function()
135 {
136 cleanup_webpack_assets()
137 })
138
139 // this.timeout(5000)
140
141 it('should generate regular expressions', function()
142 {
143 const settings = isomorpher_settings()
144
145 const plugin = new isomorpher_plugin(settings).development()
146 const server_side = new isomorpher(settings)
147
148 // check resulting regular expressions
149
150 const regular_expressions =
151 {
152 javascript : /\.js$/,
153 styles : /\.scss$/,
154 images_and_fonts : /\.(png|jpg|ico|woff|woff2|eot|ttf|svg)$/
155 }
156
157 for (let asset_type of Object.keys(regular_expressions))
158 {
159 plugin.regular_expression(asset_type).toString().should.equal(regular_expressions[asset_type].toString())
160 }
161 })
162
163 it('should exclude files from require hooks', function()
164 {
165 const settings = isomorpher_settings()
166
167 settings.assets.images_and_fonts.exclude = ['kitten.jpg', /^\.\/node_modules\/*/, path => path === 'function test']
168
169 const plugin = new isomorpher_plugin(settings)
170 const server_side = new isomorpher(settings)
171
172 const excludes = path => server_side.excludes(path, settings.assets.images_and_fonts)
173
174 // check require() hooks exclusion
175 excludes('kitten.jpg.backup').should.be.false
176 excludes('kitten.jpg').should.be.true
177 excludes('./node_modules/fonts/style.css').should.be.true
178 excludes('source/node_modules/fonts/style.css').should.be.false
179 excludes('function test').should.be.true
180 })
181
182 it('should include files in require hooks', function()
183 {
184 const settings = isomorpher_settings()
185
186 settings.assets.images_and_fonts.include = ['kitten.jpg', /^\.\/node_modules\/*/, path => path === 'function test']
187
188 const plugin = new isomorpher_plugin(settings)
189 const server_side = new isomorpher(settings)
190
191 const includes = path => server_side.includes(path, settings.assets.images_and_fonts)
192
193 // check require() hooks inclusion
194 includes('kitten.jpg.backup').should.be.false
195 includes('kitten.jpg').should.be.true
196 includes('./node_modules/fonts/style.css').should.be.true
197 includes('source/node_modules/fonts/style.css').should.be.false
198 includes('function test').should.be.true
199 })
200
201 it('should wait for webpack-assets.json (callback)', function(done)
202 {
203 // ensure it waits for webpack-assets.json
204 const server_side = new isomorpher(isomorpher_settings())
205
206 // run server side instance
207 server_side.server(webpack_configuration.context, () =>
208 {
209 // unmount require() hooks
210 server_side.undo()
211
212 // verify webpack-assets.json exists
213 if (!fs.existsSync(webpack_assets_path))
214 {
215 return done(new Error('Should have waited for webpack-assets.json'))
216 }
217
218 // done
219 done()
220 })
221
222 // create the webpack-assets.json (after a short delay)
223 setTimeout(create_assets_file, 150)
224 })
225
226 it('should wait for webpack-assets.json (promise)', function(done)
227 {
228 // ensure it waits for webpack-assets.json
229 const server_side = new isomorpher(isomorpher_settings()).development(false)
230
231 // run server side instance
232 server_side.server(webpack_configuration.context).then(() =>
233 {
234 // unmount require() hooks
235 server_side.undo()
236
237 // verify webpack-assets.json exists
238 if (!fs.existsSync(webpack_assets_path))
239 {
240 return done(new Error('Should have waited for webpack-assets.json'))
241 }
242
243 // done
244 done()
245 })
246
247 // create the webpack-assets.json (after a short delay)
248 setTimeout(create_assets_file, 150)
249 })
250
251 it('should require assets on server', function(done)
252 {
253 // create the webpack-assets.json
254 create_assets_file()
255
256 // ensure it waits for webpack-assets.json
257 const server_side = new isomorpher(isomorpher_settings())
258
259 // install require() hooks
260 server_side.server(webpack_configuration.context, () =>
261 {
262 // checks '/node_modules' -> '/~' case.
263 // to do: should be a proper check
264 require('./node_modules/whatever.jpg').should.equal(1)
265
266 // verify asset value
267 require('./assets/husky.jpg').should.equal(webpack_assets.assets['./assets/husky.jpg'])
268
269 // unmount require() hooks
270 server_side.undo()
271
272 // done
273 done()
274 })
275 })
276
277 it('should refresh assets in development mode', function(done)
278 {
279 // create the webpack-assets.json
280 create_assets_file()
281
282 // ensure it waits for webpack-assets.json
283 const server_side = new isomorpher(isomorpher_settings()).development()
284
285 // install require() hooks
286 server_side.server(webpack_configuration.context, () =>
287 {
288 // verify asset value
289 require('./assets/husky.jpg').should.equal(webpack_assets.assets['./assets/husky.jpg'])
290
291 // new asset data
292 const data = extend({}, webpack_assets,
293 {
294 assets:
295 {
296 "./assets/husky.jpg": "woof"
297 }
298 })
299
300 // throw new Error('intended')
301
302 // create the webpack-assets.json
303 create_assets_file(data)
304
305 // refresh assets
306 server_side.refresh()
307
308 // verify that assets are refreshed
309 require('./assets/husky.jpg').should.equal(data.assets['./assets/husky.jpg'])
310
311 // unmount require() hooks
312 server_side.undo()
313
314 // done
315 done()
316 })
317 })
318
319 it('should correctly require aliased paths', function(done)
320 {
321 // https://webpack.github.io/docs/resolving.html#aliasing
322
323 // create the webpack-assets.json
324 create_assets_file()
325
326 // aliasing node_modules
327 const aliases = { 'original_module_name': 'aliased_module_name' }
328
329 const settings = extend({}, isomorpher_settings(), { alias: aliases })
330
331 // will be checked against this value
332 const aliased_module_name_result = require('aliased_module_name')
333
334 // ensure it waits for webpack-assets.json
335 const server_side = new isomorpher(settings).development()
336
337 // install require() hooks
338 server_side.server(webpack_configuration.context, () =>
339 {
340 // verify aliasing
341
342 // should take the value from filesystem
343 require('original_module_name').should.equal(aliased_module_name_result)
344
345 // should take the value from webpack-assets.json
346 require('original_module_name/test.jpg').should.equal(true)
347
348 const test = path => () => require(path)
349
350 test('module_name_not_aliased').should.throw('module_name_not_aliased')
351 test('./original_module_name').should.throw('/original_module_name')
352 test('/original_module_name').should.throw('/original_module_name')
353
354 // unmount require() hooks
355 server_side.undo()
356
357 // done
358 done()
359 })
360 })
361
362 it('should not refresh assets in production mode', function(done)
363 {
364 // create the webpack-assets.json
365 create_assets_file()
366
367 // ensure it waits for webpack-assets.json
368 const server_side = new isomorpher(isomorpher_settings())
369
370 // install require() hooks
371 server_side.server(webpack_configuration.context, () =>
372 {
373 // refresh assets
374 const refresh = () => server_side.refresh()
375
376 // verify that refresh is not permitted in production mode
377 refresh.should.throw('.refresh() called in production mode')
378
379 // unmount require() hooks
380 server_side.undo()
381
382 // done
383 done()
384 })
385 })
386
387 it('should return undefined for assets which are absent from webpack assets', function(done)
388 {
389 // create the webpack-assets.json
390 create_assets_file()
391
392 // ensure it waits for webpack-assets.json
393 const server_side = new isomorpher(isomorpher_settings()).development()
394
395 // install require() hooks
396 server_side.server(webpack_configuration.context, () =>
397 {
398 // verify asset value
399 (typeof require('./assets/absent.jpg')).should.equal('undefined')
400
401 // unmount require() hooks
402 server_side.undo()
403
404 // done
405 done()
406 })
407 })
408
409 it('should validate options', function()
410 {
411 let options = {}
412
413 const instantiate = () => new isomorpher(options)
414
415 instantiate.should.throw('You must specify "assets" parameter')
416
417 options = { whatever: true }
418
419 instantiate.should.throw('Unknown configuration parameter')
420
421 options = { debug: 'true' }
422
423 instantiate.should.throw('must be a boolean')
424
425 options = { assets: 'true' }
426
427 instantiate.should.throw('must be an object')
428
429 options = { debug: true, webpack_assets_file_path: true }
430
431 instantiate.should.throw('must be a string')
432
433 options = { debug: true, webpack_stats_file_path: true }
434
435 instantiate.should.throw('must be a string')
436
437 options = { assets: { images: {} } }
438
439 instantiate.should.throw('You must specify file extensions')
440
441 options = { assets: { images: { extension: ['jpg'] } } }
442
443 instantiate.should.throw('Use "extensions" key')
444
445 options = { assets: { images: { extension: true } } }
446
447 instantiate.should.throw('must be a string')
448
449 options = { assets: { images: { extension: 'jpg', whatever: true } } }
450
451 instantiate.should.throw('Unknown property "whatever"')
452
453 options = { assets: { images: { extension: 'jpg', exclude: true } } }
454
455 instantiate.should.throw('must be an array')
456
457 options = { assets: { images: { extension: 'jpg', exclude: [true] } } }
458
459 instantiate.should.throw('Unsupported object type for exclusion/inclusion "true"')
460
461 options = { assets: { images: { extension: 'jpg', include: true } } }
462
463 instantiate.should.throw('must be an array')
464
465 options = { assets: { images: { extension: 'jpg', include: [true] } } }
466
467 instantiate.should.throw('Unsupported object type for exclusion/inclusion "true"')
468
469 options = { assets: { images: { extension: 'jpg', filter: true } } }
470
471 instantiate.should.throw('"filter" must be a function')
472
473 options = { assets: { images: { extension: 'jpg', path: 'true' } } }
474
475 instantiate.should.throw('"path" must be a function')
476
477 options = { assets: { images: { extension: 'jpg', parser: undefined } } }
478
479 instantiate.should.throw('"parser" must be a function')
480 })
481})
\No newline at end of file