@automerge/automerge-repo-react-hooks 1.1.2 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -4
- package/test/useDocument.test.tsx +54 -78
- package/test/useDocuments.test.tsx +48 -66
- package/test/useHandle.test.tsx +29 -46
- package/test/useRepo.test.tsx +15 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automerge/automerge-repo-react-hooks",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
4
4
|
"description": "Hooks to access an Automerge Repo from your react app.",
|
|
5
5
|
"repository": "https://github.com/automerge/automerge-repo/tree/master/packages/automerge-repo-react-hooks",
|
|
6
6
|
"author": "Peter van Hardenberg <pvh@pvh.ca>",
|
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
"scripts": {
|
|
11
11
|
"build": "tsc --noEmit && vite build",
|
|
12
12
|
"test": "vitest run",
|
|
13
|
-
"watch": "npm-watch",
|
|
13
|
+
"watch": "npm-watch build",
|
|
14
14
|
"visualize": "VISUALIZE=true vite build"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@automerge/automerge": "^2.1.9",
|
|
18
|
-
"@automerge/automerge-repo": "1.1.
|
|
18
|
+
"@automerge/automerge-repo": "1.1.4",
|
|
19
19
|
"eventemitter3": "^5.0.1",
|
|
20
20
|
"react": "^18.2.0",
|
|
21
21
|
"react-dom": "^18.2.0",
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"publishConfig": {
|
|
43
43
|
"access": "public"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "e819a7ed6302ce34f372b119ea3e8bab052e3af6"
|
|
46
46
|
}
|
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
import { AutomergeUrl, PeerId, Repo } from "@automerge/automerge-repo"
|
|
2
2
|
import { DummyStorageAdapter } from "@automerge/automerge-repo/test/helpers/DummyStorageAdapter"
|
|
3
|
-
import {
|
|
4
|
-
import React
|
|
5
|
-
import {
|
|
6
|
-
import { describe, expect, it } from "vitest"
|
|
3
|
+
import { render, waitFor } from "@testing-library/react"
|
|
4
|
+
import React from "react"
|
|
5
|
+
import { describe, expect, it, vi } from "vitest"
|
|
7
6
|
import { useDocument } from "../src/useDocument"
|
|
8
7
|
import { RepoContext } from "../src/useRepo"
|
|
9
8
|
|
|
10
9
|
const SLOW_DOC_LOAD_TIME_MS = 10
|
|
11
10
|
|
|
12
11
|
describe("useDocument", () => {
|
|
13
|
-
const repo = new Repo({
|
|
14
|
-
peerId: "bob" as PeerId,
|
|
15
|
-
network: [],
|
|
16
|
-
storage: new DummyStorageAdapter(),
|
|
17
|
-
})
|
|
18
|
-
|
|
19
12
|
function setup() {
|
|
13
|
+
const repo = new Repo({
|
|
14
|
+
peerId: "bob" as PeerId,
|
|
15
|
+
network: [],
|
|
16
|
+
storage: new DummyStorageAdapter(),
|
|
17
|
+
})
|
|
18
|
+
|
|
20
19
|
const handleA = repo.create<ExampleDoc>()
|
|
21
20
|
handleA.change(doc => (doc.foo = "A"))
|
|
22
21
|
|
|
@@ -36,121 +35,98 @@ describe("useDocument", () => {
|
|
|
36
35
|
return result
|
|
37
36
|
}
|
|
38
37
|
|
|
38
|
+
const wrapper = ({ children }) => {
|
|
39
|
+
return <RepoContext.Provider value={repo}>{children}</RepoContext.Provider>
|
|
40
|
+
}
|
|
41
|
+
|
|
39
42
|
return {
|
|
40
43
|
repo,
|
|
41
44
|
handleA,
|
|
42
45
|
handleB,
|
|
43
46
|
handleSlow,
|
|
44
|
-
wrapper
|
|
47
|
+
wrapper,
|
|
45
48
|
}
|
|
46
49
|
}
|
|
47
50
|
|
|
51
|
+
const Component = ({ url, onDoc }: {
|
|
52
|
+
url: AutomergeUrl,
|
|
53
|
+
onDoc: (doc: ExampleDoc) => void,
|
|
54
|
+
}) => {
|
|
55
|
+
const [doc] = useDocument(url)
|
|
56
|
+
onDoc(doc)
|
|
57
|
+
return null
|
|
58
|
+
}
|
|
59
|
+
|
|
48
60
|
it("should load a document", async () => {
|
|
49
61
|
const { handleA, wrapper } = setup()
|
|
62
|
+
const onDoc = vi.fn()
|
|
50
63
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
await waitFor(() => {
|
|
54
|
-
const [doc] = result.current
|
|
55
|
-
expect(doc).toEqual({ foo: "A" })
|
|
56
|
-
})
|
|
64
|
+
render(<Component url={handleA.url} onDoc={onDoc} />, {wrapper})
|
|
65
|
+
await waitFor(() => expect(onDoc).toHaveBeenLastCalledWith({ foo: "A" }))
|
|
57
66
|
})
|
|
58
67
|
|
|
59
68
|
it("should update if the url changes", async () => {
|
|
60
|
-
const {
|
|
69
|
+
const { handleA, handleB, wrapper } = setup()
|
|
70
|
+
const onDoc = vi.fn()
|
|
61
71
|
|
|
62
|
-
const {
|
|
63
|
-
|
|
64
|
-
() => {
|
|
65
|
-
const [url, setUrl] = useState<AutomergeUrl>()
|
|
66
|
-
const [doc] = useDocument(url)
|
|
67
|
-
return { setUrl, doc }
|
|
68
|
-
},
|
|
69
|
-
{ wrapper }
|
|
70
|
-
)
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
await waitFor(() => expect(result.current).not.toBeNull())
|
|
72
|
+
const { rerender } = render(<Component url={undefined} onDoc={onDoc} />, {wrapper})
|
|
73
|
+
await waitFor(() => expect(onDoc).toHaveBeenLastCalledWith(undefined))
|
|
74
74
|
|
|
75
75
|
// set url to doc A
|
|
76
|
-
|
|
77
|
-
await waitFor(() => expect(
|
|
76
|
+
rerender(<Component url={handleA.url} onDoc={onDoc} />)
|
|
77
|
+
await waitFor(() => expect(onDoc).toHaveBeenLastCalledWith({ foo: "A" }))
|
|
78
78
|
|
|
79
79
|
// set url to doc B
|
|
80
|
-
|
|
81
|
-
await waitFor(() => expect(
|
|
80
|
+
rerender(<Component url={handleB.url} onDoc={onDoc} />)
|
|
81
|
+
await waitFor(() => expect(onDoc).toHaveBeenLastCalledWith({ foo: "B" }))
|
|
82
82
|
|
|
83
83
|
// set url to undefined
|
|
84
|
-
|
|
85
|
-
await waitFor(() => expect(
|
|
84
|
+
rerender(<Component url={undefined} onDoc={onDoc} />)
|
|
85
|
+
await waitFor(() => expect(onDoc).toHaveBeenLastCalledWith(undefined))
|
|
86
86
|
})
|
|
87
87
|
|
|
88
88
|
it("sets the doc to undefined while the initial load is happening", async () => {
|
|
89
|
-
const {
|
|
90
|
-
|
|
91
|
-
const { result } = await act(() =>
|
|
92
|
-
renderHook(
|
|
93
|
-
() => {
|
|
94
|
-
const [url, setUrl] = useState<AutomergeUrl>()
|
|
95
|
-
const [doc] = useDocument(url)
|
|
96
|
-
return { setUrl, doc }
|
|
97
|
-
},
|
|
98
|
-
{ wrapper }
|
|
99
|
-
)
|
|
100
|
-
)
|
|
89
|
+
const { handleA, handleSlow, wrapper } = setup()
|
|
90
|
+
const onDoc = vi.fn()
|
|
101
91
|
|
|
102
|
-
|
|
92
|
+
const { rerender } = render(<Component url={undefined} onDoc={onDoc} />, {wrapper})
|
|
93
|
+
await waitFor(() => expect(onDoc).toHaveBeenLastCalledWith(undefined))
|
|
103
94
|
|
|
104
95
|
// start by setting url to doc A
|
|
105
|
-
|
|
106
|
-
await waitFor(() => expect(
|
|
96
|
+
rerender(<Component url={handleA.url} onDoc={onDoc} />)
|
|
97
|
+
await waitFor(() => expect(onDoc).toHaveBeenLastCalledWith({ foo: "A" }))
|
|
107
98
|
|
|
108
99
|
// Now we set the URL to a handle that's slow to load.
|
|
109
100
|
// The doc should be undefined while the load is happening.
|
|
110
|
-
|
|
111
|
-
await waitFor(() => expect(
|
|
112
|
-
await waitFor(() => expect(
|
|
101
|
+
rerender(<Component url={handleSlow.url} onDoc={onDoc} />)
|
|
102
|
+
await waitFor(() => expect(onDoc).toHaveBeenLastCalledWith(undefined))
|
|
103
|
+
await waitFor(() => expect(onDoc).toHaveBeenLastCalledWith({ foo: "slow" }))
|
|
113
104
|
})
|
|
114
105
|
|
|
115
106
|
it("avoids showing stale data", async () => {
|
|
116
|
-
const {
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const [doc] = useDocument(url)
|
|
122
|
-
return { setUrl, doc }
|
|
123
|
-
},
|
|
124
|
-
{ wrapper }
|
|
125
|
-
)
|
|
126
|
-
)
|
|
127
|
-
|
|
128
|
-
await waitFor(() => expect(result.current).not.toBeNull())
|
|
107
|
+
const { handleA, handleSlow, wrapper } = setup()
|
|
108
|
+
const onDoc = vi.fn()
|
|
109
|
+
|
|
110
|
+
const { rerender } = render(<Component url={undefined} onDoc={onDoc} />, {wrapper})
|
|
111
|
+
await waitFor(() => expect(onDoc).toHaveBeenLastCalledWith(undefined))
|
|
129
112
|
|
|
130
113
|
// Set the URL to a slow doc and then a fast doc.
|
|
131
114
|
// We should see the fast doc forever, even after
|
|
132
115
|
// the slow doc has had time to finish loading.
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
})
|
|
137
|
-
await waitFor(() => expect(result.current.doc).toEqual({ foo: "A" }))
|
|
116
|
+
rerender(<Component url={handleSlow.url} onDoc={onDoc} />)
|
|
117
|
+
rerender(<Component url={handleA.url} onDoc={onDoc} />)
|
|
118
|
+
await waitFor(() => expect(onDoc).toHaveBeenLastCalledWith({ foo: "A" }))
|
|
138
119
|
|
|
139
120
|
// wait for the slow doc to finish loading...
|
|
140
121
|
await pause(SLOW_DOC_LOAD_TIME_MS * 2)
|
|
141
122
|
|
|
142
123
|
// we didn't update the doc to the slow doc, so it should still be A
|
|
143
|
-
|
|
124
|
+
expect(onDoc).not.toHaveBeenCalledWith({ foo: "slow" })
|
|
144
125
|
})
|
|
145
126
|
})
|
|
146
127
|
|
|
147
128
|
const pause = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
|
|
148
129
|
|
|
149
|
-
const getRepoWrapper =
|
|
150
|
-
(repo: Repo) =>
|
|
151
|
-
({ children }) =>
|
|
152
|
-
<RepoContext.Provider value={repo}>{children}</RepoContext.Provider>
|
|
153
|
-
|
|
154
130
|
interface ExampleDoc {
|
|
155
131
|
foo: string
|
|
156
132
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { DocumentId, PeerId, Repo } from "@automerge/automerge-repo"
|
|
2
2
|
import { DummyStorageAdapter } from "@automerge/automerge-repo/test/helpers/DummyStorageAdapter"
|
|
3
|
-
import { act,
|
|
3
|
+
import { act, render, waitFor } from "@testing-library/react"
|
|
4
4
|
import React from "react"
|
|
5
|
-
import { describe, expect, it } from "vitest"
|
|
5
|
+
import { describe, expect, it, vi } from "vitest"
|
|
6
6
|
import { useDocuments } from "../src/useDocuments"
|
|
7
7
|
import { RepoContext } from "../src/useRepo"
|
|
8
8
|
|
|
@@ -14,7 +14,9 @@ describe("useDocuments", () => {
|
|
|
14
14
|
storage: new DummyStorageAdapter(),
|
|
15
15
|
})
|
|
16
16
|
|
|
17
|
-
const wrapper =
|
|
17
|
+
const wrapper = ({ children }) => {
|
|
18
|
+
return <RepoContext.Provider value={repo}>{children}</RepoContext.Provider>
|
|
19
|
+
}
|
|
18
20
|
|
|
19
21
|
const documentIds = range(10).map(i => {
|
|
20
22
|
const handle = repo.create({ foo: i })
|
|
@@ -24,88 +26,68 @@ describe("useDocuments", () => {
|
|
|
24
26
|
return { repo, wrapper, documentIds }
|
|
25
27
|
}
|
|
26
28
|
|
|
29
|
+
const Component = ({ ids, onDocs }: {
|
|
30
|
+
ids: DocumentId[],
|
|
31
|
+
onDocs: (documents: Record<DocumentId, unknown>) => void,
|
|
32
|
+
}) => {
|
|
33
|
+
const documents = useDocuments(ids)
|
|
34
|
+
onDocs(documents)
|
|
35
|
+
return null
|
|
36
|
+
}
|
|
37
|
+
|
|
27
38
|
it("returns a collection of documents, given a list of ids", async () => {
|
|
28
39
|
const { documentIds, wrapper } = setup()
|
|
29
|
-
const
|
|
30
|
-
() => {
|
|
31
|
-
const documents = useDocuments(documentIds)
|
|
32
|
-
return { documents }
|
|
33
|
-
},
|
|
34
|
-
{ wrapper }
|
|
35
|
-
)
|
|
40
|
+
const onDocs = vi.fn()
|
|
36
41
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
documentIds.
|
|
40
|
-
|
|
42
|
+
render(<Component ids={documentIds} onDocs={onDocs} />, { wrapper })
|
|
43
|
+
await waitFor(() => expect(onDocs).toHaveBeenCalledWith(
|
|
44
|
+
Object.fromEntries(documentIds.map((id, i) => [id, { foo: i }]))
|
|
45
|
+
))
|
|
41
46
|
})
|
|
42
47
|
|
|
43
48
|
it("updates documents when they change", async () => {
|
|
44
49
|
const { repo, documentIds, wrapper } = setup()
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
// multiply the value of foo in each document by 10
|
|
60
|
-
documentIds.forEach(id => {
|
|
61
|
-
const handle = repo.find(id)
|
|
62
|
-
handle.change(s => (s.foo *= 10))
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
await waitFor(() => {
|
|
66
|
-
const { documents } = result.current
|
|
67
|
-
documentIds.forEach((id, i) =>
|
|
68
|
-
expect(documents[id]).toEqual({ foo: i * 10 })
|
|
69
|
-
)
|
|
50
|
+
const onDocs = vi.fn()
|
|
51
|
+
|
|
52
|
+
render(<Component ids={documentIds} onDocs={onDocs} />, { wrapper })
|
|
53
|
+
await waitFor(() => expect(onDocs).toHaveBeenCalledWith(
|
|
54
|
+
Object.fromEntries(documentIds.map((id, i) => [id, { foo: i }]))
|
|
55
|
+
))
|
|
56
|
+
|
|
57
|
+
act(() => {
|
|
58
|
+
// multiply the value of foo in each document by 10
|
|
59
|
+
documentIds.forEach(id => {
|
|
60
|
+
const handle = repo.find(id)
|
|
61
|
+
handle.change(s => (s.foo *= 10))
|
|
62
|
+
})
|
|
70
63
|
})
|
|
64
|
+
await waitFor(() => expect(onDocs).toHaveBeenCalledWith(
|
|
65
|
+
Object.fromEntries(documentIds.map((id, i) => [id, { foo: i * 10 }]))
|
|
66
|
+
))
|
|
71
67
|
})
|
|
72
68
|
|
|
73
69
|
it(`removes documents when they're removed from the list of ids`, async () => {
|
|
74
|
-
const {
|
|
75
|
-
const
|
|
76
|
-
() => {
|
|
77
|
-
const [ids, setIds] = React.useState(documentIds)
|
|
78
|
-
const documents = useDocuments(ids)
|
|
79
|
-
return { documents, setIds }
|
|
80
|
-
},
|
|
81
|
-
{ wrapper }
|
|
82
|
-
)
|
|
83
|
-
const [firstId, ...restIds] = documentIds
|
|
70
|
+
const { documentIds, wrapper } = setup()
|
|
71
|
+
const onDocs = vi.fn()
|
|
84
72
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
73
|
+
const { rerender } = render(<Component ids={documentIds} onDocs={onDocs} />, { wrapper })
|
|
74
|
+
await waitFor(() => expect(onDocs).toHaveBeenCalledWith(
|
|
75
|
+
Object.fromEntries(documentIds.map((id, i) => [id, { foo: i }]))
|
|
76
|
+
))
|
|
89
77
|
|
|
90
78
|
// remove the first document
|
|
91
|
-
|
|
92
|
-
// 👆 Note that this only works because
|
|
93
|
-
// If we modified documentIds directly, the hook
|
|
94
|
-
|
|
95
|
-
await waitFor(() =>
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
})
|
|
79
|
+
rerender(<Component ids={documentIds.slice(1)} onDocs={onDocs} />)
|
|
80
|
+
// 👆 Note that this only works because documentIds.slice(1) is a different
|
|
81
|
+
// object from documentIds. If we modified documentIds directly, the hook
|
|
82
|
+
// wouldn't re-run.
|
|
83
|
+
await waitFor(() => expect(onDocs).toHaveBeenCalledWith(
|
|
84
|
+
Object.fromEntries(documentIds.map((id, i) => [id, { foo: i }]).slice(1))
|
|
85
|
+
))
|
|
99
86
|
})
|
|
100
87
|
})
|
|
101
88
|
|
|
102
89
|
const range = (n: number) => [...Array(n).keys()]
|
|
103
90
|
|
|
104
|
-
const getRepoWrapper =
|
|
105
|
-
(repo: Repo) =>
|
|
106
|
-
({ children }) =>
|
|
107
|
-
<RepoContext.Provider value={repo}>{children}</RepoContext.Provider>
|
|
108
|
-
|
|
109
91
|
interface ExampleDoc {
|
|
110
92
|
foo: number
|
|
111
93
|
}
|
package/test/useHandle.test.tsx
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { PeerId, Repo
|
|
1
|
+
import { AutomergeUrl, DocHandle, PeerId, Repo } from "@automerge/automerge-repo"
|
|
2
2
|
import { DummyStorageAdapter } from "@automerge/automerge-repo/test/helpers/DummyStorageAdapter"
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
3
|
+
import { render, waitFor } from "@testing-library/react"
|
|
4
|
+
import React from "react"
|
|
5
|
+
import { describe, expect, it, vi } from "vitest"
|
|
5
6
|
import { useHandle } from "../src/useHandle"
|
|
6
|
-
import {
|
|
7
|
-
import React, { useState } from "react"
|
|
8
|
-
import assert from "assert"
|
|
7
|
+
import { RepoContext } from "../src/useRepo"
|
|
9
8
|
|
|
10
9
|
interface ExampleDoc {
|
|
11
10
|
foo: string
|
|
@@ -39,64 +38,48 @@ describe("useHandle", () => {
|
|
|
39
38
|
}
|
|
40
39
|
}
|
|
41
40
|
|
|
41
|
+
const Component = ({ url, onHandle }: {
|
|
42
|
+
url: AutomergeUrl,
|
|
43
|
+
onHandle: (handle: DocHandle<unknown> | undefined) => void,
|
|
44
|
+
}) => {
|
|
45
|
+
const handle = useHandle(url)
|
|
46
|
+
onHandle(handle)
|
|
47
|
+
return null
|
|
48
|
+
}
|
|
49
|
+
|
|
42
50
|
it("loads a handle", async () => {
|
|
43
51
|
const { handleA, wrapper } = setup()
|
|
52
|
+
const onHandle = vi.fn()
|
|
44
53
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
() => {
|
|
48
|
-
const handle = useHandle(handleA.url)
|
|
49
|
-
return { handle }
|
|
50
|
-
},
|
|
51
|
-
{ wrapper }
|
|
52
|
-
)
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
assert.deepStrictEqual(result.current.handle, handleA)
|
|
54
|
+
render(<Component url={handleA.url} onHandle={onHandle} />, {wrapper})
|
|
55
|
+
await waitFor(() => expect(onHandle).toHaveBeenLastCalledWith(handleA))
|
|
56
56
|
})
|
|
57
57
|
|
|
58
58
|
it("returns undefined when no url given", async () => {
|
|
59
59
|
const { wrapper } = setup()
|
|
60
|
+
const onHandle = vi.fn()
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
() => {
|
|
64
|
-
const handle = useHandle()
|
|
65
|
-
return { handle }
|
|
66
|
-
},
|
|
67
|
-
{ wrapper }
|
|
68
|
-
)
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
await waitFor(() => expect(result.current.handle).toBeUndefined())
|
|
62
|
+
render(<Component url={undefined} onHandle={onHandle} />, {wrapper})
|
|
63
|
+
await waitFor(() => expect(onHandle).toHaveBeenLastCalledWith(undefined))
|
|
72
64
|
})
|
|
73
65
|
|
|
74
66
|
it("updates the handle when the url changes", async () => {
|
|
75
67
|
const { wrapper, handleA, handleB } = setup()
|
|
68
|
+
const onHandle = vi.fn()
|
|
76
69
|
|
|
77
|
-
const {
|
|
78
|
-
|
|
79
|
-
() => {
|
|
80
|
-
const [url, setUrl] = useState<AutomergeUrl>()
|
|
81
|
-
const handle = useHandle(url)
|
|
82
|
-
return { setUrl, handle }
|
|
83
|
-
},
|
|
84
|
-
{ wrapper }
|
|
85
|
-
)
|
|
86
|
-
)
|
|
87
|
-
|
|
88
|
-
await waitFor(() => expect(result.current).not.toBeNull())
|
|
70
|
+
const { rerender } = render(<Component url={undefined} onHandle={onHandle} />, {wrapper})
|
|
71
|
+
await waitFor(() => expect(onHandle).toHaveBeenLastCalledWith(undefined))
|
|
89
72
|
|
|
90
73
|
// set url to doc A
|
|
91
|
-
|
|
92
|
-
await waitFor(() => expect(
|
|
74
|
+
rerender(<Component url={handleA.url} onHandle={onHandle} />)
|
|
75
|
+
await waitFor(() => expect(onHandle).toHaveBeenLastCalledWith(handleA))
|
|
93
76
|
|
|
94
77
|
// set url to doc B
|
|
95
|
-
|
|
96
|
-
await waitFor(() => expect(
|
|
78
|
+
rerender(<Component url={handleB.url} onHandle={onHandle} />)
|
|
79
|
+
await waitFor(() => expect(onHandle).toHaveBeenLastCalledWith(handleB))
|
|
97
80
|
|
|
98
81
|
// set url to undefined
|
|
99
|
-
|
|
100
|
-
await waitFor(() => expect(
|
|
82
|
+
rerender(<Component url={undefined} onHandle={onHandle} />)
|
|
83
|
+
await waitFor(() => expect(onHandle).toHaveBeenLastCalledWith(undefined))
|
|
101
84
|
})
|
|
102
85
|
})
|
package/test/useRepo.test.tsx
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
|
-
import { renderHook } from "@testing-library/react"
|
|
2
|
-
import { describe, expect, test, vi } from "vitest"
|
|
3
|
-
import { RepoContext, useRepo } from "../src/useRepo.js"
|
|
4
1
|
import { Repo } from "@automerge/automerge-repo"
|
|
2
|
+
import { render } from "@testing-library/react"
|
|
5
3
|
import React from "react"
|
|
4
|
+
import { describe, expect, test, vi } from "vitest"
|
|
5
|
+
import { RepoContext, useRepo } from "../src/useRepo.js"
|
|
6
6
|
|
|
7
7
|
describe("useRepo", () => {
|
|
8
|
+
const Component = ({ onRepo }: {
|
|
9
|
+
onRepo: (repo: Repo) => void,
|
|
10
|
+
}) => {
|
|
11
|
+
const repo = useRepo()
|
|
12
|
+
onRepo(repo)
|
|
13
|
+
return null
|
|
14
|
+
}
|
|
15
|
+
|
|
8
16
|
test("should error when context unavailable", () => {
|
|
9
17
|
const repo = new Repo({ network: [] })
|
|
10
18
|
// Prevent console spam by swallowing console.error "uncaught error" message
|
|
11
19
|
const spy = vi.spyOn(console, "error")
|
|
12
20
|
spy.mockImplementation(() => {})
|
|
13
|
-
expect(() =>
|
|
21
|
+
expect(() => render(<Component onRepo={() => {}}/>)).toThrow(
|
|
14
22
|
/Repo was not found on RepoContext/
|
|
15
23
|
)
|
|
16
24
|
spy.mockRestore()
|
|
@@ -21,7 +29,8 @@ describe("useRepo", () => {
|
|
|
21
29
|
const wrapper = ({ children }) => (
|
|
22
30
|
<RepoContext.Provider value={repo} children={children} />
|
|
23
31
|
)
|
|
24
|
-
const
|
|
25
|
-
|
|
32
|
+
const onRepo = vi.fn()
|
|
33
|
+
render(<Component onRepo={onRepo} />, { wrapper })
|
|
34
|
+
expect(onRepo).toHaveBeenLastCalledWith(repo)
|
|
26
35
|
})
|
|
27
36
|
})
|