repos / starfx

supercharged async flow control library.
git clone https://github.com/neurosnap/starfx.git

starfx / test
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);