diff --git a/build/config.js b/build/config.js index 20fefa8506c..5749409daac 100644 --- a/build/config.js +++ b/build/config.js @@ -17,7 +17,7 @@ const banner = const weexFactoryPlugin = { intro () { - return 'module.exports = function weexFactory (exports, renderer) {' + return 'module.exports = function weexFactory (exports, document) {' }, outro () { return '}' diff --git a/package.json b/package.json index bd1247a848f..04546c1e0ba 100644 --- a/package.json +++ b/package.json @@ -122,8 +122,7 @@ "typescript": "^2.3.4", "uglify-js": "^3.0.15", "webpack": "^2.6.1", - "weex-js-runtime": "^0.20.5", - "weex-vdom-tester": "^0.2.0" + "weex-js-runtime": "^0.22.0" }, "config": { "commitizen": { diff --git a/src/platforms/weex/entry-framework.js b/src/platforms/weex/entry-framework.js index 90f5f0d81be..9b7c920cfbd 100644 --- a/src/platforms/weex/entry-framework.js +++ b/src/platforms/weex/entry-framework.js @@ -1,41 +1,19 @@ -import TextNode from 'weex/runtime/text-node' - // this will be preserved during build const VueFactory = require('./factory') const instances = {} -const modules = {} -const components = {} - -const renderer = { - TextNode, - instances, - modules, - components -} /** - * Prepare framework config, basically about the virtual-DOM and JS bridge. - * @param {object} cfg + * Prepare framework config. + * Nothing need to do actually, just an interface provided to weex runtime. */ -export function init (cfg) { - renderer.Document = cfg.Document - renderer.Element = cfg.Element - renderer.Comment = cfg.Comment - renderer.compileBundle = cfg.compileBundle -} +export function init () {} /** * Reset framework config and clear all registrations. */ export function reset () { clear(instances) - clear(modules) - clear(components) - delete renderer.Document - delete renderer.Element - delete renderer.Comment - delete renderer.compileBundle } /** @@ -63,47 +41,31 @@ export function createInstance ( data, env = {} ) { - // Virtual-DOM object. - const document = new renderer.Document(instanceId, config.bundleUrl) - + const weex = env.weex + const document = weex.document const instance = instances[instanceId] = { instanceId, config, data, document } - // Prepare native module getter and HTML5 Timer APIs. - const moduleGetter = genModuleGetter(instanceId) - const timerAPIs = getInstanceTimer(instanceId, moduleGetter) - - // Prepare `weex` instance variable. - const weexInstanceVar = { - config, - document, - supports, - requireModule: moduleGetter - } - Object.freeze(weexInstanceVar) + const timerAPIs = getInstanceTimer(instanceId, weex.requireModule) // Each instance has a independent `Vue` module instance - const Vue = instance.Vue = createVueModuleInstance(instanceId, moduleGetter) + const Vue = instance.Vue = createVueModuleInstance(instanceId, weex) // The function which create a closure the JS Bundle will run in. // It will declare some instance variables like `Vue`, HTML5 Timer APIs etc. const instanceVars = Object.assign({ Vue, - weex: weexInstanceVar + weex }, timerAPIs, env.services) appCode = `(function(global){ \n${appCode}\n })(Object.create(this))` - if (!callFunctionNative(instanceVars, appCode)) { - // If failed to compile functionBody on native side, - // fallback to 'callFunction()'. - callFunction(instanceVars, appCode) - } + callFunction(instanceVars, appCode) // Send `createFinish` signal to native. - instance.document.taskCenter.send('dom', { action: 'createFinish' }, []) + document.taskCenter.send('dom', { action: 'createFinish' }, []) return instance } @@ -118,6 +80,8 @@ export function destroyInstance (instanceId) { if (instance && instance.app instanceof instance.Vue) { instance.document.destroy() instance.app.$destroy() + delete instance.document + delete instance.app } delete instances[instanceId] } @@ -200,91 +164,12 @@ export function receiveTasks (id, tasks) { return new Error(`invalid instance id "${id}" or tasks`) } -/** - * Register native modules information. - * @param {object} newModules - */ -export function registerModules (newModules) { - for (const name in newModules) { - if (!modules[name]) { - modules[name] = {} - } - newModules[name].forEach(method => { - if (typeof method === 'string') { - modules[name][method] = true - } else { - modules[name][method.name] = method.args - } - }) - } -} - -/** - * Check whether the module or the method has been registered. - * @param {String} module name - * @param {String} method name (optional) - */ -export function isRegisteredModule (name, method) { - if (typeof method === 'string') { - return !!(modules[name] && modules[name][method]) - } - return !!modules[name] -} - -/** - * Register native components information. - * @param {array} newComponents - */ -export function registerComponents (newComponents) { - if (Array.isArray(newComponents)) { - newComponents.forEach(component => { - if (!component) { - return - } - if (typeof component === 'string') { - components[component] = true - } else if (typeof component === 'object' && typeof component.type === 'string') { - components[component.type] = component - } - }) - } -} - -/** - * Check whether the component has been registered. - * @param {String} component name - */ -export function isRegisteredComponent (name) { - return !!components[name] -} - -/** - * Detects whether Weex supports specific features. - * @param {String} condition - */ -export function supports (condition) { - if (typeof condition !== 'string') return null - - const res = condition.match(/^@(\w+)\/(\w+)(\.(\w+))?$/i) - if (res) { - const type = res[1] - const name = res[2] - const method = res[4] - switch (type) { - case 'module': return isRegisteredModule(name, method) - case 'component': return isRegisteredComponent(name) - } - } - - return null -} - /** * Create a fresh instance of Vue for each Weex instance. */ -function createVueModuleInstance (instanceId, moduleGetter) { +function createVueModuleInstance (instanceId, weex) { const exports = {} - VueFactory(exports, renderer) + VueFactory(exports, weex.document) const Vue = exports.Vue const instance = instances[instanceId] @@ -295,7 +180,7 @@ function createVueModuleInstance (instanceId, moduleGetter) { const isReservedTag = Vue.config.isReservedTag || (() => false) const isRuntimeComponent = Vue.config.isRuntimeComponent || (() => false) Vue.config.isReservedTag = name => { - return (!isRuntimeComponent(name) && components[name]) || + return (!isRuntimeComponent(name) && weex.supports(`@component/${name}`)) || isReservedTag(name) || weexRegex.test(name) } @@ -307,7 +192,7 @@ function createVueModuleInstance (instanceId, moduleGetter) { // expose weex native module getter on subVue prototype so that // vdom runtime modules can access native modules via vnode.context - Vue.prototype.$requireWeexModule = moduleGetter + Vue.prototype.$requireWeexModule = weex.requireModule // Hack `Vue` behavior to handle instance information and data // before root component created. @@ -340,39 +225,6 @@ function createVueModuleInstance (instanceId, moduleGetter) { return Vue } -/** - * Generate native module getter. Each native module has several - * methods to call. And all the behaviors is instance-related. So - * this getter will return a set of methods which additionally - * send current instance id to native when called. - * @param {string} instanceId - * @return {function} - */ -function genModuleGetter (instanceId) { - const instance = instances[instanceId] - return function (name) { - const nativeModule = modules[name] || [] - const output = {} - for (const methodName in nativeModule) { - Object.defineProperty(output, methodName, { - enumerable: true, - configurable: true, - get: function proxyGetter () { - return (...args) => { - return instance.document.taskCenter.send('module', { module: name, method: methodName }, args) - } - }, - set: function proxySetter (val) { - if (typeof val === 'function') { - return instance.document.taskCenter.send('module', { module: name, method: methodName }, [val]) - } - } - }) - } - return output - } -} - /** * Generate HTML5 Timer APIs. An important point is that the callback * will be converted into callback id when sent to native. So the @@ -430,55 +282,3 @@ function callFunction (globalObjects, body) { const result = new Function(...globalKeys) return result(...globalValues) } - -/** - * Call a new function generated on the V8 native side. - * - * This function helps speed up bundle compiling. Normally, the V8 - * engine needs to download, parse, and compile a bundle on every - * visit. If 'compileBundle()' is available on native side, - * the downloading, parsing, and compiling steps would be skipped. - * @param {object} globalObjects - * @param {string} body - * @return {boolean} - */ -function callFunctionNative (globalObjects, body) { - if (typeof renderer.compileBundle !== 'function') { - return false - } - - let fn = void 0 - let isNativeCompileOk = false - let script = '(function (' - const globalKeys = [] - const globalValues = [] - for (const key in globalObjects) { - globalKeys.push(key) - globalValues.push(globalObjects[key]) - } - for (let i = 0; i < globalKeys.length - 1; ++i) { - script += globalKeys[i] - script += ',' - } - script += globalKeys[globalKeys.length - 1] - script += ') {' - script += body - script += '} )' - - try { - const weex = globalObjects.weex || {} - const config = weex.config || {} - fn = renderer.compileBundle(script, - config.bundleUrl, - config.bundleDigest, - config.codeCachePath) - if (fn && typeof fn === 'function') { - fn(...globalValues) - isNativeCompileOk = true - } - } catch (e) { - console.error(e) - } - - return isNativeCompileOk -} diff --git a/src/platforms/weex/runtime/node-ops.js b/src/platforms/weex/runtime/node-ops.js index e71e49f62e7..303c81945ee 100755 --- a/src/platforms/weex/runtime/node-ops.js +++ b/src/platforms/weex/runtime/node-ops.js @@ -1,22 +1,24 @@ -/* globals renderer */ -// renderer is injected by weex factory wrapper +/* globals document */ +// document is injected by weex factory wrapper + +import TextNode from 'weex/runtime/text-node' export const namespaceMap = {} export function createElement (tagName) { - return new renderer.Element(tagName) + return document.createElement(tagName) } export function createElementNS (namespace, tagName) { - return new renderer.Element(namespace + ':' + tagName) + return document.createElement(namespace + ':' + tagName) } export function createTextNode (text) { - return new renderer.TextNode(text) + return new TextNode(text) } export function createComment (text) { - return new renderer.Comment(text) + return document.createComment(text) } export function insertBefore (node, target, before) { diff --git a/src/platforms/weex/util/index.js b/src/platforms/weex/util/index.js index b74949cdd01..05da30e985e 100755 --- a/src/platforms/weex/util/index.js +++ b/src/platforms/weex/util/index.js @@ -1,4 +1,4 @@ -/* globals renderer */ +/* globals document */ import { makeMap } from 'shared/util' @@ -34,8 +34,8 @@ export function getTagNamespace () { /* console.log('getTagNamespace') */ } export function isUnknownElement () { /* console.log('isUnknownElement') */ } export function query (el, document) { - // renderer is injected by weex factory wrapper - const placeholder = new renderer.Comment('root') + // document is injected by weex factory wrapper + const placeholder = document.createComment('root') placeholder.hasAttribute = placeholder.removeAttribute = function () {} // hack for patch document.documentElement.appendChild(placeholder) return placeholder diff --git a/test/weex/helpers/index.js b/test/weex/helpers/index.js index 2375cbc61ae..ca4b3436b60 100644 --- a/test/weex/helpers/index.js +++ b/test/weex/helpers/index.js @@ -1,13 +1,8 @@ -// suppress logs from vdom-tester -const domModule = require('weex-vdom-tester/lib/modules/dom') -domModule.updateFinish = domModule.createFinish = domModule.refreshFinish = () => {} - import * as Vue from '../../../packages/weex-vue-framework' import { compile } from '../../../packages/weex-template-compiler' -import { Runtime, Instance } from 'weex-vdom-tester' -import { init, config } from 'weex-js-runtime' +import WeexRuntime from 'weex-js-runtime' -init() +console.debug = () => {} // http://stackoverflow.com/a/35478115 const matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g @@ -27,32 +22,66 @@ function parseStatic (fns) { return '[' + fns.map(fn => `function () { ${fn} }`).join(',') + ']' } -export function prepareRuntime () { - let sendTasksHandler = function () {} - config.sendTasks = config.Document.handler = function () { - sendTasksHandler.apply(null, arguments) - } - Vue.init(config) - const runtime = new Runtime(Vue) - sendTasksHandler = function () { - runtime.target.callNative.apply(runtime.target, arguments) +function isObject (object) { + return object !== null && typeof object === 'object' +} + +function isEmptyObject (object) { + return isObject(object) && Object.keys(object).length < 1 +} + +function omitUseless (object) { + if (isObject(object)) { + delete object.ref + for (const key in object) { + if (isEmptyObject(object[key]) || object[key] === undefined) { + delete object[key] + } + omitUseless(object[key]) + } } - return runtime + return object } -export function resetRuntime () { - delete config.Document.handler - Vue.reset() +export function getRoot (instance) { + return omitUseless(instance.document.body.toJSON()) } -export function createInstance (runtime, code) { - const instance = new Instance(runtime) - if (code) { - instance.$create(code) +export function fireEvent (instance, ref, type, event = {}) { + const el = instance.document.getRef(ref) + if (el) { + instance.document.fireEvent(el, type, event = {}) } +} + +export function createInstance (id, code, ...args) { + WeexRuntime.config.frameworks = { Vue } + const context = WeexRuntime.init(WeexRuntime.config) + context.registerModules({ + timer: ['setTimeout', 'setInterval'] + }) + const instance = context.createInstance(id, `// { "framework": "Vue" }\n${code}`, ...args) + instance.$refresh = (data) => context.refreshInstance(id, data) + instance.$destroy = () => context.destroyInstance(id) return instance } +export function compileAndExecute (template, additional = '') { + return new Promise(resolve => { + const id = String(Date.now() * Math.random()) + const { render, staticRenderFns } = compile(template) + const instance = createInstance(id, ` + new Vue({ + el: '#whatever', + render: function () { ${render} }, + staticRenderFns: ${parseStatic(staticRenderFns)}, + ${additional} + }) + `) + setTimeout(() => resolve(instance), 10) + }) +} + export function syncPromise (arr) { let p = Promise.resolve() arr.forEach(item => { @@ -65,7 +94,7 @@ export function checkRefresh (instance, data, checker) { return () => new Promise(res => { instance.$refresh(data) setTimeout(() => { - checker(instance.getRealRoot()) + checker(getRoot(instance)) res() }) }) diff --git a/test/weex/runtime/attrs.spec.js b/test/weex/runtime/attrs.spec.js index f87537ca435..037067ac1a2 100644 --- a/test/weex/runtime/attrs.spec.js +++ b/test/weex/runtime/attrs.spec.js @@ -1,75 +1,48 @@ -import { - compileAndStringify, - prepareRuntime, - resetRuntime, - createInstance -} from '../helpers/index' +import { getRoot, fireEvent, compileAndExecute } from '../helpers/index' describe('generate attribute', () => { - let runtime - - beforeAll(() => { - runtime = prepareRuntime() - }) - - afterAll(() => { - resetRuntime() - runtime = null - }) - - it('should be generated', () => { - const { render, staticRenderFns } = compileAndStringify(` + it('should be generated', (done) => { + compileAndExecute(`
- `) - const instance = createInstance(runtime, ` - new Vue({ - render: ${render}, - staticRenderFns: ${staticRenderFns}, - el: 'body' + `).then(instance => { + expect(getRoot(instance)).toEqual({ + type: 'div', + children: [{ + type: 'text', + style: { fontSize: '100' }, + attr: { value: 'Hello World' } + }] }) - `) - expect(instance.getRealRoot()).toEqual({ - type: 'div', - children: [ - { type: 'text', style: { fontSize: '100' }, attr: { value: 'Hello World' }} - ] - }) + done() + }).catch(e => done.fail(e)) }) it('should be updated', (done) => { - const { render, staticRenderFns } = compileAndStringify(` + compileAndExecute(`
- `) - const instance = createInstance(runtime, ` - new Vue({ - data: { - x: 'Hello World' - }, - methods: { - foo: function () { - this.x = 'Hello Vue' - } - }, - render: ${render}, - staticRenderFns: ${staticRenderFns}, - el: "body" + `, ` + data: { x: 'Hello World' }, + methods: { + foo: function () { + this.x = 'Hello Vue' + } + } + `).then(instance => { + expect(getRoot(instance)).toEqual({ + type: 'div', + event: ['click'], + children: [ + { type: 'text', attr: { value: 'Hello World' }} + ] }) - `) - expect(instance.getRealRoot()).toEqual({ - type: 'div', - event: ['click'], - children: [ - { type: 'text', attr: { value: 'Hello World' }} - ] - }) - - instance.$fireEvent(instance.doc.body.ref, 'click', {}) - setTimeout(() => { - expect(instance.getRealRoot()).toEqual({ + fireEvent(instance, '_root', 'click') + return instance + }).then(instance => { + expect(getRoot(instance)).toEqual({ type: 'div', event: ['click'], children: [ @@ -77,41 +50,33 @@ describe('generate attribute', () => { ] }) done() - }) + }).catch(e => done.fail(e)) }) it('should be cleared', (done) => { - const { render, staticRenderFns } = compileAndStringify(` + compileAndExecute(`
- `) - const instance = createInstance(runtime, ` - new Vue({ - data: { - x: 'Hello World' - }, - methods: { - foo: function () { - this.x = '' - } - }, - render: ${render}, - staticRenderFns: ${staticRenderFns}, - el: "body" + `, ` + data: { x: 'Hello World' }, + methods: { + foo: function () { + this.x = '' + } + } + `).then(instance => { + expect(getRoot(instance)).toEqual({ + type: 'div', + event: ['click'], + children: [ + { type: 'text', attr: { value: 'Hello World' }} + ] }) - `) - expect(instance.getRealRoot()).toEqual({ - type: 'div', - event: ['click'], - children: [ - { type: 'text', attr: { value: 'Hello World' }} - ] - }) - - instance.$fireEvent(instance.doc.body.ref, 'click', {}) - setTimeout(() => { - expect(instance.getRealRoot()).toEqual({ + fireEvent(instance, '_root', 'click') + return instance + }).then(instance => { + expect(getRoot(instance)).toEqual({ type: 'div', event: ['click'], children: [ diff --git a/test/weex/runtime/class.spec.js b/test/weex/runtime/class.spec.js index 95a3fd4c3f8..5809ba75633 100644 --- a/test/weex/runtime/class.spec.js +++ b/test/weex/runtime/class.spec.js @@ -1,236 +1,159 @@ -import { - compileAndStringify, - prepareRuntime, - resetRuntime, - createInstance -} from '../helpers/index' +import { getRoot, fireEvent, compileAndExecute } from '../helpers/index' describe('generate class', () => { - let runtime - - beforeAll(() => { - runtime = prepareRuntime() - }) - - afterAll(() => { - resetRuntime() - runtime = null - }) - it('should be generated', () => { - const { render, staticRenderFns } = compileAndStringify(` + compileAndExecute(`
Hello World
- `) - const instance = createInstance(runtime, ` - new Vue({ - render: ${render}, - staticRenderFns: ${staticRenderFns}, - style: { - a: { - fontSize: '100' - }, - b: { - color: '#ff0000' - }, - c: { - fontWeight: 'bold' - } - }, - el: 'body' + `, ` + style: { + a: { fontSize: '100' }, + b: { color: '#ff0000' }, + c: { fontWeight: 'bold' } + } + `).then(instance => { + expect(getRoot(instance)).toEqual({ + type: 'div', + children: [{ + type: 'text', + style: { fontSize: '100', color: '#ff0000', fontWeight: 'bold' }, + attr: { value: 'Hello World' } + }] }) - `) - expect(instance.getRealRoot()).toEqual({ - type: 'div', - children: [ - { type: 'text', style: { fontSize: '100', color: '#ff0000', fontWeight: 'bold' }, attr: { value: 'Hello World' }} - ] }) }) it('should be updated', (done) => { - const { render, staticRenderFns } = compileAndStringify(` -
- Hello World + compileAndExecute(` +
+ Hello World
- `) - const instance = createInstance(runtime, ` - new Vue({ - data: { - x: 'b' - }, - render: ${render}, - staticRenderFns: ${staticRenderFns}, - style: { - a: { - fontSize: '100' - }, - b: { - color: '#ff0000' - }, - c: { - fontWeight: 'bold' - }, - d: { - color: '#0000ff', - fontWeight: 'bold' - } - }, - methods: { - foo: function () { - this.x = 'd' - } - }, - el: 'body' - }) - `) - expect(instance.getRealRoot()).toEqual({ - type: 'div', - children: [ - { + `, ` + data: { x: 'b' }, + style: { + a: { fontSize: '100' }, + b: { color: '#ff0000' }, + c: { fontWeight: 'bold' }, + d: { + color: '#0000ff', + fontWeight: 'bold' + } + }, + methods: { + foo: function () { + this.x = 'd' + } + } + `).then(instance => { + expect(getRoot(instance)).toEqual({ + type: 'div', + event: ['click'], + children: [{ type: 'text', - event: ['click'], style: { fontSize: '100', color: '#ff0000' }, attr: { value: 'Hello World' } - } - ] - }) - - instance.$fireEvent(instance.doc.body.children[0].ref, 'click', {}) - setTimeout(() => { - expect(instance.getRealRoot()).toEqual({ + }] + }) + fireEvent(instance, '_root', 'click') + return instance + }).then(instance => { + expect(getRoot(instance)).toEqual({ type: 'div', - children: [ - { - type: 'text', - event: ['click'], - style: { fontSize: '100', color: '#0000ff', fontWeight: 'bold' }, - attr: { value: 'Hello World' } - } - ] + event: ['click'], + children: [{ + type: 'text', + style: { fontSize: '100', color: '#0000ff', fontWeight: 'bold' }, + attr: { value: 'Hello World' } + }] }) done() }) }) it('should be applied in order', (done) => { - const { render, staticRenderFns } = compileAndStringify(` -
- Hello World + compileAndExecute(` +
+ Hello World
- `) - const instance = createInstance(runtime, ` - new Vue({ - data: { - arr: ['b', 'a'] - }, - render: ${render}, - staticRenderFns: ${staticRenderFns}, - style: { - a: { - color: '#ff0000' - }, - b: { - color: '#00ff00' - }, - c: { - color: '#0000ff' - } - }, - methods: { - foo: function () { - this.arr.push('c') - } - }, - el: 'body' - }) - `) - expect(instance.getRealRoot()).toEqual({ - type: 'div', - children: [ - { + `, ` + data: { + arr: ['b', 'a'] + }, + style: { + a: { color: '#ff0000' }, + b: { color: '#00ff00' }, + c: { color: '#0000ff' } + }, + methods: { + foo: function () { + this.arr.push('c') + } + } + `).then(instance => { + expect(getRoot(instance)).toEqual({ + type: 'div', + event: ['click'], + children: [{ type: 'text', - event: ['click'], style: { color: '#ff0000' }, attr: { value: 'Hello World' } - } - ] - }) - - instance.$fireEvent(instance.doc.body.children[0].ref, 'click', {}) - setTimeout(() => { - expect(instance.getRealRoot()).toEqual({ + }] + }) + fireEvent(instance, '_root', 'click') + return instance + }).then(instance => { + expect(getRoot(instance)).toEqual({ type: 'div', - children: [ - { - type: 'text', - event: ['click'], - style: { color: '#0000ff' }, - attr: { value: 'Hello World' } - } - ] + event: ['click'], + children: [{ + type: 'text', + style: { color: '#0000ff' }, + attr: { value: 'Hello World' } + }] }) done() }) }) it('should be cleared', (done) => { - const { render, staticRenderFns } = compileAndStringify(` -
- Hello World + compileAndExecute(` +
+ Hello World
- `) - const instance = createInstance(runtime, ` - new Vue({ - data: { - x: 'b' - }, - render: ${render}, - staticRenderFns: ${staticRenderFns}, - style: { - a: { - fontSize: '100' - }, - b: { - color: '#ff0000' - }, - c: { - fontWeight: 'bold' - } - }, - methods: { - foo: function () { - this.x = 'c' - } - }, - el: 'body' - }) - `) - expect(instance.getRealRoot()).toEqual({ - type: 'div', - children: [ - { + `, ` + data: { x: 'b' }, + style: { + a: { fontSize: '100' }, + b: { color: '#ff0000' }, + c: { fontWeight: 'bold' } + }, + methods: { + foo: function () { + this.x = 'c' + } + } + `).then(instance => { + expect(getRoot(instance)).toEqual({ + type: 'div', + event: ['click'], + children: [{ type: 'text', - event: ['click'], style: { fontSize: '100', color: '#ff0000' }, attr: { value: 'Hello World' } - } - ] - }) - - instance.$fireEvent(instance.doc.body.children[0].ref, 'click', {}) - setTimeout(() => { - expect(instance.getRealRoot()).toEqual({ + }] + }) + fireEvent(instance, '_root', 'click') + return instance + }).then(instance => { + expect(getRoot(instance)).toEqual({ type: 'div', - children: [ - { - type: 'text', - event: ['click'], - style: { fontSize: '100', color: '', fontWeight: 'bold' }, - attr: { value: 'Hello World' } - } - ] + event: ['click'], + children: [{ + type: 'text', + style: { fontSize: '100', color: '', fontWeight: 'bold' }, + attr: { value: 'Hello World' } + }] }) done() }) diff --git a/test/weex/runtime/components/richtext.spec.js b/test/weex/runtime/components/richtext.spec.js index 9dd3637548e..e6190b7f655 100644 --- a/test/weex/runtime/components/richtext.spec.js +++ b/test/weex/runtime/components/richtext.spec.js @@ -1,13 +1,14 @@ import { compileAndStringify, - prepareRuntime, - resetRuntime, + getRoot, + fireEvent, createInstance } from '../../helpers/index' -function compileSnippet (runtime, snippet, additional) { +function compileSnippet (snippet, additional) { const { render, staticRenderFns } = compileAndStringify(`
${snippet}
`) - const instance = createInstance(runtime, ` + const id = String(Date.now() * Math.random()) + const instance = createInstance(id, ` new Vue({ el: 'body', render: ${render}, @@ -15,23 +16,12 @@ function compileSnippet (runtime, snippet, additional) { ${additional} }) `) - return instance.getRealRoot().children[0] + return getRoot(instance).children[0] } describe('richtext component', () => { - let runtime - - beforeAll(() => { - runtime = prepareRuntime() - }) - - afterAll(() => { - resetRuntime() - runtime = null - }) - it('with no child', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` `)).toEqual({ type: 'richtext' @@ -39,7 +29,7 @@ describe('richtext component', () => { }) it('with single text node', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` single `)).toEqual({ type: 'richtext', @@ -56,7 +46,7 @@ describe('richtext component', () => { describe('span', () => { it('single node', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` single @@ -74,7 +64,7 @@ describe('richtext component', () => { }) it('multiple node', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` AAA BBB @@ -94,7 +84,7 @@ describe('richtext component', () => { }) it('with raw text', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` AAA BBBCCC @@ -123,7 +113,7 @@ describe('richtext component', () => { describe('a', () => { it('single node', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` @@ -139,7 +129,7 @@ describe('richtext component', () => { }) it('multiple node', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` @@ -161,7 +151,7 @@ describe('richtext component', () => { describe('image', () => { it('single node', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` @@ -177,7 +167,7 @@ describe('richtext component', () => { }) it('multiple node', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` @@ -197,7 +187,7 @@ describe('richtext component', () => { }) it('with width and height', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` { describe('nested', () => { it('span', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` AAA @@ -258,7 +248,7 @@ describe('richtext component', () => { }) it('image and a', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` title @@ -293,7 +283,7 @@ describe('richtext component', () => { describe('with styles', () => { it('inline', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` ABCD @@ -315,7 +305,7 @@ describe('richtext component', () => { }) it('class list', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` ABCD @@ -345,7 +335,7 @@ describe('richtext component', () => { describe('data binding', () => { it('simple', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` {{name}} @@ -361,14 +351,15 @@ describe('richtext component', () => { }) it('nested', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` {{a}} {{b}}{{c.d}} {{e}} - `, `data: { a: 'A', b: 'B', c: { d: 'CD' }, e: 'E' }`)) - .toEqual({ + `, ` + data: { a: 'A', b: 'B', c: { d: 'CD' }, e: 'E' } + `)).toEqual({ type: 'richtext', attr: { value: [{ @@ -392,7 +383,7 @@ describe('richtext component', () => { }) it('update', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` {{name}} @@ -413,7 +404,7 @@ describe('richtext component', () => { }) it('attribute', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` {{name}} @@ -437,7 +428,7 @@ describe('richtext component', () => { }) it('update attribute', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` {{name}} @@ -465,7 +456,7 @@ describe('richtext component', () => { }) it('inline style', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` ABCD EFGH @@ -492,7 +483,7 @@ describe('richtext component', () => { }) it('class list', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` ABCD @@ -533,7 +524,7 @@ describe('richtext component', () => { }) it('update inline style', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` ABCD EFGH @@ -566,7 +557,7 @@ describe('richtext component', () => { describe('itself', () => { it('inline styles', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` empty @@ -583,7 +574,7 @@ describe('richtext component', () => { }) it('class list', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` ABCD @@ -606,7 +597,7 @@ describe('richtext component', () => { }) it('update styles', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(` ABCD @@ -640,7 +631,8 @@ describe('richtext component', () => {
`) - const instance = createInstance(runtime, ` + const id = String(Date.now() * Math.random()) + const instance = createInstance(id, ` new Vue({ el: 'body', render: ${render}, @@ -653,10 +645,10 @@ describe('richtext component', () => { } }) `) - const richtext = instance.doc.body.children[0] - instance.$fireEvent(richtext.ref, 'click', {}) + const richtext = instance.document.body.children[0] + fireEvent(instance, richtext.ref, 'click') setTimeout(() => { - expect(instance.getRealRoot().children[0]).toEqual({ + expect(getRoot(instance).children[0]).toEqual({ type: 'richtext', event: ['click'], attr: { @@ -671,7 +663,7 @@ describe('richtext component', () => { }) it('v-for', () => { - expect(compileSnippet(runtime, ` + expect(compileSnippet(`
{{k}} diff --git a/test/weex/runtime/events.spec.js b/test/weex/runtime/events.spec.js index cad3994cc6e..79ddbdb176e 100644 --- a/test/weex/runtime/events.spec.js +++ b/test/weex/runtime/events.spec.js @@ -1,144 +1,98 @@ -import { - compileAndStringify, - prepareRuntime, - resetRuntime, - createInstance -} from '../helpers/index' +import { getRoot, fireEvent, compileAndStringify, compileAndExecute } from '../helpers/index' describe('generate events', () => { - let runtime - - beforeAll(() => { - runtime = prepareRuntime() - }) - - afterAll(() => { - resetRuntime() - runtime = null - }) - it('should be bound and fired for native component', (done) => { - const { render, staticRenderFns } = compileAndStringify(` -
- Hello {{x}} + compileAndExecute(` +
+ Hello {{x}}
- `) - const instance = createInstance(runtime, ` - new Vue({ - data: { - x: 'World' - }, - render: ${render}, - staticRenderFns: ${staticRenderFns}, - methods: { - foo: function () { - this.x = 'Weex' - } - }, - el: 'body' - }) - `) - expect(instance.getRealRoot()).toEqual({ - type: 'div', - children: [ - { + `, ` + data: { x: 'World' }, + methods: { + foo: function () { + this.x = 'Weex' + } + } + `).then(instance => { + expect(getRoot(instance)).toEqual({ + type: 'div', + event: ['click'], + children: [{ type: 'text', - event: ['click'], attr: { value: 'Hello World' } - } - ] - }) - - instance.$fireEvent(instance.doc.body.children[0].ref, 'click', {}) - setTimeout(() => { - expect(instance.getRealRoot()).toEqual({ + }] + }) + fireEvent(instance, '_root', 'click') + return instance + }).then(instance => { + expect(getRoot(instance)).toEqual({ type: 'div', - children: [ - { - type: 'text', - event: ['click'], - attr: { value: 'Hello Weex' } - } - ] + event: ['click'], + children: [{ + type: 'text', + attr: { value: 'Hello Weex' } + }] }) done() }) }) it('should be bound and fired by custom component', (done) => { - const subTemplate = compileAndStringify(`Hello {{x}}`) - const { render, staticRenderFns } = compileAndStringify(` + const { render, staticRenderFns } = compileAndStringify(`Hello {{x}}`) + compileAndExecute(`
Hello {{x}}
- `) - const instance = createInstance(runtime, ` - new Vue({ - data: { - x: 'World' - }, - render: ${render}, - staticRenderFns: ${staticRenderFns}, - components: { - sub: { - data: function () { - return { - x: 'Sub' - } - }, - render: ${subTemplate.render}, - staticRenderFns: ${subTemplate.staticRenderFns}, - created: function () { - this.$emit('click') - } - } - }, - methods: { - foo: function () { - this.x = 'Foo' + `, ` + data: { x: 'World' }, + components: { + sub: { + data: function () { + return { x: 'Sub' } }, - bar: function () { - this.x = 'Bar' + render: ${render}, + staticRenderFns: ${staticRenderFns}, + created: function () { + this.$emit('click') } + } + }, + methods: { + foo: function () { + this.x = 'Foo' }, - el: 'body' - }) - `) - setTimeout(() => { - expect(instance.getRealRoot()).toEqual({ + bar: function () { + this.x = 'Bar' + } + } + `).then(instance => { + expect(getRoot(instance)).toEqual({ type: 'div', - children: [ - { - type: 'text', - attr: { value: 'Hello Foo' } - }, - { - type: 'text', - event: ['click'], - attr: { value: 'Hello Sub' } - } - ] + children: [{ + type: 'text', + attr: { value: 'Hello Foo' } + }, { + type: 'text', + event: ['click'], + attr: { value: 'Hello Sub' } + }] }) - - instance.$fireEvent(instance.doc.body.children[1].ref, 'click', {}) - setTimeout(() => { - expect(instance.getRealRoot()).toEqual({ - type: 'div', - children: [ - { - type: 'text', - attr: { value: 'Hello Bar' } - }, - { - type: 'text', - event: ['click'], - attr: { value: 'Hello Sub' } - } - ] - }) - done() + fireEvent(instance, instance.document.body.children[1].ref, 'click') + return instance + }).then(instance => { + expect(getRoot(instance)).toEqual({ + type: 'div', + children: [{ + type: 'text', + attr: { value: 'Hello Bar' } + }, { + type: 'text', + event: ['click'], + attr: { value: 'Hello Sub' } + }] }) + done() }) }) }) diff --git a/test/weex/runtime/framework.spec.js b/test/weex/runtime/framework.spec.js index e11edaa3e24..3079c9e0657 100644 --- a/test/weex/runtime/framework.spec.js +++ b/test/weex/runtime/framework.spec.js @@ -1,38 +1,10 @@ import * as framework from '../../../packages/weex-vue-framework' -import { DEFAULT_ENV, Runtime, Instance } from 'weex-vdom-tester' -import { config } from 'weex-js-runtime' - -import { - syncPromise, - checkRefresh -} from '../helpers/index' - -let sendTasksHandler = () => {} -const { Document, Element, Comment } = config -function sendTasks () { - sendTasksHandler.apply(null, arguments) -} +import { getRoot, createInstance } from '../helpers/index' describe('framework APIs', () => { - let runtime - - beforeEach(() => { - Document.handler = sendTasks - framework.init({ Document, Element, Comment, sendTasks }) - runtime = new Runtime(framework) - sendTasksHandler = function () { - runtime.target.callNative(...arguments) - } - }) - - afterEach(() => { - delete Document.handler - framework.reset() - }) - it('createInstance', () => { - const instance = new Instance(runtime) - framework.createInstance(instance.id, ` + const id = String(Date.now() * Math.random()) + const instance = createInstance(id, ` new Vue({ render: function (createElement) { return createElement('div', {}, [ @@ -42,15 +14,15 @@ describe('framework APIs', () => { el: "body" }) `) - expect(instance.getRealRoot()).toEqual({ + expect(getRoot(instance)).toEqual({ type: 'div', children: [{ type: 'text', attr: { value: 'Hello' }}] }) }) it('createInstance with config', () => { - const instance = new Instance(runtime) - framework.createInstance(instance.id, ` + const id = String(Date.now() * Math.random()) + const instance = createInstance(id, ` new Vue({ render: function (createElement) { return createElement('div', {}, [ @@ -60,15 +32,18 @@ describe('framework APIs', () => { el: "body" }) `, { bundleUrl: 'http://example.com/', a: 1, b: 2 }) - expect(instance.getRealRoot()).toEqual({ + expect(getRoot(instance)).toEqual({ type: 'div', - children: [{ type: 'text', attr: { value: '{"bundleUrl":"http://example.com/","a":1,"b":2}' }}] + children: [{ + type: 'text', + attr: { value: '{"bundleUrl":"http://example.com/","a":1,"b":2,"env":{}}' } + }] }) }) it('createInstance with external data', () => { - const instance = new Instance(runtime) - framework.createInstance(instance.id, ` + const id = String(Date.now() * Math.random()) + const instance = createInstance(id, ` new Vue({ data: { a: 1, @@ -82,15 +57,15 @@ describe('framework APIs', () => { el: "body" }) `, undefined, { a: 111 }) - expect(instance.getRealRoot()).toEqual({ + expect(getRoot(instance)).toEqual({ type: 'div', children: [{ type: 'text', attr: { value: '111-2' }}] }) }) it('destroyInstance', (done) => { - const instance = new Instance(runtime) - framework.createInstance(instance.id, ` + const id = String(Date.now() * Math.random()) + const instance = createInstance(id, ` new Vue({ data: { x: 'Hello' @@ -103,32 +78,21 @@ describe('framework APIs', () => { el: "body" }) `) - expect(instance.getRealRoot()).toEqual({ + expect(getRoot(instance)).toEqual({ type: 'div', children: [{ type: 'text', attr: { value: 'Hello' }}] }) - - syncPromise([ - checkRefresh(instance, { x: 'World' }, result => { - expect(result).toEqual({ - type: 'div', - children: [{ type: 'text', attr: { value: 'World' }}] - }) - framework.destroyInstance(instance.id) - }), - checkRefresh(instance, { x: 'Weex' }, result => { - expect(result).toEqual({ - type: 'div', - children: [{ type: 'text', attr: { value: 'World' }}] - }) - done() - }) - ]) + instance.$destroy() + setTimeout(() => { + expect(instance.document).toBeUndefined() + expect(instance.app).toBeUndefined() + done() + }, 0) }) it('refreshInstance', (done) => { - const instance = new Instance(runtime) - framework.createInstance(instance.id, ` + const id = String(Date.now() * Math.random()) + const instance = createInstance(id, ` new Vue({ data: { x: 'Hello' @@ -141,37 +105,26 @@ describe('framework APIs', () => { el: "body" }) `) - expect(instance.getRealRoot()).toEqual({ + expect(getRoot(instance)).toEqual({ type: 'div', children: [{ type: 'text', attr: { value: 'Hello' }}] }) - - framework.refreshInstance(instance.id, { x: 'World' }) + instance.$refresh({ x: 'World' }) setTimeout(() => { - expect(instance.getRealRoot()).toEqual({ + expect(getRoot(instance)).toEqual({ type: 'div', children: [{ type: 'text', attr: { value: 'World' }}] }) - - framework.destroyInstance(instance.id) - const result = framework.refreshInstance(instance.id, { x: 'Weex' }) + instance.$destroy() + const result = instance.$refresh({ x: 'World' }) expect(result instanceof Error).toBe(true) - expect(result).toMatch(/refreshInstance/) - expect(result).toMatch(/not found/) - - setTimeout(() => { - expect(instance.getRealRoot()).toEqual({ - type: 'div', - children: [{ type: 'text', attr: { value: 'World' }}] - }) - done() - }) + done() }) }) it('getRoot', () => { - const instance = new Instance(runtime) - framework.createInstance(instance.id, ` + const id = String(Date.now() * Math.random()) + const instance = createInstance(id, ` new Vue({ data: { x: 'Hello' @@ -185,7 +138,7 @@ describe('framework APIs', () => { }) `) - let root = framework.getRoot(instance.id) + let root = framework.getRoot(id) expect(root.ref).toEqual('_root') expect(root.type).toEqual('div') expect(root.children.length).toEqual(1) @@ -199,9 +152,10 @@ describe('framework APIs', () => { expect(root).toMatch(/not found/) }) + // TODO: deprecated, move to weex-js-runtime it('receiveTasks: fireEvent', (done) => { - const instance = new Instance(runtime) - framework.createInstance(instance.id, ` + const id = String(Date.now() * Math.random()) + const instance = createInstance(id, ` new Vue({ data: { x: 'Hello' @@ -219,7 +173,7 @@ describe('framework APIs', () => { el: "body" }) `) - expect(instance.getRealRoot()).toEqual({ + expect(getRoot(instance)).toEqual({ type: 'div', children: [{ type: 'text', @@ -227,14 +181,12 @@ describe('framework APIs', () => { event: ['click'] }] }) - - const textRef = framework.getRoot(instance.id).children[0].ref - framework.receiveTasks(instance.id, [ + const textRef = framework.getRoot(id).children[0].ref + framework.receiveTasks(id, [ { method: 'fireEvent', args: [textRef, 'click'] } ]) - setTimeout(() => { - expect(instance.getRealRoot()).toEqual({ + expect(getRoot(instance)).toEqual({ type: 'div', children: [{ type: 'text', @@ -242,271 +194,22 @@ describe('framework APIs', () => { event: ['click'] }] }) - - framework.destroyInstance(instance.id) - const result = framework.receiveTasks(instance.id, [ + framework.destroyInstance(id) + const result = framework.receiveTasks(id, [ { method: 'fireEvent', args: [textRef, 'click'] } ]) expect(result instanceof Error).toBe(true) - expect(result).toMatch(/invalid\sinstance\sid/) - expect(result).toMatch(instance.id) done() }) }) - it('receiveTasks: callback', (done) => { - framework.registerModules({ - foo: ['a', 'b', 'c'] - }) - - const instance = new Instance(runtime) - framework.createInstance(instance.id, ` - const moduleFoo = weex.requireModule('foo') - new Vue({ - data: { - x: 'Hello' - }, - methods: { - update: function (data = {}) { - this.x = data.value || 'World' - } - }, - mounted: function () { - moduleFoo.a(data => { - this.update(data) - }) - }, - render: function (createElement) { - return createElement('div', {}, [ - createElement('text', { attrs: { value: this.x }}, []) - ]) - }, - el: "body" - }) - `) - expect(instance.getRealRoot()).toEqual({ - type: 'div', - children: [{ - type: 'text', - attr: { value: 'Hello' } - }] - }) - - let callbackId - instance.history.callNative.some(task => { - if (task.module === 'foo' && task.method === 'a') { - callbackId = task.args[0] - return true - } - }) - framework.receiveTasks(instance.id, [ - { method: 'callback', args: [callbackId, undefined, true] } - ]) - - setTimeout(() => { - expect(instance.getRealRoot()).toEqual({ - type: 'div', - children: [{ - type: 'text', - attr: { value: 'World' } - }] - }) - - framework.receiveTasks(instance.id, [ - { method: 'callback', args: [callbackId, { value: 'Weex' }, true] } - ]) - setTimeout(() => { - expect(instance.getRealRoot()).toEqual({ - type: 'div', - children: [{ - type: 'text', - attr: { value: 'Weex' } - }] - }) - - framework.receiveTasks(instance.id, [ - { method: 'callback', args: [callbackId] } - ]) - setTimeout(() => { - expect(instance.getRealRoot()).toEqual({ - type: 'div', - children: [{ - type: 'text', - attr: { value: 'World' } - }] - }) - - framework.destroyInstance(instance.id) - const result = framework.receiveTasks(instance.id, [ - { method: 'callback', args: [callbackId] } - ]) - expect(result instanceof Error).toBe(true) - expect(result).toMatch(/invalid\sinstance\sid/) - expect(result).toMatch(instance.id) - done() - }) - }) - }) - }) - - it('registerModules', () => { - framework.registerModules({ - foo: ['a', 'b', 'c'], - bar: [ - { name: 'a', args: ['string'] }, - { name: 'b', args: ['number'] }, - { name: 'c', args: ['string', 'number'] } - ] - }) - - const instance = new Instance(runtime) - framework.createInstance(instance.id, ` - const moduleFoo = weex.requireModule('foo') - const moduleBar = weex.requireModule('bar') - const moduleBaz = weex.requireModule('baz') - new Vue({ - render: function (createElement) { - const value = [] - if (typeof moduleFoo === 'object') { - value.push('foo') - value.push(Object.keys(moduleFoo)) - } - if (typeof moduleBar === 'object') { - value.push('bar') - value.push(Object.keys(moduleBar)) - } - if (typeof moduleBaz === 'object') { - value.push('baz') - value.push(Object.keys(moduleBaz)) - } - return createElement('div', {}, [ - createElement('text', { attrs: { value: value.toString() }}, []) - ]) - }, - mounted: function () { - moduleFoo.a(1, '2', true) - moduleBar.b(1) - }, - el: "body" - }) - `) - expect(instance.getRealRoot()).toEqual({ - type: 'div', - children: [{ - type: 'text', - attr: { value: 'foo,a,b,c,bar,a,b,c,baz,' } - }] - }) - - expect(instance.history.callNative - .filter(task => task.module === 'foo') - .map(task => `${task.method}(${task.args})`) - ).toEqual(['a(1,2,true)']) - - expect(instance.history.callNative - .filter(task => task.module === 'bar') - .map(task => `${task.method}(${task.args})`) - ).toEqual(['b(1)']) - }) - - it('isRegisteredModule', () => { - framework.registerModules({ - foo: ['a', 'b'], - bar: [ - { name: 'x', args: ['string'] }, - { name: 'y', args: ['number'] } - ] - }) - expect(framework.isRegisteredModule('foo')).toBe(true) - expect(framework.isRegisteredModule('bar')).toBe(true) - expect(framework.isRegisteredModule('foo', 'a')).toBe(true) - expect(framework.isRegisteredModule('foo', 'b')).toBe(true) - expect(framework.isRegisteredModule('bar', 'x')).toBe(true) - expect(framework.isRegisteredModule('bar', 'y')).toBe(true) - expect(framework.isRegisteredModule('FOO')).toBe(false) - expect(framework.isRegisteredModule(' bar ')).toBe(false) - expect(framework.isRegisteredModule('unknown')).toBe(false) - expect(framework.isRegisteredModule('#}{)=}')).toBe(false) - expect(framework.isRegisteredModule('foo', '')).toBe(false) - expect(framework.isRegisteredModule('foo', 'c')).toBe(false) - expect(framework.isRegisteredModule('bar', 'z')).toBe(false) - expect(framework.isRegisteredModule('unknown', 'unknown')).toBe(false) - }) - - it('registerComponents', () => { - framework.registerComponents(['foo', { type: 'bar' }, 'text']) - const instance = new Instance(runtime) - framework.createInstance(instance.id, ` - new Vue({ - render: function (createElement) { - return createElement('div', {}, [ - createElement('text', {}, []), - createElement('foo', {}, []), - createElement('bar', {}, []), - createElement('baz', {}, []) - ]) - }, - el: "body" - }) - `) - expect(instance.getRealRoot()).toEqual({ - type: 'div', - children: [{ type: 'text' }, { type: 'foo' }, { type: 'bar' }, { type: 'baz' }] - }) - }) - - it('isRegisteredComponent', () => { - framework.registerComponents(['foo', { type: 'bar' }, 'text']) - expect(framework.isRegisteredComponent('foo')).toBe(true) - expect(framework.isRegisteredComponent('bar')).toBe(true) - expect(framework.isRegisteredComponent('text')).toBe(true) - expect(framework.isRegisteredComponent('FOO')).toBe(false) - expect(framework.isRegisteredComponent(' bar ')).toBe(false) - expect(framework.isRegisteredComponent('')).toBe(false) - expect(framework.isRegisteredComponent('#}{)=}')).toBe(false) - }) - - it('weex.supports', () => { - framework.registerComponents(['apple', { type: 'banana' }]) - framework.registerModules({ - cat: ['eat', 'sleep'], - dog: [ - { name: 'bark', args: ['string'] } - ] - }) - expect(framework.supports('@component/apple')).toBe(true) - expect(framework.supports('@component/banana')).toBe(true) - expect(framework.supports('@module/cat')).toBe(true) - expect(framework.supports('@module/cat.eat')).toBe(true) - expect(framework.supports('@module/cat.sleep')).toBe(true) - expect(framework.supports('@module/dog.bark')).toBe(true) - expect(framework.supports('@component/candy')).toBe(false) - expect(framework.supports('@module/bird')).toBe(false) - expect(framework.supports('@module/bird.sing')).toBe(false) - expect(framework.supports('@module/dog.sleep')).toBe(false) - expect(framework.supports('apple')).toBe(null) - expect(framework.supports('')).toBe(null) - expect(framework.supports('cat')).toBe(null) - expect(framework.supports('@dog')).toBe(null) - expect(framework.supports('@component/dog#bark')).toBe(null) - }) - it('vm.$getConfig', () => { - const instance = new Instance(runtime) - instance.$create(` - new Vue({ - render: function (createElement) { - return createElement('div', {}, [ - createElement('text', { attrs: { value: JSON.stringify(this.$getConfig()) }}, []) - ]) - }, - el: "body" - }) - `) - expect(JSON.parse(instance.getRealRoot().children[0].attr.value)).toEqual({ env: DEFAULT_ENV }) - - const instance2 = new Instance(runtime) - instance2.$create(` + const id = String(Date.now() * Math.random()) + global.WXEnvironment = { + weexVersion: '0.10.0', + platform: 'Node.js' + } + const instance = createInstance(id, ` new Vue({ render: function (createElement) { return createElement('div', {}, [ @@ -515,143 +218,20 @@ describe('framework APIs', () => { }, el: "body" }) - `, undefined, { a: 1, b: 2 }) - expect(JSON.parse(instance2.getRealRoot().children[0].attr.value)).toEqual({ a: 1, b: 2, env: DEFAULT_ENV }) - }) - - it('Timer', (done) => { - const instance = new Instance(runtime) - instance.$create(` - new Vue({ - data: { - x: 0, - y: 0 - }, - render: function (createElement) { - return createElement('div', {}, [ - createElement('text', { attrs: { value: this.x + '-' + this.y }}, []) - ]) - }, - mounted: function () { - const now = Date.now() - let timer, timer2 - setTimeout(() => { - this.x = 1 - clearTimeout(timer) - clearInterval(timer2) - setInterval(() => { - this.y++ - }, 600) - }, 2000) - timer = setTimeout(() => { - this.x = 3 - }, 3000) - setTimeout(() => { - this.x = 3 - }, 4000) - timer2 = setInterval(() => { - this.y++ - }, 900) - }, - el: "body" - }) - `) - expect(instance.getRealRoot()).toEqual({ - type: 'div', - children: [{ type: 'text', attr: { value: '0-0' }}] - }) - - setTimeout(() => { - expect(instance.getRealRoot().children[0].attr.value).toEqual('0-1') - }, 950) - setTimeout(() => { - expect(instance.getRealRoot().children[0].attr.value).toEqual('0-2') - }, 1850) - setTimeout(() => { - expect(instance.getRealRoot().children[0].attr.value).toEqual('1-2') - }, 2050) - setTimeout(() => { - expect(instance.getRealRoot().children[0].attr.value).toEqual('1-3') - }, 2650) - setTimeout(() => { - expect(instance.getRealRoot().children[0].attr.value).toEqual('1-4') - }, 3250) - setTimeout(() => { - framework.destroyInstance(instance.id) - }, 3500) - setTimeout(() => { - expect(instance.getRealRoot().children[0].attr.value).toEqual('1-4') - done() - }, 4100) - }) - - it('send function param', () => { - framework.registerModules({ - foo: ['a'] - }) - - const instance = new Instance(runtime) - framework.createInstance(instance.id, ` - const moduleFoo = weex.requireModule('foo') - new Vue({ - mounted: function () { - moduleFoo.a(a => a + 1) - }, - render: function (createElement) { - return createElement('div', {}, [ - createElement('text', { attrs: { value: 'Hello' }}, []) - ]) - }, - el: "body" - }) - `) - - let callbackId - instance.history.callNative.some(task => { - if (task.module === 'foo' && task.method === 'a') { - callbackId = task.args[0] - return true - } - }) - - expect(typeof callbackId).toEqual('string') - }) - - it('send Element param', () => { - framework.registerModules({ - foo: ['a'] - }) - - const instance = new Instance(runtime) - framework.createInstance(instance.id, ` - const moduleFoo = weex.requireModule('foo') - new Vue({ - mounted: function () { - moduleFoo.a(this.$refs.x) - }, - render: function (createElement) { - return createElement('div', {}, [ - createElement('text', { attrs: { value: 'Hello' }, ref: 'x' }, []) - ]) - }, - el: "body" - }) - `) - - let callbackId - instance.history.callNative.some(task => { - if (task.module === 'foo' && task.method === 'a') { - callbackId = task.args[0] - return true + `, { bundleUrl: 'http://whatever.com/x.js' }) + expect(JSON.parse(getRoot(instance).children[0].attr.value)).toEqual({ + bundleUrl: 'http://whatever.com/x.js', + env: { + weexVersion: '0.10.0', + platform: 'Node.js' } }) - - expect(typeof callbackId).toEqual('string') + delete global.WXEnvironment }) it('registering global assets', () => { - const instance = new Instance(runtime) - framework.createInstance(instance.id, ` + const id = String(Date.now() * Math.random()) + const instance = createInstance(id, ` Vue.component('test', { render (h) { return h('div', 'Hello') @@ -664,15 +244,15 @@ describe('framework APIs', () => { el: 'body' }) `) - expect(instance.getRealRoot()).toEqual({ + expect(getRoot(instance)).toEqual({ type: 'div', children: [{ type: 'text', attr: { value: 'Hello' }}] }) }) it('adding prototype methods', () => { - const instance = new Instance(runtime) - framework.createInstance(instance.id, ` + const id = String(Date.now() * Math.random()) + const instance = createInstance(id, ` Vue.prototype.$test = () => 'Hello' const Test = { render (h) { @@ -686,15 +266,15 @@ describe('framework APIs', () => { el: 'body' }) `) - expect(instance.getRealRoot()).toEqual({ + expect(getRoot(instance)).toEqual({ type: 'div', children: [{ type: 'text', attr: { value: 'Hello' }}] }) }) it('using global mixins', () => { - const instance = new Instance(runtime) - framework.createInstance(instance.id, ` + const id = String(Date.now() * Math.random()) + const instance = createInstance(id, ` Vue.mixin({ created () { this.test = true @@ -714,7 +294,7 @@ describe('framework APIs', () => { el: 'body' }) `) - expect(instance.getRealRoot()).toEqual({ + expect(getRoot(instance)).toEqual({ type: 'div', children: [{ type: 'text', attr: { value: 'Hello' }}] }) diff --git a/test/weex/runtime/node.spec.js b/test/weex/runtime/node.spec.js index e90e96d922d..06a20c63a85 100644 --- a/test/weex/runtime/node.spec.js +++ b/test/weex/runtime/node.spec.js @@ -1,26 +1,15 @@ import { compileAndStringify, - prepareRuntime, - resetRuntime, createInstance, + getRoot, syncPromise, checkRefresh } from '../helpers/index' describe('node in render function', () => { - let runtime - - beforeAll(() => { - runtime = prepareRuntime() - }) - - afterAll(() => { - resetRuntime() - runtime = null - }) - it('should be generated', () => { - const instance = createInstance(runtime, ` + const id = String(Date.now() * Math.random()) + const instance = createInstance(id, ` new Vue({ render: function (createElement) { return createElement('div', {}, [ @@ -30,7 +19,7 @@ describe('node in render function', () => { el: "body" }) `) - expect(instance.getRealRoot()).toEqual({ + expect(getRoot(instance)).toEqual({ type: 'div', children: [ { type: 'text', attr: { value: 'Hello' }} @@ -39,7 +28,8 @@ describe('node in render function', () => { }) it('should be generated with all types of text', () => { - const instance = createInstance(runtime, ` + const id = String(Date.now() * Math.random()) + const instance = createInstance(id, ` new Vue({ render: function (createElement) { return createElement('div', {}, [ @@ -51,7 +41,7 @@ describe('node in render function', () => { el: "body" }) `) - expect(instance.getRealRoot()).toEqual({ + expect(getRoot(instance)).toEqual({ type: 'div', children: [ { type: 'text', attr: { value: 'Hello' }}, @@ -66,7 +56,8 @@ describe('node in render function', () => { }) it('should be generated with module diff', (done) => { - const instance = createInstance(runtime, ` + const id = String(Date.now() * Math.random()) + const instance = createInstance(id, ` new Vue({ data: { counter: 0 @@ -112,7 +103,7 @@ describe('node in render function', () => { el: "body" }) `) - expect(instance.getRealRoot()).toEqual({ + expect(getRoot(instance)).toEqual({ type: 'div', children: [ { type: 'text', attr: { value: 'Hello' }} @@ -157,7 +148,8 @@ describe('node in render function', () => { }) it('should be generated with sub components', () => { - const instance = createInstance(runtime, ` + const id = String(Date.now() * Math.random()) + const instance = createInstance(id, ` new Vue({ render: function (createElement) { return createElement('div', {}, [ @@ -178,7 +170,7 @@ describe('node in render function', () => { el: "body" }) `) - expect(instance.getRealRoot()).toEqual({ + expect(getRoot(instance)).toEqual({ type: 'div', children: [ { type: 'text', attr: { value: 'Hello' }}, @@ -193,7 +185,8 @@ describe('node in render function', () => { {{item.v}}
`) - const instance = createInstance(runtime, ` + const id = String(Date.now() * Math.random()) + const instance = createInstance(id, ` new Vue({ data: { list: [ @@ -228,7 +221,7 @@ describe('node in render function', () => { el: "body" }) `) - expect(instance.getRealRoot()).toEqual({ + expect(getRoot(instance)).toEqual({ type: 'div', children: [ { type: 'text', attr: { value: 'Hello' }}, @@ -282,7 +275,8 @@ describe('node in render function', () => { }) it('should be generated with node structure diff', (done) => { - const instance = createInstance(runtime, ` + const id = String(Date.now() * Math.random()) + const instance = createInstance(id, ` new Vue({ data: { counter: 0 @@ -334,7 +328,7 @@ describe('node in render function', () => { el: "body" }) `) - expect(instance.getRealRoot()).toEqual({ + expect(getRoot(instance)).toEqual({ type: 'div', children: [ { type: 'text', attr: { value: 'Hello' }} @@ -401,7 +395,8 @@ describe('node in render function', () => { }) it('should be generated with component diff', (done) => { - const instance = createInstance(runtime, ` + const id = String(Date.now() * Math.random()) + const instance = createInstance(id, ` new Vue({ data: { counter: 0 @@ -462,7 +457,7 @@ describe('node in render function', () => { el: "body" }) `) - expect(instance.getRealRoot()).toEqual({ + expect(getRoot(instance)).toEqual({ type: 'div', children: [ { type: 'text', attr: { value: '111-2' }} diff --git a/test/weex/runtime/style.spec.js b/test/weex/runtime/style.spec.js index a8be3e5b3f7..752f57580bd 100644 --- a/test/weex/runtime/style.spec.js +++ b/test/weex/runtime/style.spec.js @@ -1,84 +1,58 @@ -import { - compileAndStringify, - prepareRuntime, - resetRuntime, - createInstance -} from '../helpers/index' +import { getRoot, fireEvent, compileAndExecute } from '../helpers/index' describe('generate style', () => { - let runtime - - beforeAll(() => { - runtime = prepareRuntime() - }) - - afterAll(() => { - resetRuntime() - runtime = null - }) - it('should be generated', () => { - const { render, staticRenderFns } = compileAndStringify(` + compileAndExecute(`
Hello World
- `) - const instance = createInstance(runtime, ` - new Vue({ - render: ${render}, - staticRenderFns: ${staticRenderFns}, - el: 'body' + `).then(instance => { + expect(getRoot(instance)).toEqual({ + type: 'div', + children: [{ + type: 'text', + style: { fontSize: '100' }, + attr: { value: 'Hello World' } + }] }) - `) - expect(instance.getRealRoot()).toEqual({ - type: 'div', - children: [ - { type: 'text', style: { fontSize: '100' }, attr: { value: 'Hello World' }} - ] }) }) it('should be generated by array binding', (done) => { - const { render, staticRenderFns } = compileAndStringify(` + compileAndExecute(`
Hello {{z}}
- `) - const instance = createInstance(runtime, ` - new Vue({ - data: { - x: { fontSize: 100, color: '#00ff00' }, - y: { color: '#ff0000', fontWeight: 'bold' }, - z: 'World' - }, - methods: { - foo: function () { - this.x.fontSize = 200 - this.x.color = '#0000ff' - Vue.delete(this.y, 'fontWeight') - this.z = 'Weex' + `, ` + data: { + x: { fontSize: 100, color: '#00ff00' }, + y: { color: '#ff0000', fontWeight: 'bold' }, + z: 'World' + }, + methods: { + foo: function () { + this.x.fontSize = 200 + this.x.color = '#0000ff' + Vue.delete(this.y, 'fontWeight') + this.z = 'Weex' + } + } + `).then(instance => { + expect(getRoot(instance)).toEqual({ + type: 'div', + children: [ + { + type: 'text', + event: ['click'], + style: { fontSize: 100, color: '#ff0000', fontWeight: 'bold' }, + attr: { value: 'Hello World' } } - }, - render: ${render}, - staticRenderFns: ${staticRenderFns}, - el: 'body' + ] }) - `) - expect(instance.getRealRoot()).toEqual({ - type: 'div', - children: [ - { - type: 'text', - event: ['click'], - style: { fontSize: 100, color: '#ff0000', fontWeight: 'bold' }, - attr: { value: 'Hello World' } - } - ] - }) - - instance.$fireEvent(instance.doc.body.children[0].ref, 'click', {}) - setTimeout(() => { - expect(instance.getRealRoot()).toEqual({ + fireEvent(instance, instance.document.body.children[0].ref, 'click') + return instance + }).then(instance => { + expect(getRoot(instance)).toEqual({ type: 'div', children: [ { @@ -94,52 +68,46 @@ describe('generate style', () => { }) it('should be generated by map binding', (done) => { - const { render, staticRenderFns } = compileAndStringify(` + compileAndExecute(`
Hello {{z}}
- `) - const instance = createInstance(runtime, ` - new Vue({ - data: { - x: 100, - y: { color: '#ff0000', fontWeight: 'bold' }, - z: 'World' - }, - methods: { - foo: function () { - this.x = 200 - this.y.color = '#0000ff' - Vue.delete(this.y, 'fontWeight') - this.z = 'Weex' + `, ` + data: { + x: 100, + y: { color: '#ff0000', fontWeight: 'bold' }, + z: 'World' + }, + methods: { + foo: function () { + this.x = 200 + this.y.color = '#0000ff' + Vue.delete(this.y, 'fontWeight') + this.z = 'Weex' + } + } + `).then(instance => { + expect(getRoot(instance)).toEqual({ + type: 'div', + children: [ + { + type: 'text', + event: ['click'], + style: { fontSize: 100, color: '#00ff00' }, + attr: { value: 'Hello' } + }, + { + type: 'text', + style: { color: '#ff0000', fontWeight: 'bold' }, + attr: { value: 'World' } } - }, - render: ${render}, - staticRenderFns: ${staticRenderFns}, - el: 'body' + ] }) - `) - expect(instance.getRealRoot()).toEqual({ - type: 'div', - children: [ - { - type: 'text', - event: ['click'], - style: { fontSize: 100, color: '#00ff00' }, - attr: { value: 'Hello' } - }, - { - type: 'text', - style: { color: '#ff0000', fontWeight: 'bold' }, - attr: { value: 'World' } - } - ] - }) - - instance.$fireEvent(instance.doc.body.children[0].ref, 'click', {}) - setTimeout(() => { - expect(instance.getRealRoot()).toEqual({ + fireEvent(instance, instance.document.body.children[0].ref, 'click') + return instance + }).then(instance => { + expect(getRoot(instance)).toEqual({ type: 'div', children: [ {