]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
test: observer collection tests
authorEvan You <yyx990803@gmail.com>
Thu, 20 Sep 2018 15:43:14 +0000 (11:43 -0400)
committerEvan You <yyx990803@gmail.com>
Thu, 20 Sep 2018 15:43:14 +0000 (11:43 -0400)
packages/observer/__tests__/autorun.spec.ts
packages/observer/__tests__/collections.spec.ts [deleted file]
packages/observer/__tests__/collections/Map.spec.ts [new file with mode: 0644]
packages/observer/__tests__/collections/Set.spec.ts [new file with mode: 0644]
packages/observer/__tests__/collections/WeakMap.spec.ts [new file with mode: 0644]
packages/observer/__tests__/collections/WeakSet.spec.ts [new file with mode: 0644]
packages/observer/src/collectionHandlers.ts
packages/scheduler/__tests__/scheduler.spec.ts

index c0c8c4739431df9fbb86c0a95c85d04f82bf45b9..f8b2e1a50a14305f91c8b9ce23519fd72fe09382 100644 (file)
@@ -488,7 +488,7 @@ describe('observer/autorun', () => {
     expect(childSpy).toHaveBeenCalledTimes(5)
   })
 
-  test('should observe class method invocations', () => {
+  it('should observe class method invocations', () => {
     class Model {
       count: number
       constructor() {
@@ -508,7 +508,7 @@ describe('observer/autorun', () => {
     expect(dummy).toBe(1)
   })
 
-  test('scheduler', () => {
+  it('scheduler', () => {
     let runner: any, dummy
     const scheduler = jest.fn(_runner => {
       runner = _runner
@@ -533,7 +533,7 @@ describe('observer/autorun', () => {
     expect(dummy).toBe(2)
   })
 
-  test('events: onTrack', () => {
+  it('events: onTrack', () => {
     let events: any[] = []
     let dummy
     const onTrack = jest.fn((e: DebuggerEvent) => {
@@ -572,7 +572,7 @@ describe('observer/autorun', () => {
     ])
   })
 
-  test('events: onTrigger', () => {
+  it('events: onTrigger', () => {
     let events: any[] = []
     let dummy
     const onTrigger = jest.fn((e: DebuggerEvent) => {
@@ -610,7 +610,7 @@ describe('observer/autorun', () => {
     })
   })
 
-  test('stop', () => {
+  it('stop', () => {
     let dummy
     const obj = observable({ prop: 1 })
     const runner = autorun(() => {
@@ -623,7 +623,7 @@ describe('observer/autorun', () => {
     expect(dummy).toBe(2)
   })
 
-  test('markNonReactive', () => {
+  it('markNonReactive', () => {
     const obj = observable({
       foo: markNonReactive({
         prop: 0
diff --git a/packages/observer/__tests__/collections.spec.ts b/packages/observer/__tests__/collections.spec.ts
deleted file mode 100644 (file)
index bb99db9..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-describe('observer/collections', () => {
-  describe('Map', () => {})
-})
diff --git a/packages/observer/__tests__/collections/Map.spec.ts b/packages/observer/__tests__/collections/Map.spec.ts
new file mode 100644 (file)
index 0000000..c9d2de2
--- /dev/null
@@ -0,0 +1,210 @@
+import { observable, autorun, unwrap, isObservable } from '../../src'
+
+describe('observer/collections', () => {
+  describe('Map', () => {
+    test('instanceof', () => {
+      const original = new Map()
+      const observed = observable(original)
+      expect(isObservable(observed)).toBe(true)
+      expect(original instanceof Map).toBe(true)
+      expect(observed instanceof Map).toBe(true)
+    })
+
+    it('should observe mutations', () => {
+      let dummy
+      const map = observable(new Map())
+      autorun(() => {
+        dummy = map.get('key')
+      })
+
+      expect(dummy).toBe(undefined)
+      map.set('key', 'value')
+      expect(dummy).toBe('value')
+      map.set('key', 'value2')
+      expect(dummy).toBe('value2')
+      map.delete('key')
+      expect(dummy).toBe(undefined)
+    })
+
+    it('should observe size mutations', () => {
+      let dummy
+      const map = observable(new Map())
+      autorun(() => (dummy = map.size))
+
+      expect(dummy).toBe(0)
+      map.set('key1', 'value')
+      map.set('key2', 'value2')
+      expect(dummy).toBe(2)
+      map.delete('key1')
+      expect(dummy).toBe(1)
+      map.clear()
+      expect(dummy).toBe(0)
+    })
+
+    it('should observe for of iteration', () => {
+      let dummy
+      const map = observable(new Map())
+      autorun(() => {
+        dummy = 0
+        // eslint-disable-next-line no-unused-vars
+        for (let [key, num] of map) {
+          key
+          dummy += num
+        }
+      })
+
+      expect(dummy).toBe(0)
+      map.set('key1', 3)
+      expect(dummy).toBe(3)
+      map.set('key2', 2)
+      expect(dummy).toBe(5)
+      map.delete('key1')
+      expect(dummy).toBe(2)
+      map.clear()
+      expect(dummy).toBe(0)
+    })
+
+    it('should observe forEach iteration', () => {
+      let dummy: any
+      const map = observable(new Map())
+      autorun(() => {
+        dummy = 0
+        map.forEach((num: any) => (dummy += num))
+      })
+
+      expect(dummy).toBe(0)
+      map.set('key1', 3)
+      expect(dummy).toBe(3)
+      map.set('key2', 2)
+      expect(dummy).toBe(5)
+      map.delete('key1')
+      expect(dummy).toBe(2)
+      map.clear()
+      expect(dummy).toBe(0)
+    })
+
+    it('should observe keys iteration', () => {
+      let dummy
+      const map = observable(new Map())
+      autorun(() => {
+        dummy = 0
+        for (let key of map.keys()) {
+          dummy += key
+        }
+      })
+
+      expect(dummy).toBe(0)
+      map.set(3, 3)
+      expect(dummy).toBe(3)
+      map.set(2, 2)
+      expect(dummy).toBe(5)
+      map.delete(3)
+      expect(dummy).toBe(2)
+      map.clear()
+      expect(dummy).toBe(0)
+    })
+
+    it('should observe values iteration', () => {
+      let dummy
+      const map = observable(new Map())
+      autorun(() => {
+        dummy = 0
+        for (let num of map.values()) {
+          dummy += num
+        }
+      })
+
+      expect(dummy).toBe(0)
+      map.set('key1', 3)
+      expect(dummy).toBe(3)
+      map.set('key2', 2)
+      expect(dummy).toBe(5)
+      map.delete('key1')
+      expect(dummy).toBe(2)
+      map.clear()
+      expect(dummy).toBe(0)
+    })
+
+    it('should observe entries iteration', () => {
+      let dummy
+      const map = observable(new Map())
+      autorun(() => {
+        dummy = 0
+        // eslint-disable-next-line no-unused-vars
+        for (let [key, num] of map.entries()) {
+          key
+          dummy += num
+        }
+      })
+
+      expect(dummy).toBe(0)
+      map.set('key1', 3)
+      expect(dummy).toBe(3)
+      map.set('key2', 2)
+      expect(dummy).toBe(5)
+      map.delete('key1')
+      expect(dummy).toBe(2)
+      map.clear()
+      expect(dummy).toBe(0)
+    })
+
+    it('should be triggered by clearing', () => {
+      let dummy
+      const map = observable(new Map())
+      autorun(() => (dummy = map.get('key')))
+
+      expect(dummy).toBe(undefined)
+      map.set('key', 3)
+      expect(dummy).toBe(3)
+      map.clear()
+      expect(dummy).toBe(undefined)
+    })
+
+    it('should not observe custom property mutations', () => {
+      let dummy
+      const map: any = observable(new Map())
+      autorun(() => (dummy = map.customProp))
+
+      expect(dummy).toBe(undefined)
+      map.customProp = 'Hello World'
+      expect(dummy).toBe(undefined)
+    })
+
+    it('should not observe non value changing mutations', () => {
+      let dummy
+      const map = observable(new Map())
+      const mapSpy = jest.fn(() => (dummy = map.get('key')))
+      autorun(mapSpy)
+
+      expect(dummy).toBe(undefined)
+      expect(mapSpy).toHaveBeenCalledTimes(1)
+      map.set('key', 'value')
+      expect(dummy).toBe('value')
+      expect(mapSpy).toHaveBeenCalledTimes(2)
+      map.set('key', 'value')
+      expect(dummy).toBe('value')
+      expect(mapSpy).toHaveBeenCalledTimes(2)
+      map.delete('key')
+      expect(dummy).toBe(undefined)
+      expect(mapSpy).toHaveBeenCalledTimes(3)
+      map.delete('key')
+      expect(dummy).toBe(undefined)
+      expect(mapSpy).toHaveBeenCalledTimes(3)
+      map.clear()
+      expect(dummy).toBe(undefined)
+      expect(mapSpy).toHaveBeenCalledTimes(3)
+    })
+
+    it('should not observe raw data', () => {
+      let dummy
+      const map = observable(new Map())
+      autorun(() => (dummy = unwrap(map).get('key')))
+
+      expect(dummy).toBe(undefined)
+      map.set('key', 'Hello')
+      expect(dummy).toBe(undefined)
+      map.delete('key')
+      expect(dummy).toBe(undefined)
+    })
+  })
+})
diff --git a/packages/observer/__tests__/collections/Set.spec.ts b/packages/observer/__tests__/collections/Set.spec.ts
new file mode 100644 (file)
index 0000000..5c6b3f9
--- /dev/null
@@ -0,0 +1,279 @@
+import { observable, autorun, isObservable, unwrap } from '../../src'
+
+describe('Set', () => {
+  it('instanceof', () => {
+    const original = new Set()
+    const observed = observable(original)
+    expect(isObservable(observed)).toBe(true)
+    expect(original instanceof Set).toBe(true)
+    expect(observed instanceof Set).toBe(true)
+  })
+
+  it('should observe mutations', () => {
+    let dummy
+    const set = observable(new Set())
+    autorun(() => (dummy = set.has('value')))
+
+    expect(dummy).toBe(false)
+    set.add('value')
+    expect(dummy).toBe(true)
+    set.delete('value')
+    expect(dummy).toBe(false)
+  })
+
+  it('should observe for of iteration', () => {
+    let dummy
+    const set = observable(new Set())
+    autorun(() => {
+      dummy = 0
+      for (let num of set) {
+        dummy += num
+      }
+    })
+
+    expect(dummy).toBe(0)
+    set.add(2)
+    set.add(1)
+    expect(dummy).toBe(3)
+    set.delete(2)
+    expect(dummy).toBe(1)
+    set.clear()
+    expect(dummy).toBe(0)
+  })
+
+  it('should observe forEach iteration', () => {
+    let dummy: any
+    const set = observable(new Set())
+    autorun(() => {
+      dummy = 0
+      set.forEach(num => (dummy += num))
+    })
+
+    expect(dummy).toBe(0)
+    set.add(2)
+    set.add(1)
+    expect(dummy).toBe(3)
+    set.delete(2)
+    expect(dummy).toBe(1)
+    set.clear()
+    expect(dummy).toBe(0)
+  })
+
+  it('should observe values iteration', () => {
+    let dummy
+    const set = observable(new Set())
+    autorun(() => {
+      dummy = 0
+      for (let num of set.values()) {
+        dummy += num
+      }
+    })
+
+    expect(dummy).toBe(0)
+    set.add(2)
+    set.add(1)
+    expect(dummy).toBe(3)
+    set.delete(2)
+    expect(dummy).toBe(1)
+    set.clear()
+    expect(dummy).toBe(0)
+  })
+
+  it('should observe keys iteration', () => {
+    let dummy
+    const set = observable(new Set())
+    autorun(() => {
+      dummy = 0
+      for (let num of set.keys()) {
+        dummy += num
+      }
+    })
+
+    expect(dummy).toBe(0)
+    set.add(2)
+    set.add(1)
+    expect(dummy).toBe(3)
+    set.delete(2)
+    expect(dummy).toBe(1)
+    set.clear()
+    expect(dummy).toBe(0)
+  })
+
+  it('should observe entries iteration', () => {
+    let dummy
+    const set = observable(new Set())
+    autorun(() => {
+      dummy = 0
+      // eslint-disable-next-line no-unused-vars
+      for (let [key, num] of set.entries()) {
+        key
+        dummy += num
+      }
+    })
+
+    expect(dummy).toBe(0)
+    set.add(2)
+    set.add(1)
+    expect(dummy).toBe(3)
+    set.delete(2)
+    expect(dummy).toBe(1)
+    set.clear()
+    expect(dummy).toBe(0)
+  })
+
+  it('should be triggered by clearing', () => {
+    let dummy
+    const set = observable(new Set())
+    autorun(() => (dummy = set.has('key')))
+
+    expect(dummy).toBe(false)
+    set.add('key')
+    expect(dummy).toBe(true)
+    set.clear()
+    expect(dummy).toBe(false)
+  })
+
+  it('should not observe custom property mutations', () => {
+    let dummy
+    const set: any = observable(new Set())
+    autorun(() => (dummy = set.customProp))
+
+    expect(dummy).toBe(undefined)
+    set.customProp = 'Hello World'
+    expect(dummy).toBe(undefined)
+  })
+
+  it('should observe size mutations', () => {
+    let dummy
+    const set = observable(new Set())
+    autorun(() => (dummy = set.size))
+
+    expect(dummy).toBe(0)
+    set.add('value')
+    set.add('value2')
+    expect(dummy).toBe(2)
+    set.delete('value')
+    expect(dummy).toBe(1)
+    set.clear()
+    expect(dummy).toBe(0)
+  })
+
+  it('should not observe non value changing mutations', () => {
+    let dummy
+    const set = observable(new Set())
+    const setSpy = jest.fn(() => (dummy = set.has('value')))
+    autorun(setSpy)
+
+    expect(dummy).toBe(false)
+    expect(setSpy).toHaveBeenCalledTimes(1)
+    set.add('value')
+    expect(dummy).toBe(true)
+    expect(setSpy).toHaveBeenCalledTimes(2)
+    set.add('value')
+    expect(dummy).toBe(true)
+    expect(setSpy).toHaveBeenCalledTimes(2)
+    set.delete('value')
+    expect(dummy).toBe(false)
+    expect(setSpy).toHaveBeenCalledTimes(3)
+    set.delete('value')
+    expect(dummy).toBe(false)
+    expect(setSpy).toHaveBeenCalledTimes(3)
+    set.clear()
+    expect(dummy).toBe(false)
+    expect(setSpy).toHaveBeenCalledTimes(3)
+  })
+
+  it('should not observe raw data', () => {
+    let dummy
+    const set = observable(new Set())
+    autorun(() => (dummy = unwrap(set).has('value')))
+
+    expect(dummy).toBe(false)
+    set.add('value')
+    expect(dummy).toBe(false)
+  })
+
+  it('should not observe raw iterations', () => {
+    let dummy = 0
+    const set = observable(new Set())
+    autorun(() => {
+      dummy = 0
+      for (let [num] of unwrap(set).entries()) {
+        dummy += num
+      }
+      for (let num of unwrap(set).keys()) {
+        dummy += num
+      }
+      for (let num of unwrap(set).values()) {
+        dummy += num
+      }
+      unwrap(set).forEach(num => {
+        dummy += num
+      })
+      for (let num of unwrap(set)) {
+        dummy += num
+      }
+    })
+
+    expect(dummy).toBe(0)
+    set.add(2)
+    set.add(3)
+    expect(dummy).toBe(0)
+    set.delete(2)
+    expect(dummy).toBe(0)
+  })
+
+  it('should not be triggered by raw mutations', () => {
+    let dummy
+    const set = observable(new Set())
+    autorun(() => (dummy = set.has('value')))
+
+    expect(dummy).toBe(false)
+    unwrap(set).add('value')
+    expect(dummy).toBe(false)
+    dummy = true
+    unwrap(set).delete('value')
+    expect(dummy).toBe(true)
+    unwrap(set).clear()
+    expect(dummy).toBe(true)
+  })
+
+  it('should not observe raw size mutations', () => {
+    let dummy
+    const set = observable(new Set())
+    autorun(() => (dummy = unwrap(set).size))
+
+    expect(dummy).toBe(0)
+    set.add('value')
+    expect(dummy).toBe(0)
+  })
+
+  it('should not be triggered by raw size mutations', () => {
+    let dummy
+    const set = observable(new Set())
+    autorun(() => (dummy = set.size))
+
+    expect(dummy).toBe(0)
+    unwrap(set).add('value')
+    expect(dummy).toBe(0)
+  })
+
+  it('should support objects as key', () => {
+    let dummy
+    const key = {}
+    const set = observable(new Set())
+    const setSpy = jest.fn(() => (dummy = set.has(key)))
+    autorun(setSpy)
+
+    expect(dummy).toBe(false)
+    expect(setSpy).toHaveBeenCalledTimes(1)
+
+    set.add({})
+    expect(dummy).toBe(false)
+    expect(setSpy).toHaveBeenCalledTimes(1)
+
+    set.add(key)
+    expect(dummy).toBe(true)
+    expect(setSpy).toHaveBeenCalledTimes(2)
+  })
+})
diff --git a/packages/observer/__tests__/collections/WeakMap.spec.ts b/packages/observer/__tests__/collections/WeakMap.spec.ts
new file mode 100644 (file)
index 0000000..db97dd0
--- /dev/null
@@ -0,0 +1,77 @@
+import { observable, autorun, unwrap, isObservable } from '../../src'
+
+describe('observer/collections/WeakMap', () => {
+  test('instanceof', () => {
+    const original = new WeakMap()
+    const observed = observable(original)
+    expect(isObservable(observed)).toBe(true)
+    expect(original instanceof WeakMap).toBe(true)
+    expect(observed instanceof WeakMap).toBe(true)
+  })
+
+  it('should observe mutations', () => {
+    let dummy
+    const key = {}
+    const map = observable(new WeakMap())
+    autorun(() => {
+      dummy = map.get(key)
+    })
+
+    expect(dummy).toBe(undefined)
+    map.set(key, 'value')
+    expect(dummy).toBe('value')
+    map.set(key, 'value2')
+    expect(dummy).toBe('value2')
+    map.delete(key)
+    expect(dummy).toBe(undefined)
+  })
+
+  it('should not observe custom property mutations', () => {
+    let dummy
+    const map: any = observable(new Map())
+    autorun(() => (dummy = map.customProp))
+
+    expect(dummy).toBe(undefined)
+    map.customProp = 'Hello World'
+    expect(dummy).toBe(undefined)
+  })
+
+  it('should not observe non value changing mutations', () => {
+    let dummy
+    const key = {}
+    const map = observable(new Map())
+    const mapSpy = jest.fn(() => (dummy = map.get(key)))
+    autorun(mapSpy)
+
+    expect(dummy).toBe(undefined)
+    expect(mapSpy).toHaveBeenCalledTimes(1)
+    map.set(key, 'value')
+    expect(dummy).toBe('value')
+    expect(mapSpy).toHaveBeenCalledTimes(2)
+    map.set(key, 'value')
+    expect(dummy).toBe('value')
+    expect(mapSpy).toHaveBeenCalledTimes(2)
+    map.delete(key)
+    expect(dummy).toBe(undefined)
+    expect(mapSpy).toHaveBeenCalledTimes(3)
+    map.delete(key)
+    expect(dummy).toBe(undefined)
+    expect(mapSpy).toHaveBeenCalledTimes(3)
+    map.clear()
+    expect(dummy).toBe(undefined)
+    expect(mapSpy).toHaveBeenCalledTimes(3)
+  })
+
+  it('should not observe raw data', () => {
+    let dummy
+    const key = {}
+    const map = observable(new Map())
+    autorun(() => (dummy = unwrap(map).get('key')))
+
+    expect(dummy).toBe(undefined)
+    map.set(key, 'Hello')
+    expect(dummy).toBe(undefined)
+    map.delete(key)
+    expect(dummy).toBe(undefined)
+  })
+})
diff --git a/packages/observer/__tests__/collections/WeakSet.spec.ts b/packages/observer/__tests__/collections/WeakSet.spec.ts
new file mode 100644 (file)
index 0000000..1efd9b3
--- /dev/null
@@ -0,0 +1,79 @@
+import { observable, isObservable, autorun, unwrap } from '../../src'
+
+describe('WeakSet', () => {
+  it('instanceof', () => {
+    const original = new Set()
+    const observed = observable(original)
+    expect(isObservable(observed)).toBe(true)
+    expect(original instanceof Set).toBe(true)
+    expect(observed instanceof Set).toBe(true)
+  })
+
+  it('should observe mutations', () => {
+    let dummy
+    const value = {}
+    const set = observable(new WeakSet())
+    autorun(() => (dummy = set.has(value)))
+
+    expect(dummy).toBe(false)
+    set.add(value)
+    expect(dummy).toBe(true)
+    set.delete(value)
+    expect(dummy).toBe(false)
+  })
+
+  it('should not observe custom property mutations', () => {
+    let dummy
+    const set: any = observable(new WeakSet())
+    autorun(() => (dummy = set.customProp))
+
+    expect(dummy).toBe(undefined)
+    set.customProp = 'Hello World'
+    expect(dummy).toBe(undefined)
+  })
+
+  it('should not observe non value changing mutations', () => {
+    let dummy
+    const value = {}
+    const set = observable(new WeakSet())
+    const setSpy = jest.fn(() => (dummy = set.has(value)))
+    autorun(setSpy)
+
+    expect(dummy).toBe(false)
+    expect(setSpy).toHaveBeenCalledTimes(1)
+    set.add(value)
+    expect(dummy).toBe(true)
+    expect(setSpy).toHaveBeenCalledTimes(2)
+    set.add(value)
+    expect(dummy).toBe(true)
+    expect(setSpy).toHaveBeenCalledTimes(2)
+    set.delete(value)
+    expect(dummy).toBe(false)
+    expect(setSpy).toHaveBeenCalledTimes(3)
+    set.delete(value)
+    expect(dummy).toBe(false)
+    expect(setSpy).toHaveBeenCalledTimes(3)
+  })
+
+  it('should not observe raw data', () => {
+    const value = {}
+    let dummy
+    const set = observable(new WeakSet())
+    autorun(() => (dummy = unwrap(set).has(value)))
+
+    expect(dummy).toBe(false)
+    set.add(value)
+    expect(dummy).toBe(false)
+  })
+
+  it('should not be triggered by raw mutations', () => {
+    const value = {}
+    let dummy
+    const set = observable(new WeakSet())
+    autorun(() => (dummy = set.has(value)))
+
+    expect(dummy).toBe(false)
+    unwrap(set).add(value)
+    expect(dummy).toBe(false)
+  })
+})
index 859677e9768ad56142e778bcb4de335cda3a4b5c..113ec8a360a5022c8147bb81a23c03ec4b0c2277 100644 (file)
@@ -2,25 +2,17 @@ import { unwrap } from './index'
 import { track, trigger } from './autorun'
 import { OperationTypes } from './operations'
 
-function instrument(
-  target: any,
-  key: string | symbol,
-  args: any[],
-  type: OperationTypes
-) {
-  target = unwrap(target)
-  const proto: any = Reflect.getPrototypeOf(target)
-  track(target, type)
-  return proto[key].apply(target, args)
+function makeInstrumentedMethod(method: string | symbol, type: OperationTypes) {
+  return function(...args: any[]) {
+    const target = unwrap(this)
+    const proto: any = Reflect.getPrototypeOf(target)
+    track(target, type, args[0])
+    return proto[method].apply(target, args)
+  }
 }
 
-function get(key: string | symbol) {
-  return instrument(this, key, [key], OperationTypes.GET)
-}
-
-function has(key: string | symbol): boolean {
-  return instrument(this, key, [key], OperationTypes.HAS)
-}
+const get = makeInstrumentedMethod('get', OperationTypes.GET)
+const has = makeInstrumentedMethod('has', OperationTypes.HAS)
 
 function size(target: any) {
   target = unwrap(target)
@@ -69,18 +61,20 @@ const mutableInstrumentations: any = {
     const hadKey = proto.has.call(target, key)
     const oldValue = proto.get.call(target, key)
     const result = proto.set.apply(target, arguments)
-    if (__DEV__) {
-      const extraInfo = { oldValue, newValue: value }
-      if (!hadKey) {
-        trigger(target, OperationTypes.ADD, key, extraInfo)
-      } else {
-        trigger(target, OperationTypes.SET, key, extraInfo)
-      }
-    } else {
-      if (!hadKey) {
-        trigger(target, OperationTypes.ADD, key)
+    if (value !== oldValue) {
+      if (__DEV__) {
+        const extraInfo = { oldValue, newValue: value }
+        if (!hadKey) {
+          trigger(target, OperationTypes.ADD, key, extraInfo)
+        } else {
+          trigger(target, OperationTypes.SET, key, extraInfo)
+        }
       } else {
-        trigger(target, OperationTypes.SET, key)
+        if (!hadKey) {
+          trigger(target, OperationTypes.ADD, key)
+        } else {
+          trigger(target, OperationTypes.SET, key)
+        }
       }
     }
     return result
@@ -133,11 +127,9 @@ const immutableInstrumentations: any = {
   clear: makeWarning(OperationTypes.CLEAR)
 }
 ;['forEach', 'keys', 'values', 'entries', Symbol.iterator].forEach(key => {
-  mutableInstrumentations[key] = immutableInstrumentations[key] = function(
-    ...args: any[]
-  ) {
-    return instrument(this, key, args, OperationTypes.ITERATE)
-  }
+  mutableInstrumentations[key] = immutableInstrumentations[
+    key
+  ] = makeInstrumentedMethod(key, OperationTypes.ITERATE)
 })
 
 function getInstrumented(
index 27265c422d6f0c3c4a5bdf4b0c2006744fce1fcf..fccd4ffd2151bca5aeb46621bc04dc73617419a6 100644 (file)
@@ -1,7 +1,7 @@
 import { queueJob, nextTick } from '../src/index'
 
 describe('scheduler', () => {
-  test('queueJob', async () => {
+  it('queueJob', async () => {
     const calls: any = []
     const job1 = () => {
       calls.push('job1')
@@ -16,7 +16,7 @@ describe('scheduler', () => {
     expect(calls).toEqual(['job1', 'job2'])
   })
 
-  test('queueJob while already flushing', async () => {
+  it('queueJob while already flushing', async () => {
     const calls: any = []
     const job1 = () => {
       calls.push('job1')
@@ -34,7 +34,7 @@ describe('scheduler', () => {
     expect(calls).toEqual(['job1', 'job2'])
   })
 
-  test('queueJob w/ postFlushCb', async () => {
+  it('queueJob w/ postFlushCb', async () => {
     const calls: any = []
     const job1 = () => {
       calls.push('job1')
@@ -54,7 +54,7 @@ describe('scheduler', () => {
     expect(calls).toEqual(['job1', 'job2', 'cb1', 'cb2'])
   })
 
-  test('queueJob w/ postFlushCb while flushing', async () => {
+  it('queueJob w/ postFlushCb while flushing', async () => {
     const calls: any = []
     const job1 = () => {
       calls.push('job1')
@@ -78,7 +78,7 @@ describe('scheduler', () => {
     expect(calls).toEqual(['job1', 'job2', 'cb1', 'cb2'])
   })
 
-  test('should dedupe queued tasks', async () => {
+  it('should dedupe queued tasks', async () => {
     const calls: any = []
     const job1 = () => {
       calls.push('job1')