Skip to content

Commit

Permalink
add some unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
L-Qun committed Aug 27, 2024
1 parent 5205122 commit 727a321
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 12 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,14 @@ const anAtom = atom(0);
const Header = () => {
const num = useAtomValueWithSchedule(anAtom, {
priority: LowPriority,
priority: LOW_PRIORITY,
});
return <div className="header">Header-{num}</div>;
};
const Footer = () => {
const num = useAtomValueWithSchedule(anAtom, {
priority: LowPriority,
priority: LOW_PRIORITY,
});
return <div className="footer">Footer-{num}</div>;
};
Expand All @@ -128,7 +128,7 @@ const Sidebar = () => {
const Content = () => {
const [num, setNum] = useAtomWithSchedule(anAtom, {
priority: ImmediatePriority,
priority: IMMEDIATE_PRIORITY,
});
return (
<div className="content">
Expand Down
56 changes: 56 additions & 0 deletions __tests__/basic.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { atom } from 'jotai'
import { render, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { useEffect, useRef } from 'react'

import { useAtomValueWithSchedule, useSetAtomWithSchedule } from '../src'

const useCommitCount = () => {
const commitCountRef = useRef(1)
useEffect(() => {
commitCountRef.current += 1
})
return commitCountRef.current
}

describe('the same behavior as jotai if the `priority` field is not passed', () => {
it('trigger state updates correctly', async () => {
const anAtom = atom(0)
function Control() {
const dispatch = useSetAtomWithSchedule(anAtom)
return (
<>
<button type="button" onClick={() => dispatch((num) => num + 1)}>
button
</button>
<div>Control commits: {useCommitCount()}</div>
</>
)
}
function Display() {
const num = useAtomValueWithSchedule(anAtom)
return (
<>
<div>number: {num}</div>
<div>Display commits: {useCommitCount()}</div>
</>
)
}
function App() {
return (
<>
<Display />
<Control />
</>
)
}
const { findByText, getByText } = render(<App />)
await findByText('number: 0')
await userEvent.click(getByText('button'))
await waitFor(() => {
findByText('number: 1')
findByText('Display commits: 1')
findByText('Control commits: 2')
})
})
})
67 changes: 67 additions & 0 deletions __tests__/priority.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { atom } from 'jotai'
import { render, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'

import {
IMMEDIATE_PRIORITY,
LOW_PRIORITY,
NORMAL_PRIORITY,
useAtomValueWithSchedule,
useSetAtomWithSchedule,
} from '../src'

it('batching rendering if we pass different `priority`', async () => {
const anAtom = atom(0)
function ImmediatePriorityCpn() {
const num = useAtomValueWithSchedule(anAtom, {
priority: IMMEDIATE_PRIORITY,
})
return <div>number of ImmediatePriorityCpn: {num}</div>
}
function NormalPriorityCpn() {
const num = useAtomValueWithSchedule(anAtom, {
priority: NORMAL_PRIORITY,
})
return <div>number of NormalPriorityCpn: {num}</div>
}
function LowPriorityCpn() {
const num = useAtomValueWithSchedule(anAtom, {
priority: LOW_PRIORITY,
})
return <div>number of LowPriorityCpn: {num}</div>
}
function App() {
const dispatch = useSetAtomWithSchedule(anAtom)
return (
<>
<ImmediatePriorityCpn />
<NormalPriorityCpn />
<LowPriorityCpn />
<button type="button" onClick={() => dispatch((num) => num + 1)}>
button
</button>
</>
)
}
const { findByText, getByText } = render(<App />)

await userEvent.click(getByText('button'))

await waitFor(() => {
findByText('number of ImmediatePriorityCpn: 1')
findByText('number of NormalPriorityCpn: 0')
findByText('number of LowPriorityCpn: 0')
})

await waitFor(() => {
findByText('number of ImmediatePriorityCpn: 1')
findByText('number of NormalPriorityCpn: 1')
findByText('number of LowPriorityCpn: 0')
})

await waitFor(() => {
findByText('number of ImmediatePriorityCpn: 1')
findByText('number of NormalPriorityCpn: 1')
findByText('number of LowPriorityCpn: 1')
})
})
4 changes: 1 addition & 3 deletions src/useSetAtomWithSchedule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ export function useSetAtomWithSchedule<Value, Args extends unknown[], Result>(
const store = useStore(options)
const setAtom = useCallback(
(...args: Args) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
if (import.meta.env?.MODE !== 'production' && !('write' in atom)) {
if (!('write' in atom)) {
// useAtom can pass non writable atom with wrong type assertion,
// so we should check here.
throw new Error('not writable atom')
Expand Down
18 changes: 12 additions & 6 deletions src/workLoop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,18 @@ function handleNextBatch() {
}
}

const channel = new MessageChannel()
const port = channel.port2
channel.port1.onmessage = handleNextBatch

export const enqueueWorkExecution = () => {
port.postMessage(null)
let enqueueWorkExecution: () => void
if (typeof MessageChannel !== 'undefined') {
const channel = new MessageChannel()
const port = channel.port2
channel.port1.onmessage = handleNextBatch
enqueueWorkExecution = (): void => {
port.postMessage(null)
}
} else {
enqueueWorkExecution = (): void => {
setTimeout(handleNextBatch, 0)
}
}

export const initiateWorkLoop = () => {
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
"jotai-scheduler": ["./src/index.ts"]
}
},
"include": ["src", "__tests__"],
"exclude": ["dist", "examples", "jotai"]
}

0 comments on commit 727a321

Please sign in to comment.