-
Notifications
You must be signed in to change notification settings - Fork 26
/
Copy pathtemplate-loader.spec.js
139 lines (117 loc) · 3.62 KB
/
template-loader.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
const requireFromString = require('require-from-string')
const SourceMapConsumer = require('source-map').SourceMapConsumer
const loader = require('../lib/template-loader')
const Vue = require('vue')
const Component = require('vue-class-component').default
const styleLoaderPath = require.resolve('../lib/scoped-style-loader.js')
function mockRender (options, data = {}) {
const mock = {
_c (tag, data, children) {
if (Array.isArray(data)) {
children = data
data = null
}
return {
tag,
data,
children
}
},
_m (index) {
return options.staticRenderFns[index].call(this)
},
_v (str) {
return String(str)
},
_s (str) {
return String(str)
}
}
Object.defineProperty(mock, '_self', {
get () {
return this
}
})
return options.render.call(Object.assign(mock, data))
}
function loadCode(data, { sourceMap, style, query = {}} = {}) {
const result = { code: null, map: null }
loader.call({
resourcePath: '/path/to/test.html',
cacheable: () => {},
options: {},
query,
sourceMap,
request: 'foo.html' + (style ? `?style=${style}` : ''),
callback (err, code, map) {
result.code = code
result.map = map
}
}, data)
return result
}
function load (data, options) {
return requireFromString(loadCode(data, options).code)
}
describe('vue-template-loader', () => {
it('renders static element', () => {
const withRender = load('<div><p>hi</p></div>')
const options = withRender({})
const vnode = mockRender(options)
expect(vnode.tag).toBe('div')
expect(vnode.children[0].children[0]).toBe('hi')
})
it('renders data bound element', () => {
const withRender = load('<div><p>{{ value }}</p></div>')
const options = withRender({})
const vnode = mockRender(options, { value: 'hello' })
expect(vnode.children[0].children[0]).toBe('hello')
})
it('is used as decorator', () => {
const WithRender = load('<div><p>hi</p></div>')
@WithRender
@Component
class Comp extends Vue {
value = 123
}
const c = new Comp()
expect(c.value).toBe(123)
const vnode = mockRender(Comp.options)
expect(vnode.children[0].children[0]).toBe('hi')
})
it('does not inject style related code if it is not specified', () => {
const { code } = loadCode('<div>hi</div>')
expect(code).toMatchSnapshot()
})
it('inject normal styles', () => {
const { code } = loadCode('<div>hi</div>', { style: './style.css' })
expect(code).toMatchSnapshot()
})
it('inject scoped id and scoped css', () => {
const { code } = loadCode('<div>hi</div>', { style: './style.css', query: { scoped: true }})
expect(code.replace(styleLoaderPath, '{{scoped-style-loader}}')).toMatchSnapshot()
})
it('disable HMR by option', () => {
const { code } = loadCode('<div>hi</div>', { query: { hmr: false }})
expect(code).toMatchSnapshot()
})
it('generates source map', () => {
const { code, map } = loadCode('<div>hi</div>', { sourceMap: true })
const generatedPos = { line: null, column: null }
code.split('\n').forEach((line, i) => {
const pos = line.indexOf('var render =')
if (pos >= 0) {
generatedPos.line = i + 1
generatedPos.column = pos
}
})
const smc = new SourceMapConsumer(map)
const originalPos = smc.originalPositionFor(generatedPos)
expect(originalPos.line).toBe(1)
expect(originalPos.column).toBe(0)
})
it('sets functional', () => {
const { code } = loadCode('<div>{{ props.data }}</div>', { query: { functional: true }})
expect(code).toMatchSnapshot()
})
})