@powerhousedao/academy 5.1.0-dev.9 → 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 +43 -1108
- 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 +9 -118
- package/docs/academy/01-GetStarted/02-DefineToDoListDocumentModel.md +28 -110
- package/docs/academy/01-GetStarted/03-ImplementOperationReducers.md +145 -191
- package/docs/academy/01-GetStarted/04-BuildToDoListEditor.md +218 -0
- package/docs/academy/{02-MasteryTrack/01-BuilderEnvironment → 01-GetStarted}/05-VetraStudio.md +6 -48
- 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 +76 -255
- package/docs/academy/03-ExampleUsecases/Chatroom/04-ImplementOperationReducers.md +160 -281
- package/docs/academy/03-ExampleUsecases/Chatroom/05-ImplementChatroomEditor.md +35 -188
- 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 +12 -49
- package/src/css/custom.css +18 -26
- package/docs/academy/01-GetStarted/04-WriteDocumentModelTests.md +0 -378
- package/docs/academy/01-GetStarted/05-BuildToDoListEditor.md +0 -560
- 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/01-BuilderEnvironment → 01-GetStarted}/images/Modules.png +0 -0
- /package/docs/academy/{02-MasteryTrack/01-BuilderEnvironment → 01-GetStarted}/images/VetraStudioDrive.png +0 -0
- /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,462 +0,0 @@
|
|
|
1
|
-
# Step 3 — Adding our own tests for the document model actions
|
|
2
|
-
|
|
3
|
-
Similarly to the operation handler logic, when you add a new module to your document model, we generate some boilerplate tests for your code.
|
|
4
|
-
|
|
5
|
-
Take a look in `document-models/todo-list/src/tests/todos.test.ts`
|
|
6
|
-
|
|
7
|
-
You will see that we have some basic "sanity check" style tests for you already. These make sure that your operations are at least able to result in a valid document model state. You should copy these boilerplate checks in your other tests to ensure that your outputs are valid.
|
|
8
|
-
|
|
9
|
-
```ts
|
|
10
|
-
/**
|
|
11
|
-
* This is a scaffold file meant for customization:
|
|
12
|
-
* - change it by adding new tests or modifying the existing ones
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { describe, it, expect } from "vitest";
|
|
16
|
-
import { generateMock } from "@powerhousedao/codegen";
|
|
17
|
-
import {
|
|
18
|
-
reducer,
|
|
19
|
-
utils,
|
|
20
|
-
isTodoListDocument,
|
|
21
|
-
addTodoItem,
|
|
22
|
-
AddTodoItemInputSchema,
|
|
23
|
-
updateTodoItem,
|
|
24
|
-
UpdateTodoItemInputSchema,
|
|
25
|
-
deleteTodoItem,
|
|
26
|
-
DeleteTodoItemInputSchema,
|
|
27
|
-
} from "todo-tutorial/document-models/todo-list";
|
|
28
|
-
|
|
29
|
-
describe("Todos Operations", () => {
|
|
30
|
-
it("should handle addTodoItem operation", () => {
|
|
31
|
-
// the `createDocument` utility function from your document model creates
|
|
32
|
-
// an a new empty document, i.e. one with your default initial state
|
|
33
|
-
const document = utils.createDocument();
|
|
34
|
-
|
|
35
|
-
// the generate mock function takes one of your generated input schemas
|
|
36
|
-
// and creates an object populated with random values for each field
|
|
37
|
-
const input = generateMock(AddTodoItemInputSchema());
|
|
38
|
-
|
|
39
|
-
// we call your document model's reducer with the new document we just created
|
|
40
|
-
// and the action we want to test, `addTodoItem` in this case
|
|
41
|
-
// the reducer returns a new object, which is the document with the action applied
|
|
42
|
-
// if successful, there will be an operation which corresponds to this action
|
|
43
|
-
// in the updated document's operations list
|
|
44
|
-
const updatedDocument = reducer(document, addTodoItem(input));
|
|
45
|
-
|
|
46
|
-
// when you generate a document model, we give you some validation utilities like
|
|
47
|
-
// `isTodoListDocument` which confirms the document is of the correct form in a way
|
|
48
|
-
// that typescript recognizes
|
|
49
|
-
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
50
|
-
|
|
51
|
-
// at the start a document will have 0 operations, so after applying this action
|
|
52
|
-
// there should now be one operation
|
|
53
|
-
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
54
|
-
|
|
55
|
-
// the operation added to the list should correspond to the correct action type
|
|
56
|
-
expect(updatedDocument.operations.global[0].action.type).toBe(
|
|
57
|
-
"ADD_TODO_ITEM",
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
// the operation added should have used the correct input
|
|
61
|
-
expect(updatedDocument.operations.global[0].action.input).toStrictEqual(
|
|
62
|
-
input,
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
// the index of the operation should be 0, since it is the first and only operation
|
|
66
|
-
expect(updatedDocument.operations.global[0].index).toEqual(0);
|
|
67
|
-
});
|
|
68
|
-
it("should handle updateTodoItem operation", () => {
|
|
69
|
-
// ...
|
|
70
|
-
});
|
|
71
|
-
it("should handle deleteTodoItem operation", () => {
|
|
72
|
-
// ...
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
Since testing the `addTodoItemOperation` is such a simple case, we have not added further testing here. You are welcome to add a more test cases for it if you want.
|
|
78
|
-
|
|
79
|
-
## Tests for update operations
|
|
80
|
-
|
|
81
|
-
### Test updating the todo item text
|
|
82
|
-
|
|
83
|
-
Let's add some more sophisticated tests for our `updateTodoItem` operation. We want to know that we can update todos successfully, and that we we do so it only changes the values we want to change, while leaving the rest as is.
|
|
84
|
-
|
|
85
|
-
Delete the existing "should handle updateTodoItem operation" test.
|
|
86
|
-
|
|
87
|
-
```typescript
|
|
88
|
-
// removed-start
|
|
89
|
-
it("should handle updateTodoItem operation", () => {
|
|
90
|
-
const document = utils.createDocument();
|
|
91
|
-
const input = generateMock(UpdateTodoItemInputSchema());
|
|
92
|
-
const updatedDocument = reducer(document, updateTodoItem(input));
|
|
93
|
-
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
94
|
-
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
95
|
-
expect(updatedDocument.operations.global[0].action.type).toBe(
|
|
96
|
-
"UPDATE_TODO_ITEM",
|
|
97
|
-
);
|
|
98
|
-
expect(updatedDocument.operations.global[0].action.input).toStrictEqual(
|
|
99
|
-
input,
|
|
100
|
-
);
|
|
101
|
-
expect(updatedDocument.operations.global[0].index).toEqual(0);
|
|
102
|
-
});
|
|
103
|
-
// removed-end
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
Let's test that the text of a todo item is updated correctly first. Put this code in the place where you just deleted the existing test case:
|
|
107
|
-
|
|
108
|
-
```ts
|
|
109
|
-
it("should handle updateTodoItem operation to update text", () => {
|
|
110
|
-
// we need there to already be a todo item in the document,
|
|
111
|
-
// since we want to test updating an existing document
|
|
112
|
-
const mockItem = generateMock(TodoItemSchema());
|
|
113
|
-
|
|
114
|
-
// we also need to generate a mock input for the update operation we are testing
|
|
115
|
-
const input: UpdateTodoItemInput = generateMock(
|
|
116
|
-
UpdateTodoItemInputSchema(),
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
// since the mocks are generated with random values, we need to set the `id` on our mock input
|
|
120
|
-
// to match the `id` of the existing mock input
|
|
121
|
-
input.id = mockItem.id;
|
|
122
|
-
|
|
123
|
-
// we want to easily check if the item's text was updated to be our new value,
|
|
124
|
-
// so we assign a variable and use that for the mock input's text field
|
|
125
|
-
const newText = "new text";
|
|
126
|
-
input.text = newText;
|
|
127
|
-
|
|
128
|
-
// we are only testing updating the text here, so we want the checked field on the input
|
|
129
|
-
// to be undefined, i.e. it should not change anything on the existing item
|
|
130
|
-
input.checked = undefined;
|
|
131
|
-
|
|
132
|
-
// we can pass a different initial state to the `createDocument` utility,
|
|
133
|
-
// so in this case we pass in an `items` array with our existing item already in it
|
|
134
|
-
const document = utils.createDocument({
|
|
135
|
-
global: {
|
|
136
|
-
items: [mockItem],
|
|
137
|
-
},
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
/* The following checks are copied from the boilerplate */
|
|
141
|
-
|
|
142
|
-
// create an updated document by applying the reducer with the action and input
|
|
143
|
-
const updatedDocument = reducer(document, updateTodoItem(input));
|
|
144
|
-
|
|
145
|
-
// use our validator to check that the document conforms to the document model schema
|
|
146
|
-
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
147
|
-
|
|
148
|
-
// there should now be one operation in the operations list
|
|
149
|
-
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
150
|
-
|
|
151
|
-
// the operation applied should correspond to an action of the correct type
|
|
152
|
-
expect(updatedDocument.operations.global[0].action.type).toBe(
|
|
153
|
-
"UPDATE_TODO_ITEM",
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
// the operation applied should have used the correct input
|
|
157
|
-
expect(updatedDocument.operations.global[0].action.input).toStrictEqual(
|
|
158
|
-
input,
|
|
159
|
-
);
|
|
160
|
-
|
|
161
|
-
// the operation applied should be the first operation in the list
|
|
162
|
-
expect(updatedDocument.operations.global[0].index).toEqual(0);
|
|
163
|
-
|
|
164
|
-
/* The following checks are unique to this test case */
|
|
165
|
-
|
|
166
|
-
// find the updated item in the items list by its `id`
|
|
167
|
-
const updatedItem = updatedDocument.state.global.items.find(
|
|
168
|
-
(item) => item.id === input.id,
|
|
169
|
-
);
|
|
170
|
-
|
|
171
|
-
// the item's text should now be updated to be our new text
|
|
172
|
-
expect(updatedItem?.text).toBe(newText);
|
|
173
|
-
|
|
174
|
-
// the item's `checked` field should be unchanged.
|
|
175
|
-
expect(updatedItem?.checked).toBe(mockItem.checked);
|
|
176
|
-
});
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
#### Check your work
|
|
180
|
-
|
|
181
|
-
Running `pnpm tsc && pnpm lint && pnpm test` should pass
|
|
182
|
-
|
|
183
|
-
### Test updating the todo item checked state
|
|
184
|
-
|
|
185
|
-
Now let's do the same thing, but for the checked state of an item. This test is essentially just the same as the above, but we update the `checked` field while leaving the `text` field `undefined`.
|
|
186
|
-
|
|
187
|
-
Add this code below the test case we just added:
|
|
188
|
-
|
|
189
|
-
```ts
|
|
190
|
-
it("should handle updateTodoItem operation to update checked", () => {
|
|
191
|
-
// generate a mock existing item
|
|
192
|
-
const mockItem = generateMock(TodoItemSchema());
|
|
193
|
-
|
|
194
|
-
// generate a mock input
|
|
195
|
-
const input: UpdateTodoItemInput = generateMock(
|
|
196
|
-
UpdateTodoItemInputSchema(),
|
|
197
|
-
);
|
|
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 randomly generated value from the mock
|
|
203
|
-
const newChecked = !mockItem.checked;
|
|
204
|
-
input.checked = newChecked;
|
|
205
|
-
|
|
206
|
-
// leave the `text` field unchanged
|
|
207
|
-
input.text = undefined;
|
|
208
|
-
|
|
209
|
-
// create a document with the existing item in it
|
|
210
|
-
const document = utils.createDocument({
|
|
211
|
-
global: {
|
|
212
|
-
items: [mockItem],
|
|
213
|
-
},
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
// apply the reducer with the action and the mock input
|
|
217
|
-
const updatedDocument = reducer(document, updateTodoItem(input));
|
|
218
|
-
|
|
219
|
-
/* The following checks are copied from the boilerplate */
|
|
220
|
-
|
|
221
|
-
// validate your document
|
|
222
|
-
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
223
|
-
|
|
224
|
-
// check your operations
|
|
225
|
-
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
226
|
-
|
|
227
|
-
// check the operation's action type
|
|
228
|
-
expect(updatedDocument.operations.global[0].action.type).toBe(
|
|
229
|
-
"UPDATE_TODO_ITEM",
|
|
230
|
-
);
|
|
231
|
-
|
|
232
|
-
// check the operation's input
|
|
233
|
-
expect(updatedDocument.operations.global[0].action.input).toStrictEqual(
|
|
234
|
-
input,
|
|
235
|
-
);
|
|
236
|
-
|
|
237
|
-
// check the operation's index
|
|
238
|
-
expect(updatedDocument.operations.global[0].index).toEqual(0);
|
|
239
|
-
|
|
240
|
-
/* The following checks are unique to this test case */
|
|
241
|
-
|
|
242
|
-
// get the updated item by it's `id`
|
|
243
|
-
const updatedItem = updatedDocument.state.global.items.find(
|
|
244
|
-
(item) => item.id === input.id,
|
|
245
|
-
);
|
|
246
|
-
|
|
247
|
-
// the item's `text` field should remain unchanged
|
|
248
|
-
expect(updatedItem?.text).toBe(mockItem.text);
|
|
249
|
-
|
|
250
|
-
// the item's `checked` field should be updated to our new checked value
|
|
251
|
-
expect(updatedItem?.checked).toBe(newChecked);
|
|
252
|
-
});
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
#### Check your work
|
|
256
|
-
|
|
257
|
-
Running `pnpm tsc && pnpm lint && pnpm test` should pass
|
|
258
|
-
|
|
259
|
-
## Test for deleting todo items
|
|
260
|
-
|
|
261
|
-
You will have seen that the tests for the `deleteTodoItem` operation passed, even though we didn't set up an existing item to delete. This is because the boilerplate just checks that the operation was applied with the correct inputs, which it technically was. Checking that it actually had the _result_ we want is our job.
|
|
262
|
-
|
|
263
|
-
Update the `deleteTodoItem` operation test case to also create an existing item and then check that is was actually deleted:
|
|
264
|
-
|
|
265
|
-
```typescript
|
|
266
|
-
it("should handle deleteTodoItem operation", () => {
|
|
267
|
-
// removed-start
|
|
268
|
-
const document = utils.createDocument();
|
|
269
|
-
const input = generateMock(DeleteTodoItemInputSchema());
|
|
270
|
-
// removed-end
|
|
271
|
-
// added-start
|
|
272
|
-
const mockItem = generateMock(TodoItemSchema());
|
|
273
|
-
const document = utils.createDocument({
|
|
274
|
-
global: {
|
|
275
|
-
items: [mockItem],
|
|
276
|
-
},
|
|
277
|
-
});
|
|
278
|
-
const input: DeleteTodoItemInput = generateMock(
|
|
279
|
-
DeleteTodoItemInputSchema(),
|
|
280
|
-
);
|
|
281
|
-
input.id = mockItem.id;
|
|
282
|
-
// added-end
|
|
283
|
-
const updatedDocument = reducer(document, deleteTodoItem(input));
|
|
284
|
-
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
285
|
-
|
|
286
|
-
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
287
|
-
expect(updatedDocument.operations.global[0].action.type).toBe(
|
|
288
|
-
"DELETE_TODO_ITEM",
|
|
289
|
-
);
|
|
290
|
-
expect(updatedDocument.operations.global[0].action.input).toStrictEqual(
|
|
291
|
-
input,
|
|
292
|
-
);
|
|
293
|
-
expect(updatedDocument.operations.global[0].index).toEqual(0);
|
|
294
|
-
// added-start
|
|
295
|
-
const updatedItems = updatedDocument.state.global.items;
|
|
296
|
-
expect(updatedItems).toHaveLength(0);
|
|
297
|
-
// added-end
|
|
298
|
-
});
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
#### Check your work
|
|
302
|
-
|
|
303
|
-
Running `pnpm tsc && pnpm lint && pnpm test` should pass
|
|
304
|
-
|
|
305
|
-
## Final result
|
|
306
|
-
|
|
307
|
-
After these updates, your `document-models/todo-list/src/tests/todos.test.ts` file should look like this:
|
|
308
|
-
|
|
309
|
-
```ts
|
|
310
|
-
/**
|
|
311
|
-
* This is a scaffold file meant for customization:
|
|
312
|
-
* - change it by adding new tests or modifying the existing ones
|
|
313
|
-
*/
|
|
314
|
-
|
|
315
|
-
import { describe, it, expect } from "vitest";
|
|
316
|
-
import { generateMock } from "@powerhousedao/codegen";
|
|
317
|
-
import type {
|
|
318
|
-
AddTodoItemInput,
|
|
319
|
-
DeleteTodoItemInput,
|
|
320
|
-
UpdateTodoItemInput,
|
|
321
|
-
} from "todo-tutorial/document-models/todo-list";
|
|
322
|
-
import {
|
|
323
|
-
reducer,
|
|
324
|
-
utils,
|
|
325
|
-
isTodoListDocument,
|
|
326
|
-
addTodoItem,
|
|
327
|
-
AddTodoItemInputSchema,
|
|
328
|
-
updateTodoItem,
|
|
329
|
-
UpdateTodoItemInputSchema,
|
|
330
|
-
deleteTodoItem,
|
|
331
|
-
DeleteTodoItemInputSchema,
|
|
332
|
-
TodoItemSchema,
|
|
333
|
-
} from "todo-tutorial/document-models/todo-list";
|
|
334
|
-
|
|
335
|
-
describe("Todos Operations", () => {
|
|
336
|
-
it("should handle addTodoItem operation", () => {
|
|
337
|
-
const document = utils.createDocument();
|
|
338
|
-
const input: AddTodoItemInput = generateMock(AddTodoItemInputSchema());
|
|
339
|
-
|
|
340
|
-
const updatedDocument = reducer(document, addTodoItem(input));
|
|
341
|
-
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
342
|
-
|
|
343
|
-
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
344
|
-
expect(updatedDocument.operations.global[0].action.type).toBe(
|
|
345
|
-
"ADD_TODO_ITEM",
|
|
346
|
-
);
|
|
347
|
-
expect(updatedDocument.operations.global[0].action.input).toStrictEqual(
|
|
348
|
-
input,
|
|
349
|
-
);
|
|
350
|
-
expect(updatedDocument.operations.global[0].index).toEqual(0);
|
|
351
|
-
});
|
|
352
|
-
it("should handle updateTodoItem operation to update text", () => {
|
|
353
|
-
const mockItem = generateMock(TodoItemSchema());
|
|
354
|
-
const input: UpdateTodoItemInput = generateMock(
|
|
355
|
-
UpdateTodoItemInputSchema(),
|
|
356
|
-
);
|
|
357
|
-
input.id = mockItem.id;
|
|
358
|
-
const newText = "new text";
|
|
359
|
-
input.text = newText;
|
|
360
|
-
input.checked = undefined;
|
|
361
|
-
const document = utils.createDocument({
|
|
362
|
-
global: {
|
|
363
|
-
items: [mockItem],
|
|
364
|
-
},
|
|
365
|
-
});
|
|
366
|
-
|
|
367
|
-
const updatedDocument = reducer(document, updateTodoItem(input));
|
|
368
|
-
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
369
|
-
|
|
370
|
-
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
371
|
-
expect(updatedDocument.operations.global[0].action.type).toBe(
|
|
372
|
-
"UPDATE_TODO_ITEM",
|
|
373
|
-
);
|
|
374
|
-
expect(updatedDocument.operations.global[0].action.input).toStrictEqual(
|
|
375
|
-
input,
|
|
376
|
-
);
|
|
377
|
-
expect(updatedDocument.operations.global[0].index).toEqual(0);
|
|
378
|
-
const updatedItem = updatedDocument.state.global.items.find(
|
|
379
|
-
(item) => item.id === input.id,
|
|
380
|
-
);
|
|
381
|
-
expect(updatedItem?.text).toBe(newText);
|
|
382
|
-
expect(updatedItem?.checked).toBe(mockItem.checked);
|
|
383
|
-
});
|
|
384
|
-
it("should handle updateTodoItem operation to update checked", () => {
|
|
385
|
-
const mockItem = generateMock(TodoItemSchema());
|
|
386
|
-
const input: UpdateTodoItemInput = generateMock(
|
|
387
|
-
UpdateTodoItemInputSchema(),
|
|
388
|
-
);
|
|
389
|
-
input.id = mockItem.id;
|
|
390
|
-
const newChecked = !mockItem.checked;
|
|
391
|
-
input.checked = newChecked;
|
|
392
|
-
input.text = undefined;
|
|
393
|
-
const document = utils.createDocument({
|
|
394
|
-
global: {
|
|
395
|
-
items: [mockItem],
|
|
396
|
-
},
|
|
397
|
-
});
|
|
398
|
-
|
|
399
|
-
const updatedDocument = reducer(document, updateTodoItem(input));
|
|
400
|
-
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
401
|
-
|
|
402
|
-
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
403
|
-
expect(updatedDocument.operations.global[0].action.type).toBe(
|
|
404
|
-
"UPDATE_TODO_ITEM",
|
|
405
|
-
);
|
|
406
|
-
expect(updatedDocument.operations.global[0].action.input).toStrictEqual(
|
|
407
|
-
input,
|
|
408
|
-
);
|
|
409
|
-
expect(updatedDocument.operations.global[0].index).toEqual(0);
|
|
410
|
-
const updatedItem = updatedDocument.state.global.items.find(
|
|
411
|
-
(item) => item.id === input.id,
|
|
412
|
-
);
|
|
413
|
-
expect(updatedItem?.text).toBe(mockItem.text);
|
|
414
|
-
expect(updatedItem?.checked).toBe(newChecked);
|
|
415
|
-
});
|
|
416
|
-
it("should handle deleteTodoItem operation", () => {
|
|
417
|
-
const mockItem = generateMock(TodoItemSchema());
|
|
418
|
-
const document = utils.createDocument({
|
|
419
|
-
global: {
|
|
420
|
-
items: [mockItem],
|
|
421
|
-
},
|
|
422
|
-
});
|
|
423
|
-
const input: DeleteTodoItemInput = generateMock(
|
|
424
|
-
DeleteTodoItemInputSchema(),
|
|
425
|
-
);
|
|
426
|
-
input.id = mockItem.id;
|
|
427
|
-
const updatedDocument = reducer(document, deleteTodoItem(input));
|
|
428
|
-
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
429
|
-
|
|
430
|
-
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
431
|
-
expect(updatedDocument.operations.global[0].action.type).toBe(
|
|
432
|
-
"DELETE_TODO_ITEM",
|
|
433
|
-
);
|
|
434
|
-
expect(updatedDocument.operations.global[0].action.input).toStrictEqual(
|
|
435
|
-
input,
|
|
436
|
-
);
|
|
437
|
-
expect(updatedDocument.operations.global[0].index).toEqual(0);
|
|
438
|
-
const updatedItems = updatedDocument.state.global.items;
|
|
439
|
-
expect(updatedItems).toHaveLength(0);
|
|
440
|
-
});
|
|
441
|
-
});
|
|
442
|
-
```
|
|
443
|
-
|
|
444
|
-
## Check your work
|
|
445
|
-
|
|
446
|
-
To make sure all works as expected, we should:
|
|
447
|
-
|
|
448
|
-
- check types
|
|
449
|
-
run: `pnpm tsc`
|
|
450
|
-
|
|
451
|
-
- check linting
|
|
452
|
-
run: `pnpm lint`
|
|
453
|
-
|
|
454
|
-
- check tests
|
|
455
|
-
run: `pnpm test`
|
|
456
|
-
|
|
457
|
-
- make sure your code matches the code in the completed step branch
|
|
458
|
-
run: `git diff your-branch-name step-3-complete-implemented-tests-for-todo-operations`
|
|
459
|
-
|
|
460
|
-
### Up next: generating an editor for our `TodoList` documents
|
|
461
|
-
|
|
462
|
-
Up next, we'll generate a boilerplate document editor for our `TodoList` documents.
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
# Step 4 — Generating a document model editor for `TodoList` documents
|
|
2
|
-
|
|
3
|
-
## Generate the editor template
|
|
4
|
-
|
|
5
|
-
Run the command below to generate the editor template for the `TodoList` document model.
|
|
6
|
-
This command reads the `TodoList` document model definition from the `document-models` folder and generates the editor template in the `editors/todo-list-editor` folder.
|
|
7
|
-
|
|
8
|
-
```bash
|
|
9
|
-
pnpm generate --editor TodoListEditor --document-types powerhouse/todo-list
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
Notice the `--editor` flag which specifies the editor name, and the `--document-types` flag defines the document type `powerhouse/todo-list`.
|
|
13
|
-
|
|
14
|
-
Once complete, you'll have a new directory structure:
|
|
15
|
-
|
|
16
|
-
```
|
|
17
|
-
editors/todo-list-editor/
|
|
18
|
-
├── components/
|
|
19
|
-
│ └── EditName.tsx # Auto-generated component for editing document name
|
|
20
|
-
├── editor.tsx # Main editor component (do not change this)
|
|
21
|
-
└── module.ts # Editor module export (do not change this)
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## Check your work
|
|
25
|
-
|
|
26
|
-
To make sure all works as expected, we should:
|
|
27
|
-
|
|
28
|
-
- check types
|
|
29
|
-
run: `pnpm tsc`
|
|
30
|
-
|
|
31
|
-
- check linting
|
|
32
|
-
run: `pnpm lint`
|
|
33
|
-
|
|
34
|
-
- check tests
|
|
35
|
-
run: `pnpm test`
|
|
36
|
-
|
|
37
|
-
- test in connect
|
|
38
|
-
run: `pnpm connect` — you should now be able to create a `TodoList` type document and open it. You will see the generic `EditName` component in the document
|
|
39
|
-
|
|
40
|
-
- make sure your code matches the code in the completed step branch
|
|
41
|
-
run: `git diff your-branch-name step-4-complete-generated-todo-list-document-editor`
|
|
42
|
-
|
|
43
|
-
## Up next: adding UI components for updating our `TodoList` documents
|
|
44
|
-
|
|
45
|
-
Next, we will add some UI components to create, read, update, and delete data in our `TodoList` document editor.
|