test(weex): add more test cases for recycle-list (#7104)

This commit is contained in:
Hanks 2017-11-23 09:42:07 +08:00 committed by Evan You
parent 0bf0cbef76
commit 46c8016562
15 changed files with 509 additions and 17 deletions

View File

@ -1,21 +1,14 @@
import fs from 'fs'
import path from 'path'
import {
readFile,
readObject,
compileVue,
compileWithDeps,
createInstance,
getRoot,
getEvents,
fireEvent
} from '../helpers'
function readFile (filename) {
return fs.readFileSync(path.resolve(__dirname, filename), 'utf8')
}
function readObject (filename) {
return (new Function(`return ${readFile(filename)}`))()
}
// Create one-off render test case
function createRenderTestCase (name) {
const source = readFile(`${name}.vue`)
@ -72,6 +65,8 @@ describe('Usage', () => {
describe('recycle-list', () => {
it('text node', createRenderTestCase('recycle-list/text-node'))
it('attributes', createRenderTestCase('recycle-list/attrs'))
// it('class name', createRenderTestCase('recycle-list/classname'))
// it('inline style', createRenderTestCase('recycle-list/inline-style'))
it('v-if', createRenderTestCase('recycle-list/v-if'))
it('v-else', createRenderTestCase('recycle-list/v-else'))
it('v-else-if', createRenderTestCase('recycle-list/v-else-if'))
@ -79,6 +74,66 @@ describe('Usage', () => {
it('v-for-iterator', createRenderTestCase('recycle-list/v-for-iterator'))
it('v-on', createRenderTestCase('recycle-list/v-on'))
it('v-on-inline', createRenderTestCase('recycle-list/v-on-inline'))
it('stateless component', done => {
compileWithDeps('recycle-list/components/stateless.vue', [{
name: 'banner',
path: 'recycle-list/components/banner.vue'
}]).then(code => {
const id = String(Date.now() * Math.random())
const instance = createInstance(id, code)
setTimeout(() => {
const target = readObject('recycle-list/components/stateless.vdom.js')
expect(getRoot(instance)).toEqual(target)
done()
}, 50)
}).catch(err => {
expect(err).toBe(null)
done()
})
})
// it('stateless component with props', done => {
// compileWithDeps('recycle-list/components/stateless-with-props.vue', [{
// name: 'poster',
// path: 'recycle-list/components/poster.vue'
// }]).then(code => {
// const id = String(Date.now() * Math.random())
// const instance = createInstance(id, code)
// setTimeout(() => {
// const target = readObject('recycle-list/components/stateless-with-props.vdom.js')
// expect(getRoot(instance)).toEqual(target)
// done()
// }, 50)
// }).catch(err => {
// expect(err).toBe(null)
// done()
// })
// })
// it('stateful component', done => {
// compileWithDeps('recycle-list/components/stateful.vue', [{
// name: 'counter',
// path: 'recycle-list/components/counter.vue'
// }]).then(code => {
// const id = String(Date.now() * Math.random())
// const instance = createInstance(id, code)
// setTimeout(() => {
// const target = readObject('recycle-list/components/stateful.vdom.js')
// expect(getRoot(instance)).toEqual(target)
// const event = getEvents(instance)[0]
// fireEvent(instance, event.ref, event.type, {})
// setTimeout(() => {
// // TODO: check render results
// // expect(getRoot(instance)).toEqual(target)
// done()
// })
// }, 50)
// }).catch(err => {
// expect(err).toBe(null)
// done()
// })
// })
})
})

View File

@ -0,0 +1,26 @@
({
type: 'recycle-list',
attr: {
listData: [
{ type: 'A', color: 'red' },
{ type: 'A', color: 'blue' }
],
templateKey: 'type',
alias: 'item'
},
children: [{
type: 'cell-slot',
attr: { templateType: 'A' },
style: {
backgroundColor: '#FF6600'
},
children: [{
type: 'text',
attr: {
// not supported yet
// classList: ['text', { '@binding': 'item.color' }],
value: 'content'
}
}]
}]
})

View File

@ -0,0 +1,37 @@
<template>
<recycle-list :list-data="longList" template-key="type" alias="item">
<cell-slot template-type="A" class="cell">
<text :class="['text', item.color]">content</text>
</cell-slot>
</recycle-list>
</template>
<style scoped>
.cell {
background-color: #FF6600;
}
.text {
font-size: 100px;
text-align: center;
}
.red {
color: #FF0000;
}
.blue {
color: #0000FF;
}
</style>
<script>
module.exports = {
data () {
return {
longList: [
{ type: 'A', color: 'red' },
{ type: 'A', color: 'blue' }
]
}
}
}
</script>

View File

@ -0,0 +1,19 @@
<template recyclable="true">
<div class="banner">
<text class="title">BANNER</text>
</div>
</template>
<style scoped>
.banner {
height: 120px;
justify-content: center;
align-items: center;
background-color: rgb(162, 217, 192);
}
.title {
font-weight: bold;
color: #41B883;
font-size: 60px;
}
</style>

View File

@ -0,0 +1,36 @@
<template recyclable="true">
<div>
<text class="output">{{count}}</text>
<text class="button" @click="inc">+</text>
</div>
</template>
<script>
module.exports = {
props: ['start'],
data () {
return {
count: parseInt(this.start, 10) || 42
}
},
methods: {
inc () {
this.count++
}
}
}
</script>
<style scoped>
.output {
font-size: 150px;
text-align: center;
}
.button {
font-size: 100px;
text-align: center;
border-width: 2px;
border-color: #DDD;
background-color: #F5F5F5;
}
</style>

View File

@ -0,0 +1,33 @@
<template>
<div>
<image class="image" :src="imageUrl"></image>
<text class="title">{{title}}</text>
</div>
</template>
<script>
module.exports = {
props: {
imageUrl: {
type: String,
default: 'https://gw.alicdn.com/tfs/TB1KF_ybRTH8KJjy0FiXXcRsXXa-890-1186.png'
},
title: {
type: String,
default: 'I WANT YOU!'
}
}
}
</script>
<style scoped>
.image {
width: 750px;
height: 1000px;
}
.title {
font-size: 80px;
text-align: center;
color: #E95659;
}
</style>

View File

@ -0,0 +1,45 @@
({
type: 'recycle-list',
attr: {
listData: [
{ type: 'A', number: 24 },
{ type: 'A', number: 42 }
],
templateKey: 'type',
alias: 'item'
},
children: [{
type: 'cell-slot',
attr: { templateType: 'A' },
children: [{
type: 'div',
attr: {
'@isComponentRoot': true,
'@componentProps': {
start: { '@binding': 'item.number' }
}
},
children: [{
type: 'text',
style: { fontSize: '150px', textAlign: 'center' },
attr: {
value: { '@binding': 'count' } // need confirm
}
}, {
type: 'text',
event: ['click'],
style: {
fontSize: '100px',
textAlign: 'center',
borderWidth: '2px',
borderColor: '#DDDDDD',
backgroundColor: '#F5F5F5'
},
attr: { value: '+' }
}]
}, {
type: 'text',
attr: { value: 'other' }
}]
}]
})

View File

@ -0,0 +1,22 @@
<template>
<recycle-list :list-data="longList" template-key="type" alias="item">
<cell-slot template-type="A">
<counter :start="item.number"></counter>
<text>other</text>
</cell-slot>
</recycle-list>
</template>
<script>
// require('./counter.vue')
module.exports = {
data () {
return {
longList: [
{ type: 'A', number: 24 },
{ type: 'A', number: 42 }
]
}
}
}
</script>

View File

@ -0,0 +1,50 @@
({
type: 'recycle-list',
attr: {
listData: [
{ type: 'A', poster: 'xx', title: 'x' },
{ type: 'A', poster: 'yy', title: 'y' }
],
templateKey: 'type',
alias: 'item'
},
children: [{
type: 'cell-slot',
attr: { templateType: 'A' },
children: [{
type: 'div',
attr: {
'@isComponentRoot': true,
'@componentProps': {
imageUrl: { '@binding': 'item.poster' },
title: { '@binding': 'item.title' }
}
},
children: [{
type: 'image',
style: {
width: '750px',
height: '1000px'
},
attr: {
src: { '@binding': 'imageUrl' }
}
}, {
type: 'text',
style: {
fontSize: '80px',
textAlign: 'center',
color: '#E95659'
},
attr: {
value: { '@binding': 'title' }
}
}]
}, {
type: 'text',
attr: {
value: 'content'
}
}]
}]
})

View File

@ -0,0 +1,22 @@
<template>
<recycle-list :list-data="longList" template-key="type" alias="item">
<cell-slot template-type="A">
<poster :image-url="item.poster" :title="item.title"></poster>
<text>content</text>
</cell-slot>
</recycle-list>
</template>
<script>
// require('./poster.vue')
module.exports = {
data () {
return {
longList: [
{ type: 'A', poster: 'xx', title: 'x' },
{ type: 'A', poster: 'yy', title: 'y' }
]
}
}
}
</script>

View File

@ -0,0 +1,45 @@
({
type: 'recycle-list',
attr: {
listData: [
{ type: 'A' },
{ type: 'A' }
],
templateKey: 'type',
alias: 'item'
},
children: [{
type: 'cell-slot',
attr: { templateType: 'A' },
children: [{
type: 'div',
// not supported yet
// attr: {
// '@isComponentRoot': true,
// '@componentProps': {}
// },
// style: {
// height: '120px',
// justifyContent: 'center',
// alignItems: 'center',
// backgroundColor: 'rgb(162, 217, 192)'
// },
children: [{
type: 'text',
// style: {
// fontWeight: 'bold',
// color: '#41B883',
// fontSize: '60px'
// },
attr: {
value: 'BANNER'
}
}]
}, {
type: 'text',
attr: {
value: 'content'
}
}]
}]
})

View File

@ -0,0 +1,22 @@
<template>
<recycle-list :list-data="longList" template-key="type" alias="item">
<cell-slot template-type="A">
<banner></banner>
<text>content</text>
</cell-slot>
</recycle-list>
</template>
<script>
// require('./banner.vue')
module.exports = {
data () {
return {
longList: [
{ type: 'A' },
{ type: 'A' }
]
}
}
}
</script>

View File

@ -0,0 +1,28 @@
({
type: 'recycle-list',
attr: {
listData: [
{ type: 'A', color: '#606060' },
{ type: 'A', color: '#E5E5E5' }
],
templateKey: 'type',
alias: 'item'
},
children: [{
type: 'cell-slot',
attr: { templateType: 'A' },
style: {
backgroundColor: '#FF6600'
},
children: [{
type: 'text',
style: {
fontSize: '100px',
color: { '@binding': 'item.color' }
},
attr: {
value: 'content'
}
}]
}]
})

View File

@ -0,0 +1,21 @@
<template>
<recycle-list :list-data="longList" template-key="type" alias="item">
<cell-slot template-type="A" style="background-color:#FF6600">
<text :style="{ fontSize: '100px', color: item.color }">content</text>
</cell-slot>
</recycle-list>
</template>
<script>
module.exports = {
data () {
return {
longList: [
{ type: 'A', color: '#606060' },
{ type: 'A', color: '#E5E5E5' }
]
}
}
}
</script>

View File

@ -1,3 +1,5 @@
import fs from 'fs'
import path from 'path'
import * as Vue from '../../../packages/weex-vue-framework'
import { compile } from '../../../packages/weex-template-compiler'
import WeexRuntime from 'weex-js-runtime'
@ -5,7 +7,15 @@ import styler from 'weex-styler'
const styleRE = /<\s*style\s*\w*>([^(<\/)]*)<\/\s*style\s*>/g
const scriptRE = /<\s*script.*>([^]*)<\/\s*script\s*>/
const templateRE = /<\s*template\s*>([^]*)<\/\s*template\s*>/
const templateRE = /<\s*template\s*([^>]*)>([^]*)<\/\s*template\s*>/
export function readFile (filename) {
return fs.readFileSync(path.resolve(__dirname, '../cases/', filename), 'utf8')
}
export function readObject (filename) {
return (new Function(`return ${readFile(filename)}`))()
}
console.debug = () => {}
@ -39,21 +49,28 @@ export function compileVue (source, componentName) {
}
const scriptMatch = scriptRE.exec(source)
const script = scriptMatch ? scriptMatch[1] : ''
const { render, staticRenderFns } = compile(templateRE.exec(source)[1])
const templateMatch = templateRE.exec(source)
const compileOptions = {}
if (/\s*recyclable\=?/i.test(templateMatch[1])) {
compileOptions.recyclable = true
}
const res = compile(templateMatch[2], compileOptions)
const name = 'test_case_' + (Math.random() * 99999999).toFixed(0)
const generateCode = styles => (`
var test_case = Object.assign({
var ${name} = Object.assign({
style: ${JSON.stringify(styles)},
render: function () { ${render} },
staticRenderFns: ${parseStatic(staticRenderFns)},
render: function () { ${res.render} },
${res['@render'] ? ('"@render": function () {' + res['@render'] + '},') : ''}
staticRenderFns: ${parseStatic(res.staticRenderFns)},
}, (function(){
var module = { exports: {} };
${script};
return module.exports;
})());
` + (componentName
? `Vue.component('${componentName}', test_case);\n`
: `test_case.el = 'body';new Vue(test_case);`)
? `Vue.component('${componentName}', ${name});\n`
: `${name}.el = 'body';new Vue(${name});`)
)
let cssText = ''
@ -71,6 +88,20 @@ export function compileVue (source, componentName) {
})
}
export function compileWithDeps (entryPath, deps) {
return new Promise((resolve, reject) => {
if (Array.isArray(deps)) {
Promise.all(deps.map(dep => {
return compileVue(readFile(dep.path), dep.name).catch(reject)
})).then(depCodes => {
compileVue(readFile(entryPath)).then(entryCode => {
resolve(depCodes.join('\n') + entryCode)
}).catch(reject)
}).catch(reject)
}
})
}
function isObject (object) {
return object !== null && typeof object === 'object'
}