Passed
Push — main ( 238ec8...50243d )
by Lorenzo
03:03
created

Cached.spec.ts ➔ get   A

Complexity

Conditions 2

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 6
c 0
b 0
f 0
rs 10
cc 2
1
import { randomUUID } from 'crypto';
2
import { Cached } from '@/cache/decorators/Cached';
3
import { registeredBeans, registeredMethods } from '@/core';
4
import { Executor } from '@/core/executor';
5
6
jest.mock('@/core', () => ({
7
  registeredBeans: new Map(),
8
  registeredMethods: new Map(),
9
  logger: {
10
    info: jest.fn(),
11
    debug: jest.fn(),
12
    error: jest.fn(),
13
  },
14
}));
15
16
const createProxy = (actualBean: any) => new Proxy(actualBean, {
17
  get(target, prop) {
18
    const interceptor = (target as any)._interceptors.get(prop as string);
19
    if (interceptor) {
20
      return interceptor(target, prop as string);
21
    }
22
    return target[prop as keyof typeof target];
23
  }
24
});
25
26
describe('Cached.ts', () => {
27
  beforeEach(() => {
28
    jest.resetAllMocks();
29
    registeredMethods.clear();
30
    registeredBeans.clear();
31
  });
32
33
  it('execute a cached function', async () => {
34
    // GIVEN
35
    class Class {
36
      @Cached()
37
      getUUIDCached() {
38
        return randomUUID();
39
      }
40
41
      getUUID() {
42
        return randomUUID();
43
      }
44
    }
45
    const bean = createProxy(new Class());
46
    (bean as any)._interceptors = new Map();
47
    registeredBeans.set('Class', bean as any);
48
    registeredMethods.set(bean.getUUID, bean as any);
49
    registeredMethods.set(bean.getUUIDCached, bean as any);
50
    await Executor.execute();
51
52
    // WHEN
53
    const resultNoCache = bean.getUUID();
54
    const resultCache = bean.getUUIDCached();
55
56
    // THEN
57
    expect(bean.getUUID()).not.toStrictEqual(resultNoCache);
58
    expect(bean.getUUIDCached()).toStrictEqual(resultCache);
59
  });
60
61
  it('execute an async cached function', async () => {
62
    // GIVEN
63
    class Class {
64
      @Cached()
65
      async getUUIDCached() {
66
        return randomUUID();
67
      }
68
69
      async getUUID() {
70
        return randomUUID();
71
      }
72
    }
73
    const bean = createProxy(new Class());
74
    (bean as any)._interceptors = new Map();
75
    registeredBeans.set('Class', bean as any);
76
    registeredMethods.set(bean.getUUID, bean as any);
77
    registeredMethods.set(bean.getUUIDCached, bean as any);
78
    await Executor.execute();
79
80
    // WHEN
81
    const resultNoCache = await bean.getUUID();
82
    const resultCache = await bean.getUUIDCached();
83
84
    // THEN
85
    expect(await bean.getUUID()).not.toStrictEqual(resultNoCache);
86
    expect(await bean.getUUIDCached()).toStrictEqual(resultCache);
87
  });
88
89
  it('caches a function by its arguments', async () => {
90
    // GIVEN
91
    class Class {
92
      @Cached()
93
      getUUIDCached(anArgument: string) {
94
        return `${randomUUID()}/${anArgument}`;
95
      }
96
    }
97
    const bean = createProxy(new Class());
98
    (bean as any)._interceptors = new Map();
99
    registeredBeans.set('Class', bean as any);
100
    registeredMethods.set(bean.getUUIDCached, bean as any);
101
    await Executor.execute();
102
103
    // WHEN
104
    const resultCache = bean.getUUIDCached('first');
105
106
    // THEN
107
    expect(bean.getUUIDCached('second')).not.toStrictEqual(resultCache);
108
    expect(bean.getUUIDCached('first')).toStrictEqual(resultCache);
109
  });
110
111
  it('caches an async function by its arguments', async () => {
112
    // GIVEN
113
    class Class {
114
      @Cached()
115
      async getUUIDCached(anArgument: string) {
116
        return `${randomUUID()}/${anArgument}`;
117
      }
118
    }
119
    const bean = createProxy(new Class());
120
    (bean as any)._interceptors = new Map();
121
    registeredBeans.set('Class', bean as any);
122
    registeredMethods.set(bean.getUUIDCached, bean as any);
123
    await Executor.execute();
124
125
    // WHEN
126
    const resultCache = await bean.getUUIDCached('first');
127
128
    // THEN
129
    expect(await bean.getUUIDCached('second')).not.toStrictEqual(resultCache);
130
    expect(await bean.getUUIDCached('first')).toStrictEqual(resultCache);
131
  });
132
133
  it('invalidates a cache when expired', async () => {
134
    // GIVEN
135
    class Class {
136
      @Cached()
137
      getUUIDCached() {
138
        return randomUUID();
139
      }
140
    }
141
    const bean = createProxy(new Class());
142
    (bean as any)._interceptors = new Map();
143
    registeredBeans.set('Class', bean as any);
144
    registeredMethods.set(bean.getUUIDCached, bean as any);
145
    await Executor.execute();
146
147
    // WHEN
148
    const resultCache = bean.getUUIDCached();
149
    expect(bean.getUUIDCached()).toStrictEqual(resultCache);
150
    jest.useFakeTimers().setSystemTime(Date.now() + 60_001);
151
152
    // THEN
153
    expect(bean.getUUIDCached()).not.toStrictEqual(resultCache);
154
  });
155
});
156