You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by da...@apache.org on 2017/08/17 03:59:44 UTC
[27/43] incubator-weex git commit: * [test] refactor the unit test
cases of runtime
* [test] refactor the unit test cases of runtime
Project: http://git-wip-us.apache.org/repos/asf/incubator-weex/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-weex/commit/9e13c860
Tree: http://git-wip-us.apache.org/repos/asf/incubator-weex/tree/9e13c860
Diff: http://git-wip-us.apache.org/repos/asf/incubator-weex/diff/9e13c860
Branch: refs/heads/0.16-dev
Commit: 9e13c86051e4e8e615ea0be0ae86e7237b546494
Parents: bade955
Author: Hanks <zh...@gmail.com>
Authored: Thu Aug 10 16:27:05 2017 +0800
Committer: Hanks <zh...@gmail.com>
Committed: Thu Aug 10 16:27:05 2017 +0800
----------------------------------------------------------------------
html5/test/unit/default/app/bundle.js | 96 ----
html5/test/unit/default/helper/document.js | 145 -----
html5/test/unit/default/runtime.js | 485 -----------------
html5/test/unit/default/vm/compiler.js | 614 ---------------------
html5/test/unit/default/vm/directive.js | 279 ----------
html5/test/unit/runtime/legacy-framework.js | 353 ++++++++++++
html5/test/unit/runtime/vdom/directive.js | 82 +++
html5/test/unit/runtime/vdom/index.js | 639 ++++++++++++++++++++++
html5/test/unit/runtime/vdom/listener.js | 381 +++++++++++++
html5/test/unit/runtime/vdom/node.js | 39 ++
html5/test/unit/shared/BroadcastChannel.js | 7 -
html5/test/unit/shared/arrayFrom.js | 5 -
html5/test/unit/shared/index.js | 20 +-
html5/test/unit/vdom/directive.js | 82 ---
html5/test/unit/vdom/index.js | 659 -----------------------
html5/test/unit/vdom/listener.js | 423 ---------------
html5/test/unit/vdom/node.js | 39 --
package.json | 6 +-
18 files changed, 1505 insertions(+), 2849 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e13c860/html5/test/unit/default/app/bundle.js
----------------------------------------------------------------------
diff --git a/html5/test/unit/default/app/bundle.js b/html5/test/unit/default/app/bundle.js
index 64e860a..f44b2f6 100644
--- a/html5/test/unit/default/app/bundle.js
+++ b/html5/test/unit/default/app/bundle.js
@@ -362,70 +362,6 @@ describe('parsing a bundle file', () => {
.to.deep.equal(template)
})
})
-
- describe.skip('render', () => {
- it('a component', () => {
- app.render('main')
-
- expect(callTasksSpy.callCount).to.be.equal(4)
-
- expect(readySpy.calledTwice).to.be.true
- expect(readySpy.firstCall.args[0].a).to.be.equal('b')
- expect(readySpy.secondCall.args[0].b).to.be.equal('c')
-
- const task1 = callTasksSpy.firstCall.args[0][0]
- expect(task1).to.deep.equal({
- module: 'dom',
- method: 'createBody',
- args: [{
- type: 'container',
- ref: '_root',
- attr: {},
- style: {}
- }]
- })
-
- const task2 = callTasksSpy.secondCall.args[0][0]
- expect(task2).to.deep.equal({
- module: 'dom',
- method: 'addElement',
- args: ['_root', {
- type: 'text',
- ref: app.doc.body.children[0].ref,
- attr: {
- value: 'Hello World'
- },
- style: {}
- }, -1]
- })
-
- const task3 = callTasksSpy.thirdCall.args[0][0]
- expect(task3).to.deep.equal({
- module: 'dom',
- method: 'addElement',
- args: ['_root', {
- type: 'container',
- ref: app.doc.body.children[1].ref,
- attr: {},
- style: {}
- }, -1]
- })
-
- const task4 = callTasksSpy.getCall(3).args[0][0]
- expect(task4).to.deep.equal({
- module: 'dom',
- method: 'addElement',
- args: [app.doc.body.children[1].ref, {
- type: 'text',
- ref: app.doc.body.children[1].children[0].ref,
- attr: {
- value: 'Hello World'
- },
- style: {}
- }, -1]
- })
- })
- })
})
describe('use define/require(backward compatibility)', () => {
@@ -469,37 +405,5 @@ describe('parsing a bundle file', () => {
.to.deep.equal(componentTemplate)
})
})
-
- describe.skip('require(old)', () => {
- it('a component', () => {
- app.require('main')()
-
- expect(callTasksSpy.calledTwice).to.be.true
-
- const task1 = callTasksSpy.firstCall.args[0][0]
- expect(task1.module).to.be.equal('dom')
- expect(task1.method).to.be.equal('createBody')
- expect(task1.args[0]).to.deep.equal({
- type: 'container',
- ref: '_root',
- attr: {},
- style: {}
- })
-
- const task2 = callTasksSpy.secondCall.args[0][0]
- expect(task2.module).to.be.equal('dom')
- expect(task2.method).to.be.equal('addElement')
- expect(task2.args[1]).to.deep.equal({
- type: 'text',
- ref: app.doc.body.children[0].ref,
- attr: {
- value: 'Hello World'
- },
- style: {}
- })
- expect(task2.args[0]).to.be.equal('_root')
- expect(task2.args[2]).to.be.equal(-1)
- })
- })
})
})
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e13c860/html5/test/unit/default/helper/document.js
----------------------------------------------------------------------
diff --git a/html5/test/unit/default/helper/document.js b/html5/test/unit/default/helper/document.js
deleted file mode 100644
index bac9c25..0000000
--- a/html5/test/unit/default/helper/document.js
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-function Document () {
- this.refs = {}
-}
-
-Document.prototype.createBody = function (config) {
- const doc = this
- const body = this.body = new Element(config)
- this.refs._root = this.body
- if (config.children) {
- config.children.forEach(function (child) {
- appendToDoc(doc, child, body.ref, -1)
- })
- }
-}
-
-Document.prototype.addElement = function (parentRef, config, index) {
- appendToDoc(this, config, parentRef, index)
-}
-
-function appendToDoc (doc, config, parentRef, index) {
- const parent = doc.refs[parentRef]
- const el = new Element(config)
- doc.refs[el.ref] = el
- el.parentRef = parentRef
-
- if (index < 0) {
- parent.children.push(el)
- }
- else {
- parent.children.splice(index, 0, el)
- }
-
- if (config.children) {
- config.children.forEach(function (child) {
- appendToDoc(doc, child, el.ref, -1)
- })
- }
-}
-
-Document.prototype.moveElement = function (ref, parentRef, index) {
- const el = this.refs[ref]
- const oldParent = this.refs[el.parentRef]
- const oldIndex = oldParent.children.indexOf(el)
-
- const parent = this.refs[parentRef]
-
- if (parent === oldParent && oldIndex <= index) {
- index = index - 1
- }
-
- oldParent.children.splice(oldIndex, 1)
- parent.children.splice(index, 0, el)
- el.parentRef = parentRef
-}
-
-Document.prototype.removeElement = function (ref) {
- removeEl(this, ref)
-}
-
-function removeEl (doc, ref) {
- const el = doc.refs[ref]
- const parent = doc.refs[el.parentRef]
- const index = parent.children.indexOf(el)
- const children = el.children || []
- parent.children.splice(index, 1)
- delete doc.refs[ref]
- children.forEach(function (child) {
- removeEl(doc, child.ref)
- })
-}
-
-Document.prototype.addEvent = function (ref, type) {
- const el = this.refs[ref]
- const index = el.event.indexOf(type)
- if (index < 0) {
- el.event.push(type)
- }
-}
-
-Document.prototype.removeEvent = function (ref, type) {
- const el = this.refs[ref]
- const index = el.event.indexOf(type)
- if (index >= 0) {
- el.event.splice(index, 1)
- }
-}
-
-Document.prototype.toJSON = function () {
- const body = this.refs._root
- if (body) {
- return body.toJSON()
- }
- return {}
-}
-
-function Element (config) {
- this.ref = config.ref
- this.parentRef = config.parentRef
- this.type = config.type
- this.attr = config.attr || {}
- this.style = config.style || {}
- this.event = config.event || []
- this.children = [] // todo children
-}
-
-Element.prototype.toJSON = function () {
- const result = { type: this.type }
- if (Object.keys(this.attr).length > 0) {
- result.attr = this.attr
- }
- if (Object.keys(this.style).length > 0) {
- result.style = this.style
- }
- if (this.event.length > 0) {
- result.event = this.event
- }
- if (this.children.length > 0) {
- result.children = this.children.map(function (child) {
- return child.toJSON()
- })
- }
-
- return result
-}
-
-exports.Document = Document
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e13c860/html5/test/unit/default/runtime.js
----------------------------------------------------------------------
diff --git a/html5/test/unit/default/runtime.js b/html5/test/unit/default/runtime.js
deleted file mode 100644
index 9a52fff..0000000
--- a/html5/test/unit/default/runtime.js
+++ /dev/null
@@ -1,485 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-import chai from 'chai'
-import sinon from 'sinon'
-import sinonChai from 'sinon-chai'
-const {
- expect
-} = chai
-chai.use(sinonChai)
-
-import runtime from '../../../runtime'
-import frameworks from '../../../frameworks'
-import defaultConfig from '../../../frameworks/legacy/config'
-import { init as resetTaskHandler } from '../../../runtime/bridge/TaskCenter'
-
-const { init, config } = runtime
-config.frameworks = frameworks
-runtime.setNativeConsole()
-
-import Vm from '../../../frameworks/legacy/vm'
-import { clearModules, getModule } from '../../../frameworks/legacy/app/register'
-
-const framework = init(config)
-
-function clearRefs (json) {
- delete json.ref
- if (json.children) {
- json.children.forEach(clearRefs)
- }
-}
-
-describe('framework entry', () => {
- const oriCallNative = global.callNative
- const oriCallAddElement = global.callAddElement
- const oriDocumentHandler = config.Document.handler
- const callNativeSpy = sinon.spy()
- const callAddElementSpy = sinon.spy()
- const documentHandlerSpy = sinon.spy()
- const instanceId = Date.now() + ''
-
- before(() => {
- global.callNative = (id, tasks, callbackId) => {
- callNativeSpy(id, tasks, callbackId)
- /* istanbul ignore if */
- if (callbackId !== '-1') {
- framework.callJS(id, [{
- method: 'callback',
- args: [callbackId, null, true]
- }])
- }
- }
- global.callAddElement = (name, id, ref, json, index, callbackId) => {
- callAddElementSpy(name, ref, json, index, callbackId)
- /* istanbul ignore if */
- if (callbackId !== '-1') {
- framework.callJS(id, [{
- method: 'callback',
- args: [callbackId, null, true]
- }])
- }
- }
- config.Document.handler = oriDocumentHandler
- resetTaskHandler()
- })
-
- afterEach(() => {
- callNativeSpy.reset()
- callAddElementSpy.reset()
- documentHandlerSpy.reset()
- })
-
- after(() => {
- config.Document.handler = oriDocumentHandler
- global.callNative = oriCallNative
- global.callAddElement = oriCallAddElement
- })
-
- describe('createInstance', () => {
- it('a simple bundle', () => {
- const code = `
- define('@weex-component/main',
- function(require, exports, module) {
- module.exports = {
- data: function() {
- return {
- text: 'Hello World',
- showText: true
- };
- }
- }
-
- ;module.exports.style = {}
-
- ;module.exports.template = {
- 'type': 'container',
- 'children': [{
- 'type': 'text',
- 'shown': function() {
- return this.showText
- },
- 'attr': {
- 'value': function() {
- return this.text
- }
- }
- }]
- }
- }
- )
-
- bootstrap('@weex-component/main')
- `
- framework.createInstance(instanceId, code)
- expect(callNativeSpy.callCount).to.be.equal(2)
- expect(callAddElementSpy.callCount).to.be.equal(1)
-
- expect(callNativeSpy.firstCall.args[0]).to.be.equal(instanceId)
- expect(callNativeSpy.firstCall.args[1]).to.deep.equal([{
- module: 'dom',
- method: 'createBody',
- args: [{
- ref: '_root',
- type: 'container',
- attr: {},
- style: {}
- }]
- }])
- // expect(callNativeSpy.firstCall.args[2]).to.not.equal('-1')
-
- expect(callAddElementSpy.firstCall.args[0]).to.be.equal(instanceId)
- delete callAddElementSpy.firstCall.args[1].ref
- expect(callAddElementSpy.firstCall.args[1]).to.deep.equal({
- type: 'text',
- attr: { value: 'Hello World' },
- style: {}
- })
-
- // expect(callNativeSpy.secondCall.args[2]).to.not.equal('-1')
-
- expect(callNativeSpy.secondCall.args[0]).to.be.equal(instanceId)
- expect(callNativeSpy.secondCall.args[1]).to.deep.equal([{
- module: 'dom',
- method: 'createFinish',
- args: []
- }])
- // expect(callNativeSpy.thirdCall.args[2]).to.not.equal('-1')
- })
-
- it('with a exist instanceId', () => {
- const code = ''
- const result = framework.createInstance(instanceId, code)
- expect(result).to.be.an.instanceof(Error)
- })
-
- it('js bundle format version checker', function () {
- const weexFramework = frameworks.Weex
- frameworks.Weex = {
- init: function () {},
- createInstance: sinon.spy()
- }
- frameworks.xxx = {
- init: function () {},
- createInstance: sinon.spy()
- }
- frameworks.yyy = {
- init: function () {},
- createInstance: sinon.spy()
- }
-
- // test framework xxx
- let code = `// {"framework":"xxx","version":"0.3.1"}
- 'This is a piece of JavaScript from a third-party Framework...'`
- framework.createInstance(instanceId + '~', code)
- expect(frameworks.xxx.createInstance.callCount).equal(1)
- expect(frameworks.yyy.createInstance.callCount).equal(0)
- expect(frameworks.Weex.createInstance.callCount).equal(0)
- expect(frameworks.xxx.createInstance.firstCall.args.slice(0, 4)).eql([
- instanceId + '~',
- code,
- { env: {}},
- undefined
- ])
-
- // also support spaces in JSON string
- // also ignore spaces between double-slash and JSON string
- code = `//{ "framework":"xxx" }
- 'This is a piece of JavaScript from a third-party Framework...'`
- framework.createInstance(instanceId + '~~', code)
- expect(frameworks.xxx.createInstance.callCount).equal(2)
- expect(frameworks.yyy.createInstance.callCount).equal(0)
- expect(frameworks.Weex.createInstance.callCount).equal(0)
-
- // also support non-strict JSON format
- code = `// {framework:"xxx",'version':"0.3.1"}
- 'This is a piece of JavaScript from a third-party Framework...'`
- framework.createInstance(instanceId + '~~~', code)
- expect(frameworks.xxx.createInstance.callCount).equal(2)
- expect(frameworks.yyy.createInstance.callCount).equal(0)
- expect(frameworks.Weex.createInstance.callCount).equal(1)
- expect(frameworks.Weex.createInstance.firstCall.args.slice(0, 4)).eql([
- instanceId + '~~~',
- code,
- { env: {}},
- undefined
- ])
-
- // test framework yyy
- /* eslint-disable */
- code = `
-
-
-
- // {"framework":"yyy"}
-
-'JS Bundle with space and empty lines behind'` // modified from real generated code from tb
- /* eslint-enable */
- framework.createInstance(instanceId + '~~~~', code)
- expect(frameworks.xxx.createInstance.callCount).equal(2)
- expect(frameworks.yyy.createInstance.callCount).equal(1)
- expect(frameworks.Weex.createInstance.callCount).equal(1)
- expect(frameworks.yyy.createInstance.firstCall.args.slice(0, 4)).eql([
- instanceId + '~~~~',
- code,
- { env: {}},
- undefined
- ])
-
- // test framework Weex (wrong format at the middle)
- code = `'Some JS bundle code here ... // {"framework":"xxx"}\n ... end.'`
- framework.createInstance(instanceId + '~~~~~', code)
- expect(frameworks.xxx.createInstance.callCount).equal(2)
- expect(frameworks.yyy.createInstance.callCount).equal(1)
- expect(frameworks.Weex.createInstance.callCount).equal(2)
- expect(frameworks.Weex.createInstance.secondCall.args.slice(0, 4)).eql([
- instanceId + '~~~~~',
- code,
- { env: {}},
- undefined
- ])
-
- // test framework Weex (without any JSON string in comment)
- code = `'Some JS bundle code here'`
- framework.createInstance(instanceId + '~~~~~~', code)
- expect(frameworks.xxx.createInstance.callCount).equal(2)
- expect(frameworks.yyy.createInstance.callCount).equal(1)
- expect(frameworks.Weex.createInstance.callCount).equal(3)
- expect(frameworks.Weex.createInstance.thirdCall.args.slice(0, 4)).eql([
- instanceId + '~~~~~~',
- code,
- { env: {}},
- undefined
- ])
-
- // revert frameworks
- delete frameworks.xxx
- delete frameworks.yyy
- frameworks.Weex = weexFramework
- })
- })
-
- describe('getRoot', () => {
- it('with a exist instanceId', () => {
- const json = framework.getRoot(instanceId)
- expect(json.ref).eql('_root')
- clearRefs(json)
- const expectJSON = {
- type: 'container',
- attr: {},
- style: {},
- children: [{
- type: 'text',
- attr: {
- value: 'Hello World'
- },
- style: {}
- }]
- }
- expect(json).to.be.deep.equal(expectJSON)
- })
-
- it('with a non-exist instanceId', () => {
- const result = framework.getRoot('123')
- expect(result).to.be.an.instanceof(Error)
- })
- })
-
- describe('callJS', () => {
- it('fireEvent with no params', () => {
- framework.callJS()
- })
-
- it('fireEvent with a exist instanceId', () => {
- framework.callJS(instanceId, [{
- method: 'fireEvent',
- args: []
- }])
- })
-
- it('callback with a exist instanceId', () => {
- framework.callJS(instanceId, [{
- method: 'callback',
- args: []
- }])
- })
-
- it('with a non-exist instanceId', () => {
- const result = framework.callJS('123', [{
- method: 'fireEvent',
- args: []
- }])
- expect(result).to.be.an.instanceof(Error)
- })
-
- it('with a non-array tasks', () => {
- const result = framework.callJS(instanceId, {
- method: 'fireEvent',
- args: []
- })
- expect(result).to.be.an.instanceof(Error)
- })
- })
-
- describe('refreshInstance', () => {
- it('modify showText to false', () => {
- const json = framework.getRoot(instanceId)
- const textRef = json.children[0].ref
- framework.refreshInstance(instanceId, { showText: false })
- expect(callNativeSpy.callCount).to.be.equal(2)
- expect(callNativeSpy.firstCall.args[0]).to.be.equal(instanceId)
- expect(callNativeSpy.firstCall.args[1]).to.deep.equal([{
- module: 'dom',
- method: 'removeElement',
- args: [textRef]
- }])
- // expect(callNativeSpy.firstCall.args[2]).to.be.equal('-1')
-
- expect(callNativeSpy.secondCall.args[0]).to.be.equal(instanceId)
- expect(callNativeSpy.secondCall.args[1]).to.deep.equal([{
- module: 'dom',
- method: 'refreshFinish',
- args: []
- }])
- // expect(callNativeSpy.secondCall.args[2]).to.be.equal('-1')
- })
-
- it('with a non-exist instanceId', () => {
- const result = framework.refreshInstance('123', {})
- expect(result).to.be.an.instanceof(Error)
- })
- })
-
- describe('destroyInstance', () => {
- it('with no params', () => {
- framework.destroyInstance()
- })
-
- it('with a exist instanceId', () => {
- const result = framework.destroyInstance(instanceId)
- expect(result[instanceId]).to.be.undefined
- })
-
- it('with a non-exist instanceId', () => {
- const result = framework.destroyInstance('123')
- expect(result).to.be.an.instanceof(Error)
- })
- })
-
- describe('registerComponents', () => {
- it('with old format', () => {
- framework.registerComponents(['a', 'b', 'c'])
- expect(defaultConfig.nativeComponentMap).to.contain.keys('a', 'b', 'c')
- })
-
- it('with new format', () => {
- framework.registerComponents([{
- type: 'd',
- append: 'tree'
- }])
- expect(defaultConfig.nativeComponentMap).to.contain.keys('d')
- expect(defaultConfig.nativeComponentMap['d']).to.be.deep.equal({
- type: 'd',
- append: 'tree'
- })
- })
-
- it('with non-array', () => {
- framework.registerComponents({
- type: 'e'
- })
- expect(defaultConfig.nativeComponentMap).not.contain.keys('e')
- })
-
- it('with methods', () => {
- const components = [{
- type: 'x',
- methods: ['foo', 'bar']
- }, {
- type: 'y',
- methods: []
- }, {
- type: 'z',
- methods: null
- }]
- framework.registerComponents(components)
- expect(defaultConfig.nativeComponentMap).to.contain.keys('x', 'y', 'z')
- })
- })
-
- describe('register modules', () => {
- it('with object of modules', () => {
- clearModules()
- const modules = {
- a: [{
- name: 'b',
- args: ['string']
- }]
- }
-
- framework.registerModules(modules)
- expect(getModule('b')).an.object
- clearModules()
- })
- })
-
- describe('register methods', () => {
- it('with object of methods', () => {
- const methods = {
- a: sinon.spy()
- }
-
- framework.registerMethods(methods)
- expect(Vm.prototype.a).a.function
- delete Vm.prototype.a
- })
- })
-})
-
-describe('config', () => {
- it('config is an object', () => {
- init({})
- })
-})
-
-describe.skip('freeze the prototypes of vdom', function () {
- const { Document, Element, Comment, Listener } = config
-
- before(() => {
- runtime.freezePrototype()
- })
-
- it('Document.prototype', () => {
- expect(Document.prototype).to.be.frozen
- })
-
- it('Element & Element.prototype', () => {
- expect(Element).to.be.frozen
- expect(Element.prototype).to.be.frozen
- })
-
- it('Comment & Comment.prototype', () => {
- expect(Comment).to.be.frozen
- expect(Comment.prototype).to.be.frozen
- })
-
- it('Listener & Listener.prototype', () => {
- expect(Listener).to.be.frozen
- expect(Listener.prototype).to.be.frozen
- })
-})
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e13c860/html5/test/unit/default/vm/compiler.js
----------------------------------------------------------------------
diff --git a/html5/test/unit/default/vm/compiler.js b/html5/test/unit/default/vm/compiler.js
deleted file mode 100644
index 654f1ed..0000000
--- a/html5/test/unit/default/vm/compiler.js
+++ /dev/null
@@ -1,614 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-import chai from 'chai'
-import sinon from 'sinon'
-import sinonChai from 'sinon-chai'
-const { expect } = chai
-chai.use(sinonChai)
-
-import * as compiler from '../../../../frameworks/legacy/vm/compiler'
-import * as directive from '../../../../frameworks/legacy/vm/directive'
-import { initState } from '../../../../frameworks/legacy/core/state'
-
-describe.skip('generate workflow', () => {
- let contentIndex = 0
- const vm = {}
- Object.assign(vm, compiler, directive, {
- _watchers: [],
- _createBlock: function () { return { element: {}} },
- _mergeContext: function () { return this },
- _createBody: type => { return { type } },
- _createElement: type => { return { type } },
- _attachTarget: (element, dest) => element,
- _bindElement: () => {},
- _setId: function () {},
- _bindSubVm: function () {},
- _bindSubVmAfterInitialized: function () {},
- _applyNaitveComponentOptions: function () {}
- })
-
- vm.constructor = function () {
- contentIndex++
- this._content = { index: contentIndex }
- this.$on = sinon.spy()
- }
-
- beforeEach(() => {
- contentIndex = 0
- sinon.spy(vm, '_compile')
- sinon.spy(vm, '_compileNativeComponent')
- sinon.spy(vm, '_createBody')
- sinon.spy(vm, '_createElement')
- sinon.spy(vm, '_bindElement')
- sinon.spy(vm, '_attachTarget')
- sinon.spy(vm, '_createBlock')
- sinon.spy(vm, '_mergeContext')
- sinon.spy(vm, 'constructor')
- })
-
- afterEach(() => {
- vm._compile.restore()
- vm._compileNativeComponent.restore()
- vm._createBody.restore()
- vm._createElement.restore()
- vm._bindElement.restore()
- vm._attachTarget.restore()
- vm._createBlock.restore()
- vm._mergeContext.restore()
- vm.constructor.restore()
- contentIndex = 0
- })
-
- it('generate a body', (done) => {
- const target = {
- type: 'a'
- }
- const dest = {
- ref: '_documentElement'
- }
-
- function check () {
- expect(vm._compile).callCount(1)
- expect(vm._compile).calledWith(target, dest)
- expect(vm._createBody).callCount(1)
- expect(vm._bindElement).callCount(1)
- expect(vm._createElement).callCount(0)
- expect(vm._attachTarget).callCount(1)
- expect(vm._createBlock).callCount(0)
- expect(vm._mergeContext).callCount(0)
- expect(vm.constructor).callCount(0)
- done()
- }
-
- vm._compile(target, dest)
- check()
- })
-
- it('generate a single element', (done) => {
- const target = {
- type: 'a'
- }
- const dest = {}
-
- function check () {
- expect(vm._compile).callCount(1)
- expect(vm._compile).calledWith(target, dest)
- expect(vm._createBody).callCount(0)
- expect(vm._bindElement).callCount(1)
- expect(vm._createElement).callCount(1)
- expect(vm._attachTarget).callCount(1)
- expect(vm._createBlock).callCount(0)
- expect(vm._mergeContext).callCount(0)
- expect(vm.constructor).callCount(0)
- done()
- }
-
- vm._compile(target, dest)
- check()
- })
-
- it('generate some child nodes', (done) => {
- const target = [{
- type: 'a'
- }, {
- type: 'b'
- }]
- const dest = {}
-
- function check () {
- expect(vm._compile).callCount(3)
- expect(vm._compile.args[0]).eql(
- [target, dest])
- expect(vm._compile.args[1]).eql(
- [target[0], { element: {}}, undefined])
- expect(vm._compile.args[2]).eql(
- [target[1], { element: {}}, undefined])
- expect(vm._createBlock).callCount(1)
- expect(vm._mergeContext).callCount(0)
- expect(vm.constructor).callCount(0)
- done()
- }
-
- vm._compile(target, dest)
- check()
- })
-
- it('generate content holder', (done) => {
- const target = {
- type: 'a', children: [
- { type: 'b' },
- { type: 'content' },
- { type: 'c' }
- ]
- }
- const dest = {}
-
- function check () {
- expect(vm._compile).callCount(4)
- expect(vm._compile.args[0]).eql(
- [target, dest])
- expect(vm._compile.args[1]).eql(
- [target.children[0], { type: 'a' }])
- expect(vm._compile.args[2]).eql(
- [target.children[1], { type: 'a' }])
- expect(vm._compile.args[3]).eql(
- [target.children[2], { type: 'a' }])
- expect(vm._content).is.an.object
- expect(vm._content).eql({ element: {}})
- expect(vm._createBlock).callCount(1)
- expect(vm._mergeContext).callCount(0)
- expect(vm.constructor).callCount(0)
- done()
- }
-
- vm._compile(target, dest)
- check()
- })
-
- it('generate a repeat element', (done) => {
- const target = {
- type: 'a',
- repeat: () => [1, 2, 3]
- }
- const dest = {}
-
- function checkRepeatVm (args, target, meta) {
- expect(args[0]).eql(target)
- expect(args[2]).eql(meta)
- const vm = args[1]
- expect(vm.element).eql({})
- expect(vm.data).eql([1, 2, 3])
- }
-
- function check () {
- expect(vm._compile).callCount(4)
- expect(vm._compile.args[0]).eql([target, dest])
- checkRepeatVm(vm._compile.args[1], target, { repeat: 1 })
- checkRepeatVm(vm._compile.args[2], target, { repeat: 2 })
- checkRepeatVm(vm._compile.args[3], target, { repeat: 3 })
- expect(vm._createBlock).callCount(1)
- expect(vm._mergeContext).callCount(3)
- expect(vm.constructor).callCount(0)
- done()
- }
-
- vm._compile(target, dest)
- check()
- })
-
- it('can\'t not use repeat on root element', (done) => {
- const target = {
- type: 'a',
- repeat: () => [1, 2, 3]
- }
- const dest = {
- type: 'document'
- }
-
- function check () {
- expect(vm._compile).callCount(1)
- expect(vm._createBody).callCount(0)
- expect(vm._createBlock).callCount(0)
- expect(vm._mergeContext).callCount(0)
- expect(vm.constructor).callCount(0)
- done()
- }
-
- vm._compile(target, dest)
- check()
- })
-
- it('generate a shown element', (done) => {
- const target = {
- type: 'a',
- shown: () => true
- }
- const dest = {}
-
- function check () {
- expect(vm._compile).callCount(2)
- expect(vm._compile.args[0]).eql(
- [target, dest])
- expect(vm._compile.args[1][0]).eql(target)
- expect(vm._compile.args[1][1].display).eql(true)
- expect(vm._compile.args[1][2]).eql({ shown: true })
- expect(vm._createBlock).callCount(1)
- expect(vm._mergeContext).callCount(0)
- expect(vm.constructor).callCount(0)
- done()
- }
-
- vm._compile(target, dest)
- check()
- })
-
- it('can\'t not use shown on root element', (done) => {
- const target = {
- type: 'a',
- shown: () => true
- }
- const dest = {
- type: 'document'
- }
-
- function check () {
- expect(vm._compile).callCount(1)
- expect(vm._createBody).callCount(0)
- expect(vm._createBlock).callCount(0)
- expect(vm._mergeContext).callCount(0)
- expect(vm.constructor).callCount(0)
- done()
- }
-
- vm._compile(target, dest)
- check()
- })
-
- it('generate a repeat shown element', (done) => {
- let index = 0
- const target = {
- type: 'a',
- repeat: () => [1, 2, 3],
- shown: () => {
- index++
- return index % 2
- }
- }
- const dest = {}
-
- function checkRepeatVm (args, target, meta) {
- expect(args[0]).eql(target)
- expect(args[2]).eql(meta)
- const vm = args[1]
- expect(vm.element).eql({})
- expect(vm.data).eql([1, 2, 3])
- }
-
- function check () {
- expect(vm._compile).callCount(6)
- expect(vm._compile.args[0]).eql([target, dest])
- checkRepeatVm(vm._compile.args[1], target, { repeat: 1 })
- expect(vm._compile.args[2][0]).eql(target)
- expect(vm._compile.args[2][1].display).eql(true)
- expect(vm._compile.args[2][2]).eql({ repeat: 1, shown: true })
- checkRepeatVm(vm._compile.args[3], target, { repeat: 2 })
- checkRepeatVm(vm._compile.args[4], target, { repeat: 3 })
- expect(vm._compile.args[5][0]).eql(target)
- expect(vm._compile.args[5][1].display).eql(true)
- expect(vm._compile.args[5][2]).eql({ repeat: 3, shown: true })
- expect(vm._createBlock).callCount(4)
- expect(vm._mergeContext).callCount(3)
- expect(vm.constructor).callCount(0)
- done()
- }
-
- vm._compile(target, dest)
- check()
- })
-
- it('generate an element with children', (done) => {
- const target = {
- type: 'a',
- children: [{ type: 'b' }, { type: 'c' }]
- }
- const dest = {}
-
- function check () {
- expect(vm._compile).callCount(3)
- expect(vm._compile.args[0]).eql([target, dest])
- expect(vm._compile.args[1]).eql([target.children[0], { type: 'a' }])
- expect(vm._compile.args[2]).eql([target.children[1], { type: 'a' }])
- expect(vm._createBlock).callCount(0)
- expect(vm._mergeContext).callCount(0)
- expect(vm.constructor).callCount(0)
- done()
- }
-
- vm._compile(target, dest)
- check()
- })
-
- it('generate an whole element with children', (done) => {
- const target = {
- type: 'a',
- append: 'tree',
- children: [{ type: 'b' }, { type: 'c' }]
- }
- const dest = {}
-
- function check () {
- expect(vm._compile).callCount(3)
- expect(vm._compile.args[0]).eql([target, dest])
- expect(vm._compile.args[1]).eql([target.children[0], {
- attr: {
- append: 'tree'
- }, type: 'a' }])
- expect(vm._compile.args[2]).eql([target.children[1], {
- attr: {
- append: 'tree'
- }, type: 'a' }])
- expect(vm._createBlock).callCount(0)
- expect(vm._mergeContext).callCount(0)
- expect(vm.constructor).callCount(0)
- done()
- }
-
- vm._compile(target, dest)
- check()
- })
-
- it('generate an element with repeat shown children', (done) => {
- let index = 0
- const target = {
- type: 'a',
- children: [
- {
- type: 'b',
- repeat: () => [1, 2, 3],
- shown: () => {
- index++
- return index % 2
- }
- },
- { type: 'c' }
- ]
- }
- const dest = {}
-
- function checkRepeatVm (args, target, meta) {
- expect(args[0]).eql(target)
- expect(args[2]).eql(meta)
- const vm = args[1]
- expect(vm.element).eql({})
- expect(vm.data).eql([1, 2, 3])
- }
-
- function check () {
- expect(vm._compile).callCount(8)
- expect(vm._compile.args[0]).eql([target, dest])
- expect(vm._compile.args[1]).eql([target.children[0], { type: 'a' }])
- checkRepeatVm(vm._compile.args[2], target.children[0], { repeat: 1 })
- expect(vm._compile.args[3][0]).eql(target.children[0])
- expect(vm._compile.args[3][1].display).eql(true)
- expect(vm._compile.args[3][2]).eql({ repeat: 1, shown: true })
- checkRepeatVm(vm._compile.args[4], target.children[0], { repeat: 2 })
- checkRepeatVm(vm._compile.args[5], target.children[0], { repeat: 3 })
- expect(vm._compile.args[6][0]).eql(target.children[0])
- expect(vm._compile.args[6][1].display).eql(true)
- expect(vm._compile.args[6][2]).eql({ repeat: 3, shown: true })
- expect(vm._compile.args[7]).eql([target.children[1], { type: 'a' }])
- expect(vm._createBlock).callCount(4)
- expect(vm._mergeContext).callCount(3)
- expect(vm.constructor).callCount(0)
- done()
- }
-
- vm._compile(target, dest)
- check()
- })
-
- it('generate an element with repeat shown tree', (done) => {
- let index = 0
- const target = {
- type: 'a',
- children: [
- {
- type: 'b',
- children: [{ type: 'c' }],
- repeat: () => [1, 2, 3],
- shown: function () {
- index++
- return index % 2
- }
- },
- { type: 'd' }
- ]
- }
- const dest = {}
-
- function checkRepeatVm (args, target, meta) {
- expect(args[0]).eql(target)
- expect(args[2]).eql(meta)
- const vm = args[1]
- expect(vm.element).eql({})
- expect(vm.data).eql([1, 2, 3])
- }
-
- function check () {
- expect(vm._compile).callCount(10)
- expect(vm._compile.args[0]).eql([target, dest])
- expect(vm._compile.args[1]).eql([target.children[0], { type: 'a' }])
- checkRepeatVm(vm._compile.args[2], target.children[0], { repeat: 1 })
- expect(vm._compile.args[3][0]).eql(target.children[0])
- expect(vm._compile.args[3][1].display).eql(true)
- expect(vm._compile.args[3][2]).eql({ repeat: 1, shown: true })
- expect(vm._compile.args[4]).eql([target.children[0].children[0],
- { type: 'b' }])
- checkRepeatVm(vm._compile.args[5], target.children[0], { repeat: 2 })
- checkRepeatVm(vm._compile.args[6], target.children[0], { repeat: 3 })
- expect(vm._compile.args[7][0]).eql(target.children[0])
- expect(vm._compile.args[7][1].display).eql(true)
- expect(vm._compile.args[7][2]).eql({ repeat: 3, shown: true })
- expect(vm._compile.args[8]).eql([target.children[0].children[0],
- { type: 'b' }])
- expect(vm._compile.args[9]).eql([target.children[1], { type: 'a' }])
- expect(vm._createBlock).callCount(4)
- expect(vm._mergeContext).callCount(3)
- expect(vm.constructor).callCount(0)
- done()
- }
-
- vm._compile(target, dest)
- check()
- })
-
- it('generate an element with custom children', (done) => {
- const target = {
- type: 'a',
- children: [
- { type: 'b', component: true },
- { type: 'c' }
- ]
- }
- const dest = {}
-
- function check () {
- expect(vm._compile).callCount(3)
- expect(vm._compile.args[0]).eql([target, dest])
- expect(vm._compile.args[1]).eql([target.children[0], { type: 'a' }])
- expect(vm._compile.args[2]).eql([target.children[1], { type: 'a' }])
- expect(vm._createBlock).callCount(0)
- expect(vm._mergeContext).callCount(0)
- expect(vm.constructor).callCount(1)
- expect(vm.constructor.args[0][0]).eql('b')
- expect(vm.constructor.args[0][1]).eql({})
- expect(vm.constructor.args[0][3]).eql({ type: 'a' })
- done()
- }
-
- vm._compile(target, dest)
- check()
- })
-
- it('with custom repeat show children', (done) => {
- let index = 0
- const target = {
- type: 'a',
- children: [
- {
- type: 'b',
- component: true,
- repeat: () => [1, 2, 3],
- shown: function () {
- index++
- return index % 2
- }
- },
- { type: 'd' }
- ]
- }
- const dest = {}
-
- function checkRepeatVm (args, target, meta) {
- expect(args[0]).eql(target)
- expect(args[2]).eql(meta)
- const vm = args[1]
- expect(vm.element).eql({})
- expect(vm.data).eql([1, 2, 3])
- }
-
- function check () {
- expect(vm._compile).callCount(8)
- expect(vm._compile.args[0]).eql([target, dest])
- expect(vm._compile.args[1]).eql([target.children[0], { type: 'a' }])
- checkRepeatVm(vm._compile.args[2], target.children[0], { repeat: 1 })
- expect(vm._compile.args[3][0]).eql(target.children[0])
- expect(vm._compile.args[3][1].display).eql(true)
- expect(vm._compile.args[3][2]).eql({ repeat: 1, shown: true })
- checkRepeatVm(vm._compile.args[4], target.children[0], { repeat: 2 })
- checkRepeatVm(vm._compile.args[5], target.children[0], { repeat: 3 })
- expect(vm._compile.args[6][0]).eql(target.children[0])
- expect(vm._compile.args[6][1].display).eql(true)
- expect(vm._compile.args[6][2]).eql({ repeat: 3, shown: true })
- expect(vm._compile.args[7]).eql([target.children[1], { type: 'a' }])
- expect(vm._createBlock).callCount(4)
- expect(vm._mergeContext).callCount(3)
-
- expect(vm.constructor).callCount(2)
- expect(vm.constructor.args[0][0]).eql('b')
- expect(vm.constructor.args[0][3]).eql({ element: {}, display: true })
- expect(vm.constructor.args[1][0]).eql('b')
- expect(vm.constructor.args[1][3]).eql({ element: {}, display: true })
-
- done()
- }
-
- vm._compile(target, dest)
- check()
- })
-})
-
-describe.skip('merge context', () => {
- const { mergeContext } = compiler
- let vm
-
- beforeEach(() => {
- vm = {
- _data: { a: 1, b: 2 }
- }
- initState(vm)
- })
-
- afterEach(() => {
- vm = null
- })
-
- it('merge external data', () => {
- const context = mergeContext(vm, { a: 3 })
- expect(context).not.equal(vm)
- expect(context.a).eql(3)
- expect(context.b).eql(2)
- })
-
- it('react with changes, but not with internal for ext-key', () => {
- const context = mergeContext(vm, { a: 3 })
- vm.a = 4
- vm.b = 5
- expect(context.a).eql(3)
- expect(context.b).eql(5)
- context.a = 6
- expect(context.a).eql(6)
- })
-
- it('merge external data if key not bound', () => {
- const context = mergeContext(vm, { c: 3 })
- expect(context).not.equal(vm)
- expect(context.a).eql(1)
- expect(context.b).eql(2)
- expect(context.c).eql(3)
- })
-
- it('not react with changes for extra key', () => {
- const context = mergeContext(vm, { c: 3 })
- vm.c = 9
- expect(context.a).eql(1)
- expect(context.b).eql(2)
- expect(context.c).eql(3)
- })
-})
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e13c860/html5/test/unit/default/vm/directive.js
----------------------------------------------------------------------
diff --git a/html5/test/unit/default/vm/directive.js b/html5/test/unit/default/vm/directive.js
index caa93c5..fa21969 100644
--- a/html5/test/unit/default/vm/directive.js
+++ b/html5/test/unit/default/vm/directive.js
@@ -52,84 +52,6 @@ function initElement (el) {
}
}
-// exports._watch(calc, callback)
-// exports._bindKey(obj, key, calc)
-// exports._bindDir(el, name, data)
-describe.skip('watch key or props', () => {
- let vm, cb
- const update = function () { return this.a + this.b }
- const update2 = function () { return this.plus() }
- const callPlus = sinon.spy()
- const methodNames = ['_watch', '_bindKey', '_bindDir']
- beforeEach(() => {
- vm = {
- _data: { a: 1, b: 2 },
- _methods: {
- plus: function () {
- callPlus()
- return this.a + this.b
- }
- },
- _watchers: [],
- _app: {}
- }
- extendVm(vm, methodNames)
- cb = sinon.spy()
- })
- afterEach(() => {
- vm = null
- cb = null
- })
- // - watch update when data source changed
- it('watch simple exp', () => {
- vm._watch(update, cb)
- const value = update.call(vm)
- expect(cb).not.called
- expect(value).equal(3)
- vm.a = 2
- expect(vm._data).eql({ a: 2, b: 2 })
- expect(cb).calledOnce
- expect(cb).calledOn(undefined)
- expect(cb).calledWith(4)
- vm.b = 3
- expect(vm._data).eql({ a: 2, b: 3 })
- expect(cb).calledTwice
- expect(cb).calledWith(5)
- })
-
- // - update object key-value when data source changed
- it('watch k-v pairs', () => {
- const el = { attr: { c: 3 }}
- initElement(el)
- const attr = el.attr
- vm._bindKey = directive._bindKey
- vm._bindKey(el, 'attr', 'd', update)
- expect(attr.d).equal(3)
- vm.a = 2
- expect(vm._data).eql({ a: 2, b: 2 })
- expect(attr.d).equal(4)
- vm.b = 3
- expect(vm._data).eql({ a: 2, b: 3 })
- expect(attr.d).equal(5)
- })
- // - update prop value when data source changed
- it('watch element props', () => {
- const el = { attr: { c: 3 }}
- initElement(el)
- vm._bindDir(el, 'attr', { d: 4, e: update, f: update2 })
- expect(el.attr).eql({ c: 3, d: 4, e: 3, f: 3 })
- expect(callPlus).calledOnce
- vm.a = 2
- expect(vm._data).eql({ a: 2, b: 2 })
- expect(el.attr).eql({ c: 3, d: 4, e: 4, f: 4 })
- expect(callPlus).calledTwice
- vm.b = 3
- expect(vm._data).eql({ a: 2, b: 3 })
- expect(el.attr).eql({ c: 3, d: 4, e: 5, f: 5 })
- expect(callPlus).calledThird
- })
-})
-
describe('apply component options', () => {
it('apply top prop', () => {
nativeComponentMap['test-apply'] = {
@@ -177,207 +99,6 @@ describe('apply component options', () => {
})
})
-// exports._setId(id, el, vm) ?
-// exports._setAttr(el, attr)
-// exports._setClass(el, classList)
-// exports._setStyle(el, style)
-describe.skip('set props', () => {
- let vm, el
- const update = function () { return this.a + this.b }
- const methodNames = [
- '_watch', '_bindKey', '_bindDir',
- '_setId', '_setAttr', '_setClass', '_setStyle',
- '_setEvent', '_bindEvents', '_bindElement']
-
- before(() => {
- sinon.stub(console, 'info')
- sinon.stub(console, 'warn')
- sinon.stub(console, 'error')
- })
-
- after(() => {
- console.info.restore()
- console.warn.restore()
- console.error.restore()
- })
-
- beforeEach(() => {
- el = {
- attr: {}, style: {}
- }
- initElement(el)
- vm = {
- _ids: {},
- _options: {
- style: {
- x: { e: 0, f: 5 },
- y: { f: 6 },
- z: { e: 10 }
- }
- },
- _data: { a: 1, b: 2, classNameVar: 'x', idVar: 'n' },
- _methods: {},
- _watchers: [],
- _app: {}
- }
- extendVm(vm, methodNames)
- })
- afterEach(() => {
- el = null
- vm = null
- })
- // - set value to id
- it('set value to id', () => {
- const targetVm = {}
- vm._setId('m', el, targetVm)
- expect(vm._ids).a('object')
- expect(vm._ids.m).a('object')
- expect(vm._ids.m.el).equal(el)
- expect(vm._ids.m.vm).equal(targetVm)
- })
- // - set function to id
- it('set function to id', () => {
- const targetVm = {}
- vm._setId(function () { return this.idVar }, el, targetVm)
- expect(vm._ids.n).a('object')
- expect(vm._ids.n.el).equal(el)
- expect(vm._ids.n.vm).equal(targetVm)
- vm.idVar = 'l'
- expect(vm._ids.l).a('object')
- expect(vm._ids.l.el).equal(el)
- expect(vm._ids.l.vm).equal(targetVm)
- })
- // - set value to attr
- // - set function to attr
- it('set value to attr', () => {
- vm._setAttr(el, { c: 1, d: update })
- expect(el.attr).eql({ c: 1, d: 3 })
- })
- // - set value to class
- it('set value to classList', () => {
- vm._setClass(el, [])
- expect(el.classStyle).eql({})
- vm._setClass(el, ['x', 'y'])
- expect(el.classStyle).eql({ e: 0, f: 6 })
- vm._setClass(el, [])
- expect(el.classStyle).eql({})
- })
- // - set value to class with another class order
- it('set value to classList with another class order', () => {
- vm._setClass(el, ['y', 'x'])
- expect(el.classStyle).eql({ e: 0, f: 5 })
- })
- // - set a function to class
- it('set a function to classList', () => {
- vm._setClass(el, function () {
- return [this.classNameVar, 'y']
- })
- expect(el.classStyle).eql({ e: 0, f: 6 })
- vm.classNameVar = 'z'
- expect(el.classStyle).eql({ e: 10, f: 6 })
- })
- // - set value to style
- // - set function to style
- it('set value to style', () => {
- vm._setStyle(el, { c: 1, d: update })
- expect(el.style).eql({ c: 1, d: 3 })
- })
-
- it('bind elements', () => {
- // _data: a, b, classNameVar, idVar
- // _css: {
- // x: {e: 0, f: 5},
- // y: {f: 6},
- // z: {e: 10}
- // },
- el.event = {}
-
- vm._bindElement(el, {
- id: 'abc',
- attr: {
- a: function () { return this.a },
- b: 456
- },
- style: {
- a: 123,
- b: function () { return this.b }
- },
- events: { click: 'foo' }
- })
- expect(vm._ids).a('object')
- expect(vm._ids.abc).a('object')
- expect(vm._ids.abc.el).equal(el)
- expect(vm._ids.abc.vm).equal(vm)
- expect(el.attr.a).eql(1)
- expect(el.attr.b).eql(456)
- expect(el.style.a).eql(123)
- expect(el.style.b).eql(2)
- expect(el.event.click).a('function')
- })
-})
-
-// exports._bindEvents(el, events)
-describe.skip('bind events', () => {
- let vm, el, cb
- const app = {}
- const methodNames = ['_setEvent', '_bindEvents']
-
- beforeEach(() => {
- cb = sinon.spy()
- el = { event: {}}
- initElement(el)
-
- vm = {
- _data: { a: 1 },
- _methods: {
- foo: cb
- },
- _app: app
- }
-
- extendVm(vm, methodNames)
- })
- afterEach(() => {
- vm = null
- el = null
- cb = null
- })
-
- // - bind method to eventManager
- it('add event to manager by type', () => {
- vm._bindEvents(el, { click: 'foo' })
- expect(el.event.click).a('function')
- })
- // - bind method to eventManager
- it('add event to manager by handler', () => {
- const cb2 = sinon.spy()
- vm._bindEvents(el, { click: cb2 })
- expect(el.event.click).a('function')
- })
- // - fireEvent to call method
- // - with right event info
- it('fire event from manager by type', () => {
- const e = {}
- vm._bindEvents(el, { click: 'foo' })
- el.event.click(e)
- expect(cb).calledOnce
- expect(cb).calledOn(vm)
- expect(cb).calledWith(e)
- })
- // - fireEvent to call method
- // - with right event info
- it('fire event from manager by handler', () => {
- const e = {}
- vm._bindEvents(el, { click: function ($event) {
- this.foo(this.a, $event)
- } })
- el.event.click(e)
- expect(cb).calledOnce
- expect(cb).calledOn(vm)
- expect(cb).calledWith(1, e)
- })
-})
-
// exports._bindSubVm(subVm, template)
describe('bind external infomations to sub vm', () => {
let vm, subVm
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e13c860/html5/test/unit/runtime/legacy-framework.js
----------------------------------------------------------------------
diff --git a/html5/test/unit/runtime/legacy-framework.js b/html5/test/unit/runtime/legacy-framework.js
new file mode 100644
index 0000000..b25d14d
--- /dev/null
+++ b/html5/test/unit/runtime/legacy-framework.js
@@ -0,0 +1,353 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import chai from 'chai'
+import sinon from 'sinon'
+import sinonChai from 'sinon-chai'
+const {
+ expect
+} = chai
+chai.use(sinonChai)
+
+import runtime from '../../../runtime'
+import frameworks from '../../../frameworks'
+import defaultConfig from '../../../frameworks/legacy/config'
+import { init as resetTaskHandler } from '../../../runtime/bridge/TaskCenter'
+
+const { init, config } = runtime
+config.frameworks = frameworks
+runtime.setNativeConsole()
+
+import Vm from '../../../frameworks/legacy/vm'
+import { clearModules, getModule } from '../../../frameworks/legacy/app/register'
+
+const framework = init(config)
+
+function clearRefs (json) {
+ delete json.ref
+ if (json.children) {
+ json.children.forEach(clearRefs)
+ }
+}
+
+describe('framework entry', () => {
+ const oriCallNative = global.callNative
+ const oriCallAddElement = global.callAddElement
+ const oriDocumentHandler = config.Document.handler
+ const callNativeSpy = sinon.spy()
+ const callAddElementSpy = sinon.spy()
+ const documentHandlerSpy = sinon.spy()
+ const instanceId = Date.now() + ''
+
+ before(() => {
+ global.callNative = (id, tasks, callbackId) => {
+ callNativeSpy(id, tasks, callbackId)
+ /* istanbul ignore if */
+ if (callbackId !== '-1') {
+ framework.callJS(id, [{
+ method: 'callback',
+ args: [callbackId, null, true]
+ }])
+ }
+ }
+ global.callAddElement = (name, id, ref, json, index, callbackId) => {
+ callAddElementSpy(name, ref, json, index, callbackId)
+ /* istanbul ignore if */
+ if (callbackId !== '-1') {
+ framework.callJS(id, [{
+ method: 'callback',
+ args: [callbackId, null, true]
+ }])
+ }
+ }
+ config.Document.handler = oriDocumentHandler
+ resetTaskHandler()
+ })
+
+ afterEach(() => {
+ callNativeSpy.reset()
+ callAddElementSpy.reset()
+ documentHandlerSpy.reset()
+ })
+
+ after(() => {
+ config.Document.handler = oriDocumentHandler
+ global.callNative = oriCallNative
+ global.callAddElement = oriCallAddElement
+ })
+
+ describe('createInstance', () => {
+ it('a simple bundle', () => {
+ const code = `
+ define('@weex-component/main',
+ function(require, exports, module) {
+ module.exports = {
+ data: function() {
+ return {
+ text: 'Hello World',
+ showText: true
+ };
+ }
+ }
+
+ ;module.exports.style = {}
+
+ ;module.exports.template = {
+ 'type': 'container',
+ 'children': [{
+ 'type': 'text',
+ 'shown': function() {
+ return this.showText
+ },
+ 'attr': {
+ 'value': function() {
+ return this.text
+ }
+ }
+ }]
+ }
+ }
+ )
+
+ bootstrap('@weex-component/main')
+ `
+ framework.createInstance(instanceId, code)
+ expect(callNativeSpy.callCount).to.be.equal(2)
+ expect(callAddElementSpy.callCount).to.be.equal(1)
+
+ expect(callNativeSpy.firstCall.args[0]).to.be.equal(instanceId)
+ expect(callNativeSpy.firstCall.args[1]).to.deep.equal([{
+ module: 'dom',
+ method: 'createBody',
+ args: [{
+ ref: '_root',
+ type: 'container',
+ attr: {},
+ style: {}
+ }]
+ }])
+ // expect(callNativeSpy.firstCall.args[2]).to.not.equal('-1')
+
+ expect(callAddElementSpy.firstCall.args[0]).to.be.equal(instanceId)
+ delete callAddElementSpy.firstCall.args[1].ref
+ expect(callAddElementSpy.firstCall.args[1]).to.deep.equal({
+ type: 'text',
+ attr: { value: 'Hello World' },
+ style: {}
+ })
+
+ // expect(callNativeSpy.secondCall.args[2]).to.not.equal('-1')
+
+ expect(callNativeSpy.secondCall.args[0]).to.be.equal(instanceId)
+ expect(callNativeSpy.secondCall.args[1]).to.deep.equal([{
+ module: 'dom',
+ method: 'createFinish',
+ args: []
+ }])
+ // expect(callNativeSpy.thirdCall.args[2]).to.not.equal('-1')
+ })
+
+ it('with a exist instanceId', () => {
+ const code = ''
+ const result = framework.createInstance(instanceId, code)
+ expect(result).to.be.an.instanceof(Error)
+ })
+ })
+
+ describe('getRoot', () => {
+ it('with a exist instanceId', () => {
+ const json = framework.getRoot(instanceId)
+ expect(json.ref).eql('_root')
+ clearRefs(json)
+ const expectJSON = {
+ type: 'container',
+ attr: {},
+ style: {},
+ children: [{
+ type: 'text',
+ attr: {
+ value: 'Hello World'
+ },
+ style: {}
+ }]
+ }
+ expect(json).to.be.deep.equal(expectJSON)
+ })
+
+ it('with a non-exist instanceId', () => {
+ const result = framework.getRoot('123')
+ expect(result).to.be.an.instanceof(Error)
+ })
+ })
+
+ describe('callJS', () => {
+ it('fireEvent with no params', () => {
+ framework.callJS()
+ })
+
+ it('fireEvent with a exist instanceId', () => {
+ framework.callJS(instanceId, [{
+ method: 'fireEvent',
+ args: []
+ }])
+ })
+
+ it('callback with a exist instanceId', () => {
+ framework.callJS(instanceId, [{
+ method: 'callback',
+ args: []
+ }])
+ })
+
+ it('with a non-exist instanceId', () => {
+ const result = framework.callJS('123', [{
+ method: 'fireEvent',
+ args: []
+ }])
+ expect(result).to.be.an.instanceof(Error)
+ })
+
+ it('with a non-array tasks', () => {
+ const result = framework.callJS(instanceId, {
+ method: 'fireEvent',
+ args: []
+ })
+ expect(result).to.be.an.instanceof(Error)
+ })
+ })
+
+ describe('refreshInstance', () => {
+ it('modify showText to false', () => {
+ const json = framework.getRoot(instanceId)
+ const textRef = json.children[0].ref
+ framework.refreshInstance(instanceId, { showText: false })
+ expect(callNativeSpy.callCount).to.be.equal(2)
+ expect(callNativeSpy.firstCall.args[0]).to.be.equal(instanceId)
+ expect(callNativeSpy.firstCall.args[1]).to.deep.equal([{
+ module: 'dom',
+ method: 'removeElement',
+ args: [textRef]
+ }])
+ // expect(callNativeSpy.firstCall.args[2]).to.be.equal('-1')
+
+ expect(callNativeSpy.secondCall.args[0]).to.be.equal(instanceId)
+ expect(callNativeSpy.secondCall.args[1]).to.deep.equal([{
+ module: 'dom',
+ method: 'refreshFinish',
+ args: []
+ }])
+ // expect(callNativeSpy.secondCall.args[2]).to.be.equal('-1')
+ })
+
+ it('with a non-exist instanceId', () => {
+ const result = framework.refreshInstance('123', {})
+ expect(result).to.be.an.instanceof(Error)
+ })
+ })
+
+ describe('destroyInstance', () => {
+ it('with no params', () => {
+ framework.destroyInstance()
+ })
+
+ it('with a exist instanceId', () => {
+ const result = framework.destroyInstance(instanceId)
+ expect(result[instanceId]).to.be.undefined
+ })
+
+ it('with a non-exist instanceId', () => {
+ const result = framework.destroyInstance('123')
+ expect(result).to.be.an.instanceof(Error)
+ })
+ })
+
+ describe('registerComponents', () => {
+ it('with old format', () => {
+ framework.registerComponents(['a', 'b', 'c'])
+ expect(defaultConfig.nativeComponentMap).to.contain.keys('a', 'b', 'c')
+ })
+
+ it('with new format', () => {
+ framework.registerComponents([{
+ type: 'd',
+ append: 'tree'
+ }])
+ expect(defaultConfig.nativeComponentMap).to.contain.keys('d')
+ expect(defaultConfig.nativeComponentMap['d']).to.be.deep.equal({
+ type: 'd',
+ append: 'tree'
+ })
+ })
+
+ it('with non-array', () => {
+ framework.registerComponents({
+ type: 'e'
+ })
+ expect(defaultConfig.nativeComponentMap).not.contain.keys('e')
+ })
+
+ it('with methods', () => {
+ const components = [{
+ type: 'x',
+ methods: ['foo', 'bar']
+ }, {
+ type: 'y',
+ methods: []
+ }, {
+ type: 'z',
+ methods: null
+ }]
+ framework.registerComponents(components)
+ expect(defaultConfig.nativeComponentMap).to.contain.keys('x', 'y', 'z')
+ })
+ })
+
+ describe('register modules', () => {
+ it('with object of modules', () => {
+ clearModules()
+ const modules = {
+ a: [{
+ name: 'b',
+ args: ['string']
+ }]
+ }
+
+ framework.registerModules(modules)
+ expect(getModule('b')).an.object
+ clearModules()
+ })
+ })
+
+ describe('register methods', () => {
+ it('with object of methods', () => {
+ const methods = {
+ a: sinon.spy()
+ }
+
+ framework.registerMethods(methods)
+ expect(Vm.prototype.a).a.function
+ delete Vm.prototype.a
+ })
+ })
+})
+
+describe('config', () => {
+ it('config is an object', () => {
+ init({})
+ })
+})
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e13c860/html5/test/unit/runtime/vdom/directive.js
----------------------------------------------------------------------
diff --git a/html5/test/unit/runtime/vdom/directive.js b/html5/test/unit/runtime/vdom/directive.js
new file mode 100644
index 0000000..6c9109b
--- /dev/null
+++ b/html5/test/unit/runtime/vdom/directive.js
@@ -0,0 +1,82 @@
+import { expect } from 'chai'
+import { filterDirective } from '../../../../runtime/vdom/directive'
+
+describe('filterDirective', () => {
+ it('other type', () => {
+ expect(filterDirective(0)).to.be.equal(0)
+ expect(filterDirective(53)).to.be.equal(53)
+ expect(filterDirective(null)).to.be.equal(null)
+ const reg = /\w+/i
+ expect(filterDirective(reg)).to.be.equal(reg)
+ })
+
+ it('normal string', () => {
+ expect(filterDirective('')).to.be.equal('')
+ expect(filterDirective('-1')).to.be.equal('-1')
+ expect(filterDirective('abc')).to.be.equal('abc')
+ expect(filterDirective(' a bc d')).to.be.equal(' a bc d')
+ expect(filterDirective(' a {{ bc }}')).to.be.equal(' a {{ bc }}')
+ })
+
+ it('binding', () => {
+ expect(filterDirective('[[abc]]')).to.deep.equal({ '@binding': 'abc' })
+ expect(filterDirective('[[ xyz ]]')).to.deep.equal({ '@binding': 'xyz' })
+ expect(filterDirective('[[ x y z ]]')).to.deep.equal({ '@binding': 'x y z' })
+ })
+
+ it('binding and normal string', () => {
+ expect(filterDirective('xyz[[abc]]ttt')).to.deep.equal(['xyz', { '@binding': 'abc' }, 'ttt'])
+ expect(filterDirective(' x [[ w ]] t ')).to.deep.equal([' x ', { '@binding': 'w' }, ' t '])
+ expect(filterDirective('[[ wn]][xx{uur}]')).to.deep.equal([{ '@binding': 'wn' }, '[xx{uur}]'])
+ })
+
+ it('multi-binding', () => {
+ expect(filterDirective('[[abc]][[wpc]]')).to.deep.equal([{ '@binding': 'abc' }, { '@binding': 'wpc' }])
+ expect(filterDirective('abcd[[ xyz ]]ef[[w]]gh')).to.deep.equal([
+ 'abcd',
+ { '@binding': 'xyz' },
+ 'ef',
+ { '@binding': 'w' },
+ 'gh'
+ ])
+ expect(filterDirective(' a [[ b ]] [[c]] d [[e]][[f]]g')).to.deep.equal([
+ ' a ',
+ { '@binding': 'b' },
+ ' ',
+ { '@binding': 'c' },
+ ' d ',
+ { '@binding': 'e' },
+ { '@binding': 'f' },
+ 'g'
+ ])
+ })
+
+ it('parse object', () => {
+ expect(filterDirective({ key: '[[x]]' })).to.deep.equal({ key: { '@binding': 'x' }})
+ expect(filterDirective({ a: '[[A]]', b: '[[B]]' })).to.deep.equal({
+ a: { '@binding': 'A' },
+ b: { '@binding': 'B' }
+ })
+ expect(filterDirective({
+ a: '[[A]]',
+ x: 'X',
+ y: {
+ b: ' - [[B]] - ',
+ z: {
+ c: ['[[C]] + [[C]]', 'cc'],
+ w: 24
+ }
+ }
+ })).to.deep.equal({
+ a: { '@binding': 'A' },
+ x: 'X',
+ y: {
+ b: [' - ', { '@binding': 'B' }, ' - '],
+ z: {
+ c: [[{ '@binding': 'C' }, ' + ', { '@binding': 'C' }], 'cc'],
+ w: 24
+ }
+ }
+ })
+ })
+})
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/9e13c860/html5/test/unit/runtime/vdom/index.js
----------------------------------------------------------------------
diff --git a/html5/test/unit/runtime/vdom/index.js b/html5/test/unit/runtime/vdom/index.js
new file mode 100644
index 0000000..c79bcf6
--- /dev/null
+++ b/html5/test/unit/runtime/vdom/index.js
@@ -0,0 +1,639 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import chai from 'chai'
+import sinon from 'sinon'
+import sinonChai from 'sinon-chai'
+const { expect } = chai
+chai.use(sinonChai)
+
+import {
+ Document,
+ Element,
+ Comment,
+ isWeexElement,
+ registerElement,
+ clearWeexElements
+} from '../../../../runtime/vdom'
+
+describe('document constructor', () => {
+ it('create & destroy document', () => {
+ const doc = new Document('foo', 'http://path/to/url')
+ expect(doc).is.an.object
+ expect(doc.id).eql('foo')
+ expect(doc.URL).eql('http://path/to/url')
+ expect(doc.documentElement).is.an.object
+ expect(doc.documentElement.role).equal('documentElement')
+ doc.destroy()
+ })
+})
+
+describe('component methods management', () => {
+ before(() => {
+ registerElement('x', ['foo', 'bar'])
+ registerElement('y', [])
+ registerElement('z')
+ })
+
+ after(() => {
+ clearWeexElements()
+ })
+
+ it('has registered element types', () => {
+ expect(isWeexElement('x')).to.be.true
+ })
+
+ it('will call component method', () => {
+ const spy = sinon.spy()
+ const doc = new Document('test', '', spy)
+ const x = new Element('x')
+ const y = new Element('y')
+ const z = new Element('z')
+ const n = new Element('n')
+ expect(x.foo).is.function
+ expect(x.bar).is.function
+ expect(x.baz).is.undefined
+ expect(y.foo).is.undefined
+ expect(z.foo).is.undefined
+ expect(n.foo).is.undefined
+
+ doc.createBody('r')
+ doc.documentElement.appendChild(doc.body)
+ doc.body.appendChild(x)
+ doc.body.appendChild(y)
+ doc.body.appendChild(z)
+ doc.body.appendChild(n)
+ expect(spy.args.length).eql(5)
+
+ x.foo(1, 2, 3)
+ expect(spy.args.length).eql(6)
+ expect(spy.args[5]).eql([[{ component: 'x', method: 'foo', ref: x.ref, args: [1, 2, 3] }]])
+ })
+})
+
+describe('document methods', () => {
+ let doc
+
+ beforeEach(() => {
+ doc = new Document('foo', null, function () {})
+ })
+
+ afterEach(() => {
+ doc.destroy()
+ })
+
+ it('open & close with a listener', () => {
+ expect(doc.listener.batched).is.false
+ doc.close()
+ expect(doc.listener.batched).is.true
+ doc.open()
+ expect(doc.listener.batched).is.false
+ })
+
+ it('create body', () => {
+ const ele = doc.createBody('container',
+ { attr: { id: 'a' }, style: { fontSize: 16 }})
+ expect(ele.role).equal('body')
+ expect(ele.attr).to.have.a.property('id', 'a')
+ expect(ele.style).to.have.a.property('fontSize', 16)
+ expect(ele).have.a.property('ref')
+ expect(ele).have.a.property('children')
+ expect(ele).have.a.property('pureChildren')
+ expect(ele).have.a.property('insertBefore')
+ expect(ele).have.a.property('setStyle')
+
+ const ref = ele.ref
+ expect(doc.nodeMap[ref]).equal(ele)
+ })
+
+ it('create element', () => {
+ const ele = doc.createElement('container',
+ { attr: { id: 'a' }, style: { fontSize: 16 }})
+ expect(ele.attr).to.have.a.property('id', 'a')
+ expect(ele.style).to.have.a.property('fontSize', 16)
+ expect(ele).have.a.property('ref')
+ expect(ele).have.a.property('children')
+ expect(ele).have.a.property('pureChildren')
+ expect(ele).have.a.property('insertBefore')
+ expect(ele).have.a.property('setStyle')
+
+ expect(doc.nodeMap[ele.ref]).is.undefined
+ doc.documentElement.appendChild(ele)
+ expect(doc.nodeMap[ele.ref]).equal(ele)
+ })
+
+ it('create comment', () => {
+ const comment = doc.createComment('start')
+ expect(comment).have.a.property('ref')
+ expect(comment).not.have.a.property('appendChild')
+ expect(comment).have.a.property('value', 'start')
+ expect(comment.toString()).eql('<!-- start -->')
+
+ const ref = comment.ref
+ expect(doc.nodeMap[ref]).is.undefined
+ doc.documentElement.appendChild(comment)
+ expect(doc.nodeMap[ref]).equal(comment)
+ })
+})
+
+describe('Element in document methods', () => {
+ let doc, el, el2, el3
+
+ beforeEach(() => {
+ doc = new Document('foo', null, function () {})
+ el = new Element('bar', {
+ attr: { a: 11, b: 12 },
+ style: { c: 13, d: 14 },
+ classStyle: { a: 211, c: 213 }
+ })
+ el2 = new Element('baz', {
+ attr: { a: 21, b: 22 },
+ style: { c: 23, d: 24 },
+ classStyle: { a: 221, c: 223 }
+ })
+ el3 = new Element('qux', {
+ attr: { a: 31, b: 32 },
+ style: { c: 33, d: 34 },
+ classStyle: { a: 231, c: 233 }
+ })
+ })
+
+ afterEach(() => {
+ doc.destroy()
+ })
+
+ it('init correctly', () => {
+ expect(el).is.an.object
+ expect(el.type).eql('bar')
+ expect(el.attr).eql({ a: 11, b: 12 })
+ expect(el.style).eql({ c: 13, d: 14 })
+ expect(el.event).eql({})
+ expect(el.children).eql([])
+ expect(el.pureChildren).eql([])
+ expect(doc.nodeMap).is.an.object
+ expect(doc.documentElement).is.an.object
+ expect(Object.keys(doc.nodeMap)).eql([doc.documentElement.ref])
+ doc.documentElement.appendChild(el)
+ doc.documentElement.appendChild(el2)
+ el2.appendChild(el3)
+ expect(Object.keys(doc.nodeMap)).eql([
+ doc.documentElement.ref,
+ el.ref
+ ])
+ })
+
+ it('has correct exports', () => {
+ const ref = el.ref
+ const finalStyle = el.toStyle()
+ expect(finalStyle).eql({ a: 211, c: 13, d: 14 })
+ expect(el.toJSON()).eql({
+ ref: ref, type: 'bar',
+ attr: el.attr, style: finalStyle
+ })
+ expect(el.toString()).eql(
+ '<bar attr={"a":11,"b":12} style={"a":211,"c":13,"d":14}></bar>')
+ })
+
+ it('createBody', () => {
+ doc.createBody('r')
+ doc.documentElement.appendChild(doc.body)
+ expect(doc.body).is.an.object
+ expect(doc.body.role).eql('body')
+ expect(doc.body.type).eql('r')
+ expect(doc.body.docId).eql('foo')
+ })
+
+ it('appendChild', () => {
+ el.appendChild(el2)
+ expect(el.children.length).eql(1)
+ expect(el.children[0]).equal(el2)
+ expect(el2.parentNode.ref).eql(el.ref)
+
+ expect(el.docId).is.not.ok
+ expect(el2.docId).is.not.ok
+
+ doc.createBody('r')
+ doc.documentElement.appendChild(doc.body)
+ doc.body.appendChild(el)
+ expect(doc.body.children.length).eql(1)
+ expect(el.parentNode.ref).eql(doc.body.ref)
+ expect(el.docId).is.ok
+ expect(el2.docId).is.ok
+
+ expect(el3.docId).is.not.ok
+ el.appendChild(el3)
+ expect(el.children.length).eql(2)
+ expect(el.children[0]).equal(el2)
+ expect(el.children[1]).equal(el3)
+ expect(el3.parentNode.ref).eql(el.ref)
+ expect(el3.docId).is.ok
+
+ expect(el2.previousSibling).is.not.ok
+ expect(el2.nextSibling).eql(el3)
+ expect(el3.previousSibling).eql(el2)
+ expect(el3.nextSibling).is.not.ok
+ })
+
+ it('insertBefore', () => {
+ doc.createBody('r')
+ doc.documentElement.appendChild(doc.body)
+ doc.body.appendChild(el)
+ expect(el.parentNode.ref).eql(doc.body.ref)
+
+ el.appendChild(el2)
+ expect(el2.parentNode.ref).eql(el.ref)
+ expect(el.children.length).eql(1)
+ expect(el.children[0]).equal(el2)
+
+ el.insertBefore(el3, el2)
+ expect(el.children.length).eql(2)
+ expect(el.children[0]).equal(el3)
+ expect(el.children[1]).equal(el2)
+ expect(el3.parentNode.ref).eql(el.ref)
+
+ expect(el.docId).eql('foo')
+ expect(el2.docId).eql('foo')
+ expect(el3.docId).eql('foo')
+
+ expect(el3.previousSibling).is.not.ok
+ expect(el3.nextSibling).eql(el2)
+ expect(el2.previousSibling).eql(el3)
+ expect(el2.nextSibling).is.not.ok
+
+ el.insertBefore(el2, el3)
+ expect(el.children.length).eql(2)
+ expect(el.children[0]).equal(el2)
+ expect(el.children[1]).equal(el3)
+
+ expect(el.docId).eql('foo')
+ expect(el2.docId).eql('foo')
+ expect(el3.docId).eql('foo')
+
+ expect(el2.previousSibling).is.not.ok
+ expect(el2.nextSibling).eql(el3)
+ expect(el3.previousSibling).eql(el2)
+ expect(el3.nextSibling).is.not.ok
+ })
+
+ it('insertAfter', () => {
+ doc.createBody('r')
+ doc.documentElement.appendChild(doc.body)
+ doc.body.appendChild(el)
+ expect(el.parentNode.ref).eql(doc.body.ref)
+
+ el.appendChild(el2)
+ el.insertAfter(el3, el2)
+ expect(el.children.length).eql(2)
+ expect(el.children[0]).equal(el2)
+ expect(el.children[1]).equal(el3)
+ expect(el2.parentNode.ref).eql(el.ref)
+ expect(el3.parentNode.ref).eql(el.ref)
+
+ expect(el.docId).eql('foo')
+ expect(el2.docId).eql('foo')
+ expect(el3.docId).eql('foo')
+
+ expect(el2.previousSibling).is.not.ok
+ expect(el2.nextSibling).eql(el3)
+ expect(el3.previousSibling).eql(el2)
+ expect(el3.nextSibling).is.not.ok
+
+ el.insertAfter(el2, el3, true)
+ expect(el.children.length).eql(2)
+ expect(el.children[0]).equal(el3)
+ expect(el.children[1]).equal(el2)
+
+ expect(el3.previousSibling).is.not.ok
+ expect(el3.nextSibling).eql(el2)
+ expect(el2.previousSibling).eql(el3)
+ expect(el2.nextSibling).is.not.ok
+ })
+
+ it('removeChild', () => {
+ doc.createBody('r')
+ doc.documentElement.appendChild(doc.body)
+ doc.body.appendChild(el)
+ doc.body.appendChild(el2)
+ el2.appendChild(el3)
+
+ expect(el.docId).eql('foo')
+ expect(el2.docId).eql('foo')
+ expect(el3.docId).eql('foo')
+ doc.body.removeChild(el)
+ expect(doc.body.children.length).equal(1)
+ expect(doc.body.children[0]).equal(el2)
+ expect(el.docId).is.not.ok
+ expect(el2.docId).eql('foo')
+ expect(el3.docId).eql('foo')
+ doc.body.removeChild(el2)
+ expect(doc.body.children.length).equal(0)
+ expect(el.docId).is.not.ok
+ expect(el2.docId).is.not.ok
+ expect(el3.docId).is.not.ok
+ })
+
+ it('clear', () => {
+ doc.createBody('r')
+ doc.documentElement.appendChild(doc.body)
+ doc.body.appendChild(el)
+ doc.body.appendChild(el2)
+ doc.body.appendChild(el3)
+
+ expect(el.docId).eql('foo')
+ expect(el2.docId).eql('foo')
+ expect(el3.docId).eql('foo')
+
+ doc.body.clear()
+ expect(doc.body.children.length).equal(0)
+ expect(el.docId).is.not.ok
+ expect(el2.docId).is.not.ok
+ expect(el3.docId).is.not.ok
+ })
+
+ it('modify attr, style, event', () => {
+ doc.createBody('r')
+ doc.documentElement.appendChild(doc.body)
+ doc.body.appendChild(el)
+
+ el.setAttr('a', 21)
+ expect(el.toJSON().attr).eql({ a: 21, b: 12 })
+ el.setAttr('a', 22, true)
+ expect(el.toJSON().attr).eql({ a: 22, b: 12 })
+ el.setAttr('a', 23, false)
+ expect(el.toJSON().attr).eql({ a: 23, b: 12 })
+
+ el.setStyle('c', 21)
+ expect(el.toJSON().style).eql({ a: 211, c: 21, d: 14 })
+ el.setStyle('c', 22, true)
+ expect(el.toJSON().style).eql({ a: 211, c: 22, d: 14 })
+ el.setStyle('c', 23, false)
+ expect(el.toJSON().style).eql({ a: 211, c: 23, d: 14 })
+
+ el.setClassStyle({ a: 311, c: 313 })
+ expect(el.toJSON().style).eql({ a: 311, c: 23, d: 14 })
+
+ const handler = function () {}
+ el.addEvent('click', handler)
+ expect(el.toJSON().event).eql(['click'])
+ expect(el.event.click).equal(handler)
+ el.removeEvent('click')
+ expect(el.event.click).is.undefined
+ })
+})
+
+describe('Node', () => {
+ let doc, el, el2, el3, c, c2, c3, spy
+
+ beforeEach(() => {
+ spy = sinon.spy()
+ doc = new Document('foo', '', spy)
+ doc.createBody('r')
+ doc.documentElement.appendChild(doc.body)
+ el = new Element('bar')
+ el2 = new Element('baz')
+ el3 = new Element('qux')
+ c = new Comment('aaa')
+ c2 = new Comment('bbb')
+ c3 = new Comment('ccc')
+ })
+
+ afterEach(() => {
+ doc.destroy()
+ })
+
+ it('prev and next', () => {
+ expect(el.previousSibling).is.not.ok
+ expect(el.nextSibling).is.not.ok
+
+ doc.body.appendChild(el)
+ doc.body.appendChild(el2)
+ doc.body.appendChild(c)
+ doc.body.appendChild(el3)
+ doc.body.appendChild(c2)
+ doc.body.appendChild(c3)
+
+ expect(el.previousSibling).is.not.ok
+ expect(el2.previousSibling).equal(el)
+ expect(c.previousSibling).equal(el2)
+ expect(el3.previousSibling).equal(c)
+ expect(c2.previousSibling).equal(el3)
+ expect(c3.previousSibling).equal(c2)
+
+ expect(el.nextSibling).equal(el2)
+ expect(el2.nextSibling).equal(c)
+ expect(c.nextSibling).equal(el3)
+ expect(el3.nextSibling).equal(c2)
+ expect(c2.nextSibling).equal(c3)
+ expect(c3.nextSibling).is.not.ok
+ })
+
+ it('tree operations with renderer', () => {
+ doc.body.appendChild(el)
+ el.appendChild(el2)
+ el.appendChild(el3)
+
+ expect(spy.args.length).eql(4)
+ el.insertBefore(el3, el2) // [el3, el2]
+ expect(spy.args.length).eql(5)
+ expect(spy.args[4][0]).eql([{
+ module: 'dom', method: 'moveElement',
+ args: [el3.ref, el.ref, 0]
+ }])
+ el.insertAfter(el3, el2) // [el2, el3]
+ expect(spy.args.length).eql(6)
+ expect(spy.args[5][0]).eql([{
+ module: 'dom', method: 'moveElement',
+ args: [el3.ref, el.ref, 2]
+ }])
+ el.removeChild(el2) // [el3]
+ expect(spy.args.length).eql(7)
+ expect(spy.args[6][0]).eql([{
+ module: 'dom', method: 'removeElement',
+ args: [el2.ref]
+ }])
+ el.clear() // []
+ expect(spy.args.length).eql(8)
+ expect(spy.args[7][0]).eql([{
+ module: 'dom', method: 'removeElement',
+ args: [el3.ref]
+ }])
+ })
+})
+
+describe('complicated situations', () => {
+ let doc, el, el2, el3, c, c2, c3, spy
+
+ beforeEach(() => {
+ spy = sinon.spy()
+ doc = new Document('foo', '', spy)
+ doc.createBody('r')
+ doc.documentElement.appendChild(doc.body)
+ el = new Element('bar')
+ el2 = new Element('baz')
+ el3 = new Element('qux')
+ c = new Comment('aaa')
+ c2 = new Comment('bbb')
+ c3 = new Comment('ccc')
+ })
+
+ afterEach(() => {
+ doc.destroy()
+ })
+
+ it('move a node to its original position', () => {
+ doc.body.appendChild(el)
+ doc.body.appendChild(el2)
+ doc.body.appendChild(el3)
+
+ expect(spy.args.length).eql(4)
+ expect(doc.body.children).eql([el, el2, el3])
+ expect(doc.body.pureChildren).eql([el, el2, el3])
+
+ doc.body.insertAfter(el2, el)
+ expect(spy.args.length).eql(4)
+ expect(doc.body.children).eql([el, el2, el3])
+ expect(doc.body.pureChildren).eql([el, el2, el3])
+
+ doc.body.insertAfter(el3, el2, true)
+ expect(spy.args.length).eql(4)
+ expect(doc.body.children).eql([el, el2, el3])
+ expect(doc.body.pureChildren).eql([el, el2, el3])
+
+ doc.body.insertBefore(el, el2)
+ expect(spy.args.length).eql(4)
+ expect(doc.body.children).eql([el, el2, el3])
+ expect(doc.body.pureChildren).eql([el, el2, el3])
+
+ doc.body.insertBefore(el2, el3, true)
+ expect(spy.args.length).eql(4)
+ expect(doc.body.children).eql([el, el2, el3])
+ expect(doc.body.pureChildren).eql([el, el2, el3])
+
+ doc.body.insertAfter(c, el)
+ doc.body.insertAfter(c2, el2)
+ doc.body.insertAfter(c3, el3)
+ expect(spy.args.length).eql(4)
+ expect(doc.body.children).eql([el, c, el2, c2, el3, c3])
+ expect(doc.body.pureChildren).eql([el, el2, el3])
+
+ doc.body.insertBefore(el, c)
+ doc.body.insertBefore(el, c, true)
+ doc.body.insertBefore(c, el2)
+ doc.body.insertBefore(c, el2, true)
+ doc.body.insertAfter(c, el)
+ doc.body.insertAfter(c, el, true)
+ doc.body.insertAfter(el2, c)
+ doc.body.insertAfter(el2, c, true)
+ expect(spy.args.length).eql(4)
+ expect(doc.body.children).eql([el, c, el2, c2, el3, c3])
+ expect(doc.body.pureChildren).eql([el, el2, el3])
+
+ // move to another place that not change the pureChildren
+ doc.body.insertBefore(el, el2)
+ expect(spy.args.length).eql(4)
+ expect(doc.body.children).eql([c, el, el2, c2, el3, c3])
+ expect(doc.body.pureChildren).eql([el, el2, el3])
+
+ doc.body.insertBefore(el, c)
+ expect(spy.args.length).eql(4)
+ expect(doc.body.children).eql([el, c, el2, c2, el3, c3])
+ expect(doc.body.pureChildren).eql([el, el2, el3])
+
+ doc.body.insertAfter(c, el2)
+ expect(spy.args.length).eql(4)
+ expect(doc.body.children).eql([el, el2, c, c2, el3, c3])
+ expect(doc.body.pureChildren).eql([el, el2, el3])
+
+ doc.body.insertBefore(c2, c)
+ expect(spy.args.length).eql(4)
+ expect(doc.body.children).eql([el, el2, c2, c, el3, c3])
+ expect(doc.body.pureChildren).eql([el, el2, el3])
+ })
+
+ it('insert before a comment', () => {
+ doc.body.appendChild(el)
+ doc.body.appendChild(c)
+ doc.body.appendChild(c2)
+ doc.body.appendChild(el2)
+ expect(spy.args.length).eql(3)
+ expect(doc.body.children).eql([el, c, c2, el2])
+ expect(doc.body.pureChildren).eql([el, el2])
+
+ doc.body.insertBefore(el3, c)
+ expect(spy.args.length).eql(4)
+ expect(doc.body.children).eql([el, el3, c, c2, el2])
+ expect(doc.body.pureChildren).eql([el, el3, el2])
+ expect(spy.args[3][0]).eql([{
+ module: 'dom', method: 'addElement',
+ args: [doc.body.ref, el3.toJSON(), 1] }])
+ })
+
+ it('insert before a comment which has no more element after', () => {
+ doc.body.appendChild(el)
+ doc.body.appendChild(el2)
+ doc.body.appendChild(c)
+ doc.body.appendChild(c2)
+ expect(spy.args.length).eql(3)
+ expect(doc.body.children).eql([el, el2, c, c2])
+ expect(doc.body.pureChildren).eql([el, el2])
+
+ doc.body.insertBefore(el3, c)
+ expect(spy.args.length).eql(4)
+ expect(doc.body.children).eql([el, el2, el3, c, c2])
+ expect(doc.body.pureChildren).eql([el, el2, el3])
+ expect(spy.args[3][0]).eql([{
+ module: 'dom', method: 'addElement',
+ args: [doc.body.ref, el3.toJSON(), 2] }])
+ })
+
+ it('insert after a comment', () => {
+ doc.body.appendChild(el)
+ doc.body.appendChild(c)
+ doc.body.appendChild(c2)
+ doc.body.appendChild(el2)
+ expect(spy.args.length).eql(3)
+ expect(doc.body.children).eql([el, c, c2, el2])
+ expect(doc.body.pureChildren).eql([el, el2])
+
+ doc.body.insertAfter(el3, c2)
+ expect(spy.args.length).eql(4)
+ expect(doc.body.children).eql([el, c, c2, el3, el2])
+ expect(doc.body.pureChildren).eql([el, el3, el2])
+ expect(spy.args[3][0]).eql([{
+ module: 'dom', method: 'addElement',
+ args: [doc.body.ref, el3.toJSON(), 1] }])
+ })
+
+ it('insert after a comment which has no more element before', () => {
+ doc.body.appendChild(c)
+ doc.body.appendChild(c2)
+ doc.body.appendChild(el)
+ doc.body.appendChild(el2)
+ expect(spy.args.length).eql(3)
+ expect(doc.body.children).eql([c, c2, el, el2])
+ expect(doc.body.pureChildren).eql([el, el2])
+
+ doc.body.insertAfter(el3, c2)
+ expect(spy.args.length).eql(4)
+ expect(doc.body.children).eql([c, c2, el3, el, el2])
+ expect(doc.body.pureChildren).eql([el3, el, el2])
+ expect(spy.args[3][0]).eql([{
+ module: 'dom', method: 'addElement',
+ args: [doc.body.ref, el3.toJSON(), 0] }])
+ })
+})