Skip to content

Commit

Permalink
add test for unstable_derive (#2665)
Browse files Browse the repository at this point in the history
  • Loading branch information
David Maskasky authored Jul 19, 2024
1 parent b3b49c5 commit b30da26
Showing 1 changed file with 169 additions and 6 deletions.
175 changes: 169 additions & 6 deletions tests/vanilla/store.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,10 @@ describe('aborting atoms', () => {
})

describe('unstable_derive for scoping atoms', () => {
/**
* a
* S1[a]: a1
*/
it('primitive atom', async () => {
const a = atom('a')
a.onMount = (setSelf) => setSelf((v) => v + ':mounted')
Expand Down Expand Up @@ -594,9 +598,14 @@ describe('unstable_derive for scoping atoms', () => {
expect(derivedStore.get(a)).toBe('a:mounted:updated')
})

/**
* a, b, c(a + b)
* S1[a]: a1, b0, c0(a1 + b0)
*/
it('derived atom (scoping primitive)', async () => {
const a = atom('a')
const b = atom((get) => get(a))
const b = atom('b')
const c = atom((get) => get(a) + get(b))
const scopedAtoms = new Set<Atom<unknown>>([a])

const store = createStore()
Expand All @@ -617,14 +626,18 @@ describe('unstable_derive for scoping atoms', () => {
]
})

expect(store.get(b)).toBe('a')
expect(derivedStore.get(b)).toBe('a')
derivedStore.set(a, 'b')
expect(store.get(c)).toBe('ab')
expect(derivedStore.get(c)).toBe('ab')
derivedStore.set(a, 'a2')
await new Promise((resolve) => setTimeout(resolve))
expect(store.get(b)).toBe('a')
expect(derivedStore.get(b)).toBe('b')
expect(store.get(c)).toBe('ab')
expect(derivedStore.get(c)).toBe('a2b')
})

/**
* a, b(a)
* S1[b]: a0, b1(a1)
*/
it('derived atom (scoping derived)', async () => {
const a = atom('a')
const b = atom(
Expand Down Expand Up @@ -691,4 +704,154 @@ describe('unstable_derive for scoping atoms', () => {
expect(derivedStore.get(a)).toBe('a4')
expect(derivedStore.get(b)).toBe('a5')
})

/**
* a, b, c(a), d(c), e(d + b)
* S1[d]: a0, b0, c0(a0), d1(c1(a1)), e0(d1(c1(a1)) + b0)
*/
it('derived atom (scoping derived chain)', async () => {
const a = atom('a')
const b = atom('b')
const c = atom(
(get) => get(a),
(_get, set, v: string) => set(a, v),
)
const d = atom(
(get) => get(c),
(_get, set, v: string) => set(c, v),
)
const e = atom(
(get) => get(d) + get(b),
(_get, set, av: string, bv: string) => {
set(d, av)
set(b, bv)
},
)
const scopedAtoms = new Set<Atom<unknown>>([d])

function makeStores() {
const baseStore = createStore()
const deriStore = baseStore.unstable_derive((getAtomState) => {
const scopedAtomStateMap = new WeakMap()
const scopedAtomStateSet = new WeakSet()
return [
(atom, originAtomState) => {
if (
scopedAtomStateSet.has(originAtomState as never) ||
scopedAtoms.has(atom)
) {
let atomState = scopedAtomStateMap.get(atom)
if (!atomState) {
atomState = { d: new Map(), p: new Set(), n: 0 }
scopedAtomStateMap.set(atom, atomState)
scopedAtomStateSet.add(atomState)
}
return atomState
}
return getAtomState(atom, originAtomState)
},
]
})
expect(getAtoms(baseStore)).toEqual(['a', 'b', 'a', 'a', 'ab'])
expect(getAtoms(deriStore)).toEqual(['a', 'b', 'a', 'a', 'ab'])
return { baseStore, deriStore }
}
type Store = ReturnType<typeof createStore>
function getAtoms(store: Store) {
return [
store.get(a),
store.get(b),
store.get(c),
store.get(d),
store.get(e),
]
}

/**
* base[d]: a0, b0, c0(a0), d0(c0(a0)), e0(d0(c0(a0)) + b0)
* deri[d]: a0, b0, c0(a0), d1(c1(a1)), e0(d1(c1(a1)) + b0)
*/
{
// UPDATE a0
// NOCHGE b0 and a1
const { baseStore, deriStore } = makeStores()
baseStore.set(a, '*')
expect(getAtoms(baseStore)).toEqual(['*', 'b', '*', '*', '*b'])
expect(getAtoms(deriStore)).toEqual(['*', 'b', '*', 'a', 'ab'])
}
{
// UPDATE b0
// NOCHGE a0 and a1
const { baseStore, deriStore } = makeStores()
baseStore.set(b, '*')
expect(getAtoms(baseStore)).toEqual(['a', '*', 'a', 'a', 'a*'])
expect(getAtoms(deriStore)).toEqual(['a', '*', 'a', 'a', 'a*'])
}
{
// UPDATE c0, c0 -> a0
// NOCHGE b0 and a1
const { baseStore, deriStore } = makeStores()
baseStore.set(c, '*')
expect(getAtoms(baseStore)).toEqual(['*', 'b', '*', '*', '*b'])
expect(getAtoms(deriStore)).toEqual(['*', 'b', '*', 'a', 'ab'])
}
{
// UPDATE d0, d0 -> c0 -> a0
// NOCHGE b0 and a1
const { baseStore, deriStore } = makeStores()
baseStore.set(d, '*')
expect(getAtoms(baseStore)).toEqual(['*', 'b', '*', '*', '*b'])
expect(getAtoms(deriStore)).toEqual(['*', 'b', '*', 'a', 'ab'])
}
{
// UPDATE e0, e0 -> d0 -> c0 -> a0
// └--------------> b0
// NOCHGE a1
const { baseStore, deriStore } = makeStores()
baseStore.set(e, '*', '*')
expect(getAtoms(baseStore)).toEqual(['*', '*', '*', '*', '**'])
expect(getAtoms(deriStore)).toEqual(['*', '*', '*', 'a', 'a*'])
}
{
// UPDATE a0
// NOCHGE b0 and a1
const { baseStore, deriStore } = makeStores()
deriStore.set(a, '*')
expect(getAtoms(baseStore)).toEqual(['*', 'b', '*', '*', '*b'])
expect(getAtoms(deriStore)).toEqual(['*', 'b', '*', 'a', 'ab'])
}
{
// UPDATE b0
// NOCHGE a0 and a1
const { baseStore, deriStore } = makeStores()
deriStore.set(b, '*')
expect(getAtoms(baseStore)).toEqual(['a', '*', 'a', 'a', 'a*'])
expect(getAtoms(deriStore)).toEqual(['a', '*', 'a', 'a', 'a*'])
}
{
// UPDATE c0, c0 -> a0
// NOCHGE b0 and a1
const { baseStore, deriStore } = makeStores()
deriStore.set(c, '*')
expect(getAtoms(baseStore)).toEqual(['*', 'b', '*', '*', '*b'])
expect(getAtoms(deriStore)).toEqual(['*', 'b', '*', 'a', 'ab'])
}
{
// UPDATE d1, d1 -> c1 -> a1
// NOCHGE b0 and a0
const { baseStore, deriStore } = makeStores()
deriStore.set(d, '*')
expect(getAtoms(baseStore)).toEqual(['a', 'b', 'a', 'a', 'ab'])
expect(getAtoms(deriStore)).toEqual(['a', 'b', 'a', '*', '*b'])
}
{
// UPDATE e0, e0 -> d1 -> c1 -> a1
// └--------------> b0
// NOCHGE a0
const { baseStore, deriStore } = makeStores()
deriStore.set(e, '*', '*')
expect(getAtoms(baseStore)).toEqual(['a', '*', 'a', 'a', 'a*'])
expect(getAtoms(deriStore)).toEqual(['a', '*', 'a', '*', '**'])
}
})
})

0 comments on commit b30da26

Please sign in to comment.