diff --git a/__tests__/ScopeProvider/01_basic_spec.tsx b/__tests__/ScopeProvider/01_basic_spec.test.tsx
similarity index 100%
rename from __tests__/ScopeProvider/01_basic_spec.tsx
rename to __tests__/ScopeProvider/01_basic_spec.test.tsx
diff --git a/__tests__/ScopeProvider/02_removeScope.tsx b/__tests__/ScopeProvider/02_removeScope.test.tsx
similarity index 100%
rename from __tests__/ScopeProvider/02_removeScope.tsx
rename to __tests__/ScopeProvider/02_removeScope.test.tsx
diff --git a/__tests__/ScopeProvider/03_nested.tsx b/__tests__/ScopeProvider/03_nested.test.tsx
similarity index 100%
rename from __tests__/ScopeProvider/03_nested.tsx
rename to __tests__/ScopeProvider/03_nested.test.tsx
diff --git a/__tests__/ScopeProvider/04_derived.tsx b/__tests__/ScopeProvider/04_derived.test.tsx
similarity index 100%
rename from __tests__/ScopeProvider/04_derived.tsx
rename to __tests__/ScopeProvider/04_derived.test.tsx
diff --git a/__tests__/ScopeProvider/05_derived_self.tsx b/__tests__/ScopeProvider/05_derived_self.test.tsx
similarity index 100%
rename from __tests__/ScopeProvider/05_derived_self.tsx
rename to __tests__/ScopeProvider/05_derived_self.test.tsx
diff --git a/__tests__/ScopeProvider/06_implicit_parent.tsx b/__tests__/ScopeProvider/06_implicit_parent.test.tsx
similarity index 100%
rename from __tests__/ScopeProvider/06_implicit_parent.tsx
rename to __tests__/ScopeProvider/06_implicit_parent.test.tsx
diff --git a/__tests__/ScopeProvider/07_writable.tsx b/__tests__/ScopeProvider/07_writable.test.tsx
similarity index 100%
rename from __tests__/ScopeProvider/07_writable.tsx
rename to __tests__/ScopeProvider/07_writable.test.tsx
diff --git a/__tests__/ScopeProvider/08_family.tsx b/__tests__/ScopeProvider/08_family.test.tsx
similarity index 100%
rename from __tests__/ScopeProvider/08_family.tsx
rename to __tests__/ScopeProvider/08_family.test.tsx
diff --git a/__tests__/ScopeProvider/09_scope_provider.tsx b/__tests__/ScopeProvider/09_mount.test.tsx
similarity index 65%
rename from __tests__/ScopeProvider/09_scope_provider.tsx
rename to __tests__/ScopeProvider/09_mount.test.tsx
index f223c20..61a3cc8 100644
--- a/__tests__/ScopeProvider/09_scope_provider.tsx
+++ b/__tests__/ScopeProvider/09_mount.test.tsx
@@ -41,3 +41,33 @@ describe('ScopeProvider', () => {
expect(container.querySelector(base)).toBe(null)
})
})
+
+it('computed atom mounts once for the unscoped and once for the scoped', () => {
+ const baseAtom = atom(0)
+ const deriveAtom = atom(
+ (get) => get(baseAtom),
+ () => {},
+ )
+ const onUnmount = jest.fn()
+ const onMount = jest.fn(() => onUnmount)
+ deriveAtom.onMount = onMount
+ function Component() {
+ return useAtomValue(deriveAtom)
+ }
+ function App() {
+ return (
+ <>
+
+
+
+
+
+
+ >
+ )
+ }
+ const { unmount } = render()
+ expect(onMount).toHaveBeenCalledTimes(2)
+ unmount()
+ expect(onUnmount).toHaveBeenCalledTimes(2)
+})
diff --git a/__tests__/createIsolation/01_basic_spec.tsx b/__tests__/createIsolation/01_basic_spec.test.tsx
similarity index 100%
rename from __tests__/createIsolation/01_basic_spec.tsx
rename to __tests__/createIsolation/01_basic_spec.test.tsx
diff --git a/__tests__/utils.ts b/__tests__/utils.ts
index d08ffa0..0d210fe 100644
--- a/__tests__/utils.ts
+++ b/__tests__/utils.ts
@@ -1,4 +1,6 @@
import { fireEvent } from '@testing-library/react'
+import { Store } from 'src/ScopeProvider/types'
+import { INTERNAL_DevStoreRev4, INTERNAL_PrdStore } from 'jotai/vanilla/store'
function getElements(container: HTMLElement, querySelectors: string[]): Element[] {
return querySelectors.map((querySelector) => {
@@ -21,3 +23,30 @@ export function clickButton(container: HTMLElement, querySelector: string) {
}
fireEvent.click(button)
}
+
+export function getDevStore(store: Store): INTERNAL_PrdStore & INTERNAL_DevStoreRev4 {
+ if (!isDevStore(store)) {
+ throw new Error('Store is not a dev store')
+ }
+ return store
+}
+
+export function isDevStore(store: Store): store is INTERNAL_PrdStore & INTERNAL_DevStoreRev4 {
+ return (
+ 'dev4_get_internal_weak_map' in store &&
+ 'dev4_get_mounted_atoms' in store &&
+ 'dev4_restore_atoms' in store
+ )
+}
+
+export function assertIsDevStore(
+ store: Store,
+): asserts store is INTERNAL_PrdStore & INTERNAL_DevStoreRev4 {
+ if (!isDevStore(store)) {
+ throw new Error('Store is not a dev store')
+ }
+}
+
+export function delay(ms: number) {
+ return new Promise((resolve) => setTimeout(resolve, ms))
+}
diff --git a/package.json b/package.json
index 354addb..4869ae4 100644
--- a/package.json
+++ b/package.json
@@ -44,8 +44,8 @@
"jest": {
"testEnvironment": "jsdom",
"preset": "ts-jest/presets/js-with-ts",
- "testPathIgnorePatterns": [
- "utils.ts"
+ "testMatch": [
+ "**/__tests__/**/*.test.*"
]
},
"keywords": [
@@ -59,6 +59,7 @@
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.5.1",
"@types/jest": "^29.5.6",
+ "@types/minimalistic-assert": "^1.0.3",
"@types/node": "^20.8.7",
"@types/react": "^18.2.31",
"@types/react-dom": "^18.2.14",
@@ -75,8 +76,8 @@
"html-webpack-plugin": "^5.5.3",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
- "jotai": "2.9.2",
"microbundle": "^0.15.1",
+ "minimalistic-assert": "^1.0.1",
"npm-run-all": "^4.1.5",
"prettier": "^3.0.3",
"react": "^18.2.0",
@@ -90,7 +91,7 @@
"webpack-dev-server": "^4.15.1"
},
"peerDependencies": {
- "jotai": ">=2.9.2",
+ "jotai": ">=2.9.3",
"react": ">=17.0.0"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6b6cbad..4a0209d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -4,6 +4,11 @@ settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
+dependencies:
+ jotai:
+ specifier: '>=2.9.3'
+ version: 2.9.3(@types/react@18.2.31)(react@18.2.0)
+
devDependencies:
'@testing-library/dom':
specifier: ^9.3.3
@@ -17,6 +22,9 @@ devDependencies:
'@types/jest':
specifier: ^29.5.6
version: 29.5.6
+ '@types/minimalistic-assert':
+ specifier: ^1.0.3
+ version: 1.0.3
'@types/node':
specifier: ^20.8.7
version: 20.8.7
@@ -65,12 +73,12 @@ devDependencies:
jest-environment-jsdom:
specifier: ^29.7.0
version: 29.7.0
- jotai:
- specifier: 2.9.2
- version: 2.9.2(@types/react@18.2.31)(react@18.2.0)
microbundle:
specifier: ^0.15.1
version: 0.15.1
+ minimalistic-assert:
+ specifier: ^1.0.1
+ version: 1.0.1
npm-run-all:
specifier: ^4.1.5
version: 4.1.5
@@ -2102,6 +2110,10 @@ packages:
resolution: {integrity: sha512-i8MBln35l856k5iOhKk2XJ4SeAWg75mLIpZB4v6imOagKL6twsukBZGDMNhdOVk7yRFTMPpfILocMos59Q1otQ==}
dev: true
+ /@types/minimalistic-assert@1.0.3:
+ resolution: {integrity: sha512-Ku87cam4YxiXcEpeUemo+vO8QWGQ7U2CwEEcLcYFhxG8b4CK8gWxSX/oWjePWKwqPaWWxxVqXAdAjGdlJtVzDA==}
+ dev: true
+
/@types/node@20.8.7:
resolution: {integrity: sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==}
dependencies:
@@ -2114,7 +2126,6 @@ packages:
/@types/prop-types@15.7.9:
resolution: {integrity: sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==}
- dev: true
/@types/qs@6.9.9:
resolution: {integrity: sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg==}
@@ -2136,7 +2147,6 @@ packages:
'@types/prop-types': 15.7.9
'@types/scheduler': 0.16.5
csstype: 3.1.2
- dev: true
/@types/resolve@1.17.1:
resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==}
@@ -2150,7 +2160,6 @@ packages:
/@types/scheduler@0.16.5:
resolution: {integrity: sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw==}
- dev: true
/@types/semver@7.5.4:
resolution: {integrity: sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==}
@@ -3521,7 +3530,6 @@ packages:
/csstype@3.1.2:
resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==}
- dev: true
/damerau-levenshtein@1.0.8:
resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
@@ -5938,8 +5946,8 @@ packages:
- ts-node
dev: true
- /jotai@2.9.2(@types/react@18.2.31)(react@18.2.0):
- resolution: {integrity: sha512-jIBXEadOHCziOuMY6HAy2KQcHipGhnsbF+twqh8Lcmcz/Yei0gdBtW5mOYdKmbQxGqkvfvXM3w/oHtJ2WNGSFg==}
+ /jotai@2.9.3(@types/react@18.2.31)(react@18.2.0):
+ resolution: {integrity: sha512-IqMWKoXuEzWSShjd9UhalNsRGbdju5G2FrqNLQJT+Ih6p41VNYe2sav5hnwQx4HJr25jq9wRqvGSWGviGG6Gjw==}
engines: {node: '>=12.20.0'}
peerDependencies:
'@types/react': '>=17.0.0'
@@ -5952,11 +5960,10 @@ packages:
dependencies:
'@types/react': 18.2.31
react: 18.2.0
- dev: true
+ dev: false
/js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
- dev: true
/js-yaml@3.14.1:
resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
@@ -6203,7 +6210,6 @@ packages:
hasBin: true
dependencies:
js-tokens: 4.0.0
- dev: true
/lower-case@2.0.2:
resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==}
@@ -7439,7 +7445,6 @@ packages:
engines: {node: '>=0.10.0'}
dependencies:
loose-envify: 1.4.0
- dev: true
/read-pkg@3.0.0:
resolution: {integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==}