Skip to content

Commit 232dd85

Browse files
Hanks10100yyx990803
authored andcommitted
test(weex): support testing the virtual dom generated form *.vue files (#6944)
Compile the *.vue file into js code, then run it in Weex context, and compare the generate virtual dom. It’s a black-box testing for `weex-template-compiler`, `weex-styler`,`weex-vue-framework` and `weex-js-runtime`.
1 parent 8a784d8 commit 232dd85

File tree

8 files changed

+223
-3
lines changed

8 files changed

+223
-3
lines changed

Diff for: package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@
125125
"typescript": "^2.5.2",
126126
"uglify-js": "^3.0.15",
127127
"webpack": "^2.6.1",
128-
"weex-js-runtime": "^0.23.0"
128+
"weex-js-runtime": "^0.23.0",
129+
"weex-styler": "^0.3.0"
129130
},
130131
"config": {
131132
"commitizen": {

Diff for: test/weex/cases/cases.spec.js

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import fs from 'fs'
2+
import path from 'path'
3+
import {
4+
compileVue,
5+
createInstance,
6+
getRoot,
7+
getEvents,
8+
fireEvent
9+
} from '../helpers'
10+
11+
function readFile (filename) {
12+
return fs.readFileSync(path.resolve(__dirname, filename), 'utf8')
13+
}
14+
15+
function readObject (filename) {
16+
return (new Function(`return ${readFile(filename)}`))()
17+
}
18+
19+
// Create one-off render test case
20+
function createRenderTestCase (name) {
21+
const source = readFile(`${name}.vue`)
22+
const target = readObject(`${name}.vdom.js`)
23+
return done => {
24+
compileVue(source).then(code => {
25+
const id = String(Date.now() * Math.random())
26+
const instance = createInstance(id, code)
27+
setTimeout(() => {
28+
expect(getRoot(instance)).toEqual(target)
29+
done()
30+
}, 50)
31+
}).catch(err => {
32+
expect(err).toBe(null)
33+
done()
34+
})
35+
}
36+
}
37+
38+
// Create event test case, will trigger the first bind event
39+
function createEventTestCase (name) {
40+
const source = readFile(`${name}.vue`)
41+
const before = readObject(`${name}.before.vdom.js`)
42+
const after = readObject(`${name}.after.vdom.js`)
43+
return done => {
44+
compileVue(source).then(code => {
45+
const id = String(Date.now() * Math.random())
46+
const instance = createInstance(id, code)
47+
setTimeout(() => {
48+
expect(getRoot(instance)).toEqual(before)
49+
const event = getEvents(instance)[0]
50+
fireEvent(instance, event.ref, event.type, {})
51+
setTimeout(() => {
52+
expect(getRoot(instance)).toEqual(after)
53+
done()
54+
}, 50)
55+
}, 50)
56+
}).catch(err => {
57+
expect(err).toBe(null)
58+
done()
59+
})
60+
}
61+
}
62+
63+
describe('Usage', () => {
64+
describe('render', () => {
65+
it('sample', createRenderTestCase('render/sample'))
66+
})
67+
68+
describe('event', () => {
69+
it('click', createEventTestCase('event/click'))
70+
})
71+
})
72+

Diff for: test/weex/cases/event/click.after.vdom.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
({
2+
type: 'div',
3+
event: ['click'],
4+
children: [{
5+
type: 'text',
6+
attr: {
7+
value: '43'
8+
}
9+
}]
10+
})

Diff for: test/weex/cases/event/click.before.vdom.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
({
2+
type: 'div',
3+
event: ['click'],
4+
children: [{
5+
type: 'text',
6+
attr: {
7+
value: '42'
8+
}
9+
}]
10+
})

Diff for: test/weex/cases/event/click.vue

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<template>
2+
<div @click="inc">
3+
<text>{{count}}</text>
4+
</div>
5+
</template>
6+
7+
<script>
8+
module.exports = {
9+
data () {
10+
return {
11+
count: 42
12+
}
13+
},
14+
methods: {
15+
inc () {
16+
this.count++
17+
}
18+
}
19+
}
20+
</script>

Diff for: test/weex/cases/render/sample.vdom.js

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
({
2+
type: 'div',
3+
style: {
4+
justifyContent: 'center'
5+
},
6+
children: [{
7+
type: 'text',
8+
attr: {
9+
value: 'Yo'
10+
},
11+
style: {
12+
color: '#41B883',
13+
fontSize: '233px',
14+
textAlign: 'center'
15+
}
16+
}]
17+
})

Diff for: test/weex/cases/render/sample.vue

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<template>
2+
<div style="justify-content:center">
3+
<text class="freestyle">{{string}}</text>
4+
</div>
5+
</template>
6+
7+
<style scoped>
8+
.freestyle {
9+
color: #41B883;
10+
font-size: 233px;
11+
text-align: center;
12+
}
13+
</style>
14+
15+
<script>
16+
module.exports = {
17+
data () {
18+
return {
19+
string: 'Yo'
20+
}
21+
}
22+
}
23+
</script>

Diff for: test/weex/helpers/index.js

+69-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import * as Vue from '../../../packages/weex-vue-framework'
22
import { compile } from '../../../packages/weex-template-compiler'
33
import WeexRuntime from 'weex-js-runtime'
4+
import styler from 'weex-styler'
5+
6+
const styleRE = /<\s*style\s*\w*>([^(<\/)]*)<\/\s*style\s*>/g
7+
const scriptRE = /<\s*script.*>([^]*)<\/\s*script\s*>/
8+
const templateRE = /<\s*template\s*>([^]*)<\/\s*template\s*>/
49

510
console.debug = () => {}
611

@@ -10,6 +15,10 @@ export function strToRegExp (str) {
1015
return new RegExp(str.replace(matchOperatorsRe, '\\$&'))
1116
}
1217

18+
function parseStatic (fns) {
19+
return '[' + fns.map(fn => `function () { ${fn} }`).join(',') + ']'
20+
}
21+
1322
export function compileAndStringify (template) {
1423
const { render, staticRenderFns } = compile(template)
1524
return {
@@ -18,8 +27,48 @@ export function compileAndStringify (template) {
1827
}
1928
}
2029

21-
function parseStatic (fns) {
22-
return '[' + fns.map(fn => `function () { ${fn} }`).join(',') + ']'
30+
/**
31+
* Compile *.vue file into js code
32+
* @param {string} source raw text of *.vue file
33+
* @param {string} componentName whether compile to a component
34+
*/
35+
export function compileVue (source, componentName) {
36+
return new Promise((resolve, reject) => {
37+
if (!templateRE.test(source)) {
38+
return reject('No Template!')
39+
}
40+
const scriptMatch = scriptRE.exec(source)
41+
const script = scriptMatch ? scriptMatch[1] : ''
42+
const { render, staticRenderFns } = compile(templateRE.exec(source)[1])
43+
44+
const generateCode = styles => (`
45+
var test_case = Object.assign({
46+
style: ${JSON.stringify(styles)},
47+
render: function () { ${render} },
48+
staticRenderFns: ${parseStatic(staticRenderFns)},
49+
}, (function(){
50+
var module = { exports: {} };
51+
${script};
52+
return module.exports;
53+
})());
54+
` + (componentName
55+
? `Vue.component('${componentName}', test_case);\n`
56+
: `test_case.el = 'body';new Vue(test_case);`)
57+
)
58+
59+
let cssText = ''
60+
let styleMatch = null
61+
while ((styleMatch = styleRE.exec(source))) {
62+
cssText += `\n${styleMatch[1]}\n`
63+
}
64+
styler.parse(cssText, (error, result) => {
65+
if (error) {
66+
return reject(error)
67+
}
68+
resolve(generateCode(result.jsonStyle))
69+
})
70+
resolve(generateCode({}))
71+
})
2372
}
2473

2574
function isObject (object) {
@@ -47,6 +96,24 @@ export function getRoot (instance) {
4796
return omitUseless(instance.document.body.toJSON())
4897
}
4998

99+
// Get all binding events in the instance
100+
export function getEvents (instance) {
101+
const events = []
102+
const recordEvent = node => {
103+
if (!node) { return }
104+
if (Array.isArray(node.event)) {
105+
node.event.forEach(type => {
106+
events.push({ ref: node.ref, type })
107+
})
108+
}
109+
if (Array.isArray(node.children)) {
110+
node.children.forEach(recordEvent)
111+
}
112+
}
113+
recordEvent(instance.document.body.toJSON())
114+
return events
115+
}
116+
50117
export function fireEvent (instance, ref, type, event = {}) {
51118
const el = instance.document.getRef(ref)
52119
if (el) {

0 commit comments

Comments
 (0)