@powerhousedao/academy 5.1.0-dev.9 → 5.1.0-staging.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 +37 -0
- package/docs/academy/01-GetStarted/01-CreateNewPowerhouseProject.md +54 -18
- package/docs/academy/01-GetStarted/02-DefineToDoListDocumentModel.md +21 -16
- package/docs/academy/01-GetStarted/03-ImplementOperationReducers.md +1 -24
- package/docs/academy/01-GetStarted/04-WriteDocumentModelTests.md +63 -16
- package/docs/academy/01-GetStarted/05-BuildToDoListEditor.md +22 -25
- package/docs/academy/01-GetStarted/images/Modules.png +0 -0
- package/docs/academy/01-GetStarted/images/VetraStudioDrive.png +0 -0
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/05-VetraStudio.md +20 -22
- package/docs/academy/02-MasteryTrack/05-Launch/05-DockerDeployment.md +384 -0
- package/docs/academy/03-ExampleUsecases/Chatroom/03-DefineChatroomDocumentModel.md +35 -98
- package/docs/academy/03-ExampleUsecases/Chatroom/04-ImplementOperationReducers.md +243 -170
- package/docs/academy/03-ExampleUsecases/Chatroom/05-ImplementChatroomEditor.md +257 -49
- package/package.json +1 -1
- package/sidebars.ts +0 -1
|
@@ -100,22 +100,20 @@ You will see that this action created a range of files for you. Before diving in
|
|
|
100
100
|
|
|
101
101
|

