From 727a32198c53d39a834bd32623b5fd793fac8332 Mon Sep 17 00:00:00 2001
From: Lincoln <778157949@qq.com>
Date: Tue, 27 Aug 2024 06:58:51 +0000
Subject: [PATCH] add some unit test
---
README.md | 6 ++--
__tests__/basic.test.tsx | 56 +++++++++++++++++++++++++++++
__tests__/priority.test.tsx | 67 +++++++++++++++++++++++++++++++++++
src/useSetAtomWithSchedule.ts | 4 +--
src/workLoop.ts | 18 ++++++----
tsconfig.json | 1 +
6 files changed, 140 insertions(+), 12 deletions(-)
create mode 100644 __tests__/basic.test.tsx
create mode 100644 __tests__/priority.test.tsx
diff --git a/README.md b/README.md
index dbb13e2..e4a569e 100644
--- a/README.md
+++ b/README.md
@@ -109,14 +109,14 @@ const anAtom = atom(0);
const Header = () => {
const num = useAtomValueWithSchedule(anAtom, {
- priority: LowPriority,
+ priority: LOW_PRIORITY,
});
return
diff --git a/__tests__/basic.test.tsx b/__tests__/basic.test.tsx
new file mode 100644
index 0000000..4aef7a5
--- /dev/null
+++ b/__tests__/basic.test.tsx
@@ -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 (
+ <>
+
+
Control commits: {useCommitCount()}
+ >
+ )
+ }
+ function Display() {
+ const num = useAtomValueWithSchedule(anAtom)
+ return (
+ <>
+
number: {num}
+
Display commits: {useCommitCount()}
+ >
+ )
+ }
+ function App() {
+ return (
+ <>
+
+
+ >
+ )
+ }
+ const { findByText, getByText } = render(
)
+ await findByText('number: 0')
+ await userEvent.click(getByText('button'))
+ await waitFor(() => {
+ findByText('number: 1')
+ findByText('Display commits: 1')
+ findByText('Control commits: 2')
+ })
+ })
+})
diff --git a/__tests__/priority.test.tsx b/__tests__/priority.test.tsx
new file mode 100644
index 0000000..f625ec2
--- /dev/null
+++ b/__tests__/priority.test.tsx
@@ -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
number of ImmediatePriorityCpn: {num}
+ }
+ function NormalPriorityCpn() {
+ const num = useAtomValueWithSchedule(anAtom, {
+ priority: NORMAL_PRIORITY,
+ })
+ return
number of NormalPriorityCpn: {num}
+ }
+ function LowPriorityCpn() {
+ const num = useAtomValueWithSchedule(anAtom, {
+ priority: LOW_PRIORITY,
+ })
+ return
number of LowPriorityCpn: {num}
+ }
+ function App() {
+ const dispatch = useSetAtomWithSchedule(anAtom)
+ return (
+ <>
+
+
+
+
+ >
+ )
+ }
+ const { findByText, getByText } = render(
)
+
+ 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')
+ })
+})
diff --git a/src/useSetAtomWithSchedule.ts b/src/useSetAtomWithSchedule.ts
index 1d1f0d7..a82677a 100644
--- a/src/useSetAtomWithSchedule.ts
+++ b/src/useSetAtomWithSchedule.ts
@@ -22,9 +22,7 @@ export function useSetAtomWithSchedule
(
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')
diff --git a/src/workLoop.ts b/src/workLoop.ts
index 9388976..202844c 100644
--- a/src/workLoop.ts
+++ b/src/workLoop.ts
@@ -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 = () => {
diff --git a/tsconfig.json b/tsconfig.json
index dedebcc..956bc59 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -17,5 +17,6 @@
"jotai-scheduler": ["./src/index.ts"]
}
},
+ "include": ["src", "__tests__"],
"exclude": ["dist", "examples", "jotai"]
}