import { act, render } from '@testing-library/react'
import * as React from 'react'
import { atom } from '../core/Atom'
import { useStateTracking } from './useStateTracking'
describe('useStateTracking', () => {
it('causes a rerender when a dependency changes', async () => {
const a = atom('', 0)
const Component = () => {
const val = useStateTracking('', () => {
return a.get()
})
return <>You are {val} years old>
}
let view = render()
await act(async () => {
view = render()
})
expect(view.container!.textContent).toMatchInlineSnapshot(`"You are 0 years old"`)
act(() => {
a.set(1)
})
expect(view.container!.textContent).toMatchInlineSnapshot(`"You are 1 years old"`)
})
it('allows using hooks inside the callback', async () => {
const _age = atom('', 0)
let setHeight: (height: number) => void
const Component = () => {
let height
const age = useStateTracking('', () => {
// eslint-disable-next-line react-hooks/rules-of-hooks
;[height, setHeight] = React.useState(20)
return _age.get()
})
return (
<>
You are {age} years old and {height} meters tall
>
)
}
let view = render()
await act(async () => {
view = render()
})
expect(view.container!.textContent).toMatchInlineSnapshot(
`"You are 0 years old and 20 meters tall"`
)
act(() => {
_age.set(1)
})
expect(view.container!.textContent).toMatchInlineSnapshot(
`"You are 1 years old and 20 meters tall"`
)
act(() => {
setHeight(21)
})
expect(view.container!.textContent).toMatchInlineSnapshot(
`"You are 1 years old and 21 meters tall"`
)
})
// it('allows throwing promises to trigger suspense boundaries', async () => {
// const a = atom('age', null)
// let resolve = (_val: string) => {
// // noop
// }
// const Component = () => {
// const val = useStateTracking('', () => {
// if (a.get() === null) {
// throw new Promise((r) => {
// resolve = r
// })
// }
// return a.get()
// })
// return <>You are {val} years old>
// }
// let view = render(
// fallback>}>
//
//
// )
// await act(async () => {
// view = render(
// fallback>}>
//
//
// )
// })
// expect(view.container!.textContent).toMatchInlineSnapshot(`"fallback"`)
// act(() => {
// a.set(1)
// })
// expect(view.container!.textContent).toMatchInlineSnapshot(`"fallback"`)
// act(() => {
// resolve('resolved')
// })
// expect(view.container!.textContent).toMatchInlineSnapshot(`"You are 1 years old"`)
// })
// it('stops reacting when the component unmounts', async () => {
// const a = atom('', 0)
// let numRenders = 0
// const Component = () => {
// const val = useStateTracking('', () => {
// numRenders++
// return a.get()
// })
// return <>You are {val} years old>
// }
// let view = render(React.createElement(Component))
// await act(async () => {
// view = render(React.createElement(Component))
// })
// expect(view.container!.textContent).toMatchInlineSnapshot(`"You are 0 years old"`)
// expect(numRenders).toBe(1)
// act(() => {
// a.set(1)
// })
// expect(view.container!.textContent).toMatchInlineSnapshot(`"You are 1 years old"`)
// expect(numRenders).toBe(2)
// await act(async () => {
// view.unmount()
// })
// act(() => {
// a.set(2)
// })
// expect(numRenders).toBe(2)
// })
})