|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
## Implement the messages reducers
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
Navigate to `/document-models/chat-room/src/reducers/messages.ts` and start writing the operation reducers for the messages module.
|
|
106
|
+
|
|
107
|
+
Open the `messages.ts` file and you should see the scaffolding code that needs to be filled for the three message operations. The generated file will look like this:
|
|
106
108
|
|
|
107
109
|
```typescript
|
|
108
|
-
import type { ChatRoomMessagesOperations } from "chatroom/document-models/chat-room";
|
|
110
|
+
import type { ChatRoomMessagesOperations } from "@powerhousedao/chatroom-package/document-models/chat-room";
|
|
109
111
|
|
|
110
112
|
export const chatRoomMessagesOperations: ChatRoomMessagesOperations = {
|
|
111
113
|
addMessageOperation(state, action) {
|
|
112
114
|
// TODO: Implement "addMessageOperation" reducer
|
|
113
115
|
throw new Error('Reducer "addMessageOperation" not yet implemented');
|
|
114
116
|
},
|
|
115
|
-
senderOperation(state, action) {
|
|
116
|
-
// TODO: Implement "senderOperation" reducer
|
|
117
|
-
throw new Error('Reducer "senderOperation" not yet implemented');
|
|
118
|
-
},
|
|
119
117
|
addEmojiReactionOperation(state, action) {
|
|
120
118
|
// TODO: Implement "addEmojiReactionOperation" reducer
|
|
121
119
|
throw new Error('Reducer "addEmojiReactionOperation" not yet implemented');
|
|
@@ -127,20 +125,19 @@ export const chatRoomMessagesOperations: ChatRoomMessagesOperations = {
|
|
|
127
125
|
};
|
|
128
126
|
```
|
|
129
127
|
|
|
130
|
-
|
|
128
|
+
### Write the messages operation reducers
|
|
131
129
|
|
|
132
|
-
|
|
133
|
-
2. Save the file.
|
|
130
|
+
Copy and paste the code below into the `messages.ts` file in the `reducers` folder, replacing the scaffolding code:
|
|
134
131
|
|
|
135
132
|
<details>
|
|
136
|
-
<summary>Operation Reducers</summary>
|
|
133
|
+
<summary>Messages Operation Reducers</summary>
|
|
137
134
|
|
|
138
135
|
```typescript
|
|
139
136
|
import {
|
|
140
137
|
MessageNotFoundError,
|
|
141
138
|
MessageContentCannotBeEmptyError,
|
|
142
139
|
} from "../../gen/messages/error.js";
|
|
143
|
-
import type { ChatRoomMessagesOperations } from "chatroom-package/document-models/chat-room";
|
|
140
|
+
import type { ChatRoomMessagesOperations } from "@powerhousedao/chatroom-package/document-models/chat-room";
|
|
144
141
|
|
|
145
142
|
export const chatRoomMessagesOperations: ChatRoomMessagesOperations = {
|
|
146
143
|
addMessageOperation(state, action) {
|
|
@@ -221,18 +218,20 @@ export const chatRoomMessagesOperations: ChatRoomMessagesOperations = {
|
|
|
221
218
|
},
|
|
222
219
|
};
|
|
223
220
|
```
|
|
221
|
+
|
|
224
222
|
</details>
|
|
225
223
|
|
|
224
|
+
## Implement the settings reducers
|
|
226
225
|
|
|
227
|
-
|
|
228
|
-
2. Save the file.
|
|
226
|
+
Navigate to `/document-models/chat-room/src/reducers/settings.ts` and implement the settings operation reducers.
|
|
229
227
|
|
|
228
|
+
Copy and paste the code below into the `settings.ts` file in the `reducers` folder:
|
|
230
229
|
|
|
231
230
|
<details>
|
|
232
|
-
<summary>Operation Reducers</summary>
|
|
231
|
+
<summary>Settings Operation Reducers</summary>
|
|
233
232
|
|
|
234
233
|
```typescript
|
|
235
|
-
import type { ChatRoomSettingsOperations } from "chatroom-package/document-models/chat-room";
|
|
234
|
+
import type { ChatRoomSettingsOperations } from "@powerhousedao/chatroom-package/document-models/chat-room";
|
|
236
235
|
|
|
237
236
|
export const chatRoomSettingsOperations: ChatRoomSettingsOperations = {
|
|
238
237
|
editChatNameOperation(state, action) {
|
|
@@ -246,231 +245,303 @@ export const chatRoomSettingsOperations: ChatRoomSettingsOperations = {
|
|
|
246
245
|
|
|
247
246
|
</details>
|
|
248
247
|
|
|
249
|
-
|
|
250
248
|
## Write the operation reducer tests
|
|
251
249
|
|
|
252
250
|
In order to make sure the operation reducers are working as expected, you need to write tests for them.
|
|
253
251
|
|
|
254
|
-
Navigate to `/document-models/chat-room/src/tests` and
|
|
252
|
+
Navigate to `/document-models/chat-room/src/tests` and you'll find test files for each module. Replace the scaffolding code with the tests below.
|
|
253
|
+
|
|
254
|
+
### Messages operation tests
|
|
255
255
|
|
|
256
|
-
|
|
257
|
-
- Uses Vitest for testing
|
|
258
|
-
- Creates an empty ChatRoom document model
|
|
259
|
-
- Tests add message, add/remove reactions, and edit operations
|
|
260
|
-
- Verifies both the operation history and the resulting state
|
|
256
|
+
Replace the content of `messages.test.ts` with:
|
|
261
257
|
|
|
262
258
|
<details>
|
|
263
|
-
<summary>Operation
|
|
259
|
+
<summary>Messages Operation Tests</summary>
|
|
264
260
|
|
|
265
261
|
```typescript
|
|
266
|
-
|
|
267
|
-
|
|
262
|
+
/**
|
|
263
|
+
* This is a scaffold file meant for customization:
|
|
264
|
+
* - change it by adding new tests or modifying the existing ones
|
|
265
|
+
*/
|
|
266
|
+
|
|
267
|
+
import { describe, it, expect } from "vitest";
|
|
268
|
+
import { generateMock } from "@powerhousedao/codegen";
|
|
268
269
|
import {
|
|
269
270
|
reducer,
|
|
270
271
|
utils,
|
|
272
|
+
isChatRoomDocument,
|
|
271
273
|
addMessage,
|
|
274
|
+
AddMessageInputSchema,
|
|
272
275
|
addEmojiReaction,
|
|
276
|
+
AddEmojiReactionInputSchema,
|
|
273
277
|
removeEmojiReaction,
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
} from "../../gen/index.js";
|
|
277
|
-
import type {
|
|
278
|
-
ChatRoomDocument,
|
|
279
|
-
AddMessageInput,
|
|
280
|
-
AddEmojiReactionInput,
|
|
281
|
-
RemoveEmojiReactionInput,
|
|
282
|
-
EditChatNameInput,
|
|
283
|
-
EditChatDescriptionInput,
|
|
284
|
-
} from "../../gen/types.js";
|
|
285
|
-
|
|
286
|
-
describe("GeneralOperations Operations", () => {
|
|
287
|
-
let document: ChatRoomDocument;
|
|
288
|
-
|
|
289
|
-
beforeEach(() => {
|
|
290
|
-
document = utils.createDocument();
|
|
291
|
-
});
|
|
278
|
+
RemoveEmojiReactionInputSchema,
|
|
279
|
+
} from "@powerhousedao/chatroom-package/document-models/chat-room";
|
|
292
280
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
messageId: generateId(),
|
|
298
|
-
sender: {
|
|
299
|
-
id: "anon-user",
|
|
300
|
-
name: null,
|
|
301
|
-
avatarUrl: null,
|
|
302
|
-
},
|
|
303
|
-
sentAt: new Date().toISOString(),
|
|
304
|
-
};
|
|
281
|
+
describe("Messages Operations", () => {
|
|
282
|
+
it("should handle addMessage operation", () => {
|
|
283
|
+
const document = utils.createDocument();
|
|
284
|
+
const input = generateMock(AddMessageInputSchema());
|
|
305
285
|
|
|
306
286
|
const updatedDocument = reducer(document, addMessage(input));
|
|
307
287
|
|
|
308
|
-
|
|
309
|
-
};
|
|
310
|
-
|
|
311
|
-
// Test adding a new message
|
|
312
|
-
it("should handle addMessage operation", () => {
|
|
313
|
-
const [updatedDocument, input] = addMessageHelper();
|
|
314
|
-
|
|
315
|
-
// Verify the operation was recorded
|
|
288
|
+
expect(isChatRoomDocument(updatedDocument)).toBe(true);
|
|
316
289
|
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
317
|
-
expect(updatedDocument.operations.global[0].action.type).toBe(
|
|
318
|
-
|
|
290
|
+
expect(updatedDocument.operations.global[0].action.type).toBe(
|
|
291
|
+
"ADD_MESSAGE",
|
|
292
|
+
);
|
|
293
|
+
expect(updatedDocument.operations.global[0].action.input).toStrictEqual(
|
|
294
|
+
input,
|
|
295
|
+
);
|
|
319
296
|
expect(updatedDocument.operations.global[0].index).toEqual(0);
|
|
320
|
-
|
|
321
|
-
// Verify the message was added to state
|
|
322
|
-
expect(updatedDocument.state.global.messages).toHaveLength(1);
|
|
323
|
-
expect(updatedDocument.state.global.messages[0]).toMatchObject({
|
|
324
|
-
id: input.messageId,
|
|
325
|
-
content: input.content,
|
|
326
|
-
sender: input.sender,
|
|
327
|
-
sentAt: input.sentAt,
|
|
328
|
-
reactions: [],
|
|
329
|
-
});
|
|
330
297
|
});
|
|
331
|
-
|
|
332
|
-
// Test adding an emoji reaction
|
|
333
298
|
it("should handle addEmojiReaction operation", () => {
|
|
334
|
-
const
|
|
335
|
-
|
|
336
|
-
let updatedDocument = doc;
|
|
299
|
+
const document = utils.createDocument();
|
|
300
|
+
const input = generateMock(AddEmojiReactionInputSchema());
|
|
337
301
|
|
|
338
|
-
const
|
|
339
|
-
messageId: addMessageInput.messageId,
|
|
340
|
-
reactedBy: "anon-user",
|
|
341
|
-
type: "THUMBS_UP",
|
|
342
|
-
};
|
|
302
|
+
const updatedDocument = reducer(document, addEmojiReaction(input));
|
|
343
303
|
|
|
344
|
-
updatedDocument
|
|
345
|
-
|
|
346
|
-
|
|
304
|
+
expect(isChatRoomDocument(updatedDocument)).toBe(true);
|
|
305
|
+
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
306
|
+
expect(updatedDocument.operations.global[0].action.type).toBe(
|
|
307
|
+
"ADD_EMOJI_REACTION",
|
|
347
308
|
);
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
expect(updatedDocument.operations.global).toHaveLength(2);
|
|
351
|
-
expect(updatedDocument.operations.global[1].action.type).toBe("ADD_EMOJI_REACTION");
|
|
352
|
-
expect(updatedDocument.operations.global[1].action.input).toStrictEqual(
|
|
353
|
-
addEmojiReactionInput,
|
|
309
|
+
expect(updatedDocument.operations.global[0].action.input).toStrictEqual(
|
|
310
|
+
input,
|
|
354
311
|
);
|
|
355
|
-
expect(updatedDocument.operations.global[
|
|
356
|
-
|
|
357
|
-
// Verify the reaction was added
|
|
358
|
-
expect(updatedDocument.state.global.messages[0].reactions).toHaveLength(1);
|
|
359
|
-
expect(updatedDocument.state.global.messages[0].reactions?.[0]).toMatchObject({
|
|
360
|
-
reactedBy: [addEmojiReactionInput.reactedBy],
|
|
361
|
-
type: addEmojiReactionInput.type,
|
|
362
|
-
});
|
|
312
|
+
expect(updatedDocument.operations.global[0].index).toEqual(0);
|
|
363
313
|
});
|
|
314
|
+
it("should handle removeEmojiReaction operation", () => {
|
|
315
|
+
const document = utils.createDocument();
|
|
316
|
+
const input = generateMock(RemoveEmojiReactionInputSchema());
|
|
364
317
|
|
|
365
|
-
|
|
366
|
-
it("should handle addEmojiReaction operation to a non existing message", () => {
|
|
367
|
-
const input: AddEmojiReactionInput = {
|
|
368
|
-
messageId: "invalid-message-id",
|
|
369
|
-
reactedBy: "anon-user",
|
|
370
|
-
type: "THUMBS_UP",
|
|
371
|
-
};
|
|
372
|
-
|
|
373
|
-
const updatedDocument = reducer(document, addEmojiReaction(input));
|
|
318
|
+
const updatedDocument = reducer(document, removeEmojiReaction(input));
|
|
374
319
|
|
|
320
|
+
expect(isChatRoomDocument(updatedDocument)).toBe(true);
|
|
375
321
|
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
376
|
-
expect(updatedDocument.operations.global[0].action.type).toBe(
|
|
377
|
-
|
|
322
|
+
expect(updatedDocument.operations.global[0].action.type).toBe(
|
|
323
|
+
"REMOVE_EMOJI_REACTION",
|
|
324
|
+
);
|
|
325
|
+
expect(updatedDocument.operations.global[0].action.input).toStrictEqual(
|
|
326
|
+
input,
|
|
327
|
+
);
|
|
328
|
+
expect(updatedDocument.operations.global[0].index).toEqual(0);
|
|
378
329
|
});
|
|
330
|
+
});
|
|
331
|
+
```
|
|
379
332
|
|
|
380
|
-
|
|
381
|
-
it("should handle removeEmojiReaction operation", () => {
|
|
382
|
-
const [doc, addMessageInput] = addMessageHelper();
|
|
383
|
-
|
|
384
|
-
let updatedDocument = doc;
|
|
385
|
-
|
|
386
|
-
const addEmojiReactionInput: AddEmojiReactionInput = {
|
|
387
|
-
messageId: addMessageInput.messageId,
|
|
388
|
-
reactedBy: "anon-user",
|
|
389
|
-
type: "THUMBS_UP",
|
|
390
|
-
};
|
|
333
|
+
</details>
|
|
391
334
|
|
|
392
|
-
|
|
393
|
-
updatedDocument,
|
|
394
|
-
addEmojiReaction(addEmojiReactionInput),
|
|
395
|
-
);
|
|
335
|
+
### Settings operation tests
|
|
396
336
|
|
|
397
|
-
|
|
398
|
-
messageId: addMessageInput.messageId,
|
|
399
|
-
senderId: "anon-user",
|
|
400
|
-
type: "THUMBS_UP",
|
|
401
|
-
};
|
|
337
|
+
Replace the content of `settings.test.ts` with:
|
|
402
338
|
|
|
403
|
-
|
|
339
|
+
<details>
|
|
340
|
+
<summary>Settings Operation Tests</summary>
|
|
404
341
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
342
|
+
```typescript
|
|
343
|
+
/**
|
|
344
|
+
* This is a scaffold file meant for customization:
|
|
345
|
+
* - change it by adding new tests or modifying the existing ones
|
|
346
|
+
*/
|
|
410
347
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
348
|
+
import { describe, it, expect } from "vitest";
|
|
349
|
+
import { generateMock } from "@powerhousedao/codegen";
|
|
350
|
+
import {
|
|
351
|
+
reducer,
|
|
352
|
+
utils,
|
|
353
|
+
isChatRoomDocument,
|
|
354
|
+
editChatName,
|
|
355
|
+
EditChatNameInputSchema,
|
|
356
|
+
editChatDescription,
|
|
357
|
+
EditChatDescriptionInputSchema,
|
|
358
|
+
} from "@powerhousedao/chatroom-package/document-models/chat-room";
|
|
414
359
|
|
|
415
|
-
|
|
360
|
+
describe("Settings Operations", () => {
|
|
416
361
|
it("should handle editChatName operation", () => {
|
|
417
|
-
const
|
|
418
|
-
|
|
419
|
-
};
|
|
362
|
+
const document = utils.createDocument();
|
|
363
|
+
const input = generateMock(EditChatNameInputSchema());
|
|
420
364
|
|
|
421
365
|
const updatedDocument = reducer(document, editChatName(input));
|
|
422
366
|
|
|
423
|
-
|
|
367
|
+
expect(isChatRoomDocument(updatedDocument)).toBe(true);
|
|
424
368
|
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
425
|
-
expect(updatedDocument.operations.global[0].action.type).toBe(
|
|
426
|
-
|
|
369
|
+
expect(updatedDocument.operations.global[0].action.type).toBe(
|
|
370
|
+
"EDIT_CHAT_NAME",
|
|
371
|
+
);
|
|
372
|
+
expect(updatedDocument.operations.global[0].action.input).toStrictEqual(
|
|
373
|
+
input,
|
|
374
|
+
);
|
|
427
375
|
expect(updatedDocument.operations.global[0].index).toEqual(0);
|
|
428
|
-
|
|
429
|
-
// Verify the name was updated
|
|
430
|
-
expect(updatedDocument.state.global.name).toBe(input.name);
|
|
431
376
|
});
|
|
432
|
-
|
|
433
|
-
// Test editing chat description
|
|
434
377
|
it("should handle editChatDescription operation", () => {
|
|
435
|
-
const
|
|
436
|
-
|
|
437
|
-
};
|
|
378
|
+
const document = utils.createDocument();
|
|
379
|
+
const input = generateMock(EditChatDescriptionInputSchema());
|
|
438
380
|
|
|
439
381
|
const updatedDocument = reducer(document, editChatDescription(input));
|
|
440
382
|
|
|
441
|
-
|
|
383
|
+
expect(isChatRoomDocument(updatedDocument)).toBe(true);
|
|
442
384
|
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
443
|
-
expect(updatedDocument.operations.global[0].action.type).toBe(
|
|
444
|
-
|
|
385
|
+
expect(updatedDocument.operations.global[0].action.type).toBe(
|
|
386
|
+
"EDIT_CHAT_DESCRIPTION",
|
|
387
|
+
);
|
|
388
|
+
expect(updatedDocument.operations.global[0].action.input).toStrictEqual(
|
|
389
|
+
input,
|
|
390
|
+
);
|
|
445
391
|
expect(updatedDocument.operations.global[0].index).toEqual(0);
|
|
392
|
+
});
|
|
393
|
+
});
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
</details>
|
|
397
|
+
|
|
398
|
+
### Document model tests
|
|
399
|
+
|
|
400
|
+
The `document-model.test.ts` file contains tests to verify the document model structure. Replace its content with:
|
|
401
|
+
|
|
402
|
+
<details>
|
|
403
|
+
<summary>Document Model Tests</summary>
|
|
404
|
+
|
|
405
|
+
```typescript
|
|
406
|
+
/**
|
|
407
|
+
* This is a scaffold file meant for customization:
|
|
408
|
+
* - change it by adding new tests or modifying the existing ones
|
|
409
|
+
*/
|
|
410
|
+
|
|
411
|
+
import { describe, it, expect } from "vitest";
|
|
412
|
+
import {
|
|
413
|
+
utils,
|
|
414
|
+
initialGlobalState,
|
|
415
|
+
initialLocalState,
|
|
416
|
+
chatRoomDocumentType,
|
|
417
|
+
isChatRoomDocument,
|
|
418
|
+
assertIsChatRoomDocument,
|
|
419
|
+
isChatRoomState,
|
|
420
|
+
assertIsChatRoomState,
|
|
421
|
+
} from "@powerhousedao/chatroom-package/document-models/chat-room";
|
|
422
|
+
import { ZodError } from "zod";
|
|
423
|
+
|
|
424
|
+
describe("ChatRoom Document Model", () => {
|
|
425
|
+
it("should create a new ChatRoom document", () => {
|
|
426
|
+
const document = utils.createDocument();
|
|
427
|
+
|
|
428
|
+
expect(document).toBeDefined();
|
|
429
|
+
expect(document.header.documentType).toBe(chatRoomDocumentType);
|
|
430
|
+
});
|
|
446
431
|
|
|
447
|
-
|
|
448
|
-
|
|
432
|
+
it("should create a new ChatRoom document with a valid initial state", () => {
|
|
433
|
+
const document = utils.createDocument();
|
|
434
|
+
expect(document.state.global).toStrictEqual(initialGlobalState);
|
|
435
|
+
expect(document.state.local).toStrictEqual(initialLocalState);
|
|
436
|
+
expect(isChatRoomDocument(document)).toBe(true);
|
|
437
|
+
expect(isChatRoomState(document.state)).toBe(true);
|
|
438
|
+
});
|
|
439
|
+
it("should reject a document that is not a ChatRoom document", () => {
|
|
440
|
+
const wrongDocumentType = utils.createDocument();
|
|
441
|
+
wrongDocumentType.header.documentType = "the-wrong-thing-1234";
|
|
442
|
+
try {
|
|
443
|
+
expect(assertIsChatRoomDocument(wrongDocumentType)).toThrow();
|
|
444
|
+
expect(isChatRoomDocument(wrongDocumentType)).toBe(false);
|
|
445
|
+
} catch (error) {
|
|
446
|
+
expect(error).toBeInstanceOf(ZodError);
|
|
447
|
+
}
|
|
449
448
|
});
|
|
449
|
+
const wrongState = utils.createDocument();
|
|
450
|
+
// @ts-expect-error - we are testing the error case
|
|
451
|
+
wrongState.state.global = {
|
|
452
|
+
...{ notWhat: "you want" },
|
|
453
|
+
};
|
|
454
|
+
try {
|
|
455
|
+
expect(isChatRoomState(wrongState.state)).toBe(false);
|
|
456
|
+
expect(assertIsChatRoomState(wrongState.state)).toThrow();
|
|
457
|
+
expect(isChatRoomDocument(wrongState)).toBe(false);
|
|
458
|
+
expect(assertIsChatRoomDocument(wrongState)).toThrow();
|
|
459
|
+
} catch (error) {
|
|
460
|
+
expect(error).toBeInstanceOf(ZodError);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const wrongInitialState = utils.createDocument();
|
|
464
|
+
// @ts-expect-error - we are testing the error case
|
|
465
|
+
wrongInitialState.initialState.global = {
|
|
466
|
+
...{ notWhat: "you want" },
|
|
467
|
+
};
|
|
468
|
+
try {
|
|
469
|
+
expect(isChatRoomState(wrongInitialState.state)).toBe(false);
|
|
470
|
+
expect(assertIsChatRoomState(wrongInitialState.state)).toThrow();
|
|
471
|
+
expect(isChatRoomDocument(wrongInitialState)).toBe(false);
|
|
472
|
+
expect(assertIsChatRoomDocument(wrongInitialState)).toThrow();
|
|
473
|
+
} catch (error) {
|
|
474
|
+
expect(error).toBeInstanceOf(ZodError);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
const missingIdInHeader = utils.createDocument();
|
|
478
|
+
// @ts-expect-error - we are testing the error case
|
|
479
|
+
delete missingIdInHeader.header.id;
|
|
480
|
+
try {
|
|
481
|
+
expect(isChatRoomDocument(missingIdInHeader)).toBe(false);
|
|
482
|
+
expect(assertIsChatRoomDocument(missingIdInHeader)).toThrow();
|
|
483
|
+
} catch (error) {
|
|
484
|
+
expect(error).toBeInstanceOf(ZodError);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
const missingNameInHeader = utils.createDocument();
|
|
488
|
+
// @ts-expect-error - we are testing the error case
|
|
489
|
+
delete missingNameInHeader.header.name;
|
|
490
|
+
try {
|
|
491
|
+
expect(isChatRoomDocument(missingNameInHeader)).toBe(false);
|
|
492
|
+
expect(assertIsChatRoomDocument(missingNameInHeader)).toThrow();
|
|
493
|
+
} catch (error) {
|
|
494
|
+
expect(error).toBeInstanceOf(ZodError);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
const missingCreatedAtUtcIsoInHeader = utils.createDocument();
|
|
498
|
+
// @ts-expect-error - we are testing the error case
|
|
499
|
+
delete missingCreatedAtUtcIsoInHeader.header.createdAtUtcIso;
|
|
500
|
+
try {
|
|
501
|
+
expect(isChatRoomDocument(missingCreatedAtUtcIsoInHeader)).toBe(false);
|
|
502
|
+
expect(assertIsChatRoomDocument(missingCreatedAtUtcIsoInHeader)).toThrow();
|
|
503
|
+
} catch (error) {
|
|
504
|
+
expect(error).toBeInstanceOf(ZodError);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
const missingLastModifiedAtUtcIsoInHeader = utils.createDocument();
|
|
508
|
+
// @ts-expect-error - we are testing the error case
|
|
509
|
+
delete missingLastModifiedAtUtcIsoInHeader.header.lastModifiedAtUtcIso;
|
|
510
|
+
try {
|
|
511
|
+
expect(isChatRoomDocument(missingLastModifiedAtUtcIsoInHeader)).toBe(false);
|
|
512
|
+
expect(
|
|
513
|
+
assertIsChatRoomDocument(missingLastModifiedAtUtcIsoInHeader),
|
|
514
|
+
).toThrow();
|
|
515
|
+
} catch (error) {
|
|
516
|
+
expect(error).toBeInstanceOf(ZodError);
|
|
517
|
+
}
|
|
450
518
|
});
|
|
451
519
|
```
|
|
452
520
|
|
|
453
521
|
</details>
|
|
454
522
|
|
|
523
|
+
## Run the tests
|
|
524
|
+
|
|
455
525
|
Now you can run the tests to make sure the operation reducers are working as expected.
|
|
456
526
|
|
|
457
527
|
```bash
|
|
458
528
|
pnpm run test
|
|
459
529
|
```
|
|
460
530
|
|
|
461
|
-
Output should be
|
|
531
|
+
Output should be similar to:
|
|
462
532
|
|
|
463
533
|
```bash
|
|
464
534
|
✓ document-models/chat-room/src/tests/document-model.test.ts (3 tests) 1ms
|
|
465
|
-
✓ document-models/chat-room/src/tests/
|
|
535
|
+
✓ document-models/chat-room/src/tests/messages.test.ts (3 tests) 8ms
|
|
536
|
+
✓ document-models/chat-room/src/tests/settings.test.ts (2 tests) 2ms
|
|
466
537
|
|
|
467
|
-
Test Files
|
|
468
|
-
Tests
|
|
538
|
+
Test Files 3 passed (3)
|
|
539
|
+
Tests 8 passed (8)
|
|
469
540
|
Start at 15:19:52
|
|
470
541
|
Duration 3.61s (transform 77ms, setup 0ms, collect 3.50s, tests 14ms, environment 0ms, prepare 474ms)
|
|
471
542
|
```
|
|
472
543
|
|
|
473
|
-
If you got
|
|
544
|
+
If you got a similar output, you have successfully implemented the operation reducers and tests for the **ChatRoom** document model.
|
|
474
545
|
|
|
475
546
|
## Compare with reference implementation
|
|
476
547
|
|
|
@@ -478,10 +549,12 @@ Verify your implementation matches the tutorial:
|
|
|
478
549
|
|
|
479
550
|
```bash
|
|
480
551
|
# View reference reducer implementation
|
|
481
|
-
git show tutorial/main:document-models/chat-room/src/reducers/
|
|
552
|
+
git show tutorial/main:document-models/chat-room/src/reducers/messages.ts
|
|
553
|
+
git show tutorial/main:document-models/chat-room/src/reducers/settings.ts
|
|
482
554
|
|
|
483
555
|
# View reference test implementation
|
|
484
|
-
git show tutorial/main:document-models/chat-room/src/tests/
|
|
556
|
+
git show tutorial/main:document-models/chat-room/src/tests/messages.test.ts
|
|
557
|
+
git show tutorial/main:document-models/chat-room/src/tests/settings.test.ts
|
|
485
558
|
|
|
486
559
|
# Compare your entire implementation
|
|
487
560
|
git diff tutorial/main -- document-models/chat-room/src/
|