import { ref , isRef } from '../ref' ; import { reactive , isReactive , toRaw , markRaw } from '../reactive' ; import { computed } from '../computed' ; import { effect } from '../effect' ; describe ( 'reactivity/reactive' , ( ) => { test ( 'Object' , ( ) => { const original = { foo : 1 } ; const observed = reactive ( original ) ; expect ( observed ) . not . toBe ( original ) ; expect ( isReactive ( observed ) ) . toBe ( true ) ; expect ( isReactive ( original ) ) . toBe ( false ) ; expect ( observed . foo ) . toBe ( 1 ) ; expect ( 'foo' in observed ) . toBe ( true ) ; expect ( Object . keys ( observed ) ) . toEqual ( [ 'foo' ] ) ; } ) ; test ( 'proto' , ( ) => { const obj = { } ; const reactiveObj = reactive ( obj ) ; expect ( isReactive ( reactiveObj ) ) . toBe ( true ) ; const prototype = reactiveObj [ '__proto__' ] ; const otherObj = { data : [ 'a' ] } ; expect ( isReactive ( otherObj ) ) . toBe ( false ) ; const reactiveOther = reactive ( otherObj ) ; expect ( isReactive ( reactiveOther ) ) . toBe ( true ) ; expect ( reactiveOther . data [ 0 ] ) . toBe ( 'a' ) ; } ) ; test ( 'nested reactives' , ( ) => { const original = { nested : { foo : 1 } , array : [ { bar : 2 } ] } ; const observed = reactive ( original ) ; expect ( isReactive ( observed . nested ) ) . toBe ( true ) ; expect ( isReactive ( observed . array ) ) . toBe ( true ) ; expect ( isReactive ( observed . array [ 0 ] ) ) . toBe ( true ) ; } ) ; test ( 'observing subtypes of IterableCollections(Map, Set)' , ( ) => { class CustomMap extends Map { } const cmap = reactive ( new CustomMap ( ) ) ; expect ( cmap instanceof Map ) . toBe ( true ) ; expect ( isReactive ( cmap ) ) . toBe ( true ) ; cmap . set ( 'key' , { } ) ; expect ( isReactive ( cmap . get ( 'key' ) ) ) . toBe ( true ) ; class CustomSet extends Set { } const cset = reactive ( new CustomSet ( ) ) ; expect ( cset instanceof Set ) . toBe ( true ) ; expect ( isReactive ( cset ) ) . toBe ( true ) ; let dummy ; effect ( ( ) => ( dummy = cset . has ( 'value' ) ) ) ; expect ( dummy ) . toBe ( false ) ; cset . add ( 'value' ) ; expect ( dummy ) . toBe ( true ) ; cset . delete ( 'value' ) ; expect ( dummy ) . toBe ( false ) ; } ) ; test ( 'observing subtypes of WeakCollections(WeakMap, WeakSet)' , ( ) => { class CustomMap extends WeakMap { } const cmap = reactive ( new CustomMap ( ) ) ; expect ( cmap instanceof WeakMap ) . toBe ( true ) ; expect ( isReactive ( cmap ) ) . toBe ( true ) ; const key = { } ; cmap . set ( key , { } ) ; expect ( isReactive ( cmap . get ( key ) ) ) . toBe ( true ) ; class CustomSet extends WeakSet { } const cset = reactive ( new CustomSet ( ) ) ; expect ( cset instanceof WeakSet ) . toBe ( true ) ; expect ( isReactive ( cset ) ) . toBe ( true ) ; let dummy ; effect ( ( ) => ( dummy = cset . has ( key ) ) ) ; expect ( dummy ) . toBe ( false ) ; cset . add ( key ) ; expect ( dummy ) . toBe ( true ) ; cset . delete ( key ) ; expect ( dummy ) . toBe ( false ) ; } ) ; test ( 'observed value should proxy mutations to original (Object)' , ( ) => { const original = { foo : 1 } ; const observed = reactive ( original ) ; observed . bar = 1 ; expect ( observed . bar ) . toBe ( 1 ) ; expect ( original . bar ) . toBe ( 1 ) ; delete observed . foo ; expect ( 'foo' in observed ) . toBe ( false ) ; expect ( 'foo' in original ) . toBe ( false ) ; } ) ; test ( 'original value change should reflect in observed value (Object)' , ( ) => { const original = { foo : 1 } ; const observed = reactive ( original ) ; original . bar = 1 ; expect ( original . bar ) . toBe ( 1 ) ; expect ( observed . bar ) . toBe ( 1 ) ; delete original . foo ; expect ( 'foo' in original ) . toBe ( false ) ; expect ( 'foo' in observed ) . toBe ( false ) ; } ) ; test ( 'observing already observed value should return same Proxy' , ( ) => { const original = { foo : 1 } ; const observed = reactive ( original ) ; const observed2 = reactive ( observed ) ; expect ( observed2 ) . toBe ( observed ) ; } ) ; test ( 'observing the same value multiple times should return same Proxy' , ( ) => { const original = { foo : 1 } ; const observed = reactive ( original ) ; const observed2 = reactive ( original ) ; expect ( observed2 ) . toBe ( observed ) ; } ) ; test ( 'should not pollute original object with Proxies' , ( ) => { const original = { foo : 1 } ; const original2 = { bar : 2 } ; const observed = reactive ( original ) ; const observed2 = reactive ( original2 ) ; observed . bar = observed2 ; expect ( observed . bar ) . toBe ( observed2 ) ; expect ( original . bar ) . toBe ( original2 ) ; } ) ; test ( 'toRaw' , ( ) => { const original = { foo : 1 } ; const observed = reactive ( original ) ; expect ( toRaw ( observed ) ) . toBe ( original ) ; expect ( toRaw ( original ) ) . toBe ( original ) ; } ) ; test ( 'toRaw on object using reactive as prototype' , ( ) => { const original = reactive ( { } ) ; const obj = Object . create ( original ) ; const raw = toRaw ( obj ) ; expect ( raw ) . toBe ( obj ) ; expect ( raw ) . not . toBe ( toRaw ( original ) ) ; } ) ; test ( 'should unwrap computed refs' , ( ) => { const a = computed ( ( ) => 1 ) ; const b = computed ( { get : ( ) => 1 , set : ( ) => { } } ) ; const obj = reactive ( { a , b } ) ; obj . a + 1 ; obj . b + 1 ; expect ( typeof obj . a ) . toBe ( `number` ) ; expect ( typeof obj . b ) . toBe ( `number` ) ; } ) ; test ( 'markRaw' , ( ) => { const obj = reactive ( { foo : { a : 1 } , bar : markRaw ( { b : 2 } ) } ) ; expect ( isReactive ( obj . foo ) ) . toBe ( true ) ; expect ( isReactive ( obj . bar ) ) . toBe ( false ) ; } ) ; test ( 'should not observe non-extensible objects' , ( ) => { const obj = reactive ( { foo : Object . preventExtensions ( { a : 1 } ) , bar : Object . freeze ( { a : 1 } ) , baz : Object . seal ( { a : 1 } ) } ) ; expect ( isReactive ( obj . foo ) ) . toBe ( false ) ; expect ( isReactive ( obj . bar ) ) . toBe ( false ) ; expect ( isReactive ( obj . baz ) ) . toBe ( false ) ; } ) ; test ( 'should not observe objects with __v_skip' , ( ) => { const original = { foo : 1 , __v_skip : true } ; const observed = reactive ( original ) ; expect ( isReactive ( observed ) ) . toBe ( false ) ; } ) ; } ) ;