forked from meteor/react-packages
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuseFind.tests.js
More file actions
155 lines (126 loc) · 4.07 KB
/
Copy pathuseFind.tests.js
File metadata and controls
155 lines (126 loc) · 4.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/* global Meteor, Tinytest */
import React, { memo, useState } from 'react'
import ReactDOM from 'react-dom'
import { waitFor } from '@testing-library/react'
import { Mongo } from 'meteor/mongo'
import { useFind } from './useFind'
if (Meteor.isClient) {
Tinytest.addAsync('useFind - Verify reference stability between rerenders', async function (test, completed) {
const container = document.createElement("DIV")
const TestDocs = new Mongo.Collection(null)
TestDocs.insert({
id: 0,
updated: 0
})
TestDocs.insert({
id: 1,
updated: 0
})
TestDocs.insert({
id: 2,
updated: 0
})
TestDocs.insert({
id: 3,
updated: 0
})
TestDocs.insert({
id: 4,
updated: 0
})
let renders = 0
const MemoizedItem = memo(({doc}) => {
renders++
return (
<li>{doc.id},{doc.updated}</li>
)
})
const Test = () => {
const docs = useFind(() => TestDocs.find(), [])
return (
<ul>
{docs.map(doc =>
<MemoizedItem key={doc.id} doc={doc} />
)}
</ul>
)
}
ReactDOM.render(<Test />, container)
test.equal(renders, 5, '5 items should have rendered, only 5, no more.')
await waitFor(() => {}, { container, timeout: 250 })
await waitFor(() => {
TestDocs.update({ id: 2 }, { $inc: { updated: 1 } })
}, { container, timeout: 250 })
test.equal(renders, 6, '6 items should have rendered - only 1 of the items should have been matched by the reconciler after a single change.')
completed()
})
Tinytest.addAsync('useFind - null return is allowed', async function (test, completed) {
const container = document.createElement("DIV")
const TestDocs = new Mongo.Collection(null)
TestDocs.insert({
id: 0,
updated: 0
})
let setReturnNull, returnValue;
const Test = () => {
const [returnNull, _setReturnNull] = useState(true)
setReturnNull = _setReturnNull
const docs = useFind(() => returnNull ? null : TestDocs.find(), [returnNull])
returnValue = docs;
if (!docs) {
return null
} else {
return (
<ul>
{docs.map(doc =>
<li key={doc.id} doc={doc} />
)}
</ul>
)
}
}
ReactDOM.render(<Test />, container)
test.isNull(returnValue, 'Return value should be null when the factory returns null')
setReturnNull(false)
await waitFor(() => {}, { container, timeout: 250 })
test.equal(returnValue.length, 1, 'Return value should be an array with one document')
completed()
})
Tinytest.addAsync(
'useFind - Immediate update before effect registration (race condition test)',
async function (test, completed) {
const container = document.createElement('div');
document.body.appendChild(container);
const TestDocs = new Mongo.Collection(null);
// Insert a single document.
TestDocs.insert({ id: 1, val: 'initial' });
const Test = () => {
const docs = useFind(() => TestDocs.find(), []);
return (
<div data-testid="doc-value">
{docs && docs[0] && docs[0].val}
</div>
);
};
// Render the component.
ReactDOM.render(<Test />, container);
// Immediately update the document (this should occur
// after the synchronous fetch in the old code but before the effect attaches).
TestDocs.update({ id: 1 }, { $set: { val: 'updated' } });
// Wait until the rendered output reflects the update.
await waitFor(() => {
const node = container.querySelector('[data-testid="doc-value"]');
if (!node || !node.textContent.includes('updated')) {
throw new Error('Updated value not rendered yet');
}
}, { container, timeout: 500 });
test.ok(
container.innerHTML.includes('updated'),
'Document should display updated value; the old code would fail to capture this update.'
);
document.body.removeChild(container);
completed();
}
);
} else {
}