@kumori/aurora-backend-handler 1.1.42 → 1.1.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitlab-ci.yml +21 -21
- package/jest.config.ts +1 -0
- package/package.json +1 -1
- package/test/backend-handler.test.ts +992 -730
- package/test/deploy-service-helper.test.ts +678 -274
- package/test/event-helper.test.ts +489 -104
- package/test/event-names.test.ts +186 -0
|
@@ -1,792 +1,1054 @@
|
|
|
1
|
-
import {
|
|
2
|
-
acceptInvite,
|
|
3
|
-
createTenant,
|
|
4
|
-
rejectInvite,
|
|
5
|
-
} from "../api/tenant-api-service";
|
|
6
|
-
import { loadUser } from "../api/user-api-service";
|
|
7
|
-
import { createAccount } from "../api/account-api-service";
|
|
8
|
-
import { createEnvironment } from "../api/environment-api-service";
|
|
9
|
-
import { changeRevision, deployService, requestRevisionData, updateService } from "../api/service-api-service";
|
|
10
|
-
import {
|
|
11
|
-
deployMarketplaceItem,
|
|
12
|
-
getMarketplaceItems,
|
|
13
|
-
} from "../api/marketplace-api-service";
|
|
14
1
|
import { BackendHandler } from "../backend-handler";
|
|
15
|
-
import { Account,
|
|
2
|
+
import type { Account, Environment, MarketplaceItem, MarketplaceService, Resource, Service, Tenant, UserData } from "@kumori/aurora-interfaces";
|
|
16
3
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
4
|
+
// ── Mocks de módulos externos ─────────────────────────────────────────────────
|
|
5
|
+
|
|
6
|
+
jest.mock("../event-helper", () =>
|
|
7
|
+
jest.fn().mockImplementation((globalEventHandler: any) => globalEventHandler),
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
jest.mock("../api/user-api-service", () => ({
|
|
11
|
+
getUserHTTP: jest.fn().mockResolvedValue({}),
|
|
12
|
+
loadUser: jest.fn(),
|
|
13
|
+
isUserLogged: jest.fn().mockResolvedValue(true),
|
|
14
|
+
createUser: jest.fn(),
|
|
15
|
+
updateUser: jest.fn(),
|
|
16
|
+
deleteUSer: jest.fn(),
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
jest.mock("../api/tenant-api-service", () => ({
|
|
20
|
+
createTenant: jest.fn(),
|
|
21
|
+
createTenantHTTP: jest.fn(),
|
|
22
|
+
updateTenant: jest.fn(),
|
|
23
|
+
updateTenantHTTP: jest.fn(),
|
|
24
|
+
deleteTenant: jest.fn(),
|
|
25
|
+
createRegistry: jest.fn(),
|
|
26
|
+
updateRegistry: jest.fn(),
|
|
27
|
+
deleteRegistry: jest.fn(),
|
|
28
|
+
inviteUser: jest.fn(),
|
|
29
|
+
removeUser: jest.fn(),
|
|
30
|
+
updateUserRole: jest.fn(),
|
|
31
|
+
acceptInvite: jest.fn(),
|
|
32
|
+
rejectInvite: jest.fn(),
|
|
33
|
+
createToken: jest.fn(),
|
|
34
|
+
deleteToken: jest.fn(),
|
|
35
|
+
}));
|
|
36
|
+
|
|
37
|
+
jest.mock("../api/account-api-service", () => ({
|
|
38
|
+
createAccount: jest.fn(),
|
|
39
|
+
updateAccount: jest.fn(),
|
|
40
|
+
deleteAccount: jest.fn(),
|
|
41
|
+
clearAccount: jest.fn(),
|
|
42
|
+
}));
|
|
22
43
|
|
|
23
|
-
jest.mock("../api/tenant-api-service", () => ({ createTenant: jest.fn() }));
|
|
24
|
-
jest.mock("../api/user-api-service", () => ({ loadUser: jest.fn() }));
|
|
25
|
-
jest.mock("../api/account-api-service", () => ({ createAccount: jest.fn() }));
|
|
26
44
|
jest.mock("../api/environment-api-service", () => ({
|
|
27
45
|
createEnvironment: jest.fn(),
|
|
46
|
+
updateEnvironment: jest.fn(),
|
|
47
|
+
deleteEnvironment: jest.fn(),
|
|
48
|
+
clearEnvironment: jest.fn(),
|
|
49
|
+
scaleEnvironment: jest.fn(),
|
|
50
|
+
}));
|
|
51
|
+
|
|
52
|
+
jest.mock("../api/service-api-service", () => ({
|
|
53
|
+
deployService: jest.fn(),
|
|
54
|
+
updateService: jest.fn(),
|
|
55
|
+
deleteService: jest.fn(),
|
|
56
|
+
restartService: jest.fn(),
|
|
57
|
+
redeployService: jest.fn(),
|
|
58
|
+
requestRevisionData: jest.fn(),
|
|
59
|
+
updateServiceLinks: jest.fn(),
|
|
60
|
+
changeRevision: jest.fn(),
|
|
61
|
+
restartInstance: jest.fn(),
|
|
28
62
|
}));
|
|
29
|
-
|
|
63
|
+
|
|
30
64
|
jest.mock("../api/marketplace-api-service", () => ({
|
|
31
65
|
deployMarketplaceItem: jest.fn(),
|
|
32
|
-
getMarketplaceItems: jest.fn(()
|
|
33
|
-
|
|
34
|
-
|
|
66
|
+
getMarketplaceItems: jest.fn().mockResolvedValue({ items: [] }),
|
|
67
|
+
getMarketplaceSchema: jest.fn(),
|
|
68
|
+
}));
|
|
69
|
+
|
|
70
|
+
jest.mock("../api/resources-api-service", () => ({
|
|
71
|
+
createResource: jest.fn(),
|
|
72
|
+
updateResource: jest.fn(),
|
|
73
|
+
deleteResource: jest.fn(),
|
|
74
|
+
}));
|
|
75
|
+
|
|
76
|
+
jest.mock("../api/planProvider-api-service", () => ({
|
|
77
|
+
getPlanProviders: jest.fn(),
|
|
78
|
+
}));
|
|
79
|
+
|
|
80
|
+
jest.mock("../websocket-manager", () => ({
|
|
81
|
+
initializeGlobalWebSocketClient: jest.fn(),
|
|
82
|
+
updateUserComplete: jest.fn(),
|
|
83
|
+
fetchAndStoreMarketplaceSchema: jest.fn().mockResolvedValue(undefined),
|
|
84
|
+
getReferenceDomain: jest.fn().mockReturnValue("test-domain.com"),
|
|
35
85
|
}));
|
|
36
86
|
|
|
37
|
-
|
|
87
|
+
// ── Helpers para construir el dummy handler ───────────────────────────────────
|
|
88
|
+
|
|
89
|
+
const makeFns = (...names: string[]) =>
|
|
90
|
+
Object.fromEntries(names.map((n) => [n, jest.fn()]));
|
|
91
|
+
|
|
92
|
+
const createDummyHandler = () => ({
|
|
38
93
|
subscribe: jest.fn(),
|
|
39
94
|
publish: jest.fn(),
|
|
40
95
|
unsubscribe: jest.fn(),
|
|
96
|
+
|
|
97
|
+
notification: {
|
|
98
|
+
publish: makeFns("creation", "deletion", "read"),
|
|
99
|
+
subscribe: makeFns("creation", "deletion", "read"),
|
|
100
|
+
unsubscribe: makeFns("creation", "deletion", "read"),
|
|
101
|
+
},
|
|
102
|
+
|
|
41
103
|
tenant: {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
created
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
inviteAccepted
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
rejectInvite: jest.fn(),
|
|
74
|
-
inviteRejected: jest.fn(),
|
|
75
|
-
inviteRejectError: jest.fn(),
|
|
76
|
-
},
|
|
77
|
-
unsubscribe: {
|
|
78
|
-
creation: jest.fn(),
|
|
79
|
-
created: jest.fn(),
|
|
80
|
-
creationError: jest.fn(),
|
|
81
|
-
update: jest.fn(),
|
|
82
|
-
updated: jest.fn(),
|
|
83
|
-
updateError: jest.fn(),
|
|
84
|
-
delete: jest.fn(),
|
|
85
|
-
deleted: jest.fn(),
|
|
86
|
-
deletionError: jest.fn(),
|
|
87
|
-
createRegistry: jest.fn(),
|
|
88
|
-
registryCreated: jest.fn(),
|
|
89
|
-
registryCreationError: jest.fn(),
|
|
90
|
-
updateRegistry: jest.fn(),
|
|
91
|
-
registryUpdated: jest.fn(),
|
|
92
|
-
registryUpdateError: jest.fn(),
|
|
93
|
-
deleteRegistry: jest.fn(),
|
|
94
|
-
registryDeleted: jest.fn(),
|
|
95
|
-
registryDeletionError: jest.fn(),
|
|
96
|
-
inviteUser: jest.fn(),
|
|
97
|
-
userInvited: jest.fn(),
|
|
98
|
-
inviteError: jest.fn(),
|
|
99
|
-
removeUser: jest.fn(),
|
|
100
|
-
userRemoved: jest.fn(),
|
|
101
|
-
removeUserError: jest.fn(),
|
|
102
|
-
acceptInvite: jest.fn(),
|
|
103
|
-
inviteAccepted: jest.fn(),
|
|
104
|
-
acceptInviteError: jest.fn(),
|
|
105
|
-
updateInvite: jest.fn(),
|
|
106
|
-
inviteUpdated: jest.fn(),
|
|
107
|
-
inviteUpdateError: jest.fn(),
|
|
108
|
-
rejectInvite: jest.fn(),
|
|
109
|
-
inviteRejected: jest.fn(),
|
|
110
|
-
inviteRejectError: jest.fn(),
|
|
111
|
-
},
|
|
104
|
+
publish: makeFns("creation", "created", "update", "updated", "delete", "deleted"),
|
|
105
|
+
subscribe: makeFns(
|
|
106
|
+
"creation", "created", "creationError",
|
|
107
|
+
"update", "updated", "updateError",
|
|
108
|
+
"delete", "deleted", "deletionError",
|
|
109
|
+
"createRegistry", "registryCreated", "registryCreationError",
|
|
110
|
+
"updateRegistry", "registryUpdated", "registryUpdateError",
|
|
111
|
+
"deleteRegistry", "registryDeleted", "registryDeletionError",
|
|
112
|
+
"inviteUser", "userInvited", "inviteError",
|
|
113
|
+
"removeUser", "userRemoved", "removeUserError",
|
|
114
|
+
"updateInvite", "inviteUpdated", "inviteUpdateError",
|
|
115
|
+
"acceptInvite", "inviteAccepted", "acceptInviteError",
|
|
116
|
+
"rejectInvite", "inviteRejected", "inviteRejectError",
|
|
117
|
+
"createToken", "tokenCreated", "tokenCreationError",
|
|
118
|
+
"deleteToken", "tokenDeleted", "tokenDeletionError",
|
|
119
|
+
),
|
|
120
|
+
unsubscribe: makeFns(
|
|
121
|
+
"creation", "created", "creationError",
|
|
122
|
+
"update", "updated", "updateError",
|
|
123
|
+
"delete", "deleted", "deletionError",
|
|
124
|
+
"createRegistry", "registryCreated", "registryCreationError",
|
|
125
|
+
"updateRegistry", "registryUpdated", "registryUpdateError",
|
|
126
|
+
"deleteRegistry", "registryDeleted", "registryDeletionError",
|
|
127
|
+
"inviteUser", "userInvited", "inviteError",
|
|
128
|
+
"removeUser", "userRemoved", "removeUserError",
|
|
129
|
+
"updateInvite", "inviteUpdated", "inviteUpdateError",
|
|
130
|
+
"acceptInvite", "inviteAccepted", "acceptInviteError",
|
|
131
|
+
"rejectInvite", "inviteRejected", "inviteRejectError",
|
|
132
|
+
"createToken", "tokenCreated", "tokenCreationError",
|
|
133
|
+
"deleteToken", "tokenDeleted", "tokenDeletionError",
|
|
134
|
+
),
|
|
112
135
|
},
|
|
136
|
+
|
|
113
137
|
user: {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
created
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
deleted
|
|
126
|
-
|
|
127
|
-
},
|
|
128
|
-
unsubscribe: {
|
|
129
|
-
creation: jest.fn(),
|
|
130
|
-
created: jest.fn(),
|
|
131
|
-
creationError: jest.fn(),
|
|
132
|
-
update: jest.fn(),
|
|
133
|
-
updated: jest.fn(),
|
|
134
|
-
updateError: jest.fn(),
|
|
135
|
-
load: jest.fn(),
|
|
136
|
-
loaded: jest.fn(),
|
|
137
|
-
loadError: jest.fn(),
|
|
138
|
-
delete: jest.fn(),
|
|
139
|
-
deleted: jest.fn(),
|
|
140
|
-
deletionError: jest.fn(),
|
|
141
|
-
},
|
|
138
|
+
publish: makeFns("creation", "load", "loaded", "update", "delete", "authError"),
|
|
139
|
+
subscribe: makeFns(
|
|
140
|
+
"creation", "created", "creationError",
|
|
141
|
+
"update", "updated", "updateError",
|
|
142
|
+
"load", "loaded", "loadError",
|
|
143
|
+
"delete", "deleted", "deletionError", "authError",
|
|
144
|
+
),
|
|
145
|
+
unsubscribe: makeFns(
|
|
146
|
+
"creation", "created", "creationError",
|
|
147
|
+
"update", "updated", "updateError",
|
|
148
|
+
"load", "loaded", "loadError",
|
|
149
|
+
"delete", "deleted", "deletionError", "authError",
|
|
150
|
+
),
|
|
142
151
|
},
|
|
152
|
+
|
|
143
153
|
account: {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
created
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
cleaned
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
updated: jest.fn(),
|
|
164
|
-
updateError: jest.fn(),
|
|
165
|
-
delete: jest.fn(),
|
|
166
|
-
deleted: jest.fn(),
|
|
167
|
-
deletionError: jest.fn(),
|
|
168
|
-
clean: jest.fn(),
|
|
169
|
-
cleaned: jest.fn(),
|
|
170
|
-
cleanError: jest.fn(),
|
|
171
|
-
},
|
|
154
|
+
publish: makeFns("creation", "created", "update", "delete"),
|
|
155
|
+
subscribe: makeFns(
|
|
156
|
+
"creation", "created", "creationError",
|
|
157
|
+
"update", "updated", "updateError",
|
|
158
|
+
"delete", "deleted", "deletionError",
|
|
159
|
+
"clean", "cleaned", "cleanError",
|
|
160
|
+
),
|
|
161
|
+
unsubscribe: makeFns(
|
|
162
|
+
"creation", "created", "creationError",
|
|
163
|
+
"update", "updated", "updateError",
|
|
164
|
+
"delete", "deleted", "deletionError",
|
|
165
|
+
"clean", "cleaned", "cleanError",
|
|
166
|
+
),
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
plan: {
|
|
170
|
+
publish: makeFns("upgrade", "upgraded", "downgrade", "downgraded"),
|
|
171
|
+
subscribe: makeFns("upgrade", "upgraded", "upgradeError", "downgrade", "downgraded", "downgradeError"),
|
|
172
|
+
unsubscribe: makeFns("upgrade", "upgraded", "upgradeError", "downgrade", "downgraded", "downgradeError"),
|
|
172
173
|
},
|
|
174
|
+
|
|
173
175
|
environment: {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
created
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
scale
|
|
188
|
-
|
|
189
|
-
scaleError: jest.fn()
|
|
190
|
-
},
|
|
191
|
-
unsubscribe: {
|
|
192
|
-
creation: jest.fn(),
|
|
193
|
-
created: jest.fn(),
|
|
194
|
-
creationError: jest.fn(),
|
|
195
|
-
update: jest.fn(),
|
|
196
|
-
updated: jest.fn(),
|
|
197
|
-
updateError: jest.fn(),
|
|
198
|
-
delete: jest.fn(),
|
|
199
|
-
deleted: jest.fn(),
|
|
200
|
-
deletionError: jest.fn(),
|
|
201
|
-
clean: jest.fn(),
|
|
202
|
-
cleaned: jest.fn(),
|
|
203
|
-
cleanError: jest.fn(),
|
|
204
|
-
scale: jest.fn(),
|
|
205
|
-
scaled: jest.fn(),
|
|
206
|
-
scaleError: jest.fn()
|
|
207
|
-
},
|
|
176
|
+
publish: makeFns("creation", "created", "update", "delete", "clean", "scale"),
|
|
177
|
+
subscribe: makeFns(
|
|
178
|
+
"creation", "created", "creationError",
|
|
179
|
+
"update", "updated", "updateError",
|
|
180
|
+
"delete", "deleted", "deletionError",
|
|
181
|
+
"clean", "cleaned", "cleanError",
|
|
182
|
+
"scale", "scaled", "scaleError",
|
|
183
|
+
),
|
|
184
|
+
unsubscribe: makeFns(
|
|
185
|
+
"creation", "created", "creationError",
|
|
186
|
+
"update", "updated", "updateError",
|
|
187
|
+
"delete", "deleted", "deletionError",
|
|
188
|
+
"clean", "cleaned", "cleanError",
|
|
189
|
+
"scale", "scaled", "scaleError",
|
|
190
|
+
),
|
|
208
191
|
},
|
|
192
|
+
|
|
209
193
|
service: {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
deployed
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
deploy: jest.fn(),
|
|
230
|
-
deployed: jest.fn(),
|
|
231
|
-
deploymentError: jest.fn(),
|
|
232
|
-
update: jest.fn(),
|
|
233
|
-
updated: jest.fn(),
|
|
234
|
-
updateError: jest.fn(),
|
|
235
|
-
delete: jest.fn(),
|
|
236
|
-
deleted: jest.fn(),
|
|
237
|
-
deletionError: jest.fn(),
|
|
238
|
-
requestLogs: jest.fn(),
|
|
239
|
-
requestRevisionData: jest.fn(),
|
|
240
|
-
updateServiceLinks: jest.fn(),
|
|
241
|
-
changeRevision: jest.fn(),
|
|
242
|
-
revisionChanged : jest.fn(),
|
|
243
|
-
revisionChangeError: jest.fn(),
|
|
244
|
-
},
|
|
194
|
+
publish: makeFns("deploy", "deployed", "deploymentError", "update", "updated", "delete", "deleted", "restart"),
|
|
195
|
+
subscribe: makeFns(
|
|
196
|
+
"deploy", "deployed", "deploymentError",
|
|
197
|
+
"update", "updated", "updateError",
|
|
198
|
+
"delete", "deleted", "deletionError",
|
|
199
|
+
"requestLogs", "restart", "restarted", "restartError",
|
|
200
|
+
"requestRevisionData", "updateServiceLinks",
|
|
201
|
+
"changeRevision", "revisionChanged", "revisionChangeError",
|
|
202
|
+
"restartInstance", "instanceRestarted", "instanceRestartError",
|
|
203
|
+
),
|
|
204
|
+
unsubscribe: makeFns(
|
|
205
|
+
"deploy", "deployed", "deploymentError",
|
|
206
|
+
"update", "updated", "updateError",
|
|
207
|
+
"delete", "deleted", "deletionError",
|
|
208
|
+
"requestLogs", "restart", "restarted", "restartError",
|
|
209
|
+
"requestRevisionData", "updateServiceLinks",
|
|
210
|
+
"changeRevision", "revisionChanged", "revisionChangeError",
|
|
211
|
+
"restartInstance", "instanceRestarted", "instanceRestartError",
|
|
212
|
+
),
|
|
245
213
|
},
|
|
214
|
+
|
|
246
215
|
marketplace: {
|
|
247
|
-
|
|
248
|
-
deployItem
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
updateItem
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
deletionError: jest.fn(),
|
|
269
|
-
loadItems: jest.fn(),
|
|
270
|
-
},
|
|
216
|
+
publish: makeFns(
|
|
217
|
+
"deployItem", "itemDeployed", "deploymentError",
|
|
218
|
+
"updateItem", "itemUpdated", "updateError",
|
|
219
|
+
"deleteItem", "itemDeleted", "deletionError",
|
|
220
|
+
"loadItems", "itemsLoaded", "loadSchema",
|
|
221
|
+
"schemaLoaded", "schemaLoadError",
|
|
222
|
+
),
|
|
223
|
+
subscribe: makeFns(
|
|
224
|
+
"deployItem", "itemDeployed", "deploymentError",
|
|
225
|
+
"updateItem", "itemUpdated", "updateError",
|
|
226
|
+
"deleteItem", "itemDeleted", "deletionError",
|
|
227
|
+
"loadItems", "itemsLoaded", "loadSchema",
|
|
228
|
+
"schemaLoaded", "schemaLoadError",
|
|
229
|
+
),
|
|
230
|
+
unsubscribe: makeFns(
|
|
231
|
+
"deployItem", "itemDeployed", "deploymentError",
|
|
232
|
+
"updateItem", "itemUpdated", "updateError",
|
|
233
|
+
"deleteItem", "itemDeleted", "deletionError",
|
|
234
|
+
"loadItems", "itemsLoaded", "loadSchema",
|
|
235
|
+
"schemaLoaded", "schemaLoadError",
|
|
236
|
+
),
|
|
271
237
|
},
|
|
238
|
+
|
|
272
239
|
resource: {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
created
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
unsubscribe: {
|
|
285
|
-
creation: jest.fn(),
|
|
286
|
-
created: jest.fn(),
|
|
287
|
-
creationError: jest.fn(),
|
|
288
|
-
update: jest.fn(),
|
|
289
|
-
updated: jest.fn(),
|
|
290
|
-
updateError: jest.fn(),
|
|
291
|
-
delete: jest.fn(),
|
|
292
|
-
deleted: jest.fn(),
|
|
293
|
-
deletionError: jest.fn(),
|
|
294
|
-
},
|
|
295
|
-
},
|
|
296
|
-
plan: {
|
|
297
|
-
subscribe: {
|
|
298
|
-
upgrade: jest.fn(),
|
|
299
|
-
upgraded: jest.fn(),
|
|
300
|
-
upgradeError: jest.fn(),
|
|
301
|
-
downgrade: jest.fn(),
|
|
302
|
-
downgraded: jest.fn(),
|
|
303
|
-
downgradeError: jest.fn(),
|
|
304
|
-
},
|
|
305
|
-
unsubscribe: {
|
|
306
|
-
upgrade: jest.fn(),
|
|
307
|
-
upgraded: jest.fn(),
|
|
308
|
-
upgradeError: jest.fn(),
|
|
309
|
-
downgrade: jest.fn(),
|
|
310
|
-
downgraded: jest.fn(),
|
|
311
|
-
downgradeError: jest.fn(),
|
|
312
|
-
},
|
|
240
|
+
publish: makeFns("creation", "created", "update", "delete", "deleted"),
|
|
241
|
+
subscribe: makeFns(
|
|
242
|
+
"creation", "created", "creationError",
|
|
243
|
+
"update", "updated", "updateError",
|
|
244
|
+
"delete", "deleted", "deletionError",
|
|
245
|
+
),
|
|
246
|
+
unsubscribe: makeFns(
|
|
247
|
+
"creation", "created", "creationError",
|
|
248
|
+
"update", "updated", "updateError",
|
|
249
|
+
"delete", "deleted", "deletionError",
|
|
250
|
+
),
|
|
313
251
|
},
|
|
252
|
+
|
|
314
253
|
organization: {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
created
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
unsubscribe: {
|
|
327
|
-
creation: jest.fn(),
|
|
328
|
-
created: jest.fn(),
|
|
329
|
-
creationError: jest.fn(),
|
|
330
|
-
update: jest.fn(),
|
|
331
|
-
updated: jest.fn(),
|
|
332
|
-
updateError: jest.fn(),
|
|
333
|
-
delete: jest.fn(),
|
|
334
|
-
deleted: jest.fn(),
|
|
335
|
-
deletionError: jest.fn(),
|
|
336
|
-
},
|
|
254
|
+
publish: makeFns("creation", "update", "delete"),
|
|
255
|
+
subscribe: makeFns(
|
|
256
|
+
"creation", "created", "creationError",
|
|
257
|
+
"update", "updated", "updateError",
|
|
258
|
+
"delete", "deleted", "deletionError",
|
|
259
|
+
),
|
|
260
|
+
unsubscribe: makeFns(
|
|
261
|
+
"creation", "created", "creationError",
|
|
262
|
+
"update", "updated", "updateError",
|
|
263
|
+
"delete", "deleted", "deletionError",
|
|
264
|
+
),
|
|
337
265
|
},
|
|
266
|
+
|
|
338
267
|
planProviders: {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
loadError: jest.fn(),
|
|
343
|
-
},
|
|
344
|
-
unsubscribe: {
|
|
345
|
-
loadPlans: jest.fn(),
|
|
346
|
-
plansLoaded: jest.fn(),
|
|
347
|
-
loadError: jest.fn(),
|
|
348
|
-
},
|
|
268
|
+
publish: makeFns("loadPlans", "plansLoaded", "loadError"),
|
|
269
|
+
subscribe: makeFns("loadPlans", "plansLoaded", "loadError"),
|
|
270
|
+
unsubscribe: makeFns("loadPlans", "plansLoaded", "loadError"),
|
|
349
271
|
},
|
|
350
272
|
});
|
|
351
273
|
|
|
352
|
-
|
|
353
|
-
let dummyGlobalEventHandler: ReturnType<typeof createDummyGlobalEventHandler>;
|
|
274
|
+
// ── Helper para construir y esperar que el constructor termine ────────────────
|
|
354
275
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
276
|
+
async function buildHandler(route = "home", handler?: ReturnType<typeof createDummyHandler>) {
|
|
277
|
+
const h = handler ?? createDummyHandler();
|
|
278
|
+
const bh = new BackendHandler(route, h, "http://localhost:9080", "v1");
|
|
279
|
+
await Promise.resolve(); // flush microtask queue (getUserHTTP().then)
|
|
280
|
+
return { bh, h };
|
|
281
|
+
}
|
|
359
282
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
}).toThrow("globalEventHandler inválido");
|
|
364
|
-
});
|
|
283
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
284
|
+
// Tests
|
|
285
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
365
286
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
"httl://localhost:9080",
|
|
371
|
-
"nightly"
|
|
287
|
+
describe("BackendHandler - constructor validation", () => {
|
|
288
|
+
it("lanza error si globalEventHandler es null", () => {
|
|
289
|
+
expect(() => new BackendHandler("home", null, "http://localhost", "v1")).toThrow(
|
|
290
|
+
"globalEventHandler inválido",
|
|
372
291
|
);
|
|
373
|
-
expect(dummyGlobalEventHandler.user.subscribe.load).toHaveBeenCalled();
|
|
374
292
|
});
|
|
375
293
|
|
|
376
|
-
it("
|
|
377
|
-
new BackendHandler(
|
|
378
|
-
"
|
|
379
|
-
dummyGlobalEventHandler,
|
|
380
|
-
"httl://localhost:9080",
|
|
381
|
-
"nightly"
|
|
382
|
-
);
|
|
383
|
-
expect(
|
|
384
|
-
dummyGlobalEventHandler.tenant.subscribe.creation
|
|
385
|
-
).toHaveBeenCalled();
|
|
386
|
-
expect(dummyGlobalEventHandler.tenant.subscribe.created).toHaveBeenCalled();
|
|
387
|
-
expect(
|
|
388
|
-
dummyGlobalEventHandler.tenant.subscribe.deletionError
|
|
389
|
-
).toHaveBeenCalled();
|
|
390
|
-
expect(
|
|
391
|
-
dummyGlobalEventHandler.planProviders.subscribe.loadPlans
|
|
392
|
-
).toHaveBeenCalled();
|
|
393
|
-
});
|
|
394
|
-
|
|
395
|
-
it("se suscribe a eventos de usuario cuando la ruta es 'user-information' o 'home'", () => {
|
|
396
|
-
new BackendHandler(
|
|
397
|
-
"home",
|
|
398
|
-
dummyGlobalEventHandler,
|
|
399
|
-
"httl://localhost:9080",
|
|
400
|
-
"nightly"
|
|
294
|
+
it("lanza error si globalEventHandler no tiene subscribe", () => {
|
|
295
|
+
expect(() => new BackendHandler("home", { publish: jest.fn() }, "http://localhost", "v1")).toThrow(
|
|
296
|
+
"globalEventHandler inválido",
|
|
401
297
|
);
|
|
402
|
-
expect(dummyGlobalEventHandler.user.subscribe.creation).toHaveBeenCalled();
|
|
403
|
-
expect(dummyGlobalEventHandler.user.subscribe.load).toHaveBeenCalled();
|
|
404
298
|
});
|
|
405
299
|
|
|
406
|
-
it("
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
).toHaveBeenCalled();
|
|
416
|
-
expect(
|
|
417
|
-
});
|
|
418
|
-
|
|
419
|
-
it("
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
);
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
300
|
+
it("no lanza error con handler válido", async () => {
|
|
301
|
+
const { h } = await buildHandler();
|
|
302
|
+
expect(h.user.subscribe.load).toHaveBeenCalled();
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
describe("BackendHandler - constructor suscripciones iniciales", () => {
|
|
307
|
+
it("suscribe a user.load y user.loaded en el constructor", async () => {
|
|
308
|
+
const { h } = await buildHandler();
|
|
309
|
+
expect(h.user.subscribe.load).toHaveBeenCalled();
|
|
310
|
+
expect(h.user.subscribe.loaded).toHaveBeenCalled();
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it("publica user.load tras inicializar", async () => {
|
|
314
|
+
const { h } = await buildHandler();
|
|
315
|
+
expect(h.user.publish.load).toHaveBeenCalled();
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
it("invoca callback de user.load con initializeGlobalWebSocketClient", async () => {
|
|
319
|
+
const { initializeGlobalWebSocketClient } = await import("../websocket-manager");
|
|
320
|
+
const { h } = await buildHandler();
|
|
321
|
+
const loadCb = (h.user.subscribe.load as jest.Mock).mock.calls[0][0];
|
|
322
|
+
loadCb({} as UserData);
|
|
323
|
+
expect(initializeGlobalWebSocketClient).toHaveBeenCalled();
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
it("invoca callback de user.loaded con updateUserComplete", async () => {
|
|
327
|
+
const { updateUserComplete } = await import("../websocket-manager");
|
|
328
|
+
const { h } = await buildHandler();
|
|
329
|
+
const loadedCb = (h.user.subscribe.loaded as jest.Mock).mock.calls[0][0];
|
|
330
|
+
loadedCb({ id: "u1" } as any);
|
|
331
|
+
expect(updateUserComplete).toHaveBeenCalledWith({ id: "u1" });
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
it("llama a subscribeForRoute en el constructor", async () => {
|
|
335
|
+
const { h } = await buildHandler("home");
|
|
336
|
+
expect(h.tenant.subscribe.creation).toHaveBeenCalled();
|
|
337
|
+
expect(h.user.subscribe.creation).toHaveBeenCalled();
|
|
338
|
+
expect(h.account.subscribe.creation).toHaveBeenCalled();
|
|
339
|
+
expect(h.environment.subscribe.creation).toHaveBeenCalled();
|
|
340
|
+
expect(h.service.subscribe.deploy).toHaveBeenCalled();
|
|
341
|
+
expect(h.marketplace.subscribe.deployItem).toHaveBeenCalled();
|
|
342
|
+
expect(h.resource.subscribe.creation).toHaveBeenCalled();
|
|
343
|
+
expect(h.organization.subscribe.creation).toHaveBeenCalled();
|
|
344
|
+
expect(h.plan.subscribe.upgrade).toHaveBeenCalled();
|
|
345
|
+
expect(h.planProviders.subscribe.loadPlans).toHaveBeenCalled();
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
describe("BackendHandler - isUserLoggedIn", () => {
|
|
350
|
+
it("retorna true cuando isUserLogged devuelve true", async () => {
|
|
351
|
+
const { isUserLogged } = await import("../api/user-api-service");
|
|
352
|
+
(isUserLogged as jest.Mock).mockResolvedValue(true);
|
|
353
|
+
const { bh } = await buildHandler();
|
|
354
|
+
const result = await bh.isUserLoggedIn();
|
|
355
|
+
expect(result).toBe(true);
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
it("retorna false cuando isUserLogged devuelve false", async () => {
|
|
359
|
+
const { isUserLogged } = await import("../api/user-api-service");
|
|
360
|
+
(isUserLogged as jest.Mock).mockResolvedValue(false);
|
|
361
|
+
const { bh } = await buildHandler();
|
|
362
|
+
const result = await bh.isUserLoggedIn();
|
|
363
|
+
expect(result).toBe(false);
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
it("retorna false cuando isUserLogged devuelve string", async () => {
|
|
367
|
+
const { isUserLogged } = await import("../api/user-api-service");
|
|
368
|
+
(isUserLogged as jest.Mock).mockResolvedValue("yes");
|
|
369
|
+
const { bh } = await buildHandler();
|
|
370
|
+
const result = await bh.isUserLoggedIn();
|
|
371
|
+
expect(result).toBe(false);
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
describe("BackendHandler - changeRoute y unsubscribe", () => {
|
|
376
|
+
it("changeRoute desuscribe eventos anteriores y suscribe nuevos", async () => {
|
|
377
|
+
const { bh, h } = await buildHandler("home");
|
|
378
|
+
const firstCallCount = (h.tenant.subscribe.creation as jest.Mock).mock.calls.length;
|
|
379
|
+
bh.changeRoute("tenants");
|
|
380
|
+
await Promise.resolve();
|
|
381
|
+
expect(h.tenant.unsubscribe.creation).toHaveBeenCalled();
|
|
382
|
+
expect((h.tenant.subscribe.creation as jest.Mock).mock.calls.length).toBeGreaterThan(firstCallCount);
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
it("changeRoute múltiple acumula y limpia correctamente", async () => {
|
|
386
|
+
const { bh, h } = await buildHandler("home");
|
|
387
|
+
bh.changeRoute("accounts");
|
|
388
|
+
bh.changeRoute("environments");
|
|
389
|
+
expect(h.account.unsubscribe.creation).toHaveBeenCalled();
|
|
390
|
+
});
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
// ── Callbacks de Tenant ───────────────────────────────────────────────────────
|
|
394
|
+
|
|
395
|
+
describe("BackendHandler - callbacks de Tenant", () => {
|
|
396
|
+
it("creation callback llama a createTenant", async () => {
|
|
397
|
+
const { createTenant } = await import("../api/tenant-api-service");
|
|
398
|
+
const { h } = await buildHandler();
|
|
399
|
+
const cb = (h.tenant.subscribe.creation as jest.Mock).mock.calls[0][0];
|
|
400
|
+
const tenant = { id: "t1", name: "T1" } as Tenant;
|
|
401
|
+
cb(tenant);
|
|
402
|
+
expect(createTenant).toHaveBeenCalledWith(tenant, "");
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
it("update callback llama a updateTenant", async () => {
|
|
406
|
+
const { updateTenant } = await import("../api/tenant-api-service");
|
|
407
|
+
const { h } = await buildHandler();
|
|
408
|
+
const cb = (h.tenant.subscribe.update as jest.Mock).mock.calls[0][0];
|
|
409
|
+
const tenant = { id: "t1" } as Tenant;
|
|
410
|
+
cb(tenant);
|
|
411
|
+
expect(updateTenant).toHaveBeenCalledWith(tenant, "");
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
it("delete callback llama a deleteTenant", async () => {
|
|
415
|
+
const { deleteTenant } = await import("../api/tenant-api-service");
|
|
416
|
+
const { h } = await buildHandler();
|
|
417
|
+
const cb = (h.tenant.subscribe.delete as jest.Mock).mock.calls[0][0];
|
|
418
|
+
cb({ id: "t1" } as Tenant);
|
|
419
|
+
expect(deleteTenant).toHaveBeenCalled();
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
it("createRegistry callback llama a createRegistry", async () => {
|
|
423
|
+
const { createRegistry } = await import("../api/tenant-api-service");
|
|
424
|
+
const { h } = await buildHandler();
|
|
425
|
+
const cb = (h.tenant.subscribe.createRegistry as jest.Mock).mock.calls[0][0];
|
|
426
|
+
cb({ tenant: { id: "t1" } as Tenant, registry: { name: "reg1" } as any });
|
|
427
|
+
expect(createRegistry).toHaveBeenCalled();
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
it("updateRegistry callback llama a updateRegistry", async () => {
|
|
431
|
+
const { updateRegistry } = await import("../api/tenant-api-service");
|
|
432
|
+
const { h } = await buildHandler();
|
|
433
|
+
const cb = (h.tenant.subscribe.updateRegistry as jest.Mock).mock.calls[0][0];
|
|
434
|
+
cb({ tenant: { id: "t1" } as Tenant, registry: { name: "reg1" } as any });
|
|
435
|
+
expect(updateRegistry).toHaveBeenCalled();
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
it("deleteRegistry callback llama a deleteRegistry", async () => {
|
|
439
|
+
const { deleteRegistry } = await import("../api/tenant-api-service");
|
|
440
|
+
const { h } = await buildHandler();
|
|
441
|
+
const cb = (h.tenant.subscribe.deleteRegistry as jest.Mock).mock.calls[0][0];
|
|
442
|
+
cb({ tenant: { id: "t1" } as Tenant, registry: { name: "reg1" } as any });
|
|
443
|
+
expect(deleteRegistry).toHaveBeenCalled();
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
it("inviteUser callback llama a inviteUser", async () => {
|
|
447
|
+
const { inviteUser } = await import("../api/tenant-api-service");
|
|
448
|
+
const { h } = await buildHandler();
|
|
449
|
+
const cb = (h.tenant.subscribe.inviteUser as jest.Mock).mock.calls[0][0];
|
|
450
|
+
cb({ tenant: "t1", user: "u1", role: "admin" as any });
|
|
451
|
+
expect(inviteUser).toHaveBeenCalled();
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
it("userInvited callback llama a updateUserRole", async () => {
|
|
455
|
+
const { updateUserRole } = await import("../api/tenant-api-service");
|
|
456
|
+
const { h } = await buildHandler();
|
|
457
|
+
const cb = (h.tenant.subscribe.userInvited as jest.Mock).mock.calls[0][0];
|
|
458
|
+
cb({ user: "u1", tenant: "t1", role: "member" as any });
|
|
459
|
+
expect(updateUserRole).toHaveBeenCalled();
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
it("removeUser callback llama a removeUser", async () => {
|
|
463
|
+
const { removeUser } = await import("../api/tenant-api-service");
|
|
464
|
+
const { h } = await buildHandler();
|
|
465
|
+
const cb = (h.tenant.subscribe.removeUser as jest.Mock).mock.calls[0][0];
|
|
466
|
+
cb({ tenant: "t1", user: "u1" });
|
|
467
|
+
expect(removeUser).toHaveBeenCalled();
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
it("updateInvite callback llama a updateUserRole", async () => {
|
|
471
|
+
const { updateUserRole } = await import("../api/tenant-api-service");
|
|
472
|
+
const { h } = await buildHandler();
|
|
473
|
+
const cb = (h.tenant.subscribe.updateInvite as jest.Mock).mock.calls[0][0];
|
|
474
|
+
cb({ user: "u1", tenant: "t1", role: "member" as any });
|
|
475
|
+
expect(updateUserRole).toHaveBeenCalled();
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
it("acceptInvite callback llama a acceptInvite", async () => {
|
|
479
|
+
const { acceptInvite } = await import("../api/tenant-api-service");
|
|
480
|
+
const { h } = await buildHandler();
|
|
481
|
+
const cb = (h.tenant.subscribe.acceptInvite as jest.Mock).mock.calls[0][0];
|
|
482
|
+
cb({ tenant: "t1" });
|
|
483
|
+
expect(acceptInvite).toHaveBeenCalledWith("t1", "");
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
it("rejectInvite callback llama a rejectInvite", async () => {
|
|
487
|
+
const { rejectInvite } = await import("../api/tenant-api-service");
|
|
488
|
+
const { h } = await buildHandler();
|
|
489
|
+
const cb = (h.tenant.subscribe.rejectInvite as jest.Mock).mock.calls[0][0];
|
|
490
|
+
cb({ tenant: "t1", leave: true });
|
|
491
|
+
expect(rejectInvite).toHaveBeenCalledWith("t1", "", true);
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
it("createToken callback llama a createToken", async () => {
|
|
495
|
+
const { createToken } = await import("../api/tenant-api-service");
|
|
496
|
+
const { h } = await buildHandler();
|
|
497
|
+
const cb = (h.tenant.subscribe.createToken as jest.Mock).mock.calls[0][0];
|
|
498
|
+
cb({ tenant: "t1", expiration: "2025-01-01", description: "desc" });
|
|
499
|
+
expect(createToken).toHaveBeenCalled();
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
it("deleteToken callback llama a deleteToken", async () => {
|
|
503
|
+
const { deleteToken } = await import("../api/tenant-api-service");
|
|
504
|
+
const { h } = await buildHandler();
|
|
505
|
+
const cb = (h.tenant.subscribe.deleteToken as jest.Mock).mock.calls[0][0];
|
|
506
|
+
cb({ tenant: "t1", token: "tok123" });
|
|
507
|
+
expect(deleteToken).toHaveBeenCalledWith("t1", "tok123", "");
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
it("loadPlans callback llama a getPlanProviders", async () => {
|
|
511
|
+
const { getPlanProviders } = await import("../api/planProvider-api-service");
|
|
512
|
+
const { h } = await buildHandler();
|
|
513
|
+
const cb = (h.planProviders.subscribe.loadPlans as jest.Mock).mock.calls[0][0];
|
|
514
|
+
cb();
|
|
515
|
+
expect(getPlanProviders).toHaveBeenCalled();
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
it("empty callbacks (created, creationError, etc.) no lanzan error", async () => {
|
|
519
|
+
const { h } = await buildHandler();
|
|
520
|
+
const created = (h.tenant.subscribe.created as jest.Mock).mock.calls[0][0];
|
|
521
|
+
const creationError = (h.tenant.subscribe.creationError as jest.Mock).mock.calls[0][0];
|
|
522
|
+
const updated = (h.tenant.subscribe.updated as jest.Mock).mock.calls[0][0];
|
|
523
|
+
const updateError = (h.tenant.subscribe.updateError as jest.Mock).mock.calls[0][0];
|
|
524
|
+
const deleted = (h.tenant.subscribe.deleted as jest.Mock).mock.calls[0][0];
|
|
525
|
+
const deletionError = (h.tenant.subscribe.deletionError as jest.Mock).mock.calls[0][0];
|
|
526
|
+
expect(() => created({})).not.toThrow();
|
|
527
|
+
expect(() => creationError({})).not.toThrow();
|
|
528
|
+
expect(() => updated({})).not.toThrow();
|
|
529
|
+
expect(() => updateError({})).not.toThrow();
|
|
530
|
+
expect(() => deleted({})).not.toThrow();
|
|
531
|
+
expect(() => deletionError({})).not.toThrow();
|
|
429
532
|
});
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
// ── Callbacks de User ─────────────────────────────────────────────────────────
|
|
536
|
+
|
|
537
|
+
describe("BackendHandler - callbacks de User", () => {
|
|
538
|
+
it("creation callback llama a createUser", async () => {
|
|
539
|
+
const { createUser } = await import("../api/user-api-service");
|
|
540
|
+
const { h } = await buildHandler();
|
|
541
|
+
const cb = (h.user.subscribe.creation as jest.Mock).mock.calls[0][0];
|
|
542
|
+
cb({} as UserData);
|
|
543
|
+
expect(createUser).toHaveBeenCalled();
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
it("update callback llama a updateUser", async () => {
|
|
547
|
+
const { updateUser } = await import("../api/user-api-service");
|
|
548
|
+
const { h } = await buildHandler();
|
|
549
|
+
const cb = (h.user.subscribe.update as jest.Mock).mock.calls[0][0];
|
|
550
|
+
cb({} as UserData);
|
|
551
|
+
expect(updateUser).toHaveBeenCalled();
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
it("load callback llama a loadUser", async () => {
|
|
555
|
+
const { loadUser } = await import("../api/user-api-service");
|
|
556
|
+
const { h } = await buildHandler();
|
|
557
|
+
// subscribeUserEvents registra su propio load callback (segundo llamado a subscribe.load)
|
|
558
|
+
const allCalls = (h.user.subscribe.load as jest.Mock).mock.calls;
|
|
559
|
+
const userEventsCb = allCalls[allCalls.length - 1][0];
|
|
560
|
+
userEventsCb({} as UserData);
|
|
561
|
+
expect(loadUser).toHaveBeenCalled();
|
|
562
|
+
});
|
|
563
|
+
|
|
564
|
+
it("delete callback llama a deleteUSer", async () => {
|
|
565
|
+
const { deleteUSer } = await import("../api/user-api-service");
|
|
566
|
+
const { h } = await buildHandler();
|
|
567
|
+
const cb = (h.user.subscribe.delete as jest.Mock).mock.calls[0][0];
|
|
568
|
+
cb({} as UserData);
|
|
569
|
+
expect(deleteUSer).toHaveBeenCalled();
|
|
570
|
+
});
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
// ── Callbacks de Account ──────────────────────────────────────────────────────
|
|
574
|
+
|
|
575
|
+
describe("BackendHandler - callbacks de Account", () => {
|
|
576
|
+
it("creation callback llama a createAccount", async () => {
|
|
577
|
+
const { createAccount } = await import("../api/account-api-service");
|
|
578
|
+
const { h } = await buildHandler();
|
|
579
|
+
const cb = (h.account.subscribe.creation as jest.Mock).mock.calls[0][0];
|
|
580
|
+
cb({ id: "a1" } as Account);
|
|
581
|
+
expect(createAccount).toHaveBeenCalled();
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
it("update callback llama a updateAccount", async () => {
|
|
585
|
+
const { updateAccount } = await import("../api/account-api-service");
|
|
586
|
+
const { h } = await buildHandler();
|
|
587
|
+
const cb = (h.account.subscribe.update as jest.Mock).mock.calls[0][0];
|
|
588
|
+
cb({ id: "a1" } as Account);
|
|
589
|
+
expect(updateAccount).toHaveBeenCalled();
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
it("delete callback llama a deleteAccount", async () => {
|
|
593
|
+
const { deleteAccount } = await import("../api/account-api-service");
|
|
594
|
+
const { h } = await buildHandler();
|
|
595
|
+
const cb = (h.account.subscribe.delete as jest.Mock).mock.calls[0][0];
|
|
596
|
+
cb({ id: "a1" } as Account);
|
|
597
|
+
expect(deleteAccount).toHaveBeenCalled();
|
|
598
|
+
});
|
|
599
|
+
|
|
600
|
+
it("clean callback llama a clearAccount", async () => {
|
|
601
|
+
const { clearAccount } = await import("../api/account-api-service");
|
|
602
|
+
const { h } = await buildHandler();
|
|
603
|
+
const cb = (h.account.subscribe.clean as jest.Mock).mock.calls[0][0];
|
|
604
|
+
cb({ id: "a1" } as Account);
|
|
605
|
+
expect(clearAccount).toHaveBeenCalled();
|
|
606
|
+
});
|
|
607
|
+
});
|
|
430
608
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
609
|
+
// ── Callbacks de Plan ─────────────────────────────────────────────────────────
|
|
610
|
+
|
|
611
|
+
describe("BackendHandler - callbacks de Plan", () => {
|
|
612
|
+
it("upgraded callback publica notificación de plan-upgrade", async () => {
|
|
613
|
+
const { h } = await buildHandler();
|
|
614
|
+
const cb = (h.plan.subscribe.upgraded as jest.Mock).mock.calls[0][0];
|
|
615
|
+
cb("premium");
|
|
616
|
+
expect(h.notification.publish.creation).toHaveBeenCalledWith(
|
|
617
|
+
expect.objectContaining({ type: "success", subtype: "plan-upgrade", data: { plan: "premium" } }),
|
|
437
618
|
);
|
|
438
|
-
expect(dummyGlobalEventHandler.service.subscribe.deploy).toHaveBeenCalled();
|
|
439
619
|
});
|
|
440
620
|
|
|
441
|
-
it("
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
"
|
|
621
|
+
it("downgraded callback publica notificación de plan-downgrade", async () => {
|
|
622
|
+
const { h } = await buildHandler();
|
|
623
|
+
const cb = (h.plan.subscribe.downgraded as jest.Mock).mock.calls[0][0];
|
|
624
|
+
cb("freemium");
|
|
625
|
+
expect(h.notification.publish.creation).toHaveBeenCalledWith(
|
|
626
|
+
expect.objectContaining({ type: "success", subtype: "plan-downgrade", data: { plan: "freemium" } }),
|
|
447
627
|
);
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
it("upgrade y downgrade empty callbacks no lanzan error", async () => {
|
|
631
|
+
const { h } = await buildHandler();
|
|
632
|
+
const upgradeCb = (h.plan.subscribe.upgrade as jest.Mock).mock.calls[0][0];
|
|
633
|
+
const upgradeErrorCb = (h.plan.subscribe.upgradeError as jest.Mock).mock.calls[0][0];
|
|
634
|
+
const downgradeCb = (h.plan.subscribe.downgrade as jest.Mock).mock.calls[0][0];
|
|
635
|
+
const downgradeErrorCb = (h.plan.subscribe.downgradeError as jest.Mock).mock.calls[0][0];
|
|
636
|
+
expect(() => upgradeCb("p")).not.toThrow();
|
|
637
|
+
expect(() => upgradeErrorCb("p")).not.toThrow();
|
|
638
|
+
expect(() => downgradeCb("p")).not.toThrow();
|
|
639
|
+
expect(() => downgradeErrorCb("p")).not.toThrow();
|
|
640
|
+
});
|
|
641
|
+
});
|
|
642
|
+
|
|
643
|
+
// ── Callbacks de Environment ──────────────────────────────────────────────────
|
|
644
|
+
|
|
645
|
+
describe("BackendHandler - callbacks de Environment", () => {
|
|
646
|
+
const mockEnv: Environment = {
|
|
647
|
+
id: "e1",
|
|
648
|
+
name: "Env1",
|
|
649
|
+
account: "acc1",
|
|
650
|
+
tenant: "ten1",
|
|
651
|
+
logo: "",
|
|
652
|
+
services: [],
|
|
653
|
+
domains: [],
|
|
654
|
+
status: { code: "", message: "", timestamp: "" },
|
|
655
|
+
usage: {
|
|
656
|
+
current: { cpu: 0, memory: 0, storage: 0, volatileStorage: 0, nonReplicatedStorage: 0, persistentStorage: 0 },
|
|
657
|
+
limit: {
|
|
658
|
+
cpu: { max: 0, min: 0 }, memory: { max: 0, min: 0 }, storage: { max: 0, min: 0 },
|
|
659
|
+
volatileStorage: { max: 0, min: 0 }, nonReplicatedStorage: { max: 0, min: 0 }, persistentStorage: { max: 0, min: 0 },
|
|
660
|
+
},
|
|
661
|
+
cost: 0,
|
|
662
|
+
},
|
|
663
|
+
type: "",
|
|
664
|
+
cluster: { name: "" },
|
|
665
|
+
};
|
|
666
|
+
|
|
667
|
+
it("creation callback llama a createEnvironment", async () => {
|
|
668
|
+
const { createEnvironment } = await import("../api/environment-api-service");
|
|
669
|
+
const { h } = await buildHandler();
|
|
670
|
+
const cb = (h.environment.subscribe.creation as jest.Mock).mock.calls[0][0];
|
|
671
|
+
cb(mockEnv);
|
|
672
|
+
expect(createEnvironment).toHaveBeenCalled();
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
it("created callback publica notificación environment-created", async () => {
|
|
676
|
+
const { h } = await buildHandler();
|
|
677
|
+
const cb = (h.environment.subscribe.created as jest.Mock).mock.calls[0][0];
|
|
678
|
+
cb(mockEnv);
|
|
679
|
+
expect(h.notification.publish.creation).toHaveBeenCalledWith(
|
|
680
|
+
expect.objectContaining({ type: "success", subtype: "environment-created", data: { environment: "Env1", account: "acc1", tenant: "ten1" } }),
|
|
457
681
|
);
|
|
458
|
-
expect(
|
|
459
|
-
dummyGlobalEventHandler.marketplace.subscribe.loadItems
|
|
460
|
-
).toHaveBeenCalled();
|
|
461
682
|
});
|
|
462
683
|
|
|
463
|
-
it("
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
684
|
+
it("update callback llama a updateEnvironment", async () => {
|
|
685
|
+
const { updateEnvironment } = await import("../api/environment-api-service");
|
|
686
|
+
const { h } = await buildHandler();
|
|
687
|
+
const cb = (h.environment.subscribe.update as jest.Mock).mock.calls[0][0];
|
|
688
|
+
cb(mockEnv);
|
|
689
|
+
expect(updateEnvironment).toHaveBeenCalled();
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
it("delete callback llama a deleteEnvironment", async () => {
|
|
693
|
+
const { deleteEnvironment } = await import("../api/environment-api-service");
|
|
694
|
+
const { h } = await buildHandler();
|
|
695
|
+
const cb = (h.environment.subscribe.delete as jest.Mock).mock.calls[0][0];
|
|
696
|
+
cb(mockEnv);
|
|
697
|
+
expect(deleteEnvironment).toHaveBeenCalled();
|
|
698
|
+
});
|
|
699
|
+
|
|
700
|
+
it("clean callback llama a clearEnvironment", async () => {
|
|
701
|
+
const { clearEnvironment } = await import("../api/environment-api-service");
|
|
702
|
+
const { h } = await buildHandler();
|
|
703
|
+
const cb = (h.environment.subscribe.clean as jest.Mock).mock.calls[0][0];
|
|
704
|
+
cb(mockEnv);
|
|
705
|
+
expect(clearEnvironment).toHaveBeenCalled();
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
it("scale callback llama a scaleEnvironment", async () => {
|
|
709
|
+
const { scaleEnvironment } = await import("../api/environment-api-service");
|
|
710
|
+
const consoleSpy = jest.spyOn(console, "log").mockImplementation(() => {});
|
|
711
|
+
const { h } = await buildHandler();
|
|
712
|
+
const cb = (h.environment.subscribe.scale as jest.Mock).mock.calls[0][0];
|
|
713
|
+
cb(mockEnv);
|
|
714
|
+
expect(scaleEnvironment).toHaveBeenCalled();
|
|
715
|
+
consoleSpy.mockRestore();
|
|
716
|
+
});
|
|
717
|
+
});
|
|
718
|
+
|
|
719
|
+
// ── Callbacks de Service ──────────────────────────────────────────────────────
|
|
720
|
+
|
|
721
|
+
describe("BackendHandler - callbacks de Service", () => {
|
|
722
|
+
const mockService: Service = {
|
|
723
|
+
id: "s1", tenant: "ten1", account: "acc1", environment: "env1",
|
|
724
|
+
name: "Svc1", logo: "", description: "", revisions: [], status: "",
|
|
725
|
+
role: [{ name: "r1", instances: [] }], links: [], resources: [], parameters: [],
|
|
726
|
+
usage: {
|
|
727
|
+
current: { cpu: 0, memory: 0, storage: 0, volatileStorage: 0, nonReplicatedStorage: 0, persistentStorage: 0 },
|
|
728
|
+
limit: {
|
|
729
|
+
cpu: { max: 0, min: 0 }, memory: { max: 0, min: 0 }, storage: { max: 0, min: 0 },
|
|
730
|
+
volatileStorage: { max: 0, min: 0 }, nonReplicatedStorage: { max: 0, min: 0 }, persistentStorage: { max: 0, min: 0 },
|
|
731
|
+
},
|
|
732
|
+
cost: 0,
|
|
733
|
+
},
|
|
734
|
+
project: "", registry: "", imageName: "", entrypoint: "", cmd: "",
|
|
735
|
+
serverChannels: [], clientChannels: [], duplexChannels: [], cloudProvider: "",
|
|
736
|
+
};
|
|
737
|
+
|
|
738
|
+
it("deployed callback publica notificación deployment-success", async () => {
|
|
739
|
+
const { h } = await buildHandler();
|
|
740
|
+
const cb = (h.service.subscribe.deployed as jest.Mock).mock.calls[0][0];
|
|
741
|
+
cb(mockService);
|
|
742
|
+
expect(h.notification.publish.creation).toHaveBeenCalledWith(
|
|
743
|
+
expect.objectContaining({ type: "success", subtype: "deployment-success" }),
|
|
469
744
|
);
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
// "httl://localhost:9080",
|
|
480
|
-
// "nightly"
|
|
481
|
-
// );
|
|
482
|
-
// const unsubscribeMock = jest.fn();
|
|
483
|
-
// (handler as any).unsubscribeFunctions.push(unsubscribeMock);
|
|
484
|
-
// handler.changeRoute("user-information");
|
|
485
|
-
// expect(unsubscribeMock).toHaveBeenCalled();
|
|
486
|
-
// expect(dummyGlobalEventHandler.user.subscribe.creation).toHaveBeenCalled();
|
|
487
|
-
// });
|
|
488
|
-
|
|
489
|
-
it("dispara los callbacks de API al invocar los métodos internos", () => {
|
|
490
|
-
const tenantCbSpy = jest
|
|
491
|
-
.spyOn(BackendHandler.prototype as any, "subscribeTenantEvents")
|
|
492
|
-
.mockImplementation(function () {
|
|
493
|
-
createTenant(
|
|
494
|
-
{
|
|
495
|
-
id: "t1",
|
|
496
|
-
name: "Tenant 1",
|
|
497
|
-
organizationsIds: [],
|
|
498
|
-
services: [],
|
|
499
|
-
accounts: [],
|
|
500
|
-
environments: [],
|
|
501
|
-
marketplaceItems: [],
|
|
502
|
-
resources: [],
|
|
503
|
-
role: "",
|
|
504
|
-
status: "",
|
|
505
|
-
users: [],
|
|
506
|
-
registry: [],
|
|
507
|
-
} as Tenant,
|
|
508
|
-
""
|
|
509
|
-
);
|
|
510
|
-
});
|
|
511
|
-
const testUserData: UserData = {
|
|
512
|
-
id: "",
|
|
513
|
-
name: "",
|
|
514
|
-
surname: "",
|
|
515
|
-
provider: [
|
|
516
|
-
{
|
|
517
|
-
name: "",
|
|
518
|
-
email: "",
|
|
519
|
-
password: "",
|
|
520
|
-
},
|
|
521
|
-
],
|
|
522
|
-
notificationsEnabled: "",
|
|
523
|
-
organizations: [],
|
|
524
|
-
clusterTokens: [],
|
|
525
|
-
tokens: [],
|
|
526
|
-
tenants: [],
|
|
527
|
-
axebowPlan: "freemium",
|
|
528
|
-
companyName: "",
|
|
529
|
-
rol: "",
|
|
530
|
-
};
|
|
531
|
-
const userCbSpy = jest
|
|
532
|
-
.spyOn(BackendHandler.prototype as any, "subscribeUserEvents")
|
|
533
|
-
.mockImplementation(function () {
|
|
534
|
-
loadUser("", testUserData);
|
|
535
|
-
});
|
|
536
|
-
const accountCbSpy = jest
|
|
537
|
-
.spyOn(BackendHandler.prototype as any, "subscribeAccountEvents")
|
|
538
|
-
.mockImplementation(function () {
|
|
539
|
-
createAccount(
|
|
540
|
-
{
|
|
541
|
-
id: "a1",
|
|
542
|
-
name: "Account 1",
|
|
543
|
-
tenant: "",
|
|
544
|
-
cloudProvider: { name: "" },
|
|
545
|
-
logo: "",
|
|
546
|
-
environments: [],
|
|
547
|
-
services: [],
|
|
548
|
-
domains: [],
|
|
549
|
-
status: "",
|
|
550
|
-
usage: {
|
|
551
|
-
current: {
|
|
552
|
-
cpu: 0,
|
|
553
|
-
memory: 0,
|
|
554
|
-
storage: 0,
|
|
555
|
-
volatileStorage: 0,
|
|
556
|
-
nonReplicatedStorage: 0,
|
|
557
|
-
persistentStorage: 0,
|
|
558
|
-
},
|
|
559
|
-
limit: {
|
|
560
|
-
cpu: { max: 0, min: 0 },
|
|
561
|
-
memory: { max: 0, min: 0 },
|
|
562
|
-
storage: { max: 0, min: 0 },
|
|
563
|
-
volatileStorage: { max: 0, min: 0 },
|
|
564
|
-
nonReplicatedStorage: { max: 0, min: 0 },
|
|
565
|
-
persistentStorage: { max: 0, min: 0 },
|
|
566
|
-
},
|
|
567
|
-
cost: 0,
|
|
568
|
-
},
|
|
569
|
-
} as Account,
|
|
570
|
-
""
|
|
571
|
-
);
|
|
572
|
-
});
|
|
573
|
-
const envCbSpy = jest
|
|
574
|
-
.spyOn(BackendHandler.prototype as any, "subscribeEnvironmentEvents")
|
|
575
|
-
.mockImplementation(function () {
|
|
576
|
-
createEnvironment(
|
|
577
|
-
{
|
|
578
|
-
id: "e1",
|
|
579
|
-
name: "Env 1",
|
|
580
|
-
account: "",
|
|
581
|
-
tenant: "",
|
|
582
|
-
logo: "",
|
|
583
|
-
services: [],
|
|
584
|
-
domains: [],
|
|
585
|
-
status: {
|
|
586
|
-
code:"",
|
|
587
|
-
message: "",
|
|
588
|
-
timestamp: ""
|
|
589
|
-
},
|
|
590
|
-
usage: {
|
|
591
|
-
current: {
|
|
592
|
-
cpu: 0,
|
|
593
|
-
memory: 0,
|
|
594
|
-
storage: 0,
|
|
595
|
-
volatileStorage: 0,
|
|
596
|
-
nonReplicatedStorage: 0,
|
|
597
|
-
persistentStorage: 0,
|
|
598
|
-
},
|
|
599
|
-
limit: {
|
|
600
|
-
cpu: { max: 0, min: 0 },
|
|
601
|
-
memory: { max: 0, min: 0 },
|
|
602
|
-
storage: { max: 0, min: 0 },
|
|
603
|
-
volatileStorage: { max: 0, min: 0 },
|
|
604
|
-
nonReplicatedStorage: { max: 0, min: 0 },
|
|
605
|
-
persistentStorage: { max: 0, min: 0 },
|
|
606
|
-
},
|
|
607
|
-
cost: 0,
|
|
608
|
-
},
|
|
609
|
-
type: "",
|
|
610
|
-
cluster: { name: "" },
|
|
611
|
-
} as Environment,
|
|
612
|
-
""
|
|
613
|
-
);
|
|
614
|
-
});
|
|
615
|
-
const serviceCbSpy = jest
|
|
616
|
-
.spyOn(BackendHandler.prototype as any, "subscribeServiceEvents")
|
|
617
|
-
.mockImplementation(function () {
|
|
618
|
-
deployService(
|
|
619
|
-
{
|
|
620
|
-
id: "s1",
|
|
621
|
-
tenant: "",
|
|
622
|
-
account: "",
|
|
623
|
-
environment: "",
|
|
624
|
-
name: "Service 1",
|
|
625
|
-
logo: "",
|
|
626
|
-
description: "",
|
|
627
|
-
revisions: [],
|
|
628
|
-
status: "",
|
|
629
|
-
role: [{ name: "", instances: [] }],
|
|
630
|
-
links: [],
|
|
631
|
-
resources: [],
|
|
632
|
-
parameters: [],
|
|
633
|
-
usage: {
|
|
634
|
-
current: {
|
|
635
|
-
cpu: 0,
|
|
636
|
-
memory: 0,
|
|
637
|
-
storage: 0,
|
|
638
|
-
volatileStorage: 0,
|
|
639
|
-
nonReplicatedStorage: 0,
|
|
640
|
-
persistentStorage: 0,
|
|
641
|
-
},
|
|
642
|
-
limit: {
|
|
643
|
-
cpu: { max: 0, min: 0 },
|
|
644
|
-
memory: { max: 0, min: 0 },
|
|
645
|
-
storage: { max: 0, min: 0 },
|
|
646
|
-
volatileStorage: { max: 0, min: 0 },
|
|
647
|
-
nonReplicatedStorage: { max: 0, min: 0 },
|
|
648
|
-
persistentStorage: { max: 0, min: 0 },
|
|
649
|
-
},
|
|
650
|
-
cost: 0,
|
|
651
|
-
},
|
|
652
|
-
project: "",
|
|
653
|
-
registry: "",
|
|
654
|
-
imageName: "",
|
|
655
|
-
entrypoint: "",
|
|
656
|
-
cmd: "",
|
|
657
|
-
serverChannels: [],
|
|
658
|
-
clientChannels: [],
|
|
659
|
-
duplexChannels: [],
|
|
660
|
-
cloudProvider: "",
|
|
661
|
-
} as Service,
|
|
662
|
-
""
|
|
663
|
-
);
|
|
664
|
-
});
|
|
665
|
-
const marketplaceDeploySpy = jest
|
|
666
|
-
.spyOn(BackendHandler.prototype as any, "subscribeMarketplaceEvents")
|
|
667
|
-
.mockImplementation(function () {
|
|
668
|
-
deployMarketplaceItem({
|
|
669
|
-
deploymentData: {
|
|
670
|
-
id: "m1",
|
|
671
|
-
tenant: "",
|
|
672
|
-
account: "",
|
|
673
|
-
environment: "",
|
|
674
|
-
name: "Market 1",
|
|
675
|
-
logo: "",
|
|
676
|
-
description: "",
|
|
677
|
-
revisions: [],
|
|
678
|
-
status: "",
|
|
679
|
-
role: [{ name: "", instances: [] }],
|
|
680
|
-
links: [],
|
|
681
|
-
resources: [],
|
|
682
|
-
parameters: [],
|
|
683
|
-
usage: {
|
|
684
|
-
current: {
|
|
685
|
-
cpu: 0,
|
|
686
|
-
memory: 0,
|
|
687
|
-
storage: 0,
|
|
688
|
-
volatileStorage: 0,
|
|
689
|
-
nonReplicatedStorage: 0,
|
|
690
|
-
persistentStorage: 0,
|
|
691
|
-
},
|
|
692
|
-
limit: {
|
|
693
|
-
cpu: { max: 0, min: 0 },
|
|
694
|
-
memory: { max: 0, min: 0 },
|
|
695
|
-
storage: { max: 0, min: 0 },
|
|
696
|
-
volatileStorage: { max: 0, min: 0 },
|
|
697
|
-
nonReplicatedStorage: { max: 0, min: 0 },
|
|
698
|
-
persistentStorage: { max: 0, min: 0 },
|
|
699
|
-
},
|
|
700
|
-
cost: 0,
|
|
701
|
-
},
|
|
702
|
-
project: "",
|
|
703
|
-
registry: "",
|
|
704
|
-
imageName: "",
|
|
705
|
-
entrypoint: "",
|
|
706
|
-
cmd: "",
|
|
707
|
-
serverChannels: [],
|
|
708
|
-
clientChannels: [],
|
|
709
|
-
duplexChannels: [],
|
|
710
|
-
cloudProvider: "",
|
|
711
|
-
},
|
|
712
|
-
step: 0,
|
|
713
|
-
selectedAccount: "",
|
|
714
|
-
step1collapsed: false,
|
|
715
|
-
step2collapsed: false,
|
|
716
|
-
step3collapsed: false,
|
|
717
|
-
step4collapsed: false,
|
|
718
|
-
defaultExecutableCollapsed: false,
|
|
719
|
-
autoScallingCollapsed: false,
|
|
720
|
-
variableCreation: "",
|
|
721
|
-
variableName: "",
|
|
722
|
-
variableValue: "",
|
|
723
|
-
variableList: [{ name: "", value: "", type: "" }],
|
|
724
|
-
openCreationPopup: false,
|
|
725
|
-
domain: "",
|
|
726
|
-
module: "",
|
|
727
|
-
version: "",
|
|
728
|
-
resourceList: [{ name: "", type: "", required: false }],
|
|
729
|
-
parameterList: [{ name: "", type: "", required: false }],
|
|
730
|
-
serviceName: "",
|
|
731
|
-
type: "",
|
|
732
|
-
artifactName: "",
|
|
733
|
-
} as MarketplaceService);
|
|
734
|
-
});
|
|
735
|
-
const marketplaceLoadSpy = jest
|
|
736
|
-
.spyOn(BackendHandler.prototype as any, "subscribeMarketplaceEvents")
|
|
737
|
-
.mockImplementation(function () {
|
|
738
|
-
getMarketplaceItems(["t1", "t2"], "");
|
|
739
|
-
});
|
|
740
|
-
|
|
741
|
-
new BackendHandler(
|
|
742
|
-
"tenants",
|
|
743
|
-
dummyGlobalEventHandler,
|
|
744
|
-
"httl://localhost:9080",
|
|
745
|
-
"nightly"
|
|
745
|
+
});
|
|
746
|
+
|
|
747
|
+
it("deploymentError callback publica notificación deployment-error con error info", async () => {
|
|
748
|
+
const { h } = await buildHandler();
|
|
749
|
+
const cb = (h.service.subscribe.deploymentError as jest.Mock).mock.calls[0][0];
|
|
750
|
+
const svcWithErr = { ...mockService, error: { code: "500", message: "err", timestamp: "now" } };
|
|
751
|
+
cb(svcWithErr);
|
|
752
|
+
expect(h.notification.publish.creation).toHaveBeenCalledWith(
|
|
753
|
+
expect.objectContaining({ type: "error", subtype: "deployment-error", info_content: { code: "500", message: "err", timestamp: "now" } }),
|
|
746
754
|
);
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
755
|
+
});
|
|
756
|
+
|
|
757
|
+
it("deploymentError callback maneja service sin error (defaults vacíos)", async () => {
|
|
758
|
+
const { h } = await buildHandler();
|
|
759
|
+
const cb = (h.service.subscribe.deploymentError as jest.Mock).mock.calls[0][0];
|
|
760
|
+
cb(mockService);
|
|
761
|
+
expect(h.notification.publish.creation).toHaveBeenCalledWith(
|
|
762
|
+
expect.objectContaining({ info_content: { code: "", message: "", timestamp: "" } }),
|
|
752
763
|
);
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
764
|
+
});
|
|
765
|
+
|
|
766
|
+
it("deploy callback llama a deployService y publica notification cuando download es falsy", async () => {
|
|
767
|
+
const { deployService } = await import("../api/service-api-service");
|
|
768
|
+
const { h } = await buildHandler();
|
|
769
|
+
const cb = (h.service.subscribe.deploy as jest.Mock).mock.calls[0][0];
|
|
770
|
+
await cb({ ...mockService, download: false });
|
|
771
|
+
expect(deployService).toHaveBeenCalled();
|
|
772
|
+
expect(h.notification.publish.creation).toHaveBeenCalledWith(
|
|
773
|
+
expect.objectContaining({ type: "info", subtype: "deployment-in-progress" }),
|
|
758
774
|
);
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
775
|
+
});
|
|
776
|
+
|
|
777
|
+
it("deploy callback no publica notificación cuando download es true", async () => {
|
|
778
|
+
const { h } = await buildHandler();
|
|
779
|
+
const cb = (h.service.subscribe.deploy as jest.Mock).mock.calls[0][0];
|
|
780
|
+
(h.notification.publish.creation as jest.Mock).mockClear();
|
|
781
|
+
await cb({ ...mockService, download: true });
|
|
782
|
+
expect(h.notification.publish.creation).not.toHaveBeenCalled();
|
|
783
|
+
});
|
|
784
|
+
|
|
785
|
+
it("update callback llama a updateService", async () => {
|
|
786
|
+
const { updateService } = await import("../api/service-api-service");
|
|
787
|
+
const { h } = await buildHandler();
|
|
788
|
+
const cb = (h.service.subscribe.update as jest.Mock).mock.calls[0][0];
|
|
789
|
+
cb(mockService);
|
|
790
|
+
expect(updateService).toHaveBeenCalled();
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
it("updated callback publica notificación deployment-updated", async () => {
|
|
794
|
+
const { h } = await buildHandler();
|
|
795
|
+
const cb = (h.service.subscribe.updated as jest.Mock).mock.calls[0][0];
|
|
796
|
+
cb(mockService);
|
|
797
|
+
expect(h.notification.publish.creation).toHaveBeenCalledWith(
|
|
798
|
+
expect.objectContaining({ type: "success", subtype: "deployment-updated" }),
|
|
764
799
|
);
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
800
|
+
});
|
|
801
|
+
|
|
802
|
+
it("delete callback publica notificación deployment-deleting y llama a deleteService", async () => {
|
|
803
|
+
const { deleteService } = await import("../api/service-api-service");
|
|
804
|
+
const { h } = await buildHandler();
|
|
805
|
+
const cb = (h.service.subscribe.delete as jest.Mock).mock.calls[0][0];
|
|
806
|
+
cb(mockService);
|
|
807
|
+
expect(h.notification.publish.creation).toHaveBeenCalledWith(
|
|
808
|
+
expect.objectContaining({ type: "info", subtype: "deployment-deleting" }),
|
|
770
809
|
);
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
810
|
+
expect(deleteService).toHaveBeenCalled();
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
it("deleted callback publica notificación deployment-deleted", async () => {
|
|
814
|
+
const { h } = await buildHandler();
|
|
815
|
+
const cb = (h.service.subscribe.deleted as jest.Mock).mock.calls[0][0];
|
|
816
|
+
cb(mockService);
|
|
817
|
+
expect(h.notification.publish.creation).toHaveBeenCalledWith(
|
|
818
|
+
expect.objectContaining({ type: "success", subtype: "deployment-deleted" }),
|
|
776
819
|
);
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
820
|
+
});
|
|
821
|
+
|
|
822
|
+
it("restart callback llama a restartService", async () => {
|
|
823
|
+
const { restartService } = await import("../api/service-api-service");
|
|
824
|
+
const { h } = await buildHandler();
|
|
825
|
+
const cb = (h.service.subscribe.restart as jest.Mock).mock.calls[0][0];
|
|
826
|
+
cb(mockService);
|
|
827
|
+
expect(restartService).toHaveBeenCalled();
|
|
828
|
+
});
|
|
829
|
+
|
|
830
|
+
it("requestRevisionData callback llama a requestRevisionData", async () => {
|
|
831
|
+
const { requestRevisionData } = await import("../api/service-api-service");
|
|
832
|
+
const { h } = await buildHandler();
|
|
833
|
+
const cb = (h.service.subscribe.requestRevisionData as jest.Mock).mock.calls[0][0];
|
|
834
|
+
cb(mockService);
|
|
835
|
+
expect(requestRevisionData).toHaveBeenCalled();
|
|
836
|
+
});
|
|
837
|
+
|
|
838
|
+
it("updateServiceLinks callback llama a updateServiceLinks", async () => {
|
|
839
|
+
const { updateServiceLinks } = await import("../api/service-api-service");
|
|
840
|
+
const { h } = await buildHandler();
|
|
841
|
+
const cb = (h.service.subscribe.updateServiceLinks as jest.Mock).mock.calls[0][0];
|
|
842
|
+
cb({ id: "link1" } as any);
|
|
843
|
+
expect(updateServiceLinks).toHaveBeenCalled();
|
|
844
|
+
});
|
|
845
|
+
|
|
846
|
+
it("changeRevision callback llama a changeRevision", async () => {
|
|
847
|
+
const { changeRevision } = await import("../api/service-api-service");
|
|
848
|
+
const { h } = await buildHandler();
|
|
849
|
+
const cb = (h.service.subscribe.changeRevision as jest.Mock).mock.calls[0][0];
|
|
850
|
+
cb(mockService);
|
|
851
|
+
expect(changeRevision).toHaveBeenCalled();
|
|
852
|
+
});
|
|
853
|
+
|
|
854
|
+
it("restartInstance callback llama a restartInstance", async () => {
|
|
855
|
+
const { restartInstance } = await import("../api/service-api-service");
|
|
856
|
+
const { h } = await buildHandler();
|
|
857
|
+
const cb = (h.service.subscribe.restartInstance as jest.Mock).mock.calls[0][0];
|
|
858
|
+
cb({ service: mockService, roleId: "r1", instanceId: "i1" });
|
|
859
|
+
expect(restartInstance).toHaveBeenCalledWith(mockService, "r1", "i1", "");
|
|
860
|
+
});
|
|
861
|
+
|
|
862
|
+
it("empty callbacks de service no lanzan error", async () => {
|
|
863
|
+
const { h } = await buildHandler();
|
|
864
|
+
const names = ["deletionError", "updateError", "requestLogs"];
|
|
865
|
+
for (const name of names) {
|
|
866
|
+
const cb = (h.service.subscribe[name as keyof typeof h.service.subscribe] as jest.Mock).mock.calls[0][0];
|
|
867
|
+
expect(() => cb(mockService)).not.toThrow();
|
|
868
|
+
}
|
|
869
|
+
});
|
|
870
|
+
});
|
|
871
|
+
|
|
872
|
+
// ── Callbacks de Marketplace ──────────────────────────────────────────────────
|
|
873
|
+
|
|
874
|
+
describe("BackendHandler - callbacks de Marketplace", () => {
|
|
875
|
+
it("deployItem callback llama a deployMarketplaceItem", async () => {
|
|
876
|
+
const { deployMarketplaceItem } = await import("../api/marketplace-api-service");
|
|
877
|
+
const { h } = await buildHandler();
|
|
878
|
+
const cb = (h.marketplace.subscribe.deployItem as jest.Mock).mock.calls[0][0];
|
|
879
|
+
cb({ deploymentData: { name: "item1" } } as MarketplaceService);
|
|
880
|
+
expect(deployMarketplaceItem).toHaveBeenCalled();
|
|
881
|
+
});
|
|
882
|
+
|
|
883
|
+
it("loadSchema callback exitoso publica schemaLoaded", async () => {
|
|
884
|
+
const { fetchAndStoreMarketplaceSchema } = await import("../websocket-manager");
|
|
885
|
+
(fetchAndStoreMarketplaceSchema as jest.Mock).mockResolvedValue(undefined);
|
|
886
|
+
const { h } = await buildHandler();
|
|
887
|
+
const cb = (h.marketplace.subscribe.loadSchema as jest.Mock).mock.calls[0][0];
|
|
888
|
+
const item: MarketplaceItem = { name: "item1" } as any;
|
|
889
|
+
await cb(JSON.stringify({ item }));
|
|
890
|
+
expect(fetchAndStoreMarketplaceSchema).toHaveBeenCalledWith(item);
|
|
891
|
+
expect(h.marketplace.publish.schemaLoaded).toHaveBeenCalledWith(item);
|
|
892
|
+
});
|
|
893
|
+
|
|
894
|
+
it("loadSchema callback con error publica schemaLoadError", async () => {
|
|
895
|
+
const { fetchAndStoreMarketplaceSchema } = await import("../websocket-manager");
|
|
896
|
+
(fetchAndStoreMarketplaceSchema as jest.Mock).mockRejectedValue(new Error("schema-err"));
|
|
897
|
+
const consoleSpy = jest.spyOn(console, "error").mockImplementation(() => {});
|
|
898
|
+
const { h } = await buildHandler();
|
|
899
|
+
const cb = (h.marketplace.subscribe.loadSchema as jest.Mock).mock.calls[0][0];
|
|
900
|
+
const payload = JSON.stringify({ item: { name: "item1" } });
|
|
901
|
+
await cb(payload);
|
|
902
|
+
expect(h.marketplace.publish.schemaLoadError).toHaveBeenCalledWith(payload);
|
|
903
|
+
consoleSpy.mockRestore();
|
|
904
|
+
});
|
|
905
|
+
|
|
906
|
+
it("loadSchema callback con JSON inválido publica schemaLoadError", async () => {
|
|
907
|
+
const consoleSpy = jest.spyOn(console, "error").mockImplementation(() => {});
|
|
908
|
+
const { h } = await buildHandler();
|
|
909
|
+
const cb = (h.marketplace.subscribe.loadSchema as jest.Mock).mock.calls[0][0];
|
|
910
|
+
await cb("not-valid-json");
|
|
911
|
+
expect(h.marketplace.publish.schemaLoadError).toHaveBeenCalled();
|
|
912
|
+
consoleSpy.mockRestore();
|
|
913
|
+
});
|
|
914
|
+
|
|
915
|
+
it("loadItems callback no lanza error", async () => {
|
|
916
|
+
const { h } = await buildHandler();
|
|
917
|
+
const cb = (h.marketplace.subscribe.loadItems as jest.Mock).mock.calls[0][0];
|
|
918
|
+
expect(() => cb(["t1", "t2"])).not.toThrow();
|
|
919
|
+
});
|
|
920
|
+
|
|
921
|
+
it("empty callbacks de marketplace no lanzan error", async () => {
|
|
922
|
+
const { h } = await buildHandler();
|
|
923
|
+
const names = ["itemDeployed", "deploymentError", "updateItem", "itemUpdated", "updateError", "deleteItem", "itemDeleted", "deletionError"];
|
|
924
|
+
for (const name of names) {
|
|
925
|
+
const cb = (h.marketplace.subscribe[name as keyof typeof h.marketplace.subscribe] as jest.Mock).mock.calls[0][0];
|
|
926
|
+
expect(() => cb({})).not.toThrow();
|
|
927
|
+
}
|
|
928
|
+
});
|
|
929
|
+
});
|
|
930
|
+
|
|
931
|
+
// ── Callbacks de Resource ─────────────────────────────────────────────────────
|
|
932
|
+
|
|
933
|
+
describe("BackendHandler - callbacks de Resource", () => {
|
|
934
|
+
const mockResource: Resource = { name: "res1", type: "domain", tenant: "ten1" } as any;
|
|
935
|
+
|
|
936
|
+
it("creation callback llama a createResource", async () => {
|
|
937
|
+
const { createResource } = await import("../api/resources-api-service");
|
|
938
|
+
const { h } = await buildHandler();
|
|
939
|
+
const cb = (h.resource.subscribe.creation as jest.Mock).mock.calls[0][0];
|
|
940
|
+
cb(mockResource);
|
|
941
|
+
expect(createResource).toHaveBeenCalledWith("ten1", mockResource, "");
|
|
942
|
+
});
|
|
943
|
+
|
|
944
|
+
it("creation callback con tenant undefined usa string vacío", async () => {
|
|
945
|
+
const { createResource } = await import("../api/resources-api-service");
|
|
946
|
+
const { h } = await buildHandler();
|
|
947
|
+
const cb = (h.resource.subscribe.creation as jest.Mock).mock.calls[0][0];
|
|
948
|
+
cb({ name: "r1", type: "domain" } as Resource);
|
|
949
|
+
expect(createResource).toHaveBeenCalledWith("", expect.anything(), "");
|
|
950
|
+
});
|
|
951
|
+
|
|
952
|
+
it("update callback llama a updateResource", async () => {
|
|
953
|
+
const { updateResource } = await import("../api/resources-api-service");
|
|
954
|
+
const { h } = await buildHandler();
|
|
955
|
+
const cb = (h.resource.subscribe.update as jest.Mock).mock.calls[0][0];
|
|
956
|
+
cb(mockResource);
|
|
957
|
+
expect(updateResource).toHaveBeenCalled();
|
|
958
|
+
});
|
|
959
|
+
|
|
960
|
+
it("delete callback llama a deleteResource", async () => {
|
|
961
|
+
const { deleteResource } = await import("../api/resources-api-service");
|
|
962
|
+
const { h } = await buildHandler();
|
|
963
|
+
const cb = (h.resource.subscribe.delete as jest.Mock).mock.calls[0][0];
|
|
964
|
+
cb(mockResource);
|
|
965
|
+
expect(deleteResource).toHaveBeenCalled();
|
|
966
|
+
});
|
|
967
|
+
|
|
968
|
+
it("deleted callback publica notificación resource-deleted", async () => {
|
|
969
|
+
const { h } = await buildHandler();
|
|
970
|
+
const cb = (h.resource.subscribe.deleted as jest.Mock).mock.calls[0][0];
|
|
971
|
+
cb({ name: "res1", type: "domain", tenant: "ten1" } as any);
|
|
972
|
+
expect(h.notification.publish.creation).toHaveBeenCalledWith(
|
|
973
|
+
expect.objectContaining({ type: "success", subtype: "resource-deleted", data: { resource: "res1", type: "domain", tenant: "ten1" } }),
|
|
782
974
|
);
|
|
975
|
+
});
|
|
976
|
+
|
|
977
|
+
it("empty callbacks de resource no lanzan error", async () => {
|
|
978
|
+
const { h } = await buildHandler();
|
|
979
|
+
const names = ["created", "creationError", "updated", "updateError", "deletionError"];
|
|
980
|
+
for (const name of names) {
|
|
981
|
+
const cb = (h.resource.subscribe[name as keyof typeof h.resource.subscribe] as jest.Mock).mock.calls[0][0];
|
|
982
|
+
expect(() => cb({})).not.toThrow();
|
|
983
|
+
}
|
|
984
|
+
});
|
|
985
|
+
});
|
|
986
|
+
|
|
987
|
+
// ── Callbacks de Organization ─────────────────────────────────────────────────
|
|
988
|
+
|
|
989
|
+
describe("BackendHandler - callbacks de Organization", () => {
|
|
990
|
+
it("todos los callbacks de organization no lanzan error", async () => {
|
|
991
|
+
const { h } = await buildHandler();
|
|
992
|
+
const names = ["creation", "created", "creationError", "update", "updated", "updateError", "delete", "deleted", "deletionError"];
|
|
993
|
+
for (const name of names) {
|
|
994
|
+
const cb = (h.organization.subscribe[name as keyof typeof h.organization.subscribe] as jest.Mock).mock.calls[0][0];
|
|
995
|
+
expect(() => cb({})).not.toThrow();
|
|
996
|
+
}
|
|
997
|
+
});
|
|
998
|
+
});
|
|
999
|
+
|
|
1000
|
+
// ── Registry, invite y token empty callbacks ──────────────────────────────────
|
|
1001
|
+
|
|
1002
|
+
describe("BackendHandler - empty callbacks adicionales", () => {
|
|
1003
|
+
it("tenant registry empty callbacks no lanzan error", async () => {
|
|
1004
|
+
const { h } = await buildHandler();
|
|
1005
|
+
const names = ["registryCreated", "registryCreationError", "registryUpdated", "registryUpdateError", "registryDeleted", "registryDeletionError"];
|
|
1006
|
+
for (const name of names) {
|
|
1007
|
+
const cb = (h.tenant.subscribe[name as keyof typeof h.tenant.subscribe] as jest.Mock).mock.calls[0][0];
|
|
1008
|
+
expect(() => cb({})).not.toThrow();
|
|
1009
|
+
}
|
|
1010
|
+
});
|
|
1011
|
+
|
|
1012
|
+
it("tenant invite/user empty callbacks no lanzan error", async () => {
|
|
1013
|
+
const { h } = await buildHandler();
|
|
1014
|
+
const names = ["inviteError", "userRemoved", "removeUserError", "inviteUpdated", "inviteUpdateError", "inviteAccepted", "acceptInviteError", "inviteRejected", "inviteRejectError"];
|
|
1015
|
+
for (const name of names) {
|
|
1016
|
+
const cb = (h.tenant.subscribe[name as keyof typeof h.tenant.subscribe] as jest.Mock).mock.calls[0][0];
|
|
1017
|
+
expect(() => cb({})).not.toThrow();
|
|
1018
|
+
}
|
|
1019
|
+
});
|
|
1020
|
+
|
|
1021
|
+
it("tenant token non-subscribed mocks tienen cero llamadas", async () => {
|
|
1022
|
+
const { h } = await buildHandler();
|
|
1023
|
+
// tokenCreated/tokenCreationError/tokenDeleted/tokenDeletionError no son suscritos por BackendHandler
|
|
1024
|
+
expect((h.tenant.subscribe.tokenCreated as jest.Mock).mock.calls).toHaveLength(0);
|
|
1025
|
+
expect((h.tenant.subscribe.tokenDeleted as jest.Mock).mock.calls).toHaveLength(0);
|
|
1026
|
+
});
|
|
1027
|
+
|
|
1028
|
+
it("user empty callbacks no lanzan error", async () => {
|
|
1029
|
+
const { h } = await buildHandler();
|
|
1030
|
+
const names = ["created", "creationError", "updated", "updateError", "loadError", "deleted", "deletionError"];
|
|
1031
|
+
for (const name of names) {
|
|
1032
|
+
const cb = (h.user.subscribe[name as keyof typeof h.user.subscribe] as jest.Mock).mock.calls[0][0];
|
|
1033
|
+
expect(() => cb({})).not.toThrow();
|
|
1034
|
+
}
|
|
1035
|
+
});
|
|
1036
|
+
|
|
1037
|
+
it("account empty callbacks no lanzan error", async () => {
|
|
1038
|
+
const { h } = await buildHandler();
|
|
1039
|
+
const names = ["created", "creationError", "updated", "updateError", "deleted", "deletionError"];
|
|
1040
|
+
for (const name of names) {
|
|
1041
|
+
const cb = (h.account.subscribe[name as keyof typeof h.account.subscribe] as jest.Mock).mock.calls[0][0];
|
|
1042
|
+
expect(() => cb({})).not.toThrow();
|
|
1043
|
+
}
|
|
1044
|
+
});
|
|
783
1045
|
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
1046
|
+
it("environment empty callbacks no lanzan error", async () => {
|
|
1047
|
+
const { h } = await buildHandler();
|
|
1048
|
+
const names = ["creationError", "updated", "updateError", "deleted", "deletionError"];
|
|
1049
|
+
for (const name of names) {
|
|
1050
|
+
const cb = (h.environment.subscribe[name as keyof typeof h.environment.subscribe] as jest.Mock).mock.calls[0][0];
|
|
1051
|
+
expect(() => cb({})).not.toThrow();
|
|
1052
|
+
}
|
|
791
1053
|
});
|
|
792
1054
|
});
|