Skip to content

Commit 8ce8420

Browse files
committed
Add unit tests.
1 parent 4e30b5f commit 8ce8420

File tree

2 files changed

+176
-1
lines changed

2 files changed

+176
-1
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
"main": "lib/index.js",
2020
"scripts": {
2121
"build": "babel src -d lib",
22-
"prepublish": "npm run build"
22+
"test": "jest src",
23+
"prepublish": "npm test && npm run build"
2324
},
2425
"dependencies": {},
2526
"peerDependencies": {

src/spec.js

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
import "jest-dom/extend-expect"
2+
import React from "react"
3+
import { render, fireEvent, cleanup, waitForElement } from "react-testing-library"
4+
import WebWorker from "./"
5+
6+
afterEach(cleanup)
7+
8+
const worker = { postMessage: jest.fn(), terminate: jest.fn() }
9+
window.Worker = jest.fn().mockImplementation(() => worker)
10+
11+
test("initializes a Worker on mount", () => {
12+
const options = {}
13+
render(<WebWorker url="/worker.js" options={options} />)
14+
expect(window.Worker).toHaveBeenCalledWith("/worker.js", options)
15+
})
16+
17+
test("passes received messages to children as render prop", async () => {
18+
const { getByText } = render(<WebWorker>{({ messages }) => messages.map(m => m.data).join()}</WebWorker>)
19+
worker.onmessage({ data: "foo" })
20+
worker.onmessage({ data: "bar" })
21+
worker.onmessage({ data: "baz" })
22+
await waitForElement(() => getByText("foo,bar,baz"))
23+
})
24+
25+
test("passes data of last received message to children as render prop", async () => {
26+
const { getByText } = render(<WebWorker>{({ data }) => data}</WebWorker>)
27+
worker.onmessage({ data: "foo" })
28+
worker.onmessage({ data: "bar" })
29+
worker.onmessage({ data: "baz" })
30+
await waitForElement(() => getByText("baz"))
31+
})
32+
33+
test("passes received errors to children as render prop", async () => {
34+
const { getByText } = render(<WebWorker>{({ errors }) => errors.map(e => e.error).join()}</WebWorker>)
35+
worker.onerror({ error: "foo" })
36+
worker.onerror({ error: "bar" })
37+
worker.onerror({ error: "baz" })
38+
await waitForElement(() => getByText("foo,bar,baz"))
39+
})
40+
41+
test("passes last received error to children as render prop", async () => {
42+
const { getByText } = render(<WebWorker>{({ error }) => error}</WebWorker>)
43+
worker.onerror({ error: "foo" })
44+
worker.onerror({ error: "bar" })
45+
worker.onerror({ error: "baz" })
46+
await waitForElement(() => getByText("baz"))
47+
})
48+
49+
test("passes updatedAt date when a message is received", async () => {
50+
const date = new Date().toISOString().substr(0, 10)
51+
const { getByText, queryByText } = render(
52+
<WebWorker>{({ updatedAt }) => (updatedAt ? updatedAt.toISOString().substr(0, 10) : null)}</WebWorker>
53+
)
54+
expect(queryByText(date)).toBeNull()
55+
worker.onmessage({ data: "foo" })
56+
await waitForElement(() => getByText(date))
57+
})
58+
59+
test("passes updatedAt date when an error is received", async () => {
60+
const date = new Date().toISOString().substr(0, 10)
61+
const { getByText, queryByText } = render(
62+
<WebWorker>{({ updatedAt }) => (updatedAt ? updatedAt.toISOString().substr(0, 10) : null)}</WebWorker>
63+
)
64+
expect(queryByText(date)).toBeNull()
65+
worker.onerror({ error: "foo" })
66+
await waitForElement(() => getByText(date))
67+
})
68+
69+
test("invokes onMessage callback with message data when a message is received", async () => {
70+
const onMessage = jest.fn()
71+
render(<WebWorker onMessage={onMessage} />)
72+
worker.onmessage({ data: "foo" })
73+
expect(onMessage).toHaveBeenCalledWith("foo")
74+
})
75+
76+
test("invokes onError callback with error when a error is received", async () => {
77+
const onError = jest.fn()
78+
render(<WebWorker onError={onError} />)
79+
worker.onerror({ error: "foo" })
80+
expect(onError).toHaveBeenCalledWith("foo")
81+
})
82+
83+
test("terminates the worker when unmounted", async () => {
84+
worker.terminate.mockClear()
85+
const { unmount } = render(<WebWorker />)
86+
unmount()
87+
expect(worker.terminate).toHaveBeenCalled()
88+
})
89+
90+
test("postMessage sends messages to the worker", async () => {
91+
worker.postMessage.mockClear()
92+
const { getByText } = render(
93+
<WebWorker>{({ postMessage }) => <button onClick={() => postMessage("hello")}>go</button>}</WebWorker>
94+
)
95+
expect(worker.postMessage).not.toHaveBeenCalled()
96+
fireEvent.click(getByText("go"))
97+
expect(worker.postMessage).toHaveBeenCalledWith("hello")
98+
})
99+
100+
test("serializer will prepare messages before sending them to the worker", async () => {
101+
worker.postMessage.mockClear()
102+
const { getByText } = render(
103+
<WebWorker serializer={JSON.stringify}>
104+
{({ postMessage }) => <button onClick={() => postMessage({ foo: "bar" })}>go</button>}
105+
</WebWorker>
106+
)
107+
expect(worker.postMessage).not.toHaveBeenCalled()
108+
fireEvent.click(getByText("go"))
109+
expect(worker.postMessage).toHaveBeenCalledWith(JSON.stringify({ foo: "bar" }))
110+
})
111+
112+
test("parser will deserialize messages received from the worker", async () => {
113+
const onMessage = jest.fn()
114+
const { getByText } = render(
115+
<WebWorker parser={JSON.parse} onMessage={onMessage}>
116+
{({ data }) => data && data.foo}
117+
</WebWorker>
118+
)
119+
worker.onmessage({ data: JSON.stringify({ foo: "bar" }) })
120+
expect(onMessage).toHaveBeenCalledWith({ foo: "bar" })
121+
await waitForElement(() => getByText("bar"))
122+
})
123+
124+
test("WebWorker.Data renders with last message data only when a message has been received", async () => {
125+
const { getByText, queryByText } = render(
126+
<WebWorker>
127+
<WebWorker.Data>{data => data}</WebWorker.Data>
128+
</WebWorker>
129+
)
130+
expect(queryByText("foo")).toBeNull()
131+
worker.onmessage({ data: "foo" })
132+
await waitForElement(() => getByText("foo"))
133+
worker.onmessage({ data: "bar" })
134+
await waitForElement(() => getByText("bar"))
135+
worker.onmessage({ data: "baz" })
136+
await waitForElement(() => getByText("baz"))
137+
})
138+
139+
test("WebWorker.Error renders with last error only when an error has been received", async () => {
140+
const { getByText, queryByText } = render(
141+
<WebWorker>
142+
<WebWorker.Error>{error => error}</WebWorker.Error>
143+
</WebWorker>
144+
)
145+
expect(queryByText("foo")).toBeNull()
146+
worker.onerror({ error: "foo" })
147+
await waitForElement(() => getByText("foo"))
148+
worker.onerror({ error: "bar" })
149+
await waitForElement(() => getByText("bar"))
150+
worker.onerror({ error: "baz" })
151+
await waitForElement(() => getByText("baz"))
152+
})
153+
154+
test("WebWorker.Pending renders only when no message has been received yet", async () => {
155+
const { getByText, queryByText } = render(
156+
<WebWorker>
157+
<WebWorker.Pending>pending</WebWorker.Pending>
158+
</WebWorker>
159+
)
160+
await waitForElement(() => getByText("pending"))
161+
worker.onmessage({ data: "foo" })
162+
expect(queryByText("pending")).toBeNull()
163+
})
164+
165+
test("WebWorker.Pending renders only when no error has been received yet", async () => {
166+
const { getByText, queryByText } = render(
167+
<WebWorker>
168+
<WebWorker.Pending>pending</WebWorker.Pending>
169+
</WebWorker>
170+
)
171+
await waitForElement(() => getByText("pending"))
172+
worker.onerror({ error: "foo" })
173+
expect(queryByText("pending")).toBeNull()
174+
})

0 commit comments

Comments
 (0)