Skip to content

Commit

Permalink
console cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
David Maskasky committed Jan 22, 2024
1 parent 695a16f commit d905d72
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 245 deletions.
6 changes: 1 addition & 5 deletions __tests__/atomEffect.strict.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ it('should run the effect on mount and cleanup on unmount once', async () => {
await waitFor(() => assert(hasRun && hasMounted))
// effect does not return a value
expect(result.current).toBe(undefined)
console.log({ effect })
// initial render should run the effect
expect(effect.mount).toBe(1)
rerender()
Expand Down Expand Up @@ -114,7 +113,6 @@ it('should not cause infinite loops when effect updates the watched atom', async
const effectAtom = atomEffect((get, set) => {
get(watchedAtom)
runCount++
console.log('incrementing watchedAtom...')
set(watchedAtom, increment)
return () => {
set(watchedAtom, (c) => c - 1)
Expand Down Expand Up @@ -165,16 +163,14 @@ it('should not cause infinite loops when effect updates the watched atom asynchr
expect(runCount).toBe(2)
})

it.only('should allow synchronous infinite loops with opt-in for first run', async () => {
it('should allow synchronous infinite loops with opt-in for first run', async () => {
expect.assertions(1)
let runCount = 0
const watchedAtom = atom(0)
const effectAtom = atomEffect((get, { recurse }) => {
const value = get(watchedAtom)
runCount++
if (value < 5) {
console.log('setting watchedAtom...')
console.log('in effect: recurse', 'watchedAtom:', get(watchedAtom))
recurse(watchedAtom, increment)
}
})
Expand Down
122 changes: 18 additions & 104 deletions __tests__/atomEffect.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { act, renderHook, waitFor } from '@testing-library/react'
import { useAtom, useAtomValue, useSetAtom } from 'jotai/react'
import { atom, getDefaultStore } from 'jotai/vanilla'
import { atomEffect } from '../src/atomEffect'
import console from '../src/debugConsole'

it('should run the effect on vanilla store', async () => {
const store = getDefaultStore()
Expand Down Expand Up @@ -142,19 +141,15 @@ it('should not cause infinite loops when effect updates the watched atom', async
set(watchedAtom, increment)
})
const store = getDefaultStore()
console.log('{subscribe to effectAtom}')
store.sub(effectAtom, () => void 0)

const incrementWatched = async () => store.set(watchedAtom, increment)
await delay(0)
// initial render should run the effect once
console.log('{waiting for runCount === 1}')
await waitFor(() => assert(runCount === 1))
expect(runCount).toBe(1)
console.log('{incrementing watchedAtom}')
// changing the value should run the effect again one time
await incrementWatched()
console.log(`{runCount is now ${runCount}}`)
expect(runCount).toBe(2)
})

Expand All @@ -166,18 +161,15 @@ it('should not cause infinite loops when effect updates the watched atom asynchr
get(watchedAtom)
runCount++
setTimeout(() => {
console.log('in async')
set(watchedAtom, increment)
}, 0)
})
const store = getDefaultStore()
console.yellow('mounting effect')
store.sub(effectAtom, () => void 0)
await delay(0)
// initial render should run the effect once
await waitFor(() => assert(runCount === 1))

console.yellow('incrementing watchedAtom')
// changing the value should run the effect again one time
store.set(watchedAtom, increment)

Expand All @@ -192,14 +184,11 @@ it('should allow synchronous infinite loops with opt-in for first run', async ()
let done = false
const effectAtom = atomEffect((get, { recurse }) => {
const value = get(watchedAtom)
const thisRunCount = runCount++
console.log('in effect', { thisRunCount, value })
runCount++
if (value >= 3) {
console.red('GTE 3, EXITING --------')
done = true
return
}
console.log('setting watchedAtom...', { value })
recurse(watchedAtom, increment)
})
const store = getDefaultStore()
Expand All @@ -217,29 +206,20 @@ it('should allow synchronous infinite loops with opt-in', async () => {
const watchedAtom = atom(0)
const effectAtom = atomEffect((get, { recurse }) => {
const value = get(watchedAtom)
const thisRunCount = runCount++
console.log('value is ', value)
console.log('runCount is ', runCount)
runCount++
if (value === 0) {
console.red('value is zero, returning...')
return
}
if (value >= 5) {
console.red('GTE 5, EXITING --------')
return
}
console.log('setting watchedAtom...', 'watchedAtom:', get(watchedAtom))
recurse(watchedAtom, increment)
console.red('effect complete', { thisRunCount, value })
})
const store = getDefaultStore()
console.yellow('mounting effect')
store.sub(effectAtom, () => void 0)
await delay(0)
console.yellow('increment watched')
store.set(watchedAtom, increment)
await waitFor(() => assert(store.get(watchedAtom) === 5))
console.log('final watchedAtom:', store.get(watchedAtom))
expect(store.get(watchedAtom)).toBe(5)
expect(runCount).toBe(6)
})
Expand All @@ -248,44 +228,25 @@ it('should allow multiple synchronous infinite loops with opt-in', async () => {
expect.assertions(1)
let runCount = 0
const watchedAtom = atom(0)
const incrementWatched = atom(null, (get, set, stats: object) => {
console.orange('SET watchedAtom', {
...stats,
toValue: increment(get(watchedAtom)),
})
set(watchedAtom, increment)
})
let level = 0

Check warning on line 231 in __tests__/atomEffect.test.ts

View workflow job for this annotation

GitHub Actions / test

'level' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 231 in __tests__/atomEffect.test.ts

View workflow job for this annotation

GitHub Actions / test

'level' is assigned a value but never used. Allowed unused vars must match /^_/u
const effectAtom = atomEffect((get, { recurse }) => {
const value = get(watchedAtom)
const thisRunCount = runCount++
console.log('value is ', value)
console.log('runCount is ', thisRunCount)
runCount++
if (value === 0) {
console.red('IS ZERO, EXITING --------')
return
}
if (value >= 3) {
console.red('GTE 3, EXITING --------')
return
}
const thisLevel = level++
recurse(incrementWatched, { recurse: 'A', thisRunCount, thisLevel, value })
recurse(incrementWatched, { recurse: 'B', thisRunCount, thisLevel, value })
console.red('END OF EFFECT', { thisRunCount, value, thisLevel })
level++
recurse(watchedAtom, increment)
recurse(watchedAtom, increment)
level--
})
const store = getDefaultStore()
console.yellow('mounting effect')
store.sub(effectAtom, () => void 0)
await delay(0)
console.yellow('increment watched')
store.set(incrementWatched, {
recurse: 'FIRST',
thisRunCount: 0,
thisLevel: 0,
value: 0,
})
store.set(watchedAtom, increment)
await delay(0)
expect({ runCount, value: store.get(watchedAtom) }).toEqual({
runCount: 6,
Expand All @@ -301,9 +262,7 @@ it('should batch while synchronous recursing', async () => {
const watchedAtom = atom(0)
const lettersAndNumbersAtom = atom([] as string[])
const updateAtom = atom(0, (_get, set) => {
console.log('update lettersAtom')
set(lettersAtom, incrementLetter)
console.log('update numbersAtom')
set(numbersAtom, increment)
})
let level = 0

Check warning on line 268 in __tests__/atomEffect.test.ts

View workflow job for this annotation

GitHub Actions / test

'level' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 268 in __tests__/atomEffect.test.ts

View workflow job for this annotation

GitHub Actions / test

'level' is assigned a value but never used. Allowed unused vars must match /^_/u
Expand All @@ -313,72 +272,55 @@ it('should batch while synchronous recursing', async () => {
get(watchedAtom)
const thisRunCount = runCount++
if (thisRunCount === 0) {
console.red('IS ZERO, EXITING --------')
return
}
if (thisRunCount >= 3) {
console.red('GTE 3, EXITING --------')
return
}
let thisLevel = level++
console.log({ letters, numbers, thisRunCount, thisLevel })
level++
set(lettersAndNumbersAtom, (lettersAndNumbers: string[]) => [
...lettersAndNumbers,
letters + String(numbers),
])
set.recurse(updateAtom)
const lettersAndNumbers = get(lettersAndNumbersAtom)
console.red('END OF EFFECT', { thisRunCount, thisLevel, lettersAndNumbers })
level--
})
const store = getDefaultStore()
console.yellow('mounting effect')
store.sub(effectAtom, () => void 0)
await delay(0)
console.yellow('increment watched')
store.set(watchedAtom, increment)
await delay(0)
// await waitFor(() => assert(runCount === 4))
expect(store.get(lettersAndNumbersAtom)).toEqual(['a0', 'b1'])
expect(runCount).toBe(4)
})

it('should allow asynchronous infinite loops with task delay', async () => {
console.yellow('should allow asynchronous infinite loops with task delay')
expect.assertions(2)
let runCount = 0
const watchedAtom = atom(0)
let level = 0

Check warning on line 301 in __tests__/atomEffect.test.ts

View workflow job for this annotation

GitHub Actions / test

'level' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 301 in __tests__/atomEffect.test.ts

View workflow job for this annotation

GitHub Actions / test

'level' is assigned a value but never used. Allowed unused vars must match /^_/u
let done = false
const effectAtom = atomEffect((get, { recurse }) => {
const value = get(watchedAtom)
const thisRunCount = runCount++
runCount++
if (value >= 3) {
console.red('GTE 3, EXITING --------')
done = true
return
}
const thisLevel = level++
level++
delay(0).then(() => {
console.log('in async')
recurse(watchedAtom, increment)
})
console.red('END OF EFFECT', { thisRunCount, thisLevel, value })
level--
})
const store = getDefaultStore()
console.yellow('mounting effect')
store.sub(effectAtom, () => void 0)
await waitFor(() => assert(done))
expect(store.get(watchedAtom)).toBe(3)
expect(runCount).toBe(4)
console.log('-'.repeat(80))
})

it('should allow asynchronous infinite loops with microtask delay', async () => {
console.yellow(
'should allow asynchronous infinite loops with microtask delay'
)
expect.assertions(2)
let runCount = 0
const watchedAtom = atom(0)
Expand All @@ -387,29 +329,24 @@ it('should allow asynchronous infinite loops with microtask delay', async () =>
let done = false
const effectAtom = atomEffect((get, { recurse }) => {
const value = get(watchedAtom)
const thisRunCount = runCount++
runCount++
if (value >= 3) {
console.red('GTE 3, EXITING --------')
done = true
return
}
const thisLevel = level++
level++
Promise.resolve().then(() => {
console.log('in async', { thisRunCount, thisLevel, value })
recurse(watchedAtom, increment)
})
console.red('END OF EFFECT', { thisRunCount, thisLevel, value })
level--
})
const store = getDefaultStore()
console.yellow('mounting effect')
store.sub(effectAtom, () => void 0)
// await waitFor(() => assert(done))
done
await delay(500)
expect(store.get(watchedAtom)).toBe(3)
expect(runCount).toBe(4)
console.log('-'.repeat(80))
})

it('should work with both recurse and set', async () => {
Expand All @@ -424,10 +361,8 @@ it('should work with both recurse and set', async () => {
if (value === 0 || value % 3) {
set.recurse(watchedAtom, increment)
set(countAtom, increment)
console.log(get(watchedAtom), get(countAtom))
return
}
console.log('----- sole increment -----')
set(watchedAtom, increment)
})
const store = getDefaultStore()
Expand All @@ -439,30 +374,28 @@ it('should work with both recurse and set', async () => {
})

it('should disallow synchronous infinite loops in cleanup', async () => {
expect.assertions(2)
expect.assertions(3)
const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {})
let runCount = 0
const watchedAtom = atom(0)
const anotherAtom = atom(0)
const effectAtom = atomEffect((get, { recurse }) => {
const value = get(watchedAtom)
get(watchedAtom)
get(anotherAtom)
const thisRunCount = runCount++
console.log('in effect', { thisRunCount, value })
runCount++
return () => {
console.log('in cleanup', { thisRunCount, value })
recurse(watchedAtom, increment)
}
})
const store = getDefaultStore()
console.yellow('mounting effect')
store.sub(effectAtom, () => void 0)
await delay(0)
store.set(anotherAtom, increment)
await delay(0)
console.yellow('increment watched')
console.log('final watchedAtom:', store.get(watchedAtom))
expect(warnSpy).toHaveBeenCalled()
expect(store.get(watchedAtom)).toBe(0)
expect(runCount).toBe(2)
warnSpy.mockRestore()
})

// FIXME: is there a way to disallow asynchronous infinite loops in cleanup?
Expand Down Expand Up @@ -754,7 +687,6 @@ it('should batch synchronous updates as a single transaction', async () => {
runCount++
const letters = get(lettersAtom)
const numbers = get(numbersAtom)
console.log({ letters, numbers })
set(lettersAndNumbersAtom, (lettersAndNumbers) => [
...lettersAndNumbers,
letters + String(numbers),
Expand All @@ -767,27 +699,9 @@ it('should batch synchronous updates as a single transaction', async () => {
expect(runCount).toBe(1)
expect(store.get(lettersAndNumbersAtom)).toEqual(['a0'])
await act(async () => {
console.log(
'setLetters',
store.get(lettersAtom),
store.get(numbersAtom),
store.get(lettersAndNumbersAtom)
)
store.set(lettersAtom, incrementLetter)
console.log(
'setNumbers',
store.get(lettersAtom),
store.get(numbersAtom),
store.get(lettersAndNumbersAtom)
)
store.set(numbersAtom, increment)
})
console.log(
'after',
store.get(lettersAtom),
store.get(numbersAtom),
store.get(lettersAndNumbersAtom)
)
expect(runCount).toBe(2)
expect(store.get(lettersAndNumbersAtom)).toEqual(['a0', 'b1'])
})
Expand Down
Loading

0 comments on commit d905d72

Please sign in to comment.