|
1 | 1 | import { PeerId, Repo, AutomergeUrl } from "@automerge/automerge-repo"
|
2 | 2 | import { DummyStorageAdapter } from "@automerge/automerge-repo/test/helpers/DummyStorageAdapter"
|
3 |
| -import { describe, it } from "vitest" |
| 3 | +import { describe, expect, it } from "vitest" |
4 | 4 | import { RepoContext } from "../src/useRepo"
|
5 | 5 | import { useDocument } from "../src/useDocument"
|
6 |
| -import { renderHook } from "@testing-library/react-hooks" |
| 6 | +import { renderHook, waitFor } from "@testing-library/react" |
7 | 7 | import React, { useState } from "react"
|
8 | 8 | import assert from "assert"
|
| 9 | +import { act } from "react-dom/test-utils" |
9 | 10 |
|
10 | 11 | interface ExampleDoc {
|
11 | 12 | foo: string
|
@@ -58,117 +59,102 @@ describe("useDocument", () => {
|
58 | 59 | it("should load a document", async () => {
|
59 | 60 | const { handleA, wrapper } = setup()
|
60 | 61 |
|
61 |
| - const { result, waitForNextUpdate } = renderHook( |
62 |
| - () => useDocument(handleA.url), |
63 |
| - { wrapper } |
64 |
| - ) |
65 |
| - |
66 |
| - await waitForNextUpdate() |
67 |
| - |
68 |
| - const [doc] = result.current |
| 62 | + const { result } = renderHook(() => useDocument(handleA.url), { wrapper }) |
69 | 63 |
|
70 |
| - assert.deepStrictEqual(doc, { foo: "A" }) |
| 64 | + await waitFor(() => { |
| 65 | + const [doc] = result.current |
| 66 | + expect(doc).toMatchObject({ foo: "A" }) |
| 67 | + }) |
71 | 68 | })
|
72 | 69 |
|
73 | 70 | it("should update if the url changes", async () => {
|
74 | 71 | const { wrapper, handleA, handleB } = setup()
|
75 | 72 |
|
76 |
| - const { result, waitForNextUpdate } = renderHook( |
77 |
| - () => { |
78 |
| - const [url, setUrl] = useState<AutomergeUrl>() |
79 |
| - const [doc] = useDocument(url) |
80 |
| - |
81 |
| - return { |
82 |
| - setUrl, |
83 |
| - doc, |
84 |
| - } |
85 |
| - }, |
86 |
| - { wrapper } |
| 73 | + const { result } = await act(() => |
| 74 | + renderHook( |
| 75 | + () => { |
| 76 | + const [url, setUrl] = useState<AutomergeUrl>() |
| 77 | + const [doc] = useDocument(url) |
| 78 | + return { setUrl, doc } |
| 79 | + }, |
| 80 | + { wrapper } |
| 81 | + ) |
87 | 82 | )
|
88 | 83 |
|
89 |
| - // initially doc is undefined |
90 |
| - assert.deepStrictEqual(result.current.doc, undefined) |
| 84 | + await waitFor(() => expect(result.current).not.toBeNull()) |
91 | 85 |
|
92 | 86 | // set url to doc A
|
93 |
| - result.current.setUrl(handleA.url) |
94 |
| - await waitForNextUpdate() |
95 |
| - assert.deepStrictEqual(result.current.doc, { foo: "A" }) |
| 87 | + act(() => result.current.setUrl(handleA.url)) |
| 88 | + await waitFor(() => expect(result.current.doc).toMatchObject({ foo: "A" })) |
96 | 89 |
|
97 | 90 | // set url to doc B
|
98 |
| - result.current.setUrl(handleB.url) |
99 |
| - await waitForNextUpdate() |
100 |
| - assert.deepStrictEqual(result.current.doc, { foo: "B" }) |
| 91 | + act(() => result.current.setUrl(handleB.url)) |
| 92 | + await waitFor(() => expect(result.current.doc).toMatchObject({ foo: "B" })) |
101 | 93 |
|
102 | 94 | // set url to undefined
|
103 |
| - result.current.setUrl(undefined) |
104 |
| - await waitForNextUpdate() |
105 |
| - assert.deepStrictEqual(result.current.doc, undefined) |
| 95 | + act(() => result.current.setUrl(undefined)) |
| 96 | + await waitFor(() => expect(result.current.doc).toBeUndefined()) |
106 | 97 | })
|
107 | 98 |
|
108 | 99 | it("sets the doc to undefined while the initial load is happening", async () => {
|
109 | 100 | const { wrapper, handleA, handleSlow } = setup()
|
110 | 101 |
|
111 |
| - const { result, waitForNextUpdate, waitFor } = renderHook( |
112 |
| - () => { |
113 |
| - const [url, setUrl] = useState<AutomergeUrl>() |
114 |
| - const [doc] = useDocument(url) |
115 |
| - |
116 |
| - return { |
117 |
| - setUrl, |
118 |
| - doc, |
119 |
| - } |
120 |
| - }, |
121 |
| - { wrapper } |
| 102 | + const { result } = await act(() => |
| 103 | + renderHook( |
| 104 | + () => { |
| 105 | + const [url, setUrl] = useState<AutomergeUrl>() |
| 106 | + const [doc] = useDocument(url) |
| 107 | + return { setUrl, doc } |
| 108 | + }, |
| 109 | + { wrapper } |
| 110 | + ) |
122 | 111 | )
|
123 | 112 |
|
124 |
| - // initially doc is undefined |
125 |
| - assert.deepStrictEqual(result.current.doc, undefined) |
| 113 | + await waitFor(() => expect(result.current).not.toBeNull()) |
126 | 114 |
|
127 | 115 | // start by setting url to doc A
|
128 |
| - result.current.setUrl(handleA.url) |
129 |
| - await waitForNextUpdate() |
130 |
| - assert.deepStrictEqual(result.current.doc, { foo: "A" }) |
| 116 | + act(() => result.current.setUrl(handleA.url)) |
| 117 | + await waitFor(() => expect(result.current.doc).toMatchObject({ foo: "A" })) |
131 | 118 |
|
132 | 119 | // Now we set the URL to a handle that's slow to load.
|
133 | 120 | // The doc should be undefined while the load is happening.
|
134 |
| - result.current.setUrl(handleSlow.url) |
135 |
| - await waitForNextUpdate() |
136 |
| - assert.deepStrictEqual(result.current.doc, undefined) |
137 |
| - await waitForNextUpdate() |
138 |
| - assert.deepStrictEqual(result.current.doc, { foo: "slow" }) |
| 121 | + act(() => result.current.setUrl(handleSlow.url)) |
| 122 | + await waitFor(() => expect(result.current.doc).toBeUndefined()) |
| 123 | + await waitFor(() => |
| 124 | + expect(result.current.doc).toMatchObject({ foo: "slow" }) |
| 125 | + ) |
139 | 126 | })
|
140 | 127 |
|
141 | 128 | it("avoids showing stale data", async () => {
|
142 | 129 | const { wrapper, handleA, handleSlow } = setup()
|
143 |
| - |
144 |
| - const { result, waitForNextUpdate, waitFor } = renderHook( |
145 |
| - () => { |
146 |
| - const [url, setUrl] = useState<AutomergeUrl>() |
147 |
| - const [doc] = useDocument(url) |
148 |
| - |
149 |
| - return { |
150 |
| - setUrl, |
151 |
| - doc, |
152 |
| - } |
153 |
| - }, |
154 |
| - { wrapper } |
| 130 | + const { result } = await act(() => |
| 131 | + renderHook( |
| 132 | + () => { |
| 133 | + const [url, setUrl] = useState<AutomergeUrl>() |
| 134 | + const [doc] = useDocument(url) |
| 135 | + return { setUrl, doc } |
| 136 | + }, |
| 137 | + { wrapper } |
| 138 | + ) |
155 | 139 | )
|
156 | 140 |
|
157 |
| - // initially doc is undefined |
158 |
| - assert.deepStrictEqual(result.current.doc, undefined) |
| 141 | + await waitFor(() => expect(result.current).not.toBeNull()) |
159 | 142 |
|
160 | 143 | // Set the URL to a slow doc and then a fast doc.
|
161 | 144 | // We should see the fast doc forever, even after
|
162 | 145 | // the slow doc has had time to finish loading.
|
163 |
| - result.current.setUrl(handleSlow.url) |
164 |
| - result.current.setUrl(handleA.url) |
165 |
| - await waitForNextUpdate() |
166 |
| - assert.deepStrictEqual(result.current.doc, { foo: "A" }) |
| 146 | + act(() => { |
| 147 | + result.current.setUrl(handleSlow.url) |
| 148 | + result.current.setUrl(handleA.url) |
| 149 | + }) |
| 150 | + await waitFor(() => expect(result.current.doc).toMatchObject({ foo: "A" })) |
167 | 151 |
|
168 | 152 | // wait for the slow doc to finish loading...
|
169 |
| - await new Promise(resolve => setTimeout(resolve, SLOW_DOC_LOAD_TIME_MS * 2)) |
| 153 | + await pause(SLOW_DOC_LOAD_TIME_MS * 2) |
170 | 154 |
|
171 | 155 | // we didn't update the doc to the slow doc, so it should still be A
|
172 |
| - assert.deepStrictEqual(result.current.doc, { foo: "A" }) |
| 156 | + await waitFor(() => expect(result.current.doc).toMatchObject({ foo: "A" })) |
173 | 157 | })
|
174 | 158 | })
|
| 159 | + |
| 160 | +const pause = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)) |
0 commit comments