Eric Bower
·
30 Jul 24
create-key.test.ts
1import { afterAll, beforeAll, describe, expect, it } from "../test.ts";
2import { type ActionWithPayload, createApi } from "../mod.ts";
3
4const getKeyOf = (action: ActionWithPayload<{ key: string }>): string =>
5 action.payload.key;
6
7const err = console.error;
8beforeAll(() => {
9 console.error = () => {};
10});
11
12afterAll(() => {
13 console.error = err;
14});
15
16const tests = describe("create-key");
17
18it(
19 tests,
20 "options object keys order for action key identity - 0: empty options",
21 () => {
22 console.warn = () => {};
23 const api = createApi();
24 api.use(api.routes());
25 // no param
26 const action0 = api.get(
27 "/users",
28 function* (ctx, next) {
29 ctx.request = {
30 method: "GET",
31 };
32 yield* next();
33 },
34 );
35 const sendNop0 = action0();
36 const sendNop1 = action0();
37 expect(getKeyOf(sendNop0)).toEqual(getKeyOf(sendNop1));
38 },
39);
40
41it(
42 tests,
43 "options object keys order for action key identity - 1: simple object",
44 () => {
45 const api = createApi();
46 api.use(api.routes());
47 // no param
48 const action0 = api.get<{
49 [key: string]: string | boolean | number | null | undefined;
50 }>(
51 "/users",
52 function* (ctx, next) {
53 ctx.request = {
54 method: "GET",
55 };
56 yield* next();
57 },
58 );
59 const sendPojo0 = action0({
60 a: "a",
61 b: "b",
62 c: 1,
63 d: 2,
64 e: true,
65 f: false,
66 "100": 100,
67 101: "101",
68 });
69 const sendPojo1 = action0({
70 a: "a",
71 b: "b",
72 c: 1,
73 d: 2,
74 e: true,
75 f: false,
76 100: 100,
77 101: "101",
78 });
79 const sendPojo2 = action0({
80 e: true,
81 f: false,
82 "100": 100,
83 "101": "101",
84 a: "a",
85 b: "b",
86 c: 1,
87 d: 2,
88 });
89 const sendPojo3 = action0({
90 e: true,
91 f: false,
92 "100": 100,
93 "101": "101",
94 a: "a",
95 b: "b",
96 c: 1,
97 d: 2000000,
98 });
99 const sendPojo4 = action0({
100 e: null,
101 f: false,
102 "100": undefined,
103 "101": "101",
104 a: "a",
105 b: "b",
106 c: 1,
107 d: `Thomas O'Malley`,
108 });
109 const sendPojo5 = action0({
110 d: `Thomas O'Malley`,
111 e: null,
112 f: false,
113 "100": undefined,
114 "101": "101",
115 a: "a",
116 b: "b",
117 c: 1,
118 });
119 expect(getKeyOf(sendPojo0)).toEqual(getKeyOf(sendPojo1));
120 expect(getKeyOf(sendPojo0)).toEqual(getKeyOf(sendPojo2));
121 expect(getKeyOf(sendPojo0)).not.toEqual(getKeyOf(sendPojo3));
122 expect(getKeyOf(sendPojo4)).toEqual(getKeyOf(sendPojo5));
123 },
124);
125
126it(
127 tests,
128 "options object keys order for action key identity - 2: object (with array values)",
129 () => {
130 interface Ip0 {
131 param1: string;
132 param2: string[];
133 }
134 const api = createApi();
135 api.use(api.routes());
136 const action = api.get<Ip0>(
137 "/users/:param1/:param2",
138 function* (ctx, next) {
139 ctx.request = {
140 method: "GET",
141 };
142 yield* next();
143 },
144 );
145 const sendFirst = action({ param1: "1", param2: ["2", "e", "f"] });
146 const sendSecond = action({ param2: ["2", "f", "e"], param1: "1" });
147 const sendThird = action({ param2: ["2", "e", "f"], param1: "1" });
148 expect(getKeyOf(sendFirst)).not.toEqual(getKeyOf(sendSecond));
149 expect(getKeyOf(sendFirst)).toEqual(getKeyOf(sendThird));
150 },
151);
152
153it(
154 tests,
155 "options object keys order for action key identity - 3: nested object",
156 () => {
157 interface Ip0 {
158 param1: string;
159 param2: string[];
160 }
161 interface Ip1 {
162 param1: string;
163 param2: string;
164 param3: number;
165 param4: Ip0;
166 param5: boolean;
167 }
168 const o1: Ip1 = {
169 param1: "1",
170 param2: "2",
171 param3: 3,
172 param4: {
173 param1: "4",
174 param2: ["5", "6"],
175 },
176 param5: true,
177 };
178 const o2: Ip1 = {
179 param4: {
180 param1: "4",
181 param2: ["5", "6"],
182 },
183 param5: true,
184 param2: "2",
185 param1: "1",
186 param3: 3,
187 };
188 const api = createApi();
189 api.use(api.routes());
190 //nested with array
191 const action2 = api.get<Ip1>(
192 "/users/:param1/:param2/:param3/:param4/:param5",
193 function* (ctx, next) {
194 ctx.request = {
195 method: "GET",
196 };
197 yield* next();
198 },
199 );
200 const sendO1 = action2(o1);
201 const sendO2 = action2(o2);
202 const sendO3 = action2({
203 ...o1,
204 param4: { ...o1.param4, param2: ["5", "6", "7"] },
205 });
206 expect(getKeyOf(sendO1)).toEqual(getKeyOf(sendO2));
207 expect(getKeyOf(sendO1)).not.toEqual(getKeyOf(sendO3));
208 },
209);
210
211it(
212 tests,
213 "options object keys order for action key identity - 4: deepNested object",
214 () => {
215 interface Ip0 {
216 param1: string;
217 param2: string[];
218 }
219 interface Ip1 {
220 param1: string;
221 param2: string;
222 param3: number;
223 param4: Ip0;
224 param5: boolean;
225 }
226 interface Ip3 {
227 param1: string;
228 param2: {
229 param3: Ip1;
230 param4: Ip0;
231 };
232 }
233 const o1: Ip1 = {
234 param1: "1",
235 param2: "2",
236 param3: 3,
237 param4: {
238 param1: "4",
239 param2: ["5", "6"],
240 },
241 param5: true,
242 };
243 const oo1: Ip3 = {
244 param1: "1",
245 param2: {
246 param3: o1,
247 param4: {
248 param1: "4",
249 param2: ["5", "6"],
250 },
251 },
252 };
253 const oo2: Ip3 = {
254 param1: "1",
255 param2: {
256 param4: {
257 param1: "4",
258 param2: ["5", "6"],
259 },
260 param3: o1,
261 },
262 };
263 const api = createApi();
264 api.use(api.routes());
265 // deepNested
266 const action4 = api.get<Ip3>(
267 "/users/:param1/:param2/:param3/:param4/:param5",
268 function* (ctx, next) {
269 ctx.request = {
270 method: "GET",
271 };
272 yield* next();
273 },
274 );
275 const send_oo1 = action4(oo1);
276 const send_oo1_shuff = action4({ param2: oo1.param2, param1: oo1.param1 });
277 const send_oo1_value_changed = action4({ ...oo1, param1: "x" });
278 const send_oo2 = action4(oo2);
279 expect(send_oo1.payload.options).toEqual(send_oo2.payload.options);
280 expect(getKeyOf(send_oo1)).toEqual(getKeyOf(send_oo1_shuff));
281 expect(getKeyOf(send_oo1)).not.toEqual(getKeyOf(send_oo1_value_changed));
282 expect(getKeyOf(send_oo1)).toEqual(getKeyOf(send_oo2));
283 },
284);
285
286it(
287 tests,
288 "options object keys order for action key identity - 5: other",
289 () => {
290 const api = createApi();
291 api.use(api.routes());
292 //array options
293 const action5 = api.post<
294 | number
295 | boolean
296 | string
297 | undefined
298 | null
299 | { param1: string; param2: (string | number)[] }[]
300 | string[]
301 >("/users/:allRecords", function* (ctx, next) {
302 ctx.request = {
303 method: "POST",
304 body: JSON.stringify(ctx.action.payload),
305 };
306 yield* next();
307 });
308 const falsy0 = action5(0);
309 const falsy1 = action5(false);
310 const falsy2 = action5("");
311 const falsy3 = action5(undefined);
312 const falsy4 = action5(null);
313 const primNo0 = action5(NaN);
314 const primNo1 = action5(1);
315 const primNo1bis = action5(1);
316 const primNo2 = action5(2);
317 const str1 = action5("1234");
318 const str1bis = action5("1234");
319 const str2 = action5("2345");
320 const aStrings1 = action5(["1", "2", "3"]);
321 const aStrings2 = action5(["1", "2", "3"]);
322 const aStrings3 = action5(["1", "2", "1"]);
323 const aObjects1 = action5([
324 { param1: "1", param2: ["2", "3"] },
325 { param1: "2", param2: ["2", "3"] },
326 ]);
327 const aObjects2 = action5([
328 { param1: "1", param2: ["2", "3"] },
329 { param1: "2", param2: ["2", "3"] },
330 ]);
331 // the objects are not identical.
332 const aObjects3 = action5([
333 { param1: "1", param2: ["2", "3"] },
334 { param1: "2", param2: ["2", 3] },
335 ]);
336 //object inside the array is shuffled
337 const aObjects4 = action5([
338 { param2: ["2", "3"], param1: "1" },
339 { param2: ["2", "3"], param1: "2" },
340 ]);
341 // cont the order of array elements is changed will get different keys.
342 const aObjects5 = action5([
343 { param1: "2", param2: ["2", "3"] },
344 { param1: "1", param2: ["2", "3"] },
345 ]);
346 expect(getKeyOf(falsy0)).not.toEqual(getKeyOf(falsy1));
347 expect(getKeyOf(falsy1)).not.toEqual(getKeyOf(falsy2));
348 expect(getKeyOf(falsy1)).not.toEqual(getKeyOf(falsy3));
349 expect(getKeyOf(falsy3)).not.toEqual(getKeyOf(falsy4));
350 expect(getKeyOf(primNo0)).not.toEqual(getKeyOf(falsy0));
351 expect(getKeyOf(primNo0)).not.toEqual(getKeyOf(primNo1));
352 expect(getKeyOf(primNo1)).not.toEqual(getKeyOf(primNo2));
353 expect(getKeyOf(primNo1)).toEqual(getKeyOf(primNo1bis));
354 expect(getKeyOf(str1)).not.toEqual(getKeyOf(str2));
355 expect(getKeyOf(str1)).toEqual(getKeyOf(str1bis));
356 expect(getKeyOf(aStrings1)).toEqual(getKeyOf(aStrings2));
357 expect(getKeyOf(aStrings1)).not.toEqual(getKeyOf(aStrings3));
358 expect(getKeyOf(aObjects1)).toEqual(getKeyOf(aObjects2));
359 expect(getKeyOf(aObjects1)).not.toEqual(getKeyOf(aObjects3));
360 expect(getKeyOf(aObjects1)).toEqual(getKeyOf(aObjects4));
361 expect(getKeyOf(aObjects1)).not.toEqual(getKeyOf(aObjects5));
362 },
363);