| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- /**
- * Test property proxy, scope inheritance,
- * data event propagation and data sync
- */
- var Vue = require('../../../src/vue')
- var Observer = require('../../../src/observe/observer')
- var u = undefined
- Observer.pathDelimiter = '.'
- describe('Scope', function () {
-
- describe('basic', function () {
-
- var vm = new Vue({
- data: {
- a: 1,
- b: {
- c: 2
- }
- }
- })
- it('should copy over data properties', function () {
- expect(vm.$scope.a).toBe(vm.$data.a)
- expect(vm.$scope.b).toBe(vm.$data.b)
- })
- it('should proxy these properties', function () {
- expect(vm.a).toBe(vm.$scope.a)
- expect(vm.b).toBe(vm.$scope.b)
- })
- it('should trigger set events', function () {
- var spy = jasmine.createSpy('basic')
- vm.$observer.on('set', spy)
- // set on scope
- vm.$scope.a = 2
- expect(spy.calls.count()).toBe(1)
- expect(spy).toHaveBeenCalledWith('a', 2, u)
- // set on vm
- vm.b.c = 3
- expect(spy.calls.count()).toBe(2)
- expect(spy).toHaveBeenCalledWith('b.c', 3, u)
- })
- it('should trigger add/delete events', function () {
- var spy = jasmine.createSpy('instantiation')
- vm.$observer
- .on('add', spy)
- .on('delete', spy)
- // add on scope
- vm.$scope.$add('c', 123)
- expect(spy.calls.count()).toBe(1)
- expect(spy).toHaveBeenCalledWith('c', 123, u)
- // delete on scope
- vm.$scope.$delete('c')
- expect(spy.calls.count()).toBe(2)
- expect(spy).toHaveBeenCalledWith('c', u, u)
- // vm $add/$delete are tested in the api suite
- })
- })
- describe('data sync', function () {
- var data = {
- a: 1,
- b: {
- c: 2
- }
- }
-
- var vm = new Vue({
- data: data
- })
- it('should retain data reference', function () {
- expect(vm.$data).toBe(data)
- })
- it('should sync set', function () {
- // vm -> data
- vm.a = 2
- expect(data.a).toBe(2)
- // data -> vm
- data.b = {d:3}
- expect(vm.$scope.b).toBe(data.b)
- expect(vm.b).toBe(data.b)
- })
- it('should sync add', function () {
- // vm -> data
- vm.$scope.$add('c', 123)
- expect(data.c).toBe(123)
- // data -> vm
- data.$add('d', 456)
- expect(vm.$scope.d).toBe(456)
- expect(vm.d).toBe(456)
- })
- it('should sync delete', function () {
- // vm -> data
- vm.$scope.$delete('d')
- expect(data.hasOwnProperty('d')).toBe(false)
- // data -> vm
- data.$delete('c')
- expect(vm.$scope.hasOwnProperty('c')).toBe(false)
- expect(vm.hasOwnProperty('c')).toBe(false)
- })
- })
- describe('inheritance', function () {
-
- var parent = new Vue({
- data: {
- a: 'parent a',
- b: { c: 2 },
- c: 'parent c',
- arr: [{a:1},{a:2}]
- }
- })
- var child = new Vue({
- parent: parent,
- data: {
- a: 'child a'
- }
- })
- it('child should inherit parent data on scope', function () {
- expect(child.$scope.b).toBe(parent.b) // object
- expect(child.$scope.c).toBe(parent.c) // primitive value
- })
- it('child should not ineherit data on instance', function () {
- expect(child.b).toBeUndefined()
- expect(child.c).toBeUndefined()
- })
- it('child should shadow parent property with same key', function () {
- expect(parent.a).toBe('parent a')
- expect(child.$scope.a).toBe('child a')
- expect(child.a).toBe('child a')
- })
- it('setting scope properties on child should affect parent', function () {
- child.$scope.c = 'modified by child'
- expect(parent.c).toBe('modified by child')
- })
- it('events on parent should propagate down to child', function () {
- // when a shadowed property changed on parent scope,
- // the event should NOT be propagated down
- var spy = jasmine.createSpy('inheritance')
- child.$observer.on('set', spy)
- parent.c = 'c changed'
- expect(spy.calls.count()).toBe(1)
- expect(spy).toHaveBeenCalledWith('c', 'c changed', u)
- spy = jasmine.createSpy('inheritance')
- child.$observer.on('add', spy)
- parent.$scope.$add('e', 123)
- expect(spy.calls.count()).toBe(1)
- expect(spy).toHaveBeenCalledWith('e', 123, u)
- spy = jasmine.createSpy('inheritance')
- child.$observer.on('delete', spy)
- parent.$scope.$delete('e')
- expect(spy.calls.count()).toBe(1)
- expect(spy).toHaveBeenCalledWith('e', u, u)
- spy = jasmine.createSpy('inheritance')
- child.$observer.on('mutate', spy)
- parent.arr.reverse()
- expect(spy.calls.mostRecent().args[0]).toBe('arr')
- expect(spy.calls.mostRecent().args[1]).toBe(parent.arr)
- expect(spy.calls.mostRecent().args[2].method).toBe('reverse')
- })
- it('shadowed properties change on parent should not propagate down', function () {
- // when a shadowed property changed on parent scope,
- // the event should NOT be propagated down
- var spy = jasmine.createSpy('inheritance')
- child.$observer.on('set', spy)
- parent.a = 'a changed'
- expect(spy.calls.count()).toBe(0)
- })
- })
- describe('inheritance with data sync on parent data', function () {
-
- var parent = new Vue({
- data: {
- arr: [{a:1},{a:2}]
- }
- })
- var child = new Vue({
- parent: parent,
- data: parent.arr[0]
- })
- it('should trigger proper events', function () {
-
- var parentSpy = jasmine.createSpy('parent')
- var childSpy = jasmine.createSpy('child')
- parent.$observer.on('set', parentSpy)
- child.$observer.on('set', childSpy)
- child.a = 3
- // make sure data sync is working
- expect(parent.arr[0].a).toBe(3)
- expect(parentSpy.calls.count()).toBe(1)
- expect(parentSpy).toHaveBeenCalledWith('arr.0.a', 3, u)
- expect(childSpy.calls.count()).toBe(2)
- expect(childSpy).toHaveBeenCalledWith('a', 3, u)
- expect(childSpy).toHaveBeenCalledWith('arr.0.a', 3, u)
- })
- })
- describe('swapping $data', function () {
-
- var oldData = { a: 1, c: 4 }
- var newData = { a: 2, b: 3 }
- var vm = new Vue({
- data: oldData
- })
- var vmSpy = jasmine.createSpy('vm')
- var vmAddSpy = jasmine.createSpy('vmAdd')
- var oldDataSpy = jasmine.createSpy('oldData')
- vm.$observer.on('set', vmSpy)
- vm.$observer.on('add', vmAddSpy)
- oldData.$observer.on('set', oldDataSpy)
- vm.$data = newData
- it('should sync new data', function () {
- expect(vm._data).toBe(newData)
- expect(vm.a).toBe(2)
- expect(vm.b).toBe(3)
- expect(vmSpy).toHaveBeenCalledWith('a', 2, u)
- expect(vmAddSpy).toHaveBeenCalledWith('b', 3, u)
- })
- it('should unsync old data', function () {
- expect(vm.hasOwnProperty('c')).toBe(false)
- vm.a = 3
- expect(oldDataSpy.calls.count()).toBe(0)
- expect(oldData.a).toBe(1)
- expect(newData.a).toBe(3)
- })
- })
- describe('scope teardown', function () {
- var parent = new Vue({
- data: {
- a: 123
- }
- })
- var child = new Vue({
- parent: parent
- })
- var spy = jasmine.createSpy('teardown')
- child.$observer.on('set', spy)
- it('should stop relaying parent events', function () {
- child._teardownScope()
- parent.a = 234
- expect(spy.calls.count()).toBe(0)
- expect(child.$scope).toBeNull()
- })
- })
- describe('computed', function () {
-
- var vm = new Vue({
- data: {
- a: 'a',
- b: 'b'
- },
- computed: {
- c: function () {
- expect(this).toBe(vm)
- return this.a + this.b
- },
- d: {
- get: function () {
- expect(this).toBe(vm)
- return this.a + this.b
- },
- set: function (newVal) {
- expect(this).toBe(vm)
- var vals = newVal.split(' ')
- this.a = vals[0]
- this.b = vals[1]
- }
- }
- }
- })
- it('get', function () {
- expect(vm.c).toBe('ab')
- expect(vm.d).toBe('ab')
- })
- it('set', function () {
- vm.c = 123 // should do nothing
- vm.d = 'c d'
- expect(vm.a).toBe('c')
- expect(vm.b).toBe('d')
- expect(vm.c).toBe('cd')
- expect(vm.d).toBe('cd')
- })
- it('inherit', function () {
- var child = new Vue({ parent: vm })
- expect(child.$scope.c).toBe('cd')
- child.$scope.d = 'e f'
- expect(vm.a).toBe('e')
- expect(vm.b).toBe('f')
- expect(vm.c).toBe('ef')
- expect(vm.d).toBe('ef')
- expect(child.$scope.a).toBe('e')
- expect(child.$scope.b).toBe('f')
- expect(child.$scope.c).toBe('ef')
- expect(child.$scope.d).toBe('ef')
- })
- })
- describe('methods', function () {
- it('should work and have correct context', function () {
- var vm = new Vue({
- data: {
- a: 1
- },
- methods: {
- test: function () {
- expect(this instanceof Vue).toBe(true)
- return this.a
- }
- }
- })
- expect(vm.test()).toBe(1)
- expect(vm.$scope.test()).toBe(1)
- })
- })
- })
|