Passed
Push — develop ( 753300...72aeea )
by Lorenzo
01:40 queued 13s
created

Class.getProp   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
1
import { flushPromises } from '@test/utils/testUtils';
2
import { isProxy } from 'util/types';
3
import { InjectBean } from '@/core/decorators/InjectBean';
4
import { Executor } from '@/core/Executor';
5
6
jest.mock('@/core', () => ({
7
  logger: {
8
    info: jest.fn(),
9
    debug: jest.fn(),
10
    error: jest.fn(),
11
  },
12
}));
13
14
describe('InjectBean.ts', () => {
15
  beforeEach(() => {
16
    jest.resetAllMocks();
17
  });
18
19
  it('injects a dependency', async () => {
20
    // GIVEN
21
    class TypeA {}
22
    const T: any = TypeA;
23
    T._beanUUID = crypto.randomUUID();
24
    T._instance = new TypeA();
25
    T._className = TypeA.name;
26
27
    // WHEN
28
    class Class {
29
      @InjectBean(TypeA)
30
      private dep: TypeA;
31
32
      getDep() {
33
        return this.dep;
34
      }
35
    }
36
    const instance = new Class();
37
    await flushPromises();
38
39
    // THEN
40
    expect(isProxy(instance.getDep())).toBe(true);
41
    expect((instance.getDep() as any)._beanUUID).toBe(T._beanUUID);
42
    expect.assertions(2);
43
  });
44
45
  it('injects multiple dependencies', async () => {
46
    // GIVEN
47
    class TypeA {}
48
    const TA: any = TypeA;
49
    TA._beanUUID = crypto.randomUUID();
50
    TA._instance = new TypeA();
51
    TA._className = TypeA.name;
52
53
    class TypeB {}
54
    const TB: any = TypeB;
55
    TB._beanUUID = crypto.randomUUID();
56
    TB._instance = new TypeB();
57
    TB._className = TypeB.name;
58
59
    // WHEN
60
    class Class {
61
      @InjectBean(TypeA)
62
        dep1: TypeA;
63
64
      @InjectBean(TypeB)
65
        dep2: TypeB;
66
67
      getDeps() {
68
        return [this.dep1, this.dep2];
69
      }
70
    }
71
    const instance = new Class();
72
    await flushPromises();
73
74
    // THEN
75
    const [dep1, dep2] = instance.getDeps();
76
    expect((dep1 as any)._beanUUID).toBe(TA._beanUUID);
77
    expect((dep2 as any)._beanUUID).toBe(TB._beanUUID);
78
  });
79
80
  it('throws an error if trying to inject a non injectable dependency', async () => {
81
    // GIVEN
82
    class TypeA {
83
      prop: string;
84
    }
85
    let instance;
86
87
    // WHEN
88
    expect(() => {
89
      class Class {
90
        @InjectBean(TypeA)
91
          dep: TypeA;
92
      }
93
      instance = new Class();
94
      expect((instance.dep as any).prop).not.toBeDefined();
95
    }).toThrow(new Error('Cannot get instance from TypeA. Make sure that TypeA has @Bean as class decorator'));
96
  });
97
98
  it('throws an error if trying to inject without specify a type', async () => {
99
    // GIVEN
100
    class TypeA {}
101
    let instance;
102
103
    // WHEN
104
    expect(() => {
105
      class Class {
106
        @InjectBean(null as any)
107
          dep: TypeA;
108
      }
109
      instance = new Class();
110
      expect((instance.dep as any).prop).not.toBeDefined();
111
    }).toThrow(new Error('Please specify the type of Bean. Example: @InjectBean(BeanClass)'));
112
  });
113
114
  it('throws an error when dependency is not found', async () => {
115
    // GIVEN
116
    class TypeA {
117
      prop: string;
118
    }
119
    class Class {
120
      @InjectBean(TypeA)
121
        dep: TypeA;
122
123
      getDep() {
124
        return this.dep;
125
      }
126
    }
127
128
    // WHEN
129
    let dep;
130
    await expect(async () => {
131
      const instance = new Class();
132
      dep = instance.getDep();
133
      await Executor.execution;
134
      // THEN
135
      expect(dep.prop).not.toBeDefined();
136
    }).rejects.toThrow(new Error('Cannot get instance from TypeA. Make sure that TypeA has @Bean as class decorator'));
137
  });
138
139
  it('throws an error if trying to use decorator improperly', async () => {
140
    // GIVEN
141
    class TypeA {}
142
    let instance;
143
144
    // WHEN
145
    expect(() => {
146
      class Class {
147
        @InjectBean({ key: 'value' })
148
          dep: TypeA;
149
      }
150
      instance = new Class();
151
      expect((instance.dep as any).key).not.toBeDefined();
152
    }).toThrow(new Error('Cannot get instance for {"key":"value"}: it is not an ExpressBean'));
153
  });
154
155
  it('proxies a dependency', async () => {
156
    // GIVEN
157
    class TypeA {
158
      prop: string = 'value';
159
160
      getProp() {
161
        return this.prop;
162
      }
163
    }
164
    const T: any = TypeA;
165
    T._beanUUID = crypto.randomUUID();
166
    T._instance = new TypeA();
167
    T._className = TypeA.name;
168
169
    // WHEN
170
    class Class {
171
      @InjectBean(TypeA)
172
      private dep: TypeA;
173
174
      getDep() {
175
        return this.dep;
176
      }
177
178
      getProp() {
179
        return this.dep.getProp();
180
      }
181
    }
182
    const instance = new Class();
183
    await flushPromises();
184
185
    // THEN
186
    expect(isProxy(instance.getDep())).toBe(true);
187
    expect((instance.getDep() as any)._beanUUID).toBe(T._beanUUID);
188
    expect(instance.getProp()).toBe('value');
189
    expect.assertions(3);
190
  });
191
});
192