@stamhoofd/backend 2.83.5 → 2.84.1

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.
Files changed (100) hide show
  1. package/index.ts +19 -4
  2. package/package.json +18 -14
  3. package/src/crons/amazon-ses.ts +26 -5
  4. package/src/crons/balance-emails.ts +18 -17
  5. package/src/email-recipient-loaders/registrations.ts +87 -0
  6. package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +5 -2
  7. package/src/endpoints/global/email/PatchEmailEndpoint.test.ts +40 -40
  8. package/src/endpoints/global/events/PatchEventNotificationsEndpoint.test.ts +28 -22
  9. package/src/endpoints/global/events/PatchEventsEndpoint.ts +81 -49
  10. package/src/endpoints/global/files/UploadFile.ts +11 -16
  11. package/src/endpoints/global/groups/GetGroupsEndpoint.test.ts +234 -0
  12. package/src/endpoints/global/groups/GetGroupsEndpoint.ts +117 -43
  13. package/src/endpoints/global/members/GetMembersEndpoint.test.ts +1054 -0
  14. package/src/endpoints/global/members/GetMembersEndpoint.ts +163 -141
  15. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.test.ts +6 -6
  16. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +0 -16
  17. package/src/endpoints/global/members/helpers/validateGroupFilter.ts +73 -0
  18. package/src/endpoints/global/registration/GetPaymentRegistrations.ts +1 -2
  19. package/src/endpoints/global/registration/GetRegistrationsCountEndpoint.ts +43 -0
  20. package/src/endpoints/global/registration/GetRegistrationsEndpoint.test.ts +1016 -0
  21. package/src/endpoints/global/registration/GetRegistrationsEndpoint.ts +234 -0
  22. package/src/endpoints/global/registration/PatchUserMembersEndpoint.test.ts +5 -5
  23. package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +474 -554
  24. package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +191 -52
  25. package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +107 -9
  26. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.test.ts +89 -0
  27. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +9 -6
  28. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.test.ts +88 -0
  29. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +0 -6
  30. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +10 -6
  31. package/src/endpoints/organization/dashboard/payments/GetMemberBalanceEndpoint.ts +10 -25
  32. package/src/endpoints/organization/dashboard/payments/PatchBalanceItemsEndpoint.ts +0 -5
  33. package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +0 -5
  34. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalanceEndpoint.ts +4 -0
  35. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesEndpoint.ts +1 -0
  36. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.test.ts +44 -19
  37. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +140 -25
  38. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +40 -10
  39. package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.test.ts +2 -2
  40. package/src/endpoints/organization/dashboard/users/PatchApiUserEndpoint.test.ts +2 -2
  41. package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +4 -1
  42. package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +2 -2
  43. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +2 -2
  44. package/src/excel-loaders/members.ts +233 -232
  45. package/src/excel-loaders/payments.ts +1 -1
  46. package/src/excel-loaders/receivable-balances.ts +1 -1
  47. package/src/excel-loaders/registrations.ts +153 -0
  48. package/src/helpers/AdminPermissionChecker.ts +65 -37
  49. package/src/helpers/AuthenticatedStructures.ts +43 -3
  50. package/src/helpers/Context.ts +29 -1
  51. package/src/helpers/GlobalHelper.ts +3 -1
  52. package/src/helpers/GroupedThrottledQueue.test.ts +219 -0
  53. package/src/helpers/GroupedThrottledQueue.ts +108 -0
  54. package/src/helpers/LimitedFilteredRequestHelper.ts +26 -1
  55. package/src/helpers/MemberCharger.ts +0 -5
  56. package/src/helpers/MembershipCharger.ts +3 -9
  57. package/src/helpers/OrganizationCharger.ts +0 -5
  58. package/src/helpers/ThrottledQueue.test.ts +194 -0
  59. package/src/helpers/ThrottledQueue.ts +145 -0
  60. package/src/helpers/XlsxTransformerColumnHelper.ts +44 -1
  61. package/src/middleware/ContextMiddleware.ts +1 -1
  62. package/src/seeds/1728928974-update-cached-outstanding-balance-from-items.ts +2 -1
  63. package/src/seeds/1735577912-update-cached-outstanding-balance-from-items.ts +2 -1
  64. package/src/services/BalanceItemPaymentService.ts +1 -33
  65. package/src/services/BalanceItemService.ts +167 -48
  66. package/src/services/FileSignService.ts +18 -13
  67. package/src/services/MemberRecordStore.ts +28 -19
  68. package/src/services/PaymentReallocationService.test.ts +25 -14
  69. package/src/services/PaymentReallocationService.ts +29 -10
  70. package/src/services/PaymentService.ts +4 -16
  71. package/src/services/PlatformMembershipService.ts +8 -4
  72. package/src/services/RegistrationService.ts +66 -2
  73. package/src/sql-filters/base-registration-filter-compilers.ts +43 -0
  74. package/src/sql-filters/groups.ts +67 -0
  75. package/src/sql-filters/members.ts +33 -58
  76. package/src/sql-filters/organization-registration-periods.ts +8 -0
  77. package/src/sql-filters/registration-periods.ts +8 -0
  78. package/src/sql-filters/registrations.ts +11 -22
  79. package/src/sql-sorters/groups.ts +24 -0
  80. package/src/sql-sorters/organization-registration-periods.ts +24 -0
  81. package/src/sql-sorters/registration-periods.ts +47 -0
  82. package/src/sql-sorters/registrations.ts +77 -0
  83. package/tests/actions/patchOrganizationMember.ts +27 -0
  84. package/tests/actions/patchPaymentStatus.ts +45 -0
  85. package/tests/actions/patchUserMember.ts +27 -0
  86. package/tests/assertions/assertBalances.ts +49 -0
  87. package/tests/e2e/api-rate-limits.test.ts +5 -5
  88. package/tests/e2e/bundle-discounts.test.ts +4060 -0
  89. package/tests/e2e/charge-members.test.ts +27 -24
  90. package/tests/e2e/documents.test.ts +398 -0
  91. package/tests/e2e/register.test.ts +292 -312
  92. package/tests/helpers/PayconiqMocker.ts +55 -0
  93. package/tests/init/index.ts +5 -0
  94. package/tests/init/initAdmin.ts +14 -0
  95. package/tests/init/initBundleDiscount.ts +47 -0
  96. package/tests/init/initPayconiq.ts +9 -0
  97. package/tests/init/initPlatformAdmin.ts +13 -0
  98. package/tests/init/initStripe.ts +21 -0
  99. package/tests/jest.setup.ts +29 -0
  100. package/src/seeds-temporary/1736266448-recall-balance-item-price-paid.ts +0 -70
package/index.ts CHANGED
@@ -16,10 +16,13 @@ import { GlobalHelper } from './src/helpers/GlobalHelper';
16
16
  import { SetupStepUpdater } from './src/helpers/SetupStepUpdater';
17
17
  import { ContextMiddleware } from './src/middleware/ContextMiddleware';
18
18
  import { AuditLogService } from './src/services/AuditLogService';
19
+ import { BalanceItemService } from './src/services/BalanceItemService';
19
20
  import { DocumentService } from './src/services/DocumentService';
20
21
  import { FileSignService } from './src/services/FileSignService';
21
22
  import { PlatformMembershipService } from './src/services/PlatformMembershipService';
22
23
  import { UniqueUserService } from './src/services/UniqueUserService';
24
+ import { QueueHandler } from '@stamhoofd/queues';
25
+ import { SimpleError } from '@simonbackx/simple-errors';
23
26
 
24
27
  process.on('unhandledRejection', (error: Error) => {
25
28
  console.error('unhandledRejection');
@@ -115,8 +118,10 @@ const start = async () => {
115
118
 
116
119
  // Register Email Recipient loaders
117
120
  await import('./src/email-recipient-loaders/members');
121
+ await import('./src/email-recipient-loaders/registrations');
118
122
  await import('./src/email-recipient-loaders/orders');
119
123
  await import('./src/email-recipient-loaders/receivable-balances');
124
+ await import('./src/excel-loaders/registrations');
120
125
 
121
126
  console.log('Opening port...');
122
127
  routerServer.listen(STAMHOOFD.PORT ?? 9090);
@@ -163,12 +168,21 @@ const start = async () => {
163
168
  console.error(err);
164
169
  }
165
170
 
171
+ await BalanceItemService.flushAll();
166
172
  await waitForCrons();
173
+ QueueHandler.abortAll(
174
+ new SimpleError({
175
+ code: 'SHUTDOWN',
176
+ message: 'Shutting down',
177
+ statusCode: 503,
178
+ }),
179
+ );
180
+ await QueueHandler.awaitAll();
167
181
 
168
182
  try {
169
183
  while (Email.currentQueue.length > 0) {
170
- console.log('Emails still in queue. Waiting 2 seconds...');
171
- await sleep(2000);
184
+ console.log(`${Email.currentQueue.length} emails still in queue. Waiting 500ms...`);
185
+ await sleep(500);
172
186
  }
173
187
  }
174
188
  catch (err) {
@@ -207,13 +221,14 @@ const start = async () => {
207
221
 
208
222
  // Register crons
209
223
  await import('./src/crons');
210
- startCrons();
211
- seeds().catch(console.error);
212
224
 
213
225
  AuditLogService.listen();
214
226
  PlatformMembershipService.listen();
215
227
  DocumentService.listen();
216
228
  SetupStepUpdater.listen();
229
+
230
+ startCrons();
231
+ seeds().catch(console.error);
217
232
  };
218
233
 
219
234
  start().catch((error) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stamhoofd/backend",
3
- "version": "2.83.5",
3
+ "version": "2.84.1",
4
4
  "main": "./dist/index.js",
5
5
  "exports": {
6
6
  ".": {
@@ -32,22 +32,26 @@
32
32
  "sinon": "^18.0.0"
33
33
  },
34
34
  "dependencies": {
35
+ "@aws-sdk/client-s3": "3.823.0",
36
+ "@aws-sdk/client-ses": "3.823.0",
37
+ "@aws-sdk/client-sesv2": "3.823.0",
38
+ "@aws-sdk/client-sqs": "3.823.0",
39
+ "@aws-sdk/s3-request-presigner": "3.823.0",
35
40
  "@bwip-js/node": "^4.5.1",
36
41
  "@mollie/api-client": "3.7.0",
37
- "@simonbackx/simple-database": "1.29.1",
42
+ "@simonbackx/simple-database": "1.32.0",
38
43
  "@simonbackx/simple-encoding": "2.22.0",
39
- "@simonbackx/simple-endpoints": "1.19.1",
44
+ "@simonbackx/simple-endpoints": "1.20.1",
40
45
  "@simonbackx/simple-logging": "^1.0.1",
41
- "@stamhoofd/backend-i18n": "2.83.5",
42
- "@stamhoofd/backend-middleware": "2.83.5",
43
- "@stamhoofd/email": "2.83.5",
44
- "@stamhoofd/models": "2.83.5",
45
- "@stamhoofd/queues": "2.83.5",
46
- "@stamhoofd/sql": "2.83.5",
47
- "@stamhoofd/structures": "2.83.5",
48
- "@stamhoofd/utility": "2.83.5",
46
+ "@stamhoofd/backend-i18n": "2.84.1",
47
+ "@stamhoofd/backend-middleware": "2.84.1",
48
+ "@stamhoofd/email": "2.84.1",
49
+ "@stamhoofd/models": "2.84.1",
50
+ "@stamhoofd/queues": "2.84.1",
51
+ "@stamhoofd/sql": "2.84.1",
52
+ "@stamhoofd/structures": "2.84.1",
53
+ "@stamhoofd/utility": "2.84.1",
49
54
  "archiver": "^7.0.1",
50
- "aws-sdk": "^2.885.0",
51
55
  "axios": "1.6.8",
52
56
  "cookie": "^0.5.0",
53
57
  "formidable": "3.5.1",
@@ -56,7 +60,7 @@
56
60
  "luxon": "3.4.4",
57
61
  "mailparser": "3.7.0",
58
62
  "mockdate": "^3.0.2",
59
- "mysql": "^2.18.1",
63
+ "mysql2": "^3.14.1",
60
64
  "node-rsa": "1.1.1",
61
65
  "openid-client": "^5.4.0",
62
66
  "postmark": "^4.0.5",
@@ -65,5 +69,5 @@
65
69
  "publishConfig": {
66
70
  "access": "public"
67
71
  },
68
- "gitHead": "6ba039bba88e801583188774a254c61e5ab28922"
72
+ "gitHead": "59df29b75109b599d5b90af17b0f69a3089b9d7e"
69
73
  }
@@ -1,9 +1,13 @@
1
1
  /* eslint-disable @typescript-eslint/no-unsafe-argument */
2
+ import {
3
+ DeleteMessageCommand,
4
+ ReceiveMessageCommand,
5
+ SQSClient,
6
+ } from '@aws-sdk/client-sqs';
2
7
  import { registerCron } from '@stamhoofd/crons';
3
8
  import { Email, EmailAddress } from '@stamhoofd/email';
4
9
  import { AuditLog, Organization } from '@stamhoofd/models';
5
10
  import { AuditLogReplacement, AuditLogReplacementType, AuditLogSource, AuditLogType } from '@stamhoofd/structures';
6
- import AWS from 'aws-sdk';
7
11
  import { ForwardHandler } from '../helpers/ForwardHandler';
8
12
 
9
13
  registerCron('checkComplaints', checkComplaints);
@@ -192,10 +196,25 @@ async function handleForward(message: any) {
192
196
  }
193
197
  }
194
198
 
199
+ let sharedClient: SQSClient | null = null;
200
+ function getClient() {
201
+ if (!sharedClient) {
202
+ sharedClient = new SQSClient({});
203
+ }
204
+ return sharedClient;
205
+ }
206
+
195
207
  async function readFromQueue(queueUrl: string) {
196
208
  console.log('[AWS Queue] Checking ' + queueUrl);
197
- const sqs = new AWS.SQS();
198
- const messages = await sqs.receiveMessage({ QueueUrl: queueUrl, MaxNumberOfMessages: 10 }).promise();
209
+
210
+ const client = getClient();
211
+
212
+ const cmd = new ReceiveMessageCommand({
213
+ MaxNumberOfMessages: 10,
214
+ QueueUrl: queueUrl,
215
+ });
216
+
217
+ const messages = await client.send(cmd);
199
218
  let didProcess = 0;
200
219
  if (messages.Messages) {
201
220
  for (const message of messages.Messages) {
@@ -204,10 +223,12 @@ async function readFromQueue(queueUrl: string) {
204
223
 
205
224
  if (message.ReceiptHandle) {
206
225
  if (STAMHOOFD.environment !== 'development') {
207
- await sqs.deleteMessage({
226
+ const deleteCmd = new DeleteMessageCommand({
208
227
  QueueUrl: queueUrl,
209
228
  ReceiptHandle: message.ReceiptHandle,
210
- }).promise();
229
+ });
230
+
231
+ await client.send(deleteCmd);
211
232
  console.log('[AWS Queue] Deleted from queue');
212
233
  }
213
234
  }
@@ -61,8 +61,13 @@ async function balanceEmails() {
61
61
  systemUser,
62
62
  templateType: EmailTemplateType.UserBalanceIncreaseNotification,
63
63
  filter: {
64
- reminderAmountIncreased: true,
65
- reminderEmailCount: 0,
64
+ $or: [
65
+ // The amount has increased since the last reminder
66
+ { reminderAmountIncreased: true },
67
+
68
+ // Or we didn't send a reminder at all yet (since the last time it was zero)
69
+ { reminderEmailCount: 0 },
70
+ ],
66
71
  },
67
72
  });
68
73
 
@@ -74,8 +79,13 @@ async function balanceEmails() {
74
79
  systemUser,
75
80
  templateType: EmailTemplateType.OrganizationBalanceIncreaseNotification,
76
81
  filter: {
77
- reminderAmountIncreased: true,
78
- reminderEmailCount: 0,
82
+ $or: [
83
+ // The amount has increased since the last reminder
84
+ { reminderAmountIncreased: true },
85
+
86
+ // Or we didn't send a reminder at all yet (since the last time it was zero)
87
+ { reminderEmailCount: 0 },
88
+ ],
79
89
  },
80
90
  subfilter: organization.privateMeta.balanceNotificationSettings.organizationContactsFilter,
81
91
  });
@@ -147,7 +157,10 @@ async function sendTemplate({
147
157
  subfilter?: StamhoofdFilter;
148
158
  }) {
149
159
  // Do not send to persons that already received a similar email before this date
150
- const weekAgo = new Date(new Date().getTime() - 1000 * 60 * 60 * 24 * organization.privateMeta.balanceNotificationSettings.minimumDaysBetween); // 5 instead of 7 so the email received is on another working day
160
+ const weekAgo = new Date(
161
+ new Date().getTime() - 1000 * 60 * 60 * 24 * Math.max(1, organization.privateMeta.balanceNotificationSettings.minimumDaysBetween)
162
+ + 12 * 1000 * 60 * 60, // Add a half day offset so we don't get trapped in small differences in time of sending
163
+ ); // 5 instead of 7 so the email received is on another working day
151
164
 
152
165
  const model = new Email();
153
166
  model.userId = null; // This is a system e-mail
@@ -172,18 +185,6 @@ async function sendTemplate({
172
185
  ],
173
186
  },
174
187
  filter,
175
- /* {
176
- // Do not send if already received any email very recently
177
- $not: {
178
- emails: {
179
- $elemMatch: {
180
- sentAt: {
181
- $gt: weekAgo,
182
- },
183
- },
184
- },
185
- },
186
- }, */
187
188
  ],
188
189
 
189
190
  },
@@ -0,0 +1,87 @@
1
+ import { Email, Member } from '@stamhoofd/models';
2
+ import { SQL } from '@stamhoofd/sql';
3
+ import { EmailRecipient, EmailRecipientFilterType, LimitedFilteredRequest, PaginatedResponse, RegistrationsBlob, mergeFilters } from '@stamhoofd/structures';
4
+ import { GetRegistrationsEndpoint } from '../endpoints/global/registration/GetRegistrationsEndpoint';
5
+ import { memberJoin } from '../sql-filters/registrations';
6
+
7
+ async function getRecipients(result: PaginatedResponse<RegistrationsBlob, LimitedFilteredRequest>, type: 'member' | 'parents' | 'unverified') {
8
+ const recipients: EmailRecipient[] = [];
9
+
10
+ for (const registration of result.results.registrations) {
11
+ const memberRecipients = registration.member.getEmailRecipients([type]);
12
+ recipients.push(...memberRecipients);
13
+ }
14
+ return recipients;
15
+ }
16
+
17
+ Email.recipientLoaders.set(EmailRecipientFilterType.RegistrationMembers, {
18
+ fetch: async (query: LimitedFilteredRequest) => {
19
+ const result = await GetRegistrationsEndpoint.buildData(query);
20
+
21
+ return new PaginatedResponse({
22
+ results: await getRecipients(result, 'member'),
23
+ next: result.next,
24
+ });
25
+ },
26
+
27
+ count: async (query: LimitedFilteredRequest) => {
28
+ query.filter = mergeFilters([query.filter, {
29
+ member: {
30
+ $elemMatch: {
31
+ $and: [
32
+ {
33
+ email: {
34
+ $neq: null,
35
+ },
36
+ },
37
+ {
38
+ email: {
39
+ $neq: '',
40
+ },
41
+ },
42
+ ],
43
+ },
44
+ },
45
+ }]);
46
+ const q = await GetRegistrationsEndpoint.buildQuery(query);
47
+ return await q.count();
48
+ },
49
+ });
50
+
51
+ Email.recipientLoaders.set(EmailRecipientFilterType.RegistrationParents, {
52
+ fetch: async (query: LimitedFilteredRequest) => {
53
+ const result = await GetRegistrationsEndpoint.buildData(query);
54
+
55
+ return new PaginatedResponse({
56
+ results: await getRecipients(result, 'parents'),
57
+ next: result.next,
58
+ });
59
+ },
60
+
61
+ count: async (query: LimitedFilteredRequest) => {
62
+ const q = (await GetRegistrationsEndpoint.buildQuery(query)).join(memberJoin);
63
+
64
+ return await q.sum(
65
+ SQL.jsonLength(SQL.column(Member.table, 'details'), '$.value.parents[*].email'),
66
+ );
67
+ },
68
+ });
69
+
70
+ Email.recipientLoaders.set(EmailRecipientFilterType.RegistrationUnverified, {
71
+ fetch: async (query: LimitedFilteredRequest) => {
72
+ const result = await GetRegistrationsEndpoint.buildData(query);
73
+
74
+ return new PaginatedResponse({
75
+ results: await getRecipients(result, 'unverified'),
76
+ next: result.next,
77
+ });
78
+ },
79
+
80
+ count: async (query: LimitedFilteredRequest) => {
81
+ const q = (await GetRegistrationsEndpoint.buildQuery(query)).join(memberJoin);
82
+
83
+ return await q.sum(
84
+ SQL.jsonLength(SQL.column('details'), '$.value.unverifiedEmails'),
85
+ );
86
+ },
87
+ });
@@ -1,7 +1,6 @@
1
1
  import { AutoEncoder, Decoder, field, StringDecoder } from '@simonbackx/simple-encoding';
2
2
  import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
3
- import { City } from '@stamhoofd/models';
4
- import { Province } from '@stamhoofd/models';
3
+ import { City, Province } from '@stamhoofd/models';
5
4
  import { City as CityStruct, Country, Province as ProvinceStruct, SearchRegions } from '@stamhoofd/structures';
6
5
  import { StringCompare } from '@stamhoofd/utility';
7
6
 
@@ -71,6 +70,10 @@ export class SearchRegionsEndpoint extends Endpoint<Params, Query, Body, Respons
71
70
  const cities = await City.where({ name: match }, {
72
71
  limit: 5,
73
72
  sort: [
73
+ {
74
+ column: { name: rawQuery },
75
+ direction: 'DESC',
76
+ },
74
77
  {
75
78
  column: { name: match },
76
79
  direction: 'DESC',
@@ -1,9 +1,9 @@
1
1
  import { Request } from '@simonbackx/simple-endpoints';
2
- import { Email, Organization, OrganizationFactory, RegistrationPeriod, RegistrationPeriodFactory, Token, User, UserFactory } from "@stamhoofd/models";
3
- import { EmailStatus, Email as EmailStruct, PermissionLevel, Permissions, Version } from "@stamhoofd/structures";
4
- import { TestUtils } from "@stamhoofd/test-utils";
5
- import { testServer } from "../../../../tests/helpers/TestServer";
6
- import { PatchEmailEndpoint } from "./PatchEmailEndpoint";
2
+ import { Email, Organization, OrganizationFactory, RegistrationPeriod, RegistrationPeriodFactory, Token, User, UserFactory } from '@stamhoofd/models';
3
+ import { EmailStatus, Email as EmailStruct, PermissionLevel, Permissions, Version } from '@stamhoofd/structures';
4
+ import { TestUtils } from '@stamhoofd/test-utils';
5
+ import { testServer } from '../../../../tests/helpers/TestServer';
6
+ import { PatchEmailEndpoint } from './PatchEmailEndpoint';
7
7
 
8
8
  const baseUrl = `/v${Version}/email`;
9
9
 
@@ -32,7 +32,7 @@ describe('Endpoint.PatchEmailEndpoint', () => {
32
32
  }).create();
33
33
 
34
34
  organization = await new OrganizationFactory({ period })
35
- .create();
35
+ .create();
36
36
 
37
37
  user = await new UserFactory({
38
38
  organization,
@@ -40,7 +40,7 @@ describe('Endpoint.PatchEmailEndpoint', () => {
40
40
  level: PermissionLevel.Read,
41
41
  }),
42
42
  })
43
- .create();
43
+ .create();
44
44
 
45
45
  token = await Token.createToken(user);
46
46
  });
@@ -50,7 +50,7 @@ describe('Endpoint.PatchEmailEndpoint', () => {
50
50
  email.subject = 'test subject';
51
51
  email.status = EmailStatus.Draft;
52
52
  email.text = 'test email {{unsubscribeUrl}}';
53
- email.html = `<!DOCTYPE html>
53
+ email.html = `<!DOCTYPE html>
54
54
  <html>
55
55
 
56
56
  <head>
@@ -66,37 +66,37 @@ describe('Endpoint.PatchEmailEndpoint', () => {
66
66
 
67
67
  </html>`;
68
68
  email.json = {
69
- "content": [
70
- {
71
- "content": [
72
- {
73
- "text": "test email",
74
- "type": "text"
75
- }
76
- ],
77
- "type": "paragraph"
78
- }
69
+ content: [
70
+ {
71
+ content: [
72
+ {
73
+ text: 'test email',
74
+ type: 'text',
75
+ },
76
+ ],
77
+ type: 'paragraph',
78
+ },
79
79
  ],
80
- "type": "doc"
80
+ type: 'doc',
81
81
  };
82
82
  email.userId = user.id;
83
83
  email.organizationId = organization.id;
84
84
 
85
85
  await email.save();
86
86
 
87
- const body = EmailStruct.create({...email, fromAddress:'test@test.be', status: EmailStatus.Sending})
87
+ const body = EmailStruct.create({ ...email, fromAddress: 'test@test.be', status: EmailStatus.Sending });
88
88
 
89
89
  await expect(async () => await patchEmail(body, token, organization))
90
- .rejects
91
- .toThrow('Missing unsubscribe button');
92
- })
90
+ .rejects
91
+ .toThrow('Missing unsubscribe button');
92
+ });
93
93
 
94
94
  test('Should throw error if no unsubscribe button in email text', async () => {
95
95
  const email = new Email();
96
96
  email.subject = 'test subject';
97
97
  email.status = EmailStatus.Draft;
98
98
  email.text = 'test email';
99
- email.html = `<!DOCTYPE html>
99
+ email.html = `<!DOCTYPE html>
100
100
  <html>
101
101
 
102
102
  <head>
@@ -112,28 +112,28 @@ describe('Endpoint.PatchEmailEndpoint', () => {
112
112
 
113
113
  </html>`;
114
114
  email.json = {
115
- "content": [
116
- {
117
- "content": [
118
- {
119
- "text": "test email",
120
- "type": "text"
121
- }
122
- ],
123
- "type": "paragraph"
124
- }
115
+ content: [
116
+ {
117
+ content: [
118
+ {
119
+ text: 'test email',
120
+ type: 'text',
121
+ },
122
+ ],
123
+ type: 'paragraph',
124
+ },
125
125
  ],
126
- "type": "doc"
126
+ type: 'doc',
127
127
  };
128
128
  email.userId = user.id;
129
129
  email.organizationId = organization.id;
130
130
 
131
131
  await email.save();
132
132
 
133
- const body = EmailStruct.create({...email, fromAddress:'test@test.be', status: EmailStatus.Sending})
133
+ const body = EmailStruct.create({ ...email, fromAddress: 'test@test.be', status: EmailStatus.Sending });
134
134
 
135
135
  await expect(async () => await patchEmail(body, token, organization))
136
- .rejects
137
- .toThrow('Missing unsubscribe button');
138
- })
139
- })
136
+ .rejects
137
+ .toThrow('Missing unsubscribe button');
138
+ });
139
+ });