-
-
Notifications
You must be signed in to change notification settings - Fork 71
/
helper.resolve-provider.ts
135 lines (121 loc) · 4.01 KB
/
helper.resolve-provider.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import { extractDependency } from '../common/core.helpers';
import { NG_MOCKS_INTERCEPTORS } from '../common/core.tokens';
import { isNgInjectionToken } from '../common/func.is-ng-injection-token';
import ngMocksUniverse from '../common/ng-mocks-universe';
import mockServiceHelper from './helper';
import MockProvider from './mock-provider';
// tries to resolve a provider based on current universe state.
export default (def: any, resolutions: Map<any, any>, changed?: (flag: boolean) => void) => {
const provider = typeof def === 'object' && def.provide ? def.provide : def;
const multi = def !== provider && !!def.multi;
// we shouldn't touch our system providers.
if (typeof def === 'object' && def.useExisting && def.useExisting.__ngMocksSkip) {
return def;
}
let mockDef: typeof def;
if (resolutions.has(provider)) {
mockDef = resolutions.get(provider);
const existingMock = ngMocksUniverse.builtProviders.get(provider);
if (existingMock) {
mockDef = existingMock;
}
// A case when a provider is actually a component, directive, pipe.
if (typeof mockDef === 'function') {
mockDef = {
provide: provider,
useClass: mockDef,
};
}
return multi && typeof mockDef === 'object' ? { ...mockDef, multi } : mockDef;
}
// we shouldn't touch excluded providers.
if (ngMocksUniverse.builtProviders.has(provider) && ngMocksUniverse.builtProviders.get(provider) === null) {
/* istanbul ignore else */
if (changed) {
changed(true);
}
return;
}
if (provider !== def && def.deps) {
extractDependency(def.deps, ngMocksUniverse.config.get('deps'));
}
if (
ngMocksUniverse.builtProviders.has(NG_MOCKS_INTERCEPTORS) &&
ngMocksUniverse.builtProviders.get(NG_MOCKS_INTERCEPTORS) === null &&
isNgInjectionToken(provider) &&
provider.toString() === 'InjectionToken HTTP_INTERCEPTORS' &&
provider !== def
) {
if (def.useFactory || def.useValue) {
/* istanbul ignore else */
if (changed) {
changed(true);
}
return;
}
const interceptor = def.useExisting || def.useClass;
if (!ngMocksUniverse.builtProviders.has(interceptor) || ngMocksUniverse.builtProviders.get(interceptor) === null) {
/* istanbul ignore else */
if (changed) {
changed(true);
}
return;
}
}
// Then we check decisions whether we should keep or replace a def.
if (ngMocksUniverse.builtProviders.has(provider)) {
mockDef = ngMocksUniverse.builtProviders.get(provider);
if (mockDef === provider) {
mockDef = def;
} else if (mockDef === undefined) {
mockDef = {
provide: provider,
useValue: undefined,
};
}
}
if (!mockDef && ngMocksUniverse.flags.has('skipMock')) {
ngMocksUniverse.config.get('depsSkip')?.add(provider);
mockDef = def;
}
if (!mockDef) {
mockDef = MockProvider(def);
}
// if provider is a value, we need to go through the value and to replace all mock instances.
if (provider !== def && mockDef && mockDef.useValue) {
const useValue = mockServiceHelper.replaceWithMocks(mockDef.useValue);
mockDef =
useValue === mockDef.useValue
? mockDef
: {
...mockDef,
useValue,
};
}
if (!isNgInjectionToken(provider) || def !== mockDef) {
resolutions.set(provider, mockDef);
}
let differs = false;
if (def === provider && mockDef !== def) {
differs = true;
} else if (
def !== provider &&
(!mockDef ||
def.provide !== mockDef.provide ||
def.useValue !== mockDef.useValue ||
def.useClass !== mockDef.useClass ||
def.useExisting !== mockDef.useExisting ||
def.useFactory !== mockDef.useFactory ||
def.deps !== mockDef.deps)
) {
differs = true;
}
if (changed && differs) {
changed(true);
}
// Touching only when we really provide a value.
if (mockDef) {
ngMocksUniverse.touches.add(provider);
}
return multi && typeof mockDef === 'object' ? { ...mockDef, multi } : mockDef;
};