node-mongo-demo
node.js and mongodb demo
git clone https://9o.is/git/node-mongo-demo.git
lucky7-bet-events.unit.test.js
(6791B)
1 import { subscribe, onChange } from '../src/events/lucky7-bets.js';
2 import mongoose from 'mongoose';
3 import { jest } from '@jest/globals';
4
5 describe('Bet Events', () => {
6 it('insert', () => {
7 setTime('2024-01-01T00:00:00Z');
8
9 const stream = createStream();
10 const bet = {
11 _id: id(),
12 userId: id(),
13 lucky: true,
14 roll: [3,4],
15 rollAt: new Date('2024-01-01T00:00:15Z'),
16 };
17
18 subscribe(bet.userId.toString(), stream);
19 onChange(createInsertEvent(bet));
20
21 expect(stream.writeJson).toHaveBeenCalledTimes(1);
22 expect(stream.writeJson).toHaveBeenCalledWith({
23 operationType: 'insert',
24 bet: {
25 id: bet._id.toString(),
26 state: 'pending',
27 lucky: bet.lucky,
28 rollAt: bet.rollAt,
29 roll: undefined,
30 win: undefined,
31 },
32 });
33 });
34
35 it('update', () => {
36 setTime('2024-01-01T00:00:00Z');
37
38 const stream = createStream();
39 const bet = {
40 _id: id(),
41 userId: id(),
42 lucky: true,
43 rollAt: new Date('2024-01-01T00:00:15Z'),
44 };
45
46 subscribe(bet.userId.toString(), stream);
47 onChange(createInsertEvent(bet));
48 onChange(createUpdateEvent(bet._id, { lucky: false }));
49
50 expect(stream.writeJson).toHaveBeenCalledTimes(2);
51 expect(stream.writeJson).toHaveBeenNthCalledWith(2, {
52 operationType: 'update',
53 bet: {
54 id: bet._id.toString(),
55 state: 'pending',
56 lucky: false,
57 },
58 });
59 });
60
61 it('finished event', () => {
62 setTime('2024-01-01T00:00:00Z');
63
64 const stream = createStream();
65 const bet = {
66 _id: id(),
67 userId: id(),
68 lucky: true,
69 roll: [3,4],
70 rollAt: new Date('2024-01-01T00:00:15Z'),
71 };
72
73 subscribe(bet.userId.toString(), stream);
74 onChange(createInsertEvent(bet));
75
76 jest.advanceTimersByTime(14999);
77 expect(stream.writeJson).toHaveBeenCalledTimes(1);
78
79 jest.advanceTimersByTime(1);
80 expect(stream.writeJson).toHaveBeenCalledTimes(2);
81
82 expect(stream.writeJson).toHaveBeenNthCalledWith(2, {
83 operationType: 'update',
84 bet: {
85 id: bet._id.toString(),
86 state: 'finished',
87 lucky: bet.lucky,
88 rollAt: bet.rollAt,
89 roll: bet.roll,
90 win: true,
91 },
92 });
93 });
94
95 it('ignores other user\' events', () => {
96 setTime('2024-01-01T00:00:00Z');
97
98 const stream = createStream();
99 const userId = id();
100 const bet = {
101 _id: id(),
102 userId: id(),
103 lucky: true,
104 roll: [3,4],
105 rollAt: new Date('2024-01-01T00:00:15Z'),
106 };
107
108 subscribe(userId.toString(), stream);
109 onChange(createInsertEvent(bet));
110
111 expect(stream.writeJson).toHaveBeenCalledTimes(0);
112 });
113
114 it('multiple bets', () => {
115 setTime('2024-01-01T00:00:00Z');
116
117 const stream = createStream();
118 const userId = id();
119
120 const bet1 = {
121 _id: id(),
122 userId,
123 lucky: true,
124 roll: [3,4],
125 rollAt: new Date('2024-01-01T00:00:15Z'),
126 };
127
128 const bet2 = {
129 _id: id(),
130 userId,
131 lucky: false,
132 roll: [5,2],
133 rollAt: new Date('2024-01-01T00:00:10Z'),
134 };
135
136 subscribe(userId.toString(), stream);
137 onChange(createInsertEvent(bet1));
138 onChange(createInsertEvent(bet2));
139
140 expect(stream.writeJson).toHaveBeenCalledTimes(2);
141
142 expect(stream.writeJson).toHaveBeenCalledWith({
143 operationType: 'insert',
144 bet: {
145 id: bet1._id.toString(),
146 state: 'pending',
147 lucky: bet1.lucky,
148 rollAt: bet1.rollAt,
149 roll: undefined,
150 win: undefined,
151 },
152 });
153
154 expect(stream.writeJson).toHaveBeenCalledWith({
155 operationType: 'insert',
156 bet: {
157 id: bet2._id.toString(),
158 state: 'pending',
159 lucky: bet2.lucky,
160 rollAt: bet2.rollAt,
161 roll: undefined,
162 win: undefined,
163 },
164 });
165 });
166
167 it('multiple users', () => {
168 setTime('2024-01-01T00:00:00Z');
169
170 const user1Id = id();
171 const user2Id = id();
172 const stream1 = createStream();
173 const stream2 = createStream();
174
175 const bet1 = {
176 _id: id(),
177 userId: user1Id,
178 lucky: true,
179 roll: [3,4],
180 rollAt: new Date('2024-01-01T00:00:15Z'),
181 };
182
183 const bet2 = {
184 _id: id(),
185 userId: user2Id,
186 lucky: false,
187 roll: [5,2],
188 rollAt: new Date('2024-01-01T00:00:10Z'),
189 };
190
191 subscribe(user1Id.toString(), stream1);
192 subscribe(user2Id.toString(), stream2);
193
194 onChange(createInsertEvent(bet2));
195 onChange(createInsertEvent(bet1));
196
197 expect(stream1.writeJson).toHaveBeenCalledTimes(1);
198 expect(stream1.writeJson).toHaveBeenCalledWith({
199 operationType: 'insert',
200 bet: {
201 id: bet1._id.toString(),
202 state: 'pending',
203 lucky: bet1.lucky,
204 rollAt: bet1.rollAt,
205 roll: undefined,
206 win: undefined,
207 },
208 });
209
210 expect(stream2.writeJson).toHaveBeenCalledTimes(1);
211 expect(stream2.writeJson).toHaveBeenCalledWith({
212 operationType: 'insert',
213 bet: {
214 id: bet2._id.toString(),
215 state: 'pending',
216 lucky: bet2.lucky,
217 rollAt: bet2.rollAt,
218 roll: undefined,
219 win: undefined,
220 },
221 });
222 });
223 });
224
225 function createInsertEvent(fullDocument) {
226 return {
227 operationType: 'insert',
228 fullDocument,
229 };
230 }
231
232 function createUpdateEvent(_id, updatedFields) {
233 return {
234 operationType: 'update',
235 documentKey: {
236 _id,
237 },
238 updateDescription: {
239 updatedFields,
240 },
241 };
242 }
243
244 function createStream() {
245 return {
246 writeJson: jest.fn(),
247 onClose: () => {},
248 };
249 }
250
251 function id(x) {
252 return new mongoose.Types.ObjectId(x);
253 }
254
255 function setTime(dt) {
256 jest.useFakeTimers().setSystemTime(new Date(dt));
257 }