From 2deda3d4328eb7aea0adb0eaf01d68537ed0e0af Mon Sep 17 00:00:00 2001 From: Hanks Date: Tue, 19 Sep 2017 03:38:27 +0800 Subject: [PATCH] refactor(weex): Adjust the weex platform entry file to fit the new weex runtime (#6620) * trim trailing whitespace * revert(weex): remove the new Function hack for V8, as Weex uses JSC now Remove the `callFunctionNative` method and `compileBundle`, which is provided by modified V8. In order to maintain the consistency of the js engine, Weex also use JSC on Android. The legacy hack for V8 engine should be removed. * refactor(weex): move module and component apis to weex runtime Modules and components should be registered in weex runtime, not the specific framework. The `registerModules`, `registerComponents`, `weex.supports` and `weex.requireModule` api is moved to weex runtime, which is in the "apache/incubator-weex" repo. * test(weex): refactor the test cases to fit the new weex-js-runtime * fix(weex): use document instead of renderer to create Element --- build/config.js | 2 +- package.json | 3 +- src/platforms/weex/entry-framework.js | 232 +------- src/platforms/weex/runtime/node-ops.js | 14 +- src/platforms/weex/util/index.js | 6 +- test/weex/helpers/index.js | 79 ++- test/weex/runtime/attrs.spec.js | 139 ++--- test/weex/runtime/class.spec.js | 313 ++++------ test/weex/runtime/components/richtext.spec.js | 88 ++- test/weex/runtime/events.spec.js | 190 +++--- test/weex/runtime/framework.spec.js | 550 +++--------------- test/weex/runtime/node.spec.js | 49 +- test/weex/runtime/style.spec.js | 178 +++--- 13 files changed, 525 insertions(+), 1318 deletions(-) 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: [ {