@powerhousedao/academy 5.1.0-staging.0 → 5.1.0
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/CHANGELOG.md +46 -1148
- package/blog/BeyondCommunication-ABlueprintForDevelopment.md +1 -2
- package/blog/TheChallengeOfChange.md +0 -1
- package/docs/academy/00-EthereumArgentinaHackathon.md +207 -0
- package/docs/academy/01-GetStarted/00-ExploreDemoPackage.mdx +27 -24
- package/docs/academy/01-GetStarted/01-CreateNewPowerhouseProject.md +10 -155
- package/docs/academy/01-GetStarted/02-DefineToDoListDocumentModel.md +35 -122
- package/docs/academy/01-GetStarted/03-ImplementOperationReducers.md +155 -178
- package/docs/academy/01-GetStarted/04-BuildToDoListEditor.md +218 -0
- package/docs/academy/{02-MasteryTrack/01-BuilderEnvironment → 01-GetStarted}/05-VetraStudio.md +22 -62
- package/docs/academy/01-GetStarted/06-ReactorMCP.md +58 -0
- package/docs/academy/01-GetStarted/_04-BuildToDoListEditor +1 -1
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/03-BuilderTools.md +2 -2
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/02-SpecifyTheStateSchema.md +44 -75
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/03-SpecifyDocumentOperations.md +22 -28
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/04-UseTheDocumentModelGenerator.md +31 -28
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/05-ImplementDocumentReducers.md +206 -211
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/06-ImplementDocumentModelTests.md +62 -176
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/07-ExampleToDoListRepository.md +0 -21
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/01-BuildingDocumentEditors.md +319 -309
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/00-DocumentToolbar.mdx +0 -4
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/01-OperationHistory.md +0 -4
- package/docs/academy/02-MasteryTrack/05-Launch/04-ConfigureEnvironment.md +1 -1
- package/docs/academy/03-ExampleUsecases/Chatroom/02-CreateNewPowerhouseProject.md +35 -111
- package/docs/academy/03-ExampleUsecases/Chatroom/03-DefineChatroomDocumentModel.md +79 -195
- package/docs/academy/03-ExampleUsecases/Chatroom/04-ImplementOperationReducers.md +241 -435
- package/docs/academy/03-ExampleUsecases/Chatroom/05-ImplementChatroomEditor.md +27 -388
- package/docs/academy/03-ExampleUsecases/Chatroom/06-LaunchALocalReactor.md +7 -95
- package/docs/academy/03-ExampleUsecases/Chatroom/_category_.json +1 -1
- package/docs/academy/04-APIReferences/00-PowerhouseCLI.md +2 -6
- package/docs/academy/04-APIReferences/01-ReactHooks.md +501 -291
- package/docs/academy/05-Architecture/00-PowerhouseArchitecture.md +39 -7
- package/docs/academy/05-Architecture/02-ReferencingMonorepoPackages +65 -0
- package/docs/academy/05-Architecture/04-MovingBeyondCRUD +61 -0
- package/docs/academy/06-ComponentLibrary/00-DocumentEngineering.md +24 -72
- package/docs/academy/08-Glossary.md +0 -7
- package/docusaurus.config.ts +3 -28
- package/package.json +1 -1
- package/sidebars.ts +13 -49
- package/src/css/custom.css +18 -26
- package/docs/academy/01-GetStarted/04-WriteDocumentModelTests.md +0 -425
- package/docs/academy/01-GetStarted/05-BuildToDoListEditor.md +0 -557
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/images/Modules.png +0 -0
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/images/VetraStudioDrive.png +0 -0
- package/docs/academy/02-MasteryTrack/05-Launch/05-DockerDeployment.md +0 -384
- package/docs/academy/03-ExampleUsecases/TodoList/00-GetTheStarterCode.md +0 -24
- package/docs/academy/03-ExampleUsecases/TodoList/01-GenerateTodoListDocumentModel.md +0 -211
- package/docs/academy/03-ExampleUsecases/TodoList/02-ImplementTodoListDocumentModelReducerOperationHandlers.md +0 -171
- package/docs/academy/03-ExampleUsecases/TodoList/03-AddTestsForTodoListActions.md +0 -462
- package/docs/academy/03-ExampleUsecases/TodoList/04-GenerateTodoListDocumentEditor.md +0 -45
- package/docs/academy/03-ExampleUsecases/TodoList/05-ImplementTodoListDocumentEditorUIComponents.md +0 -422
- package/docs/academy/03-ExampleUsecases/TodoList/06-GenerateTodoDriveExplorer.md +0 -61
- package/docs/academy/03-ExampleUsecases/TodoList/07-AddSharedComponentForShowingTodoListStats.md +0 -384
- package/docs/academy/03-ExampleUsecases/TodoList/_category_.json +0 -8
- package/docs/academy/03-ExampleUsecases/VetraPackageLibrary/VetraPackageLibrary.md +0 -7
- package/docs/academy/03-ExampleUsecases/VetraPackageLibrary/_category_.json +0 -9
- package/docs/academy/04-APIReferences/06-VetraRemoteDrive.md +0 -160
- package/docs/academy/04-APIReferences/renown-sdk/00-Overview.md +0 -316
- package/docs/academy/04-APIReferences/renown-sdk/01-Authentication.md +0 -672
- package/docs/academy/04-APIReferences/renown-sdk/02-APIReference.md +0 -957
- package/docs/academy/04-APIReferences/renown-sdk/_category_.json +0 -8
- package/docs/academy/10-TodoListTutorial/02-ImplementTodoListDocumentModelReducerOperationHandlers.md +0 -171
- package/docs/academy/10-TodoListTutorial/03-AddTestsForTodoListActions.md +0 -462
- package/docs/academy/10-TodoListTutorial/05-ImplementTodoListDocumentEditorUIComponents.md +0 -422
- package/docs/academy/10-TodoListTutorial/07-AddSharedComponentForShowingTodoListStats.md +0 -370
- package/static/img/Vetra-logo-dark.svg +0 -11
- package/static/img/vetra-logo-light.svg +0 -11
- /package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/{02-RevisionHistoryTimeline/360/237/232/247" → 02-RevisionHistoryTimeline} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /01-WhatIsADocumentModel" → 01-WhatIsADocumentModel} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /02-DAOandDocumentsModelsQ+A" → 02-DAOandDocumentsModelsQ+A} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /02-domain-modeling" → 02-domain-modeling} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /03-BenefitsOfDocumentModels" → 03-BenefitsOfDocumentModels} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /04-UtilitiesAndTips" → 04-UtilitiesAndTips} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /05-best-practices" → 05-best-practices} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /_category_.json" → _category_.json} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /three-data-layers.png" → three-data-layers.png} +0 -0
|
@@ -1,425 +0,0 @@
|
|
|
1
|
-
# Write document model tests
|
|
2
|
-
|
|
3
|
-
:::tip Tutorial Repository
|
|
4
|
-
📦 **Reference Code**: [step-4-implement-tests-for-todos-operations](https://github.com/powerhouse-inc/todo-tutorial/tree/step-4-implement-tests-for-todos-operations)
|
|
5
|
-
|
|
6
|
-
This step focuses on writing comprehensive tests for the reducers you implemented in the previous step.
|
|
7
|
-
:::
|
|
8
|
-
|
|
9
|
-
<details>
|
|
10
|
-
<summary>📖 How to use this tutorial</summary>
|
|
11
|
-
|
|
12
|
-
### Compare your tests
|
|
13
|
-
|
|
14
|
-
After writing tests:
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
# Compare your tests with the reference
|
|
18
|
-
git diff tutorial/step-4-implement-tests-for-todos-operations -- document-models/todo-list/src/tests/
|
|
19
|
-
|
|
20
|
-
# View the reference test implementation
|
|
21
|
-
git show tutorial/step-4-implement-tests-for-todos-operations:document-models/todo-list/src/tests/todos.test.ts
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
### Visual comparison with GitHub Desktop
|
|
25
|
-
|
|
26
|
-
After committing your work, compare visually:
|
|
27
|
-
1. **Branch** menu → **"Compare to Branch..."**
|
|
28
|
-
2. Select `tutorial/step-4-implement-tests-for-todos-operations`
|
|
29
|
-
3. Review differences in the visual interface
|
|
30
|
-
|
|
31
|
-
</details>
|
|
32
|
-
|
|
33
|
-
In order to make sure the operation reducers are working as expected, you need to write tests for them. When you generated your document model code, we created some boilerplate tests for you. Now we'll enhance them to properly verify our reducer logic.
|
|
34
|
-
|
|
35
|
-
## Understanding the generated test file
|
|
36
|
-
|
|
37
|
-
Navigate to `/document-models/todo-list/src/tests/todos.test.ts`. You will see that we have some basic "sanity check" style tests already. These make sure that your operations at least result in a valid document model state.
|
|
38
|
-
|
|
39
|
-
```typescript
|
|
40
|
-
import { describe, it, expect } from "vitest";
|
|
41
|
-
import { generateMock } from "@powerhousedao/codegen";
|
|
42
|
-
import {
|
|
43
|
-
reducer,
|
|
44
|
-
utils,
|
|
45
|
-
isTodoListDocument,
|
|
46
|
-
addTodoItem,
|
|
47
|
-
AddTodoItemInputSchema,
|
|
48
|
-
updateTodoItem,
|
|
49
|
-
UpdateTodoItemInputSchema,
|
|
50
|
-
deleteTodoItem,
|
|
51
|
-
DeleteTodoItemInputSchema,
|
|
52
|
-
} from "todo-tutorial/document-models/todo-list";
|
|
53
|
-
|
|
54
|
-
describe("Todos Operations", () => {
|
|
55
|
-
it("should handle addTodoItem operation", () => {
|
|
56
|
-
// The `createDocument` utility function from your document model creates
|
|
57
|
-
// a new empty document, i.e. one with your default initial state
|
|
58
|
-
const document = utils.createDocument();
|
|
59
|
-
|
|
60
|
-
// The generateMock function takes one of your generated input schemas
|
|
61
|
-
// and creates an object populated with random values for each field
|
|
62
|
-
const input = generateMock(AddTodoItemInputSchema());
|
|
63
|
-
|
|
64
|
-
// We call your document model's reducer with the new document we just created
|
|
65
|
-
// and the action we want to test, `addTodoItem` in this case.
|
|
66
|
-
// The reducer returns a new object, which is the document with the action applied.
|
|
67
|
-
// If successful, there will be an operation which corresponds to this action
|
|
68
|
-
// in the updated document's operations list.
|
|
69
|
-
const updatedDocument = reducer(document, addTodoItem(input));
|
|
70
|
-
|
|
71
|
-
// When you generate a document model, we give you validation utilities like
|
|
72
|
-
// `isTodoListDocument` which confirms the document is of the correct form
|
|
73
|
-
// in a way that TypeScript recognizes
|
|
74
|
-
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
75
|
-
|
|
76
|
-
// At the start a document will have 0 operations, so after applying this action
|
|
77
|
-
// there should now be one operation
|
|
78
|
-
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
79
|
-
|
|
80
|
-
// The operation added to the list should correspond to the correct action type
|
|
81
|
-
expect(updatedDocument.operations.global[0].action.type).toBe("ADD_TODO_ITEM");
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it("should handle updateTodoItem operation", () => {
|
|
85
|
-
// ... boilerplate test
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it("should handle deleteTodoItem operation", () => {
|
|
89
|
-
// ... boilerplate test
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## Enhance the tests
|
|
95
|
-
|
|
96
|
-
The boilerplate tests check that operations are applied, but they don't verify the **actual results**. Let's write more comprehensive tests.
|
|
97
|
-
|
|
98
|
-
### Test 1: Update the addTodoItem test
|
|
99
|
-
|
|
100
|
-
The add test is already fairly complete. We just need to add type annotations:
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
it("should handle addTodoItem operation", () => {
|
|
104
|
-
const document = utils.createDocument();
|
|
105
|
-
// added-line
|
|
106
|
-
const input: AddTodoItemInput = generateMock(AddTodoItemInputSchema());
|
|
107
|
-
|
|
108
|
-
const updatedDocument = reducer(document, addTodoItem(input));
|
|
109
|
-
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
110
|
-
|
|
111
|
-
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
112
|
-
expect(updatedDocument.operations.global[0].action.type).toBe("ADD_TODO_ITEM");
|
|
113
|
-
expect(updatedDocument.operations.global[0].action.input).toStrictEqual(input);
|
|
114
|
-
expect(updatedDocument.operations.global[0].index).toEqual(0);
|
|
115
|
-
});
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### Test 2: Replace the updateTodoItem test
|
|
119
|
-
|
|
120
|
-
Delete the existing boilerplate and add two separate tests - one for updating text, one for updating the checked state:
|
|
121
|
-
|
|
122
|
-
```typescript
|
|
123
|
-
// removed-start
|
|
124
|
-
it("should handle updateTodoItem operation", () => {
|
|
125
|
-
const document = utils.createDocument();
|
|
126
|
-
const input = generateMock(UpdateTodoItemInputSchema());
|
|
127
|
-
const updatedDocument = reducer(document, updateTodoItem(input));
|
|
128
|
-
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
129
|
-
// ...
|
|
130
|
-
});
|
|
131
|
-
// removed-end
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
**Add the new test for updating text:**
|
|
135
|
-
|
|
136
|
-
```typescript
|
|
137
|
-
it("should handle updateTodoItem operation to update text", () => {
|
|
138
|
-
// We need there to already be a todo item in the document,
|
|
139
|
-
// since we want to test updating an existing item
|
|
140
|
-
const mockItem = generateMock(TodoItemSchema());
|
|
141
|
-
|
|
142
|
-
// We also need to generate a mock input for the update operation we are testing
|
|
143
|
-
const input: UpdateTodoItemInput = generateMock(UpdateTodoItemInputSchema());
|
|
144
|
-
|
|
145
|
-
// Since the mocks are generated with random values, we need to set the `id`
|
|
146
|
-
// on our mock input to match the `id` of the existing mock item
|
|
147
|
-
input.id = mockItem.id;
|
|
148
|
-
|
|
149
|
-
// We want to easily check if the item's text was updated to our new value,
|
|
150
|
-
// so we assign a variable and use that for the mock input's text field
|
|
151
|
-
const newText = "new text";
|
|
152
|
-
input.text = newText;
|
|
153
|
-
|
|
154
|
-
// We are only testing updating the text here, so we want the checked field
|
|
155
|
-
// on the input to be undefined, i.e. it should not change anything on the existing item
|
|
156
|
-
input.checked = undefined;
|
|
157
|
-
|
|
158
|
-
// We can pass a different initial state to the `createDocument` utility,
|
|
159
|
-
// so in this case we pass in an `items` array with our existing item already in it
|
|
160
|
-
const document = utils.createDocument({
|
|
161
|
-
global: {
|
|
162
|
-
items: [mockItem],
|
|
163
|
-
},
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
// Create an updated document by applying the reducer with the action and input
|
|
167
|
-
const updatedDocument = reducer(document, updateTodoItem(input));
|
|
168
|
-
|
|
169
|
-
// Use our validator to check that the document conforms to the document model schema
|
|
170
|
-
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
171
|
-
|
|
172
|
-
// There should now be one operation in the operations list
|
|
173
|
-
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
174
|
-
expect(updatedDocument.operations.global[0].action.type).toBe("UPDATE_TODO_ITEM");
|
|
175
|
-
|
|
176
|
-
// Find the updated item in the items list by its `id`
|
|
177
|
-
const updatedItem = updatedDocument.state.global.items.find(
|
|
178
|
-
(item) => item.id === input.id,
|
|
179
|
-
);
|
|
180
|
-
|
|
181
|
-
// The item's text should now be updated to be our new text
|
|
182
|
-
expect(updatedItem?.text).toBe(newText);
|
|
183
|
-
|
|
184
|
-
// The item's `checked` field should be unchanged
|
|
185
|
-
expect(updatedItem?.checked).toBe(mockItem.checked);
|
|
186
|
-
});
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
**Add the new test for updating checked state:**
|
|
190
|
-
|
|
191
|
-
```typescript
|
|
192
|
-
it("should handle updateTodoItem operation to update checked", () => {
|
|
193
|
-
// Generate a mock existing item
|
|
194
|
-
const mockItem = generateMock(TodoItemSchema());
|
|
195
|
-
|
|
196
|
-
// Generate a mock input
|
|
197
|
-
const input: UpdateTodoItemInput = generateMock(UpdateTodoItemInputSchema());
|
|
198
|
-
|
|
199
|
-
// Set the mock input's `id` to the mock item's `id`
|
|
200
|
-
input.id = mockItem.id;
|
|
201
|
-
|
|
202
|
-
// We want the new `checked` field value to be the opposite of the
|
|
203
|
-
// randomly generated value from the mock
|
|
204
|
-
const newChecked = !mockItem.checked;
|
|
205
|
-
input.checked = newChecked;
|
|
206
|
-
|
|
207
|
-
// Leave the `text` field unchanged
|
|
208
|
-
input.text = undefined;
|
|
209
|
-
|
|
210
|
-
// Create a document with the existing item in it
|
|
211
|
-
const document = utils.createDocument({
|
|
212
|
-
global: {
|
|
213
|
-
items: [mockItem],
|
|
214
|
-
},
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
// Apply the reducer with the action and the mock input
|
|
218
|
-
const updatedDocument = reducer(document, updateTodoItem(input));
|
|
219
|
-
|
|
220
|
-
// Validate your document
|
|
221
|
-
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
222
|
-
|
|
223
|
-
// Get the updated item by its `id`
|
|
224
|
-
const updatedItem = updatedDocument.state.global.items.find(
|
|
225
|
-
(item) => item.id === input.id,
|
|
226
|
-
);
|
|
227
|
-
|
|
228
|
-
// The item's `text` field should remain unchanged
|
|
229
|
-
expect(updatedItem?.text).toBe(mockItem.text);
|
|
230
|
-
|
|
231
|
-
// The item's `checked` field should be updated to our new checked value
|
|
232
|
-
expect(updatedItem?.checked).toBe(newChecked);
|
|
233
|
-
});
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
### Test 3: Update the deleteTodoItem test
|
|
237
|
-
|
|
238
|
-
The boilerplate delete test passes even without an existing item to delete. Let's fix that:
|
|
239
|
-
|
|
240
|
-
```typescript
|
|
241
|
-
it("should handle deleteTodoItem operation", () => {
|
|
242
|
-
// removed-start
|
|
243
|
-
const document = utils.createDocument();
|
|
244
|
-
const input = generateMock(DeleteTodoItemInputSchema());
|
|
245
|
-
// removed-end
|
|
246
|
-
// added-start
|
|
247
|
-
// Create an existing item to delete
|
|
248
|
-
const mockItem = generateMock(TodoItemSchema());
|
|
249
|
-
const document = utils.createDocument({
|
|
250
|
-
global: {
|
|
251
|
-
items: [mockItem],
|
|
252
|
-
},
|
|
253
|
-
});
|
|
254
|
-
const input: DeleteTodoItemInput = generateMock(DeleteTodoItemInputSchema());
|
|
255
|
-
input.id = mockItem.id;
|
|
256
|
-
// added-end
|
|
257
|
-
|
|
258
|
-
const updatedDocument = reducer(document, deleteTodoItem(input));
|
|
259
|
-
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
260
|
-
|
|
261
|
-
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
262
|
-
expect(updatedDocument.operations.global[0].action.type).toBe("DELETE_TODO_ITEM");
|
|
263
|
-
expect(updatedDocument.operations.global[0].action.input).toStrictEqual(input);
|
|
264
|
-
expect(updatedDocument.operations.global[0].index).toEqual(0);
|
|
265
|
-
|
|
266
|
-
// added-start
|
|
267
|
-
// Verify the item was actually removed
|
|
268
|
-
const updatedItems = updatedDocument.state.global.items;
|
|
269
|
-
expect(updatedItems).toHaveLength(0);
|
|
270
|
-
// added-end
|
|
271
|
-
});
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
## Complete test file
|
|
275
|
-
|
|
276
|
-
Here's the complete test file with all updates. Don't forget to add the missing imports:
|
|
277
|
-
|
|
278
|
-
<details>
|
|
279
|
-
<summary>Complete todos.test.ts</summary>
|
|
280
|
-
|
|
281
|
-
```typescript
|
|
282
|
-
import { describe, it, expect } from "vitest";
|
|
283
|
-
import { generateMock } from "@powerhousedao/codegen";
|
|
284
|
-
import type {
|
|
285
|
-
AddTodoItemInput,
|
|
286
|
-
DeleteTodoItemInput,
|
|
287
|
-
UpdateTodoItemInput,
|
|
288
|
-
} from "todo-tutorial/document-models/todo-list";
|
|
289
|
-
import {
|
|
290
|
-
reducer,
|
|
291
|
-
utils,
|
|
292
|
-
isTodoListDocument,
|
|
293
|
-
addTodoItem,
|
|
294
|
-
AddTodoItemInputSchema,
|
|
295
|
-
updateTodoItem,
|
|
296
|
-
UpdateTodoItemInputSchema,
|
|
297
|
-
deleteTodoItem,
|
|
298
|
-
DeleteTodoItemInputSchema,
|
|
299
|
-
TodoItemSchema,
|
|
300
|
-
} from "todo-tutorial/document-models/todo-list";
|
|
301
|
-
|
|
302
|
-
describe("Todos Operations", () => {
|
|
303
|
-
it("should handle addTodoItem operation", () => {
|
|
304
|
-
const document = utils.createDocument();
|
|
305
|
-
const input: AddTodoItemInput = generateMock(AddTodoItemInputSchema());
|
|
306
|
-
|
|
307
|
-
const updatedDocument = reducer(document, addTodoItem(input));
|
|
308
|
-
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
309
|
-
|
|
310
|
-
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
311
|
-
expect(updatedDocument.operations.global[0].action.type).toBe("ADD_TODO_ITEM");
|
|
312
|
-
expect(updatedDocument.operations.global[0].action.input).toStrictEqual(input);
|
|
313
|
-
expect(updatedDocument.operations.global[0].index).toEqual(0);
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
it("should handle updateTodoItem operation to update text", () => {
|
|
317
|
-
const mockItem = generateMock(TodoItemSchema());
|
|
318
|
-
const input: UpdateTodoItemInput = generateMock(UpdateTodoItemInputSchema());
|
|
319
|
-
input.id = mockItem.id;
|
|
320
|
-
const newText = "new text";
|
|
321
|
-
input.text = newText;
|
|
322
|
-
input.checked = undefined;
|
|
323
|
-
|
|
324
|
-
const document = utils.createDocument({
|
|
325
|
-
global: {
|
|
326
|
-
items: [mockItem],
|
|
327
|
-
},
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
const updatedDocument = reducer(document, updateTodoItem(input));
|
|
331
|
-
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
332
|
-
|
|
333
|
-
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
334
|
-
expect(updatedDocument.operations.global[0].action.type).toBe("UPDATE_TODO_ITEM");
|
|
335
|
-
|
|
336
|
-
const updatedItem = updatedDocument.state.global.items.find(
|
|
337
|
-
(item) => item.id === input.id,
|
|
338
|
-
);
|
|
339
|
-
expect(updatedItem?.text).toBe(newText);
|
|
340
|
-
expect(updatedItem?.checked).toBe(mockItem.checked);
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
it("should handle updateTodoItem operation to update checked", () => {
|
|
344
|
-
const mockItem = generateMock(TodoItemSchema());
|
|
345
|
-
const input: UpdateTodoItemInput = generateMock(UpdateTodoItemInputSchema());
|
|
346
|
-
input.id = mockItem.id;
|
|
347
|
-
const newChecked = !mockItem.checked;
|
|
348
|
-
input.checked = newChecked;
|
|
349
|
-
input.text = undefined;
|
|
350
|
-
|
|
351
|
-
const document = utils.createDocument({
|
|
352
|
-
global: {
|
|
353
|
-
items: [mockItem],
|
|
354
|
-
},
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
const updatedDocument = reducer(document, updateTodoItem(input));
|
|
358
|
-
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
359
|
-
|
|
360
|
-
const updatedItem = updatedDocument.state.global.items.find(
|
|
361
|
-
(item) => item.id === input.id,
|
|
362
|
-
);
|
|
363
|
-
expect(updatedItem?.text).toBe(mockItem.text);
|
|
364
|
-
expect(updatedItem?.checked).toBe(newChecked);
|
|
365
|
-
});
|
|
366
|
-
|
|
367
|
-
it("should handle deleteTodoItem operation", () => {
|
|
368
|
-
const mockItem = generateMock(TodoItemSchema());
|
|
369
|
-
const document = utils.createDocument({
|
|
370
|
-
global: {
|
|
371
|
-
items: [mockItem],
|
|
372
|
-
},
|
|
373
|
-
});
|
|
374
|
-
|
|
375
|
-
const input: DeleteTodoItemInput = generateMock(DeleteTodoItemInputSchema());
|
|
376
|
-
input.id = mockItem.id;
|
|
377
|
-
|
|
378
|
-
const updatedDocument = reducer(document, deleteTodoItem(input));
|
|
379
|
-
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
380
|
-
|
|
381
|
-
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
382
|
-
expect(updatedDocument.operations.global[0].action.type).toBe("DELETE_TODO_ITEM");
|
|
383
|
-
|
|
384
|
-
const updatedItems = updatedDocument.state.global.items;
|
|
385
|
-
expect(updatedItems).toHaveLength(0);
|
|
386
|
-
});
|
|
387
|
-
});
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
</details>
|
|
391
|
-
|
|
392
|
-
:::tip Check your work
|
|
393
|
-
|
|
394
|
-
To make sure everything works as expected:
|
|
395
|
-
|
|
396
|
-
```bash
|
|
397
|
-
# Check types compile correctly
|
|
398
|
-
pnpm tsc
|
|
399
|
-
|
|
400
|
-
# Check linting passes
|
|
401
|
-
pnpm lint
|
|
402
|
-
|
|
403
|
-
# Run tests
|
|
404
|
-
pnpm test
|
|
405
|
-
|
|
406
|
-
# Compare with reference implementation
|
|
407
|
-
git diff tutorial/step-4-implement-tests-for-todos-operations -- document-models/todo-list/src/tests/
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
Expected test output:
|
|
411
|
-
|
|
412
|
-
```bash
|
|
413
|
-
✓ document-models/todo-list/src/tests/document-model.test.ts (3 tests) 1ms
|
|
414
|
-
✓ document-models/todo-list/src/tests/todos.test.ts (4 tests) 8ms
|
|
415
|
-
|
|
416
|
-
Test Files 2 passed (2)
|
|
417
|
-
Tests 7 passed (7)
|
|
418
|
-
```
|
|
419
|
-
|
|
420
|
-
:::
|
|
421
|
-
|
|
422
|
-
## Up next: Building the editor
|
|
423
|
-
|
|
424
|
-
In the next chapter, you'll learn how to implement a user interface (editor) for your document model so you can interact with it visually.
|
|
425
|
-
|