@stamhoofd/backend 2.79.8 → 2.80.0
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/package.json +11 -11
- package/src/audit-logs/ModelLogger.ts +2 -2
- package/src/crons/amazon-ses.ts +215 -227
- package/src/crons/clearExcelCache.test.ts +1 -1
- package/src/endpoints/admin/members/ChargeMembersEndpoint.ts +105 -0
- package/src/endpoints/admin/organizations/ChargeOrganizationsEndpoint.ts +6 -10
- package/src/endpoints/global/events/PatchEventNotificationsEndpoint.test.ts +997 -0
- package/src/endpoints/global/events/PatchEventNotificationsEndpoint.ts +19 -3
- package/src/endpoints/global/members/GetMembersEndpoint.ts +7 -7
- package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +10 -3
- package/src/helpers/AdminPermissionChecker.ts +3 -3
- package/src/helpers/ForwardHandler.ts +3 -2
- package/src/helpers/MemberCharger.ts +39 -0
- package/src/helpers/OrganizationCharger.ts +9 -20
- package/src/services/EventNotificationService.ts +3 -0
- package/tests/e2e/charge-members.test.ts +429 -0
- package/tests/jest.setup.ts +7 -1
- package/tests/toMatchMap.ts +68 -0
- package/src/services/diff.ts +0 -514
|
@@ -0,0 +1,997 @@
|
|
|
1
|
+
import { PatchableArray, PatchMap, patchObject } from '@simonbackx/simple-encoding';
|
|
2
|
+
import { Endpoint, Request } from '@simonbackx/simple-endpoints';
|
|
3
|
+
import { EventNotificationFactory, EventFactory, EventNotificationTypeFactory, Organization, OrganizationFactory, Token, User, UserFactory, EmailTemplateFactory, RecordCategoryFactory, RegistrationPeriodFactory, RecordAnswerFactory, EventNotification } from '@stamhoofd/models';
|
|
4
|
+
import { AccessRight, BaseOrganization, EmailTemplateType, Event, EventNotificationStatus, EventNotification as EventNotificationStruct, PermissionLevel, Permissions, PermissionsResourceType, RecordAnswer, RecordType, ResourcePermissions } from '@stamhoofd/structures';
|
|
5
|
+
import { TestUtils } from '@stamhoofd/test-utils';
|
|
6
|
+
import { PatchEventNotificationsEndpoint } from './PatchEventNotificationsEndpoint';
|
|
7
|
+
import { testServer } from '../../../../tests/helpers/TestServer';
|
|
8
|
+
import { EmailMocker } from '@stamhoofd/email';
|
|
9
|
+
|
|
10
|
+
const baseUrl = `/event-notifications`;
|
|
11
|
+
const endpoint = new PatchEventNotificationsEndpoint();
|
|
12
|
+
type EndpointType = typeof endpoint;
|
|
13
|
+
type Body = EndpointType extends Endpoint<any, any, infer B, any> ? B : never;
|
|
14
|
+
|
|
15
|
+
const errorWithCode = (code: string) => expect.objectContaining({ code }) as jest.Constructable;
|
|
16
|
+
const errorWithMessage = (message: string) => expect.objectContaining({ message }) as jest.Constructable;
|
|
17
|
+
const simpleError = (data: {
|
|
18
|
+
code?: string;
|
|
19
|
+
message?: string;
|
|
20
|
+
field?: string;
|
|
21
|
+
}) => {
|
|
22
|
+
const d = {
|
|
23
|
+
code: data.code ?? expect.any(String),
|
|
24
|
+
message: data.message ?? expect.any(String),
|
|
25
|
+
field: data.field ?? expect.anything(),
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
if (!data.field) {
|
|
29
|
+
delete d.field;
|
|
30
|
+
}
|
|
31
|
+
return expect.objectContaining(d) as jest.Constructable;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const minimumUserPermissions = Permissions.create({
|
|
35
|
+
resources: new Map([
|
|
36
|
+
[PermissionsResourceType.Groups, new Map([
|
|
37
|
+
['', ResourcePermissions.create({
|
|
38
|
+
accessRights: [AccessRight.EventWrite],
|
|
39
|
+
})],
|
|
40
|
+
])],
|
|
41
|
+
]),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const TestRequest = {
|
|
45
|
+
async patch(options: {
|
|
46
|
+
body?: any;
|
|
47
|
+
user?: User;
|
|
48
|
+
organization?: Organization;
|
|
49
|
+
}) {
|
|
50
|
+
const request = Request.buildJson('PATCH', baseUrl, options.organization?.getApiHost(), options.body);
|
|
51
|
+
if (options.user) {
|
|
52
|
+
const token = await Token.createToken(options.user);
|
|
53
|
+
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
54
|
+
}
|
|
55
|
+
return await testServer.test(endpoint, request);
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
describe('Endpoint.PatchEventNotificationsEndpoint', () => {
|
|
60
|
+
let admin: User;
|
|
61
|
+
|
|
62
|
+
beforeEach(async () => {
|
|
63
|
+
TestUtils.setEnvironment('userMode', 'platform');
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
beforeAll(async () => {
|
|
67
|
+
TestUtils.setEnvironment('userMode', 'platform');
|
|
68
|
+
await new EmailTemplateFactory({
|
|
69
|
+
type: EmailTemplateType.EventNotificationAccepted,
|
|
70
|
+
}).create();
|
|
71
|
+
|
|
72
|
+
await new EmailTemplateFactory({
|
|
73
|
+
type: EmailTemplateType.EventNotificationPartiallyAccepted,
|
|
74
|
+
}).create();
|
|
75
|
+
|
|
76
|
+
await new EmailTemplateFactory({
|
|
77
|
+
type: EmailTemplateType.EventNotificationRejected,
|
|
78
|
+
}).create();
|
|
79
|
+
|
|
80
|
+
await new EmailTemplateFactory({
|
|
81
|
+
type: EmailTemplateType.EventNotificationSubmittedCopy,
|
|
82
|
+
}).create();
|
|
83
|
+
|
|
84
|
+
await new EmailTemplateFactory({
|
|
85
|
+
type: EmailTemplateType.EventNotificationSubmittedReviewer,
|
|
86
|
+
}).create();
|
|
87
|
+
|
|
88
|
+
// Create an admin that will receive the emails
|
|
89
|
+
admin = await new UserFactory({
|
|
90
|
+
email: 'event-notification-reviewer@example.com',
|
|
91
|
+
globalPermissions: Permissions.create({
|
|
92
|
+
resources: new Map([
|
|
93
|
+
[PermissionsResourceType.OrganizationTags, new Map([
|
|
94
|
+
['', ResourcePermissions.create({
|
|
95
|
+
accessRights: [
|
|
96
|
+
AccessRight.OrganizationEventNotificationReviewer,
|
|
97
|
+
],
|
|
98
|
+
})],
|
|
99
|
+
])],
|
|
100
|
+
]),
|
|
101
|
+
}),
|
|
102
|
+
}).create();
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test('A normal user can create new event notifications for an event', async () => {
|
|
106
|
+
const organization = await new OrganizationFactory({}).create();
|
|
107
|
+
const user = await new UserFactory({
|
|
108
|
+
organization,
|
|
109
|
+
permissions: minimumUserPermissions,
|
|
110
|
+
}).create();
|
|
111
|
+
const event = await new EventFactory({ organization }).create();
|
|
112
|
+
const recordCategories = await new RecordCategoryFactory({
|
|
113
|
+
records: [
|
|
114
|
+
{
|
|
115
|
+
type: RecordType.Checkbox,
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
type: RecordType.Text,
|
|
119
|
+
required: true,
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
}).createMultiple(2);
|
|
123
|
+
const notificationType = (await new EventNotificationTypeFactory({ recordCategories }).create());
|
|
124
|
+
|
|
125
|
+
const body: Body = new PatchableArray();
|
|
126
|
+
body.addPut(
|
|
127
|
+
EventNotificationStruct.create({
|
|
128
|
+
typeId: notificationType.id,
|
|
129
|
+
events: [Event.create({ id: event.id })],
|
|
130
|
+
organization: BaseOrganization.create({
|
|
131
|
+
id: organization.id,
|
|
132
|
+
}),
|
|
133
|
+
status: EventNotificationStatus.Draft,
|
|
134
|
+
}),
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
const result = await TestRequest.patch({ body, user, organization });
|
|
138
|
+
expect(result.status).toBe(200);
|
|
139
|
+
|
|
140
|
+
expect(result.body).toHaveLength(1);
|
|
141
|
+
expect(result.body[0]).toMatchObject({
|
|
142
|
+
typeId: notificationType.id,
|
|
143
|
+
events: [expect.objectContaining({ id: event.id })],
|
|
144
|
+
organization: expect.objectContaining({ id: organization.id }),
|
|
145
|
+
status: EventNotificationStatus.Draft,
|
|
146
|
+
createdBy: expect.objectContaining({ id: user.id }),
|
|
147
|
+
submittedBy: null,
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test('It throws when trying to create an event notification for an invalid event notification type id', async () => {
|
|
152
|
+
const organization = await new OrganizationFactory({}).create();
|
|
153
|
+
const user = await new UserFactory({
|
|
154
|
+
organization,
|
|
155
|
+
permissions: minimumUserPermissions,
|
|
156
|
+
}).create();
|
|
157
|
+
const event = await new EventFactory({ organization }).create();
|
|
158
|
+
|
|
159
|
+
const body: Body = new PatchableArray();
|
|
160
|
+
body.addPut(
|
|
161
|
+
EventNotificationStruct.create({
|
|
162
|
+
typeId: 'invalid',
|
|
163
|
+
events: [Event.create({ id: event.id })],
|
|
164
|
+
organization: BaseOrganization.create({
|
|
165
|
+
id: organization.id,
|
|
166
|
+
}),
|
|
167
|
+
status: EventNotificationStatus.Draft,
|
|
168
|
+
}),
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
await expect(TestRequest.patch({ body, user, organization })).rejects.toThrow(
|
|
172
|
+
simpleError({ code: 'invalid_field', field: 'typeId' }),
|
|
173
|
+
);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
test('It throws when trying to create an event notification for an invalid event', async () => {
|
|
177
|
+
const organization = await new OrganizationFactory({}).create();
|
|
178
|
+
const user = await new UserFactory({
|
|
179
|
+
organization,
|
|
180
|
+
permissions: minimumUserPermissions,
|
|
181
|
+
}).create();
|
|
182
|
+
const notificationType = (await new EventNotificationTypeFactory({ }).create());
|
|
183
|
+
|
|
184
|
+
const body: Body = new PatchableArray();
|
|
185
|
+
body.addPut(
|
|
186
|
+
EventNotificationStruct.create({
|
|
187
|
+
typeId: notificationType.id,
|
|
188
|
+
events: [Event.create({ id: 'invalid' })],
|
|
189
|
+
organization: BaseOrganization.create({
|
|
190
|
+
id: organization.id,
|
|
191
|
+
}),
|
|
192
|
+
status: EventNotificationStatus.Draft,
|
|
193
|
+
}),
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
await expect(TestRequest.patch({ body, user, organization })).rejects.toThrow(
|
|
197
|
+
simpleError({ code: 'invalid_field', field: 'events' }),
|
|
198
|
+
);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
test('It throws when trying to create an event notification for a locked period', async () => {
|
|
202
|
+
await new RegistrationPeriodFactory({
|
|
203
|
+
startDate: new Date(2050, 0, 1),
|
|
204
|
+
endDate: new Date(2051, 11, 31),
|
|
205
|
+
locked: true,
|
|
206
|
+
}).create();
|
|
207
|
+
const organization = await new OrganizationFactory({}).create();
|
|
208
|
+
const user = await new UserFactory({
|
|
209
|
+
organization,
|
|
210
|
+
permissions: minimumUserPermissions,
|
|
211
|
+
}).create();
|
|
212
|
+
const event = await new EventFactory({
|
|
213
|
+
organization,
|
|
214
|
+
startDate: new Date(2050, 10, 1),
|
|
215
|
+
endDate: new Date(2051, 10, 15),
|
|
216
|
+
}).create();
|
|
217
|
+
const notificationType = (await new EventNotificationTypeFactory({ }).create());
|
|
218
|
+
|
|
219
|
+
const body: Body = new PatchableArray();
|
|
220
|
+
body.addPut(
|
|
221
|
+
EventNotificationStruct.create({
|
|
222
|
+
typeId: notificationType.id,
|
|
223
|
+
events: [Event.create({ id: event.id })],
|
|
224
|
+
organization: BaseOrganization.create({
|
|
225
|
+
id: organization.id,
|
|
226
|
+
}),
|
|
227
|
+
status: EventNotificationStatus.Draft,
|
|
228
|
+
}),
|
|
229
|
+
);
|
|
230
|
+
await expect(TestRequest.patch({ body, user, organization })).rejects.toThrow(
|
|
231
|
+
simpleError({ code: 'invalid_period', field: 'startDate' }),
|
|
232
|
+
);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
test('It throws when trying to create an event notification for an event in a different organization', async () => {
|
|
236
|
+
const organization = await new OrganizationFactory({}).create();
|
|
237
|
+
const otherOrganization = await new OrganizationFactory({}).create();
|
|
238
|
+
|
|
239
|
+
const user = await new UserFactory({
|
|
240
|
+
organization,
|
|
241
|
+
permissions: minimumUserPermissions,
|
|
242
|
+
}).create();
|
|
243
|
+
const event = await new EventFactory({ organization: otherOrganization }).create();
|
|
244
|
+
const notificationType = (await new EventNotificationTypeFactory({ }).create());
|
|
245
|
+
|
|
246
|
+
const body: Body = new PatchableArray();
|
|
247
|
+
body.addPut(
|
|
248
|
+
EventNotificationStruct.create({
|
|
249
|
+
typeId: notificationType.id,
|
|
250
|
+
events: [Event.create({ id: event.id })],
|
|
251
|
+
organization: BaseOrganization.create({
|
|
252
|
+
id: organization.id,
|
|
253
|
+
}),
|
|
254
|
+
status: EventNotificationStatus.Draft,
|
|
255
|
+
}),
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
await expect(TestRequest.patch({ body, user, organization })).rejects.toThrow(
|
|
259
|
+
simpleError({ code: 'invalid_field', field: 'events' }),
|
|
260
|
+
);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test('A normal user can move the event notification to pending state from draft', async () => {
|
|
264
|
+
const organization = await new OrganizationFactory({}).create();
|
|
265
|
+
const user = await new UserFactory({
|
|
266
|
+
organization,
|
|
267
|
+
permissions: minimumUserPermissions,
|
|
268
|
+
}).create();
|
|
269
|
+
const event = await new EventFactory({ organization }).create();
|
|
270
|
+
const eventNotification = await new EventNotificationFactory({ organization, events: [event] }).create();
|
|
271
|
+
|
|
272
|
+
const body: Body = new PatchableArray();
|
|
273
|
+
body.addPatch(
|
|
274
|
+
EventNotificationStruct.patch({
|
|
275
|
+
id: eventNotification.id,
|
|
276
|
+
status: EventNotificationStatus.Pending,
|
|
277
|
+
}),
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
const result = await TestRequest.patch({ body, user, organization });
|
|
281
|
+
expect(result.status).toBe(200);
|
|
282
|
+
|
|
283
|
+
expect(result.body).toHaveLength(1);
|
|
284
|
+
expect(result.body[0]).toMatchObject({
|
|
285
|
+
organization: expect.objectContaining({ id: organization.id }),
|
|
286
|
+
status: EventNotificationStatus.Pending,
|
|
287
|
+
submittedBy: expect.objectContaining({ id: user.id }),
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
expect(EmailMocker.transactional.getSucceededEmails()).toIncludeSameMembers([
|
|
291
|
+
expect.objectContaining({
|
|
292
|
+
to: 'event-notification-reviewer@example.com',
|
|
293
|
+
subject: EmailTemplateType.EventNotificationSubmittedReviewer,
|
|
294
|
+
text: expect.stringContaining(event.name),
|
|
295
|
+
}),
|
|
296
|
+
|
|
297
|
+
expect.objectContaining({
|
|
298
|
+
to: user.email,
|
|
299
|
+
subject: EmailTemplateType.EventNotificationSubmittedCopy,
|
|
300
|
+
text: expect.stringContaining(event.name),
|
|
301
|
+
}),
|
|
302
|
+
]);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
test('A normal user can move the event notification to pending state from rejected', async () => {
|
|
306
|
+
const organization = await new OrganizationFactory({}).create();
|
|
307
|
+
const user = await new UserFactory({
|
|
308
|
+
organization,
|
|
309
|
+
permissions: minimumUserPermissions,
|
|
310
|
+
}).create();
|
|
311
|
+
const event = await new EventFactory({ organization }).create();
|
|
312
|
+
const eventNotification = await new EventNotificationFactory({
|
|
313
|
+
organization,
|
|
314
|
+
events: [event],
|
|
315
|
+
status: EventNotificationStatus.Rejected,
|
|
316
|
+
}).create();
|
|
317
|
+
|
|
318
|
+
const body: Body = new PatchableArray();
|
|
319
|
+
body.addPatch(
|
|
320
|
+
EventNotificationStruct.patch({
|
|
321
|
+
id: eventNotification.id,
|
|
322
|
+
status: EventNotificationStatus.Pending,
|
|
323
|
+
}),
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
const result = await TestRequest.patch({ body, user, organization });
|
|
327
|
+
expect(result.status).toBe(200);
|
|
328
|
+
|
|
329
|
+
expect(result.body).toHaveLength(1);
|
|
330
|
+
expect(result.body[0]).toMatchObject({
|
|
331
|
+
organization: expect.objectContaining({ id: organization.id }),
|
|
332
|
+
status: EventNotificationStatus.Pending,
|
|
333
|
+
submittedBy: expect.objectContaining({ id: user.id }),
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
expect(EmailMocker.transactional.getSucceededEmails()).toIncludeSameMembers([
|
|
337
|
+
expect.objectContaining({
|
|
338
|
+
to: 'event-notification-reviewer@example.com',
|
|
339
|
+
subject: EmailTemplateType.EventNotificationSubmittedReviewer,
|
|
340
|
+
text: expect.stringContaining(event.name),
|
|
341
|
+
}),
|
|
342
|
+
|
|
343
|
+
expect.objectContaining({
|
|
344
|
+
to: user.email,
|
|
345
|
+
subject: EmailTemplateType.EventNotificationSubmittedCopy,
|
|
346
|
+
text: expect.stringContaining(event.name),
|
|
347
|
+
}),
|
|
348
|
+
]);
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
test('A normal user can move the event notification to pending state from partially accepted', async () => {
|
|
352
|
+
const organization = await new OrganizationFactory({}).create();
|
|
353
|
+
const user = await new UserFactory({
|
|
354
|
+
organization,
|
|
355
|
+
permissions: minimumUserPermissions,
|
|
356
|
+
}).create();
|
|
357
|
+
const event = await new EventFactory({ organization }).create();
|
|
358
|
+
const eventNotification = await new EventNotificationFactory({
|
|
359
|
+
organization,
|
|
360
|
+
events: [event],
|
|
361
|
+
status: EventNotificationStatus.PartiallyAccepted,
|
|
362
|
+
}).create();
|
|
363
|
+
|
|
364
|
+
const body: Body = new PatchableArray();
|
|
365
|
+
body.addPatch(
|
|
366
|
+
EventNotificationStruct.patch({
|
|
367
|
+
id: eventNotification.id,
|
|
368
|
+
status: EventNotificationStatus.Pending,
|
|
369
|
+
}),
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
const result = await TestRequest.patch({ body, user, organization });
|
|
373
|
+
expect(result.status).toBe(200);
|
|
374
|
+
|
|
375
|
+
expect(result.body).toHaveLength(1);
|
|
376
|
+
expect(result.body[0]).toMatchObject({
|
|
377
|
+
organization: expect.objectContaining({ id: organization.id }),
|
|
378
|
+
status: EventNotificationStatus.Pending,
|
|
379
|
+
submittedBy: expect.objectContaining({ id: user.id }),
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
expect(EmailMocker.transactional.getSucceededEmails()).toIncludeSameMembers([
|
|
383
|
+
expect.objectContaining({
|
|
384
|
+
to: 'event-notification-reviewer@example.com',
|
|
385
|
+
subject: EmailTemplateType.EventNotificationSubmittedReviewer,
|
|
386
|
+
text: expect.stringContaining(event.name),
|
|
387
|
+
}),
|
|
388
|
+
|
|
389
|
+
expect.objectContaining({
|
|
390
|
+
to: user.email,
|
|
391
|
+
subject: EmailTemplateType.EventNotificationSubmittedCopy,
|
|
392
|
+
text: expect.stringContaining(event.name),
|
|
393
|
+
}),
|
|
394
|
+
]);
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
test('A normal user cannot move the event notification to pending from accepted', async () => {
|
|
398
|
+
const organization = await new OrganizationFactory({}).create();
|
|
399
|
+
const user = await new UserFactory({
|
|
400
|
+
organization,
|
|
401
|
+
permissions: minimumUserPermissions,
|
|
402
|
+
}).create();
|
|
403
|
+
const event = await new EventFactory({ organization }).create();
|
|
404
|
+
const eventNotification = await new EventNotificationFactory({
|
|
405
|
+
organization,
|
|
406
|
+
events: [event],
|
|
407
|
+
status: EventNotificationStatus.Accepted,
|
|
408
|
+
}).create();
|
|
409
|
+
|
|
410
|
+
const body: Body = new PatchableArray();
|
|
411
|
+
body.addPatch(
|
|
412
|
+
EventNotificationStruct.patch({
|
|
413
|
+
id: eventNotification.id,
|
|
414
|
+
status: EventNotificationStatus.Pending,
|
|
415
|
+
}),
|
|
416
|
+
);
|
|
417
|
+
|
|
418
|
+
await expect(TestRequest.patch({ body, user, organization })).rejects.toThrow(
|
|
419
|
+
simpleError({ code: 'permission_denied' }),
|
|
420
|
+
);
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
test('A normal user cannot move the event notification to accepted from pending', async () => {
|
|
424
|
+
const organization = await new OrganizationFactory({}).create();
|
|
425
|
+
const user = await new UserFactory({
|
|
426
|
+
organization,
|
|
427
|
+
permissions: minimumUserPermissions,
|
|
428
|
+
}).create();
|
|
429
|
+
const event = await new EventFactory({ organization }).create();
|
|
430
|
+
const eventNotification = await new EventNotificationFactory({
|
|
431
|
+
organization,
|
|
432
|
+
events: [event],
|
|
433
|
+
status: EventNotificationStatus.Pending,
|
|
434
|
+
}).create();
|
|
435
|
+
|
|
436
|
+
const body: Body = new PatchableArray();
|
|
437
|
+
body.addPatch(
|
|
438
|
+
EventNotificationStruct.patch({
|
|
439
|
+
id: eventNotification.id,
|
|
440
|
+
status: EventNotificationStatus.Accepted,
|
|
441
|
+
}),
|
|
442
|
+
);
|
|
443
|
+
|
|
444
|
+
await expect(TestRequest.patch({ body, user, organization })).rejects.toThrow(
|
|
445
|
+
simpleError({ code: 'permission_denied' }),
|
|
446
|
+
);
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
test('A normal user cannot move the event notification to accepted from draft', async () => {
|
|
450
|
+
const organization = await new OrganizationFactory({}).create();
|
|
451
|
+
const user = await new UserFactory({
|
|
452
|
+
organization,
|
|
453
|
+
permissions: minimumUserPermissions,
|
|
454
|
+
}).create();
|
|
455
|
+
const event = await new EventFactory({ organization }).create();
|
|
456
|
+
const eventNotification = await new EventNotificationFactory({
|
|
457
|
+
organization,
|
|
458
|
+
events: [event],
|
|
459
|
+
status: EventNotificationStatus.Draft,
|
|
460
|
+
}).create();
|
|
461
|
+
|
|
462
|
+
const body: Body = new PatchableArray();
|
|
463
|
+
body.addPatch(
|
|
464
|
+
EventNotificationStruct.patch({
|
|
465
|
+
id: eventNotification.id,
|
|
466
|
+
status: EventNotificationStatus.Accepted,
|
|
467
|
+
}),
|
|
468
|
+
);
|
|
469
|
+
|
|
470
|
+
await expect(TestRequest.patch({ body, user, organization })).rejects.toThrow(
|
|
471
|
+
simpleError({ code: 'permission_denied' }),
|
|
472
|
+
);
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
test('A normal user cannot move the event notification to partially accepted from draft', async () => {
|
|
476
|
+
const organization = await new OrganizationFactory({}).create();
|
|
477
|
+
const user = await new UserFactory({
|
|
478
|
+
organization,
|
|
479
|
+
permissions: minimumUserPermissions,
|
|
480
|
+
}).create();
|
|
481
|
+
const event = await new EventFactory({ organization }).create();
|
|
482
|
+
const eventNotification = await new EventNotificationFactory({
|
|
483
|
+
organization,
|
|
484
|
+
events: [event],
|
|
485
|
+
status: EventNotificationStatus.Draft,
|
|
486
|
+
}).create();
|
|
487
|
+
|
|
488
|
+
const body: Body = new PatchableArray();
|
|
489
|
+
body.addPatch(
|
|
490
|
+
EventNotificationStruct.patch({
|
|
491
|
+
id: eventNotification.id,
|
|
492
|
+
status: EventNotificationStatus.PartiallyAccepted,
|
|
493
|
+
}),
|
|
494
|
+
);
|
|
495
|
+
|
|
496
|
+
await expect(TestRequest.patch({ body, user, organization })).rejects.toThrow(
|
|
497
|
+
simpleError({ code: 'permission_denied' }),
|
|
498
|
+
);
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
test('A normal user cannot edit an accepted event notification', async () => {
|
|
502
|
+
const organization = await new OrganizationFactory({}).create();
|
|
503
|
+
const user = await new UserFactory({
|
|
504
|
+
organization,
|
|
505
|
+
permissions: minimumUserPermissions,
|
|
506
|
+
}).create();
|
|
507
|
+
const event = await new EventFactory({ organization }).create();
|
|
508
|
+
const eventNotification = await new EventNotificationFactory({
|
|
509
|
+
organization,
|
|
510
|
+
events: [event],
|
|
511
|
+
status: EventNotificationStatus.Accepted,
|
|
512
|
+
}).create();
|
|
513
|
+
|
|
514
|
+
const body: Body = new PatchableArray();
|
|
515
|
+
body.addPatch(
|
|
516
|
+
EventNotificationStruct.patch({
|
|
517
|
+
id: eventNotification.id,
|
|
518
|
+
recordAnswers: new PatchMap(),
|
|
519
|
+
}),
|
|
520
|
+
);
|
|
521
|
+
|
|
522
|
+
await expect(TestRequest.patch({ body, user, organization })).rejects.toThrow(
|
|
523
|
+
simpleError({ code: 'permission_denied' }),
|
|
524
|
+
);
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
test('A normal user can edit an partially accepted event notification', async () => {
|
|
528
|
+
const organization = await new OrganizationFactory({}).create();
|
|
529
|
+
const user = await new UserFactory({
|
|
530
|
+
organization,
|
|
531
|
+
permissions: minimumUserPermissions,
|
|
532
|
+
}).create();
|
|
533
|
+
const event = await new EventFactory({ organization }).create();
|
|
534
|
+
|
|
535
|
+
const recordCategories = await new RecordCategoryFactory({
|
|
536
|
+
records: [
|
|
537
|
+
{
|
|
538
|
+
type: RecordType.Checkbox,
|
|
539
|
+
},
|
|
540
|
+
{
|
|
541
|
+
type: RecordType.Text,
|
|
542
|
+
required: true,
|
|
543
|
+
},
|
|
544
|
+
],
|
|
545
|
+
}).createMultiple(2);
|
|
546
|
+
|
|
547
|
+
const firstRecord = recordCategories[0].records[0];
|
|
548
|
+
|
|
549
|
+
const notificationType = (await new EventNotificationTypeFactory({ recordCategories }).create());
|
|
550
|
+
const acceptedRecordAnswers = await new RecordAnswerFactory({ recordCategories }).create();
|
|
551
|
+
const eventNotification = await new EventNotificationFactory({
|
|
552
|
+
organization,
|
|
553
|
+
events: [event],
|
|
554
|
+
status: EventNotificationStatus.PartiallyAccepted,
|
|
555
|
+
typeId: notificationType.id,
|
|
556
|
+
acceptedRecordAnswers: acceptedRecordAnswers,
|
|
557
|
+
recordAnswers: acceptedRecordAnswers,
|
|
558
|
+
}).create();
|
|
559
|
+
|
|
560
|
+
const patchedRecordAnswers = await new RecordAnswerFactory({ records: [firstRecord] }).create();
|
|
561
|
+
const patch = new PatchMap([...patchedRecordAnswers.entries()]);
|
|
562
|
+
|
|
563
|
+
const body: Body = new PatchableArray();
|
|
564
|
+
body.addPatch(
|
|
565
|
+
EventNotificationStruct.patch({
|
|
566
|
+
id: eventNotification.id,
|
|
567
|
+
recordAnswers: patch,
|
|
568
|
+
}),
|
|
569
|
+
);
|
|
570
|
+
|
|
571
|
+
const result = await TestRequest.patch({ body, user, organization });
|
|
572
|
+
expect(result.status).toBe(200);
|
|
573
|
+
expect(result.body).toHaveLength(1);
|
|
574
|
+
|
|
575
|
+
expect(result.body[0]).toMatchObject({
|
|
576
|
+
status: EventNotificationStatus.PartiallyAccepted,
|
|
577
|
+
acceptedRecordAnswers: expect.toMatchMap(acceptedRecordAnswers),
|
|
578
|
+
recordAnswers: expect.toMatchMap(
|
|
579
|
+
patchObject(acceptedRecordAnswers, patch),
|
|
580
|
+
),
|
|
581
|
+
});
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
test('A normal user cannot edit a pending event notification', async () => {
|
|
585
|
+
const organization = await new OrganizationFactory({}).create();
|
|
586
|
+
const user = await new UserFactory({
|
|
587
|
+
organization,
|
|
588
|
+
permissions: minimumUserPermissions,
|
|
589
|
+
}).create();
|
|
590
|
+
const event = await new EventFactory({ organization }).create();
|
|
591
|
+
const eventNotification = await new EventNotificationFactory({
|
|
592
|
+
organization,
|
|
593
|
+
events: [event],
|
|
594
|
+
status: EventNotificationStatus.Pending,
|
|
595
|
+
}).create();
|
|
596
|
+
|
|
597
|
+
const body: Body = new PatchableArray();
|
|
598
|
+
body.addPatch(
|
|
599
|
+
EventNotificationStruct.patch({
|
|
600
|
+
id: eventNotification.id,
|
|
601
|
+
recordAnswers: new PatchMap(),
|
|
602
|
+
}),
|
|
603
|
+
);
|
|
604
|
+
|
|
605
|
+
await expect(TestRequest.patch({ body, user, organization })).rejects.toThrow(
|
|
606
|
+
simpleError({ code: 'permission_denied' }),
|
|
607
|
+
);
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
test('An admin can accept an event notification', async () => {
|
|
611
|
+
const organization = await new OrganizationFactory({}).create();
|
|
612
|
+
const user = await new UserFactory({
|
|
613
|
+
organization,
|
|
614
|
+
permissions: minimumUserPermissions,
|
|
615
|
+
}).create();
|
|
616
|
+
const event = await new EventFactory({ organization }).create();
|
|
617
|
+
|
|
618
|
+
const recordCategories = await new RecordCategoryFactory({
|
|
619
|
+
records: [
|
|
620
|
+
{
|
|
621
|
+
type: RecordType.Checkbox,
|
|
622
|
+
},
|
|
623
|
+
{
|
|
624
|
+
type: RecordType.Text,
|
|
625
|
+
required: true,
|
|
626
|
+
},
|
|
627
|
+
],
|
|
628
|
+
}).createMultiple(2);
|
|
629
|
+
|
|
630
|
+
const notificationType = (await new EventNotificationTypeFactory({ recordCategories }).create());
|
|
631
|
+
const acceptedRecordAnswers = await new RecordAnswerFactory({ recordCategories }).create();
|
|
632
|
+
const eventNotification = await new EventNotificationFactory({
|
|
633
|
+
organization,
|
|
634
|
+
events: [event],
|
|
635
|
+
status: EventNotificationStatus.Pending,
|
|
636
|
+
typeId: notificationType.id,
|
|
637
|
+
recordAnswers: acceptedRecordAnswers,
|
|
638
|
+
submittedBy: user,
|
|
639
|
+
}).create();
|
|
640
|
+
|
|
641
|
+
const body: Body = new PatchableArray();
|
|
642
|
+
body.addPatch(
|
|
643
|
+
EventNotificationStruct.patch({
|
|
644
|
+
id: eventNotification.id,
|
|
645
|
+
status: EventNotificationStatus.Accepted,
|
|
646
|
+
}),
|
|
647
|
+
);
|
|
648
|
+
|
|
649
|
+
const result = await TestRequest.patch({ body, user: admin, organization });
|
|
650
|
+
expect(result.status).toBe(200);
|
|
651
|
+
expect(result.body).toHaveLength(1);
|
|
652
|
+
|
|
653
|
+
expect(result.body[0]).toMatchObject({
|
|
654
|
+
status: EventNotificationStatus.Accepted,
|
|
655
|
+
acceptedRecordAnswers: expect.toMatchMap(acceptedRecordAnswers),
|
|
656
|
+
recordAnswers: expect.toMatchMap(acceptedRecordAnswers),
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
// Check mails
|
|
660
|
+
expect(EmailMocker.transactional.getSucceededEmails()).toIncludeSameMembers([
|
|
661
|
+
expect.objectContaining({
|
|
662
|
+
to: user.email,
|
|
663
|
+
subject: EmailTemplateType.EventNotificationAccepted,
|
|
664
|
+
text: expect.stringContaining(event.name),
|
|
665
|
+
}),
|
|
666
|
+
]);
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
test('An admin can partially accept an event notification and set feedback', async () => {
|
|
670
|
+
const organization = await new OrganizationFactory({}).create();
|
|
671
|
+
const user = await new UserFactory({
|
|
672
|
+
organization,
|
|
673
|
+
permissions: minimumUserPermissions,
|
|
674
|
+
}).create();
|
|
675
|
+
const event = await new EventFactory({ organization }).create();
|
|
676
|
+
|
|
677
|
+
const recordCategories = await new RecordCategoryFactory({
|
|
678
|
+
records: [
|
|
679
|
+
{
|
|
680
|
+
type: RecordType.Checkbox,
|
|
681
|
+
},
|
|
682
|
+
{
|
|
683
|
+
type: RecordType.Text,
|
|
684
|
+
required: true,
|
|
685
|
+
},
|
|
686
|
+
],
|
|
687
|
+
}).createMultiple(2);
|
|
688
|
+
|
|
689
|
+
const notificationType = (await new EventNotificationTypeFactory({ recordCategories }).create());
|
|
690
|
+
const acceptedRecordAnswers = await new RecordAnswerFactory({ recordCategories }).create();
|
|
691
|
+
const eventNotification = await new EventNotificationFactory({
|
|
692
|
+
organization,
|
|
693
|
+
events: [event],
|
|
694
|
+
status: EventNotificationStatus.Pending,
|
|
695
|
+
typeId: notificationType.id,
|
|
696
|
+
recordAnswers: acceptedRecordAnswers,
|
|
697
|
+
submittedBy: user,
|
|
698
|
+
}).create();
|
|
699
|
+
|
|
700
|
+
const body: Body = new PatchableArray();
|
|
701
|
+
body.addPatch(
|
|
702
|
+
EventNotificationStruct.patch({
|
|
703
|
+
id: eventNotification.id,
|
|
704
|
+
status: EventNotificationStatus.PartiallyAccepted,
|
|
705
|
+
feedbackText: 'Some feedback',
|
|
706
|
+
}),
|
|
707
|
+
);
|
|
708
|
+
|
|
709
|
+
const result = await TestRequest.patch({ body, user: admin, organization });
|
|
710
|
+
expect(result.status).toBe(200);
|
|
711
|
+
expect(result.body).toHaveLength(1);
|
|
712
|
+
|
|
713
|
+
expect(result.body[0]).toMatchObject({
|
|
714
|
+
status: EventNotificationStatus.PartiallyAccepted,
|
|
715
|
+
feedbackText: 'Some feedback',
|
|
716
|
+
acceptedRecordAnswers: expect.toMatchMap(acceptedRecordAnswers),
|
|
717
|
+
recordAnswers: expect.toMatchMap(acceptedRecordAnswers),
|
|
718
|
+
});
|
|
719
|
+
|
|
720
|
+
// Check mails
|
|
721
|
+
expect(EmailMocker.transactional.getSucceededEmails()).toIncludeSameMembers([
|
|
722
|
+
expect.objectContaining({
|
|
723
|
+
to: user.email,
|
|
724
|
+
subject: EmailTemplateType.EventNotificationPartiallyAccepted,
|
|
725
|
+
text: expect.stringContaining(event.name),
|
|
726
|
+
html: expect.stringContaining('Some feedback'),
|
|
727
|
+
}),
|
|
728
|
+
]);
|
|
729
|
+
});
|
|
730
|
+
|
|
731
|
+
test('An admin can reject an event notification with feedback', async () => {
|
|
732
|
+
const organization = await new OrganizationFactory({}).create();
|
|
733
|
+
const user = await new UserFactory({
|
|
734
|
+
organization,
|
|
735
|
+
permissions: minimumUserPermissions,
|
|
736
|
+
}).create();
|
|
737
|
+
const event = await new EventFactory({ organization }).create();
|
|
738
|
+
|
|
739
|
+
const recordCategories = await new RecordCategoryFactory({
|
|
740
|
+
records: [
|
|
741
|
+
{
|
|
742
|
+
type: RecordType.Checkbox,
|
|
743
|
+
},
|
|
744
|
+
{
|
|
745
|
+
type: RecordType.Text,
|
|
746
|
+
required: true,
|
|
747
|
+
},
|
|
748
|
+
],
|
|
749
|
+
}).createMultiple(2);
|
|
750
|
+
|
|
751
|
+
const notificationType = (await new EventNotificationTypeFactory({ recordCategories }).create());
|
|
752
|
+
const acceptedRecordAnswers = await new RecordAnswerFactory({ recordCategories }).create();
|
|
753
|
+
const eventNotification = await new EventNotificationFactory({
|
|
754
|
+
organization,
|
|
755
|
+
events: [event],
|
|
756
|
+
status: EventNotificationStatus.Pending,
|
|
757
|
+
typeId: notificationType.id,
|
|
758
|
+
recordAnswers: acceptedRecordAnswers,
|
|
759
|
+
submittedBy: user,
|
|
760
|
+
}).create();
|
|
761
|
+
|
|
762
|
+
const body: Body = new PatchableArray();
|
|
763
|
+
body.addPatch(
|
|
764
|
+
EventNotificationStruct.patch({
|
|
765
|
+
id: eventNotification.id,
|
|
766
|
+
status: EventNotificationStatus.Rejected,
|
|
767
|
+
feedbackText: 'Some feedback',
|
|
768
|
+
}),
|
|
769
|
+
);
|
|
770
|
+
|
|
771
|
+
const result = await TestRequest.patch({ body, user: admin, organization });
|
|
772
|
+
expect(result.status).toBe(200);
|
|
773
|
+
expect(result.body).toHaveLength(1);
|
|
774
|
+
|
|
775
|
+
expect(result.body[0]).toMatchObject({
|
|
776
|
+
status: EventNotificationStatus.Rejected,
|
|
777
|
+
feedbackText: 'Some feedback',
|
|
778
|
+
acceptedRecordAnswers: expect.toMatchMap(new Map()),
|
|
779
|
+
recordAnswers: expect.toMatchMap(acceptedRecordAnswers),
|
|
780
|
+
});
|
|
781
|
+
|
|
782
|
+
// Check mails
|
|
783
|
+
expect(EmailMocker.transactional.getSucceededEmails()).toIncludeSameMembers([
|
|
784
|
+
expect.objectContaining({
|
|
785
|
+
to: user.email,
|
|
786
|
+
subject: EmailTemplateType.EventNotificationRejected,
|
|
787
|
+
text: expect.stringContaining(event.name),
|
|
788
|
+
html: expect.stringContaining('Some feedback'),
|
|
789
|
+
}),
|
|
790
|
+
]);
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
test('An admin can move an event notification back to draft', async () => {
|
|
794
|
+
const organization = await new OrganizationFactory({}).create();
|
|
795
|
+
const user = await new UserFactory({
|
|
796
|
+
organization,
|
|
797
|
+
permissions: minimumUserPermissions,
|
|
798
|
+
}).create();
|
|
799
|
+
const event = await new EventFactory({ organization }).create();
|
|
800
|
+
|
|
801
|
+
const recordCategories = await new RecordCategoryFactory({
|
|
802
|
+
records: [
|
|
803
|
+
{
|
|
804
|
+
type: RecordType.Checkbox,
|
|
805
|
+
},
|
|
806
|
+
{
|
|
807
|
+
type: RecordType.Text,
|
|
808
|
+
required: true,
|
|
809
|
+
},
|
|
810
|
+
],
|
|
811
|
+
}).createMultiple(2);
|
|
812
|
+
|
|
813
|
+
const notificationType = (await new EventNotificationTypeFactory({ recordCategories }).create());
|
|
814
|
+
const acceptedRecordAnswers = await new RecordAnswerFactory({ recordCategories }).create();
|
|
815
|
+
const eventNotification = await new EventNotificationFactory({
|
|
816
|
+
organization,
|
|
817
|
+
events: [event],
|
|
818
|
+
status: EventNotificationStatus.Accepted,
|
|
819
|
+
typeId: notificationType.id,
|
|
820
|
+
recordAnswers: acceptedRecordAnswers,
|
|
821
|
+
submittedBy: user,
|
|
822
|
+
}).create();
|
|
823
|
+
|
|
824
|
+
const body: Body = new PatchableArray();
|
|
825
|
+
body.addPatch(
|
|
826
|
+
EventNotificationStruct.patch({
|
|
827
|
+
id: eventNotification.id,
|
|
828
|
+
status: EventNotificationStatus.Draft,
|
|
829
|
+
}),
|
|
830
|
+
);
|
|
831
|
+
|
|
832
|
+
const result = await TestRequest.patch({ body, user: admin, organization });
|
|
833
|
+
expect(result.status).toBe(200);
|
|
834
|
+
expect(result.body).toHaveLength(1);
|
|
835
|
+
|
|
836
|
+
expect(result.body[0]).toMatchObject({
|
|
837
|
+
status: EventNotificationStatus.Draft,
|
|
838
|
+
acceptedRecordAnswers: expect.toMatchMap(new Map()),
|
|
839
|
+
recordAnswers: expect.toMatchMap(acceptedRecordAnswers),
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
// Check mails
|
|
843
|
+
expect(EmailMocker.transactional.getSucceededEmails()).toIncludeSameMembers([]);
|
|
844
|
+
});
|
|
845
|
+
|
|
846
|
+
test('An admin can edit an accepted event notification', async () => {
|
|
847
|
+
const organization = await new OrganizationFactory({}).create();
|
|
848
|
+
const user = await new UserFactory({
|
|
849
|
+
organization,
|
|
850
|
+
permissions: minimumUserPermissions,
|
|
851
|
+
}).create();
|
|
852
|
+
const event = await new EventFactory({ organization }).create();
|
|
853
|
+
|
|
854
|
+
const recordCategories = await new RecordCategoryFactory({
|
|
855
|
+
records: [
|
|
856
|
+
{
|
|
857
|
+
type: RecordType.Checkbox,
|
|
858
|
+
},
|
|
859
|
+
{
|
|
860
|
+
type: RecordType.Text,
|
|
861
|
+
required: true,
|
|
862
|
+
},
|
|
863
|
+
],
|
|
864
|
+
}).createMultiple(2);
|
|
865
|
+
|
|
866
|
+
const notificationType = (await new EventNotificationTypeFactory({ recordCategories }).create());
|
|
867
|
+
const acceptedRecordAnswers = await new RecordAnswerFactory({ recordCategories }).create();
|
|
868
|
+
const eventNotification = await new EventNotificationFactory({
|
|
869
|
+
organization,
|
|
870
|
+
events: [event],
|
|
871
|
+
status: EventNotificationStatus.Accepted,
|
|
872
|
+
typeId: notificationType.id,
|
|
873
|
+
recordAnswers: acceptedRecordAnswers,
|
|
874
|
+
acceptedRecordAnswers: acceptedRecordAnswers,
|
|
875
|
+
submittedBy: user,
|
|
876
|
+
}).create();
|
|
877
|
+
|
|
878
|
+
const patchedRecordAnswers = await new RecordAnswerFactory({ records: [recordCategories[0].records[0]] }).create();
|
|
879
|
+
const patch = new PatchMap([...patchedRecordAnswers.entries()]);
|
|
880
|
+
|
|
881
|
+
const body: Body = new PatchableArray();
|
|
882
|
+
body.addPatch(
|
|
883
|
+
EventNotificationStruct.patch({
|
|
884
|
+
id: eventNotification.id,
|
|
885
|
+
recordAnswers: patch,
|
|
886
|
+
}),
|
|
887
|
+
);
|
|
888
|
+
|
|
889
|
+
const result = await TestRequest.patch({ body, user: admin, organization });
|
|
890
|
+
expect(result.status).toBe(200);
|
|
891
|
+
expect(result.body).toHaveLength(1);
|
|
892
|
+
|
|
893
|
+
expect(result.body[0]).toMatchObject({
|
|
894
|
+
status: EventNotificationStatus.Accepted,
|
|
895
|
+
|
|
896
|
+
// Note: the record answers should automatically copy over to the accepted record answers
|
|
897
|
+
acceptedRecordAnswers: expect.toMatchMap(
|
|
898
|
+
patchObject(acceptedRecordAnswers, patch),
|
|
899
|
+
),
|
|
900
|
+
recordAnswers: expect.toMatchMap(
|
|
901
|
+
patchObject(acceptedRecordAnswers, patch),
|
|
902
|
+
),
|
|
903
|
+
});
|
|
904
|
+
|
|
905
|
+
// Check mails
|
|
906
|
+
expect(EmailMocker.transactional.getSucceededEmails()).toIncludeSameMembers([]);
|
|
907
|
+
});
|
|
908
|
+
|
|
909
|
+
test('An admin can delete an event notification', async () => {
|
|
910
|
+
const organization = await new OrganizationFactory({}).create();
|
|
911
|
+
const user = await new UserFactory({
|
|
912
|
+
organization,
|
|
913
|
+
permissions: minimumUserPermissions,
|
|
914
|
+
}).create();
|
|
915
|
+
const event = await new EventFactory({ organization }).create();
|
|
916
|
+
|
|
917
|
+
const recordCategories = await new RecordCategoryFactory({
|
|
918
|
+
records: [
|
|
919
|
+
{
|
|
920
|
+
type: RecordType.Checkbox,
|
|
921
|
+
},
|
|
922
|
+
{
|
|
923
|
+
type: RecordType.Text,
|
|
924
|
+
required: true,
|
|
925
|
+
},
|
|
926
|
+
],
|
|
927
|
+
}).createMultiple(2);
|
|
928
|
+
|
|
929
|
+
const notificationType = (await new EventNotificationTypeFactory({ recordCategories }).create());
|
|
930
|
+
const acceptedRecordAnswers = await new RecordAnswerFactory({ recordCategories }).create();
|
|
931
|
+
const eventNotification = await new EventNotificationFactory({
|
|
932
|
+
organization,
|
|
933
|
+
events: [event],
|
|
934
|
+
status: EventNotificationStatus.Accepted,
|
|
935
|
+
typeId: notificationType.id,
|
|
936
|
+
recordAnswers: acceptedRecordAnswers,
|
|
937
|
+
submittedBy: user,
|
|
938
|
+
}).create();
|
|
939
|
+
|
|
940
|
+
const body: Body = new PatchableArray();
|
|
941
|
+
body.addDelete(
|
|
942
|
+
eventNotification.id,
|
|
943
|
+
);
|
|
944
|
+
|
|
945
|
+
const result = await TestRequest.patch({ body, user: admin, organization });
|
|
946
|
+
expect(result.status).toBe(200);
|
|
947
|
+
expect(result.body).toHaveLength(0);
|
|
948
|
+
|
|
949
|
+
// Check mails
|
|
950
|
+
expect(EmailMocker.transactional.getSucceededEmails()).toIncludeSameMembers([]);
|
|
951
|
+
|
|
952
|
+
// Check not exists
|
|
953
|
+
const model = await EventNotification.getByID(eventNotification.id);
|
|
954
|
+
expect(model).toBeUndefined();
|
|
955
|
+
});
|
|
956
|
+
|
|
957
|
+
test('An user cannot delete an event notification', async () => {
|
|
958
|
+
const organization = await new OrganizationFactory({}).create();
|
|
959
|
+
const user = await new UserFactory({
|
|
960
|
+
organization,
|
|
961
|
+
permissions: minimumUserPermissions,
|
|
962
|
+
}).create();
|
|
963
|
+
const event = await new EventFactory({ organization }).create();
|
|
964
|
+
|
|
965
|
+
const recordCategories = await new RecordCategoryFactory({
|
|
966
|
+
records: [
|
|
967
|
+
{
|
|
968
|
+
type: RecordType.Checkbox,
|
|
969
|
+
},
|
|
970
|
+
{
|
|
971
|
+
type: RecordType.Text,
|
|
972
|
+
required: true,
|
|
973
|
+
},
|
|
974
|
+
],
|
|
975
|
+
}).createMultiple(2);
|
|
976
|
+
|
|
977
|
+
const notificationType = (await new EventNotificationTypeFactory({ recordCategories }).create());
|
|
978
|
+
const acceptedRecordAnswers = await new RecordAnswerFactory({ recordCategories }).create();
|
|
979
|
+
const eventNotification = await new EventNotificationFactory({
|
|
980
|
+
organization,
|
|
981
|
+
events: [event],
|
|
982
|
+
status: EventNotificationStatus.Accepted,
|
|
983
|
+
typeId: notificationType.id,
|
|
984
|
+
recordAnswers: acceptedRecordAnswers,
|
|
985
|
+
submittedBy: user,
|
|
986
|
+
}).create();
|
|
987
|
+
|
|
988
|
+
const body: Body = new PatchableArray();
|
|
989
|
+
body.addDelete(
|
|
990
|
+
eventNotification.id,
|
|
991
|
+
);
|
|
992
|
+
|
|
993
|
+
await expect(TestRequest.patch({ body, user, organization })).rejects.toThrow(
|
|
994
|
+
simpleError({ code: 'permission_denied' }),
|
|
995
|
+
);
|
|
996
|
+
});
|
|
997
|
+
});
|