1/* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20import chai from 'chai'; 21import sinon from 'sinon'; 22import { 23 describe, 24 it 25} from 'mocha'; 26import { 27 fakeLog, 28 fakeLogRestore 29} from '../../fakeLog'; 30import Vm from '../../../runtime/main/model'; 31import Doc from '../../../runtime/vdom/Document'; 32import Differ from '../../../runtime/main/page/api/Differ'; 33 34const expect = chai.expect; 35 36describe('api of communication between vm and data methods', () => { 37 fakeLog(); 38 39 const options = { 40 orientation: 1, 41 width: 1, 42 height: 1, 43 'aspect-ratio': 1, 44 'device-width': 1, 45 'device-height': 1, 46 resolution: 1, 47 accessType: 1 48 }; 49 50 const doc = new Doc('1', ''); 51 const differ = new Differ('test'); 52 const customComponentMap: any = {}; 53 const spyEl = sinon.spy(); 54 55 customComponentMap.parent = { 56 template: { 57 type: 'div', 58 id: 'myDiv', 59 children: [ 60 { 61 type: 'text', 62 id: 'myBar', 63 events: { 64 'click': 'proxyClick' 65 } 66 }, 67 { 68 type: 'child', 69 id: 'myChild' 70 } 71 ] 72 }, 73 proxyClick: function(e) { 74 spyEl(e); 75 } 76 }; 77 78 customComponentMap.child = { 79 template: { 80 type: 'div' 81 } 82 }; 83 84 const page = {doc, customComponentMap, options}; 85 86 const vm = new Vm( 87 'parent', 88 null, 89 { 90 __app: page, 91 __rootVm: true 92 }, 93 null, 94 null, 95 null 96 ); 97 98 const spyParent = sinon.spy(); 99 const spyChild = sinon.spy(); 100 const subVm = vm._childrenVms[0]; 101 vm.$on('event1', spyParent); 102 subVm.$on('event1', spyChild); 103 104 it('$on && $off', () => { 105 const fn = function() {}; 106 vm.$on('event1', fn); 107 expect(vm._vmEvents['event1'].length).eql(2); 108 expect(typeof vm._vmEvents['event1'][1]).eql('function'); 109 110 vm.$off('event1', fn); 111 expect(vm._vmEvents['event1'].length).eql(1); 112 expect(typeof vm._vmEvents['event1'][1]).eql('undefined'); 113 }); 114 115 it('$emit', () => { 116 expect(vm._type).eql('parent'); 117 expect(subVm._type).eql('child'); 118 119 let detail = { lunch: 'banana' }; 120 vm.$emit('event1', detail); 121 expect(spyChild.args.length).eql(0); 122 expect(spyParent.args.length).eql(1); 123 124 detail = { lunch: 'banana' }; 125 subVm.$emit('event1', detail); 126 expect(spyChild.args.length).eql(1); 127 expect(spyParent.args.length).eql(1); 128 }); 129 130 it('$dispatch', () => { 131 const detail = { lunch: 'banana' }; 132 vm.$dispatch('event1', detail); 133 expect(spyParent.args.length).eql(2); 134 expect(spyChild.args.length).eql(1); 135 136 subVm.$dispatch('event1', detail); 137 expect(spyParent.args.length).eql(3); 138 expect(spyChild.args.length).eql(2); 139 }); 140 141 it('$broadCast', () => { 142 const detail = { lunch: 'banana' }; 143 vm.$broadcast('event1', detail); 144 expect(spyParent.args.length).eql(4); 145 expect(spyChild.args.length).eql(3); 146 147 subVm.$broadcast('event1', detail); 148 expect(spyParent.args.length).eql(4); 149 expect(spyChild.args.length).eql(4); 150 }); 151 152 it('$emitDirect', () => { 153 const detail = { lunch: 'banana' }; 154 vm.$emitDirect('event1', detail); 155 expect(spyParent.args.length).eql(5); 156 }); 157 158 it('$emitElement', () => { 159 const detail = { lunch: 'banana' }; 160 vm.$emitElement('click', detail, 'myBar'); 161 sinon.assert.calledOnce(spyEl); 162 expect(spyEl.args.length).eql(1); 163 expect(spyEl.args[0][0].detail).to.deep.equal(detail); 164 }); 165 166 it('$root', () => { 167 expect(subVm.$root()._type).eql('parent'); 168 }); 169 170 it('$parent', () => { 171 expect(subVm.$parent()._type).eql('parent'); 172 }); 173 174 it('$child', () => { 175 expect(vm.$child('myChild')._type).eql('child'); 176 }); 177 178 it('$element', () => { 179 expect(vm.$element('myDiv').type).eql('div'); 180 expect(vm.$element('myChild').type).eql('div'); 181 }); 182 183 it('$set && $delete', () => { 184 const data = { 185 x: 11, 186 y: 22, 187 z: 'test-style' 188 }; 189 customComponentMap.foo = { 190 template: { 191 type: 'test.aaa', 192 children: [{ type: 'type1', component: true }] 193 } 194 }; 195 customComponentMap.bar = { 196 template: { 197 type: 'test.bbb' 198 } 199 }; 200 201 const app = { doc, customComponentMap, differ, options }; 202 const vm = new Vm('foo', customComponentMap.foo, { __app: app, __rootVm: true }, null, data, null); 203 doc.destroy(); 204 const detail = { aaa: 1 }; 205 vm.$set('test.aaa', detail); 206 expect(typeof vm._data['test.aaa']).eql('object'); 207 vm.$delete('test.aaa'); 208 expect(typeof vm._data['test.aaa']).eql('undefined'); 209 }); 210 211 it('$watch', () => { 212 const data = { 213 x: { 214 y: 1 215 } 216 }; 217 customComponentMap.foo = { 218 template: { 219 type: 'div' 220 }, 221 data: data 222 }; 223 224 const app = { doc, customComponentMap, differ, options }; 225 const vm = new Vm('foo', customComponentMap.foo, { __app: app, __rootVm: true }, null, data, null); 226 expect(vm._app).to.deep.equal(app); 227 expect(typeof doc.body).eql('object'); 228 229 data.x.y = 5; 230 vm.$watch('x.y', (value) => { 231 expect(value).eql(5); 232 }); 233 }); 234 235 fakeLogRestore(); 236}); 237