@bopen-io/messagebox-server 1.1.5 → 1.2.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 (113) hide show
  1. package/.dockerignore +11 -0
  2. package/.env.example +11 -0
  3. package/.eslintignore +2 -0
  4. package/.gcloudignore +17 -0
  5. package/.gitattributes +2 -0
  6. package/.github/workflows/build-and-push.yml +51 -0
  7. package/.github/workflows/deploy.yaml.example +64 -0
  8. package/.github/workflows/image.yaml +66 -0
  9. package/.vscode/launch.json +67 -0
  10. package/AGENTS.md +92 -0
  11. package/BASELINE.md +55 -0
  12. package/DEPLOYING.md +120 -0
  13. package/Dockerfile +63 -0
  14. package/docker-compose.yml +64 -0
  15. package/jest.config.integration.ts +26 -0
  16. package/jest.config.mjs +42 -0
  17. package/jest.config.ts +35 -0
  18. package/jest.setup.mjs +18 -0
  19. package/nginx.conf +36 -0
  20. package/package.json +68 -52
  21. package/scripts/build.js +19 -0
  22. package/scripts/mkenv.sh +31 -0
  23. package/scripts/start.sh +16 -0
  24. package/src/__tests/compose.test.ts +30 -0
  25. package/src/app.ts +210 -0
  26. package/src/compose.ts +286 -0
  27. package/src/config/firebase.ts +183 -0
  28. package/src/context.ts +49 -0
  29. package/src/index.ts +375 -0
  30. package/src/routes/__tests/acknowledgeMessage.test.ts +158 -0
  31. package/src/routes/__tests/listMessages.test.ts +240 -0
  32. package/src/routes/__tests/sendMessage.test.ts +362 -0
  33. package/src/routes/acknowledgeMessage.ts +153 -0
  34. package/src/routes/index.ts +17 -0
  35. package/src/routes/listDevices.ts +80 -0
  36. package/src/routes/listMessages.ts +195 -0
  37. package/src/routes/permissions/getPermission.ts +152 -0
  38. package/src/routes/permissions/getQuote.ts +192 -0
  39. package/src/routes/permissions/index.ts +12 -0
  40. package/src/routes/permissions/listPermissions.ts +202 -0
  41. package/src/routes/permissions/setPermission.ts +155 -0
  42. package/src/routes/registerDevice.ts +155 -0
  43. package/src/routes/sendMessage.ts +531 -0
  44. package/src/runtimeDeps.ts +29 -0
  45. package/src/swagger.ts +54 -0
  46. package/src/telemetry.ts +158 -0
  47. package/src/types/messagePermissions.ts +18 -0
  48. package/src/types/mock-knex.d.ts +18 -0
  49. package/src/types/notifications.ts +27 -0
  50. package/src/utils/logger.ts +92 -0
  51. package/src/utils/messagePermissions.ts +148 -0
  52. package/src/utils/sendFCMNotification.ts +143 -0
  53. package/tsconfig.json +36 -0
  54. package/tsconfig.types.json +11 -0
  55. package/out/knexfile.js +0 -25
  56. package/out/knexfile.js.map +0 -1
  57. package/out/src/app.js +0 -160
  58. package/out/src/app.js.map +0 -1
  59. package/out/src/config/firebase.js +0 -150
  60. package/out/src/config/firebase.js.map +0 -1
  61. package/out/src/index.js +0 -295
  62. package/out/src/index.js.map +0 -1
  63. package/out/src/migrations/2022-12-28-001-initial-migration.js +0 -28
  64. package/out/src/migrations/2022-12-28-001-initial-migration.js.map +0 -1
  65. package/out/src/migrations/2023-01-17-messages-update.js +0 -11
  66. package/out/src/migrations/2023-01-17-messages-update.js.map +0 -1
  67. package/out/src/migrations/2024-03-05-001-messageID-upgrade.js +0 -21
  68. package/out/src/migrations/2024-03-05-001-messageID-upgrade.js.map +0 -1
  69. package/out/src/migrations/2025-01-31-001-notification-permissions.js +0 -59
  70. package/out/src/migrations/2025-01-31-001-notification-permissions.js.map +0 -1
  71. package/out/src/migrations/2025-01-31-002-device-registrations.js +0 -24
  72. package/out/src/migrations/2025-01-31-002-device-registrations.js.map +0 -1
  73. package/out/src/routes/__tests/acknowledgeMessage.test.js +0 -129
  74. package/out/src/routes/__tests/acknowledgeMessage.test.js.map +0 -1
  75. package/out/src/routes/__tests/listMessages.test.js +0 -211
  76. package/out/src/routes/__tests/listMessages.test.js.map +0 -1
  77. package/out/src/routes/__tests/sendMessage.test.js +0 -307
  78. package/out/src/routes/__tests/sendMessage.test.js.map +0 -1
  79. package/out/src/routes/acknowledgeMessage.js +0 -144
  80. package/out/src/routes/acknowledgeMessage.js.map +0 -1
  81. package/out/src/routes/index.js +0 -17
  82. package/out/src/routes/index.js.map +0 -1
  83. package/out/src/routes/listDevices.js +0 -74
  84. package/out/src/routes/listDevices.js.map +0 -1
  85. package/out/src/routes/listMessages.js +0 -186
  86. package/out/src/routes/listMessages.js.map +0 -1
  87. package/out/src/routes/permissions/getPermission.js +0 -149
  88. package/out/src/routes/permissions/getPermission.js.map +0 -1
  89. package/out/src/routes/permissions/getQuote.js +0 -165
  90. package/out/src/routes/permissions/getQuote.js.map +0 -1
  91. package/out/src/routes/permissions/index.js +0 -12
  92. package/out/src/routes/permissions/index.js.map +0 -1
  93. package/out/src/routes/permissions/listPermissions.js +0 -190
  94. package/out/src/routes/permissions/listPermissions.js.map +0 -1
  95. package/out/src/routes/permissions/setPermission.js +0 -137
  96. package/out/src/routes/permissions/setPermission.js.map +0 -1
  97. package/out/src/routes/registerDevice.js +0 -150
  98. package/out/src/routes/registerDevice.js.map +0 -1
  99. package/out/src/routes/sendMessage.js +0 -451
  100. package/out/src/routes/sendMessage.js.map +0 -1
  101. package/out/src/swagger.js +0 -49
  102. package/out/src/swagger.js.map +0 -1
  103. package/out/src/types/messagePermissions.js +0 -2
  104. package/out/src/types/messagePermissions.js.map +0 -1
  105. package/out/src/types/notifications.js +0 -2
  106. package/out/src/types/notifications.js.map +0 -1
  107. package/out/src/utils/logger.js +0 -24
  108. package/out/src/utils/logger.js.map +0 -1
  109. package/out/src/utils/messagePermissions.js +0 -126
  110. package/out/src/utils/messagePermissions.js.map +0 -1
  111. package/out/src/utils/sendFCMNotification.js +0 -121
  112. package/out/src/utils/sendFCMNotification.js.map +0 -1
  113. package/out/tsconfig.tsbuildinfo +0 -1
@@ -1,211 +0,0 @@
1
- /* eslint-env jest */
2
- import listMessages from '../listMessages.js';
3
- import mockKnex from 'mock-knex';
4
- // Ensure proper handling of mock-knex
5
- const knex = listMessages.knex;
6
- let queryTracker;
7
- // Define Mock Express Response Object
8
- const mockRes = {
9
- status: jest.fn().mockReturnThis(),
10
- json: jest.fn().mockReturnThis(),
11
- sendStatus: jest.fn().mockReturnThis(),
12
- send: jest.fn().mockReturnThis(),
13
- end: jest.fn().mockReturnThis(),
14
- setHeader: jest.fn().mockReturnThis(),
15
- getHeader: jest.fn(),
16
- getHeaders: jest.fn(),
17
- header: jest.fn().mockReturnThis(),
18
- type: jest.fn().mockReturnThis(),
19
- format: jest.fn(),
20
- location: jest.fn().mockReturnThis(),
21
- redirect: jest.fn().mockReturnThis(),
22
- append: jest.fn().mockReturnThis(),
23
- render: jest.fn(),
24
- vary: jest.fn().mockReturnThis(),
25
- cookie: jest.fn().mockReturnThis(),
26
- clearCookie: jest.fn().mockReturnThis()
27
- };
28
- let validReq;
29
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
30
- let validRes;
31
- let validMessageBoxes;
32
- let validMessages;
33
- let expectedMessages;
34
- describe('listMessages', () => {
35
- beforeAll(() => {
36
- mockKnex.mock(knex);
37
- });
38
- beforeEach(() => {
39
- jest.spyOn(console, 'error').mockImplementation(() => { });
40
- queryTracker = mockKnex.getTracker();
41
- queryTracker.install();
42
- validMessages = [{
43
- sender: '028d37b941208cd6b8a4c28288eda5f2f16c2b3ab0fcb6d13c18b47fe37b971fc1',
44
- messageId: 'msg-1',
45
- body: '{}',
46
- created_at: '2024-01-01',
47
- updated_at: '2024-01-01'
48
- }];
49
- expectedMessages = [{
50
- sender: '028d37b941208cd6b8a4c28288eda5f2f16c2b3ab0fcb6d13c18b47fe37b971fc1',
51
- messageId: 'msg-1',
52
- body: '{}',
53
- createdAt: '2024-01-01',
54
- updatedAt: '2024-01-01'
55
- }];
56
- // Mock Data
57
- validRes = {
58
- status: 'success',
59
- messages: validMessages
60
- };
61
- validMessageBoxes = [
62
- { messageBoxId: 42 },
63
- { messageBoxId: 31 }
64
- ];
65
- // Fully typed mock request
66
- validReq = {
67
- auth: {
68
- identityKey: 'mockIdKey'
69
- },
70
- body: {
71
- messageBox: 'payment_inbox'
72
- },
73
- get: jest.fn(),
74
- header: jest.fn()
75
- };
76
- });
77
- afterEach(() => {
78
- jest.clearAllMocks();
79
- if (queryTracker !== null && queryTracker !== undefined) {
80
- queryTracker.uninstall();
81
- }
82
- });
83
- afterAll(() => {
84
- mockKnex.unmock(knex);
85
- });
86
- it('Throws an error if a messageBox is not provided', async () => {
87
- validReq.body.messageBox = undefined;
88
- queryTracker.on('query', (q) => {
89
- q.response([]);
90
- });
91
- await listMessages.func(validReq, mockRes);
92
- expect(mockRes.status).toHaveBeenCalledWith(400);
93
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
94
- status: 'error',
95
- code: 'ERR_MESSAGEBOX_REQUIRED',
96
- description: 'Please provide the name of a valid MessageBox!'
97
- }));
98
- });
99
- it('Throws an error if messageBox is not a string', async () => {
100
- validReq.body.messageBox = 123;
101
- queryTracker.on('query', (q) => {
102
- q.response([]);
103
- });
104
- await listMessages.func(validReq, mockRes);
105
- expect(mockRes.status).toHaveBeenCalledWith(400);
106
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
107
- status: 'error',
108
- code: 'ERR_INVALID_MESSAGEBOX',
109
- description: 'MessageBox name must be a string!'
110
- }));
111
- });
112
- it('Throws an error if no matching messageBox is found', async () => {
113
- validReq.body.messageBox = 'pay_inbox';
114
- queryTracker.on('query', (q, s) => {
115
- if (s === 1) {
116
- expect(q.method).toEqual('select');
117
- expect(q.sql).toEqual('select `messageBoxId` from `messageBox` where `identityKey` = ? and `type` = ?');
118
- q.response([undefined]);
119
- }
120
- else {
121
- q.response([]);
122
- }
123
- });
124
- await listMessages.func(validReq, mockRes);
125
- expect(mockRes.status).toHaveBeenCalledWith(200);
126
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
127
- status: 'success',
128
- messages: []
129
- }));
130
- });
131
- it('Returns ID of messageBox', async () => {
132
- queryTracker.on('query', (q, s) => {
133
- if (s === 1) {
134
- expect(q.method).toEqual('select');
135
- expect(q.sql).toEqual('select `messageBoxId` from `messageBox` where `identityKey` = ? and `type` = ?');
136
- expect(q.bindings).toEqual([
137
- 'mockIdKey',
138
- 'payment_inbox'
139
- ]);
140
- q.response([validMessageBoxes[0]]);
141
- }
142
- else if (s === 2) {
143
- q.response(validMessages);
144
- }
145
- else {
146
- q.response([]);
147
- }
148
- });
149
- await listMessages.func(validReq, mockRes);
150
- expect(mockRes.status).toHaveBeenCalledWith(200);
151
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
152
- status: 'success',
153
- messages: expectedMessages
154
- }));
155
- });
156
- it('Returns empty array if no messages found', async () => {
157
- queryTracker.on('query', (q, s) => {
158
- if (s === 1) {
159
- q.response([{ messageBoxId: 123 }]);
160
- }
161
- else if (s === 2) {
162
- expect(q.method).toEqual('select');
163
- expect(q.sql).toEqual('select `messageId`, `body`, `sender`, `created_at`, `updated_at` from `messages` where `recipient` = ? and `messageBoxId` = ?');
164
- q.response([]);
165
- }
166
- else {
167
- q.response([]);
168
- }
169
- });
170
- await listMessages.func(validReq, mockRes);
171
- expect(mockRes.status).toHaveBeenCalledWith(200);
172
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
173
- status: 'success',
174
- messages: []
175
- }));
176
- });
177
- it('Returns list of messages found', async () => {
178
- queryTracker.on('query', (q, s) => {
179
- if (s === 1) {
180
- q.response([{ messageBoxId: 123 }]);
181
- }
182
- else if (s === 2) {
183
- expect(q.method).toEqual('select');
184
- expect(q.sql).toEqual('select `messageId`, `body`, `sender`, `created_at`, `updated_at` from `messages` where `recipient` = ? and `messageBoxId` = ?');
185
- q.response(validMessages);
186
- }
187
- else {
188
- q.response([]);
189
- }
190
- });
191
- await listMessages.func(validReq, mockRes);
192
- expect(mockRes.status).toHaveBeenCalledWith(200);
193
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
194
- status: 'success',
195
- messages: expectedMessages
196
- }));
197
- });
198
- it('Throws unknown errors', async () => {
199
- queryTracker.on('query', () => {
200
- throw new Error('Failed');
201
- });
202
- await listMessages.func(validReq, mockRes);
203
- expect(mockRes.status).toHaveBeenCalledWith(500);
204
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
205
- status: 'error',
206
- code: 'ERR_INTERNAL_ERROR',
207
- description: 'An internal error has occurred while listing messages.'
208
- }));
209
- });
210
- });
211
- //# sourceMappingURL=listMessages.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"listMessages.test.js","sourceRoot":"","sources":["../../../../src/routes/__tests/listMessages.test.ts"],"names":[],"mappings":"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"}
@@ -1,307 +0,0 @@
1
- /* eslint-env jest */
2
- import sendMessage, { calculateMessagePrice } from '../sendMessage.js';
3
- import mockKnex from 'mock-knex';
4
- import { Logger } from '../../utils/logger.js';
5
- import axios from 'axios';
6
- import AxiosMockAdapter from 'axios-mock-adapter';
7
- global.fetch = jest.fn();
8
- const knex = sendMessage.knex;
9
- let queryTracker;
10
- let axiosMock;
11
- // Define Mock Express Response Object
12
- const mockRes = {
13
- status: jest.fn().mockReturnThis(),
14
- json: jest.fn().mockReturnThis(),
15
- sendStatus: jest.fn().mockReturnThis(),
16
- send: jest.fn().mockReturnThis(),
17
- end: jest.fn().mockReturnThis(),
18
- setHeader: jest.fn().mockReturnThis(),
19
- getHeader: jest.fn(),
20
- getHeaders: jest.fn(),
21
- header: jest.fn().mockReturnThis(),
22
- type: jest.fn().mockReturnThis(),
23
- format: jest.fn(),
24
- location: jest.fn().mockReturnThis(),
25
- redirect: jest.fn().mockReturnThis(),
26
- append: jest.fn().mockReturnThis(),
27
- render: jest.fn(),
28
- vary: jest.fn().mockReturnThis(),
29
- cookie: jest.fn().mockReturnThis(),
30
- clearCookie: jest.fn().mockReturnThis()
31
- };
32
- let validReq;
33
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
34
- let validRes;
35
- let validMessageBox;
36
- describe('sendMessage', () => {
37
- // Capture original console methods
38
- const originalError = console.error;
39
- const originalLog = console.log;
40
- const originalWarn = console.warn;
41
- beforeAll(() => {
42
- mockKnex.mock(knex);
43
- });
44
- beforeEach(() => {
45
- Logger.enable();
46
- jest.spyOn(console, 'error').mockImplementation((...args) => originalError(...args));
47
- jest.spyOn(console, 'log').mockImplementation((...args) => originalLog(...args));
48
- jest.spyOn(console, 'warn').mockImplementation((...args) => originalWarn(...args));
49
- const instance = axios;
50
- // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
51
- // @ts-ignore
52
- axiosMock = new AxiosMockAdapter(instance);
53
- queryTracker = mockKnex.getTracker();
54
- queryTracker.install();
55
- // Mock Data
56
- validRes = {
57
- status: 'success'
58
- };
59
- validMessageBox = {
60
- messageBoxId: 42,
61
- type: 'payment_inbox'
62
- };
63
- validReq = {
64
- auth: {
65
- identityKey: 'mockIdKey'
66
- },
67
- body: {
68
- message: {
69
- messageId: 'mock-message-id',
70
- recipient: '028d37b941208cd6b8a4c28288eda5f2f16c2b3ab0fcb6d13c18b47fe37b971fc1',
71
- messageBox: 'payment_inbox',
72
- body: JSON.stringify({})
73
- }
74
- },
75
- get: jest.fn(),
76
- header: jest.fn()
77
- };
78
- });
79
- afterEach(() => {
80
- jest.clearAllMocks();
81
- if (queryTracker !== null && queryTracker !== undefined) {
82
- queryTracker.uninstall();
83
- }
84
- axiosMock?.restore();
85
- });
86
- afterAll(() => {
87
- mockKnex.unmock(knex);
88
- });
89
- it('Throws an error if message is missing', async () => {
90
- validReq.body = {}; // Ensure body exists, but message is missing
91
- await sendMessage.func(validReq, mockRes);
92
- expect(mockRes.status).toHaveBeenCalledWith(400);
93
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
94
- status: 'error',
95
- code: 'ERR_MESSAGE_REQUIRED',
96
- description: 'Please provide a valid message to send!'
97
- }));
98
- });
99
- it('Throws an error if message is not an object', async () => {
100
- validReq.body.message = 'My message to send';
101
- await sendMessage.func(validReq, mockRes);
102
- expect(mockRes.status).toHaveBeenCalledWith(400);
103
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
104
- status: 'error',
105
- code: 'ERR_INVALID_MESSAGEBOX',
106
- description: 'Invalid message box.'
107
- }));
108
- });
109
- it('Throws an error if recipient is missing', async () => {
110
- if (validReq.body.message !== null && validReq.body.message !== undefined) {
111
- validReq.body.message.recipient = undefined;
112
- }
113
- await sendMessage.func(validReq, mockRes);
114
- expect(mockRes.status).toHaveBeenCalledWith(400);
115
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
116
- status: 'error',
117
- code: 'ERR_RECIPIENT_REQUIRED',
118
- description: 'Missing recipient(s). Provide "recipient" or "recipients".'
119
- }));
120
- });
121
- it('Throws an error if recipient is not a string', async () => {
122
- if (validReq.body.message !== null && validReq.body.message !== undefined) {
123
- validReq.body.message.recipient = 123;
124
- }
125
- await sendMessage.func(validReq, mockRes);
126
- expect(mockRes.status).toHaveBeenCalledWith(400);
127
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
128
- status: 'error',
129
- code: 'ERR_INVALID_RECIPIENT_KEY'
130
- }));
131
- });
132
- it('Returns error if messageBox is missing', async () => {
133
- if (validReq.body.message !== null && validReq.body.message !== undefined) {
134
- validReq.body.message.messageBox = undefined;
135
- }
136
- await sendMessage.func(validReq, mockRes);
137
- expect(mockRes.status).toHaveBeenCalledWith(400);
138
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
139
- status: 'error',
140
- code: 'ERR_INVALID_MESSAGEBOX'
141
- }));
142
- });
143
- it('Throws an error if messageBox is not a string', async () => {
144
- if (validReq.body.message !== null && validReq.body.message !== undefined) {
145
- validReq.body.message.messageBox = 123;
146
- }
147
- await sendMessage.func(validReq, mockRes);
148
- expect(mockRes.status).toHaveBeenCalledWith(400);
149
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
150
- status: 'error',
151
- code: 'ERR_INVALID_MESSAGEBOX',
152
- description: 'Invalid message box.'
153
- }));
154
- });
155
- it('Throws an error if the message body is not a string', async () => {
156
- if (validReq.body.message !== null && validReq.body.message !== undefined) {
157
- validReq.body.message.body = 42;
158
- }
159
- await sendMessage.func(validReq, mockRes);
160
- expect(mockRes.status).toHaveBeenCalledWith(400);
161
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
162
- status: 'error',
163
- code: 'ERR_INVALID_MESSAGE_BODY',
164
- description: 'Invalid message body.'
165
- }));
166
- });
167
- it('Returns error if message body is missing', async () => {
168
- if (validReq.body.message !== null && validReq.body.message !== undefined) {
169
- validReq.body.message.body = undefined;
170
- }
171
- await sendMessage.func(validReq, mockRes);
172
- expect(mockRes.status).toHaveBeenCalledWith(400);
173
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
174
- status: 'error',
175
- code: 'ERR_INVALID_MESSAGE_BODY',
176
- description: 'Invalid message body.'
177
- }));
178
- });
179
- it('Returns base price for an empty message', () => {
180
- const price = calculateMessagePrice('');
181
- expect(price).toBe(2); // Base price only
182
- });
183
- it('Calculates price for a small message (below 1KB)', () => {
184
- const price = calculateMessagePrice('Hello, world!');
185
- expect(price).toBe(5); // Base price only
186
- });
187
- it('Calculates price for a 2KB message', () => {
188
- const message = 'a'.repeat(2048); // 2KB
189
- const price = calculateMessagePrice(message);
190
- expect(price).toBe(8); // Base price + 2KB
191
- });
192
- it('Adds priority fee when enabled', () => {
193
- const price = calculateMessagePrice('Hello', true);
194
- expect(price).toBe(5); // Base price
195
- });
196
- it('Handles large messages (5KB)', () => {
197
- const message = 'a'.repeat(5120); // 5KB
198
- const price = calculateMessagePrice(message);
199
- expect(price).toBe(17); // Base price + 5KB
200
- });
201
- it('Handles edge case of exactly 1KB message', () => {
202
- const message = 'a'.repeat(1024); // Exactly 1KB
203
- const price = calculateMessagePrice(message);
204
- expect(price).toBe(5); // Base price + 1KB
205
- });
206
- it('Handles edge case of 1KB + 1 byte message', () => {
207
- const message = 'a'.repeat(1025); // 1KB + 1 byte
208
- const price = calculateMessagePrice(message);
209
- expect(price).toBe(8); // Rounded up to 2KB
210
- });
211
- it('Handles messages larger than 10KB', () => {
212
- const message = 'a'.repeat(10240); // 10KB
213
- const price = calculateMessagePrice(message);
214
- expect(price).toBe(32); // Base price + 10KB
215
- });
216
- it('Returns error if messageId is missing', async () => {
217
- if (validReq.body.message !== undefined && validReq.body.message !== null) {
218
- validReq.body.message.messageId = undefined;
219
- }
220
- await sendMessage.func(validReq, mockRes);
221
- expect(mockRes.status).toHaveBeenCalledWith(400);
222
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
223
- status: 'error',
224
- code: 'ERR_MESSAGEID_REQUIRED',
225
- description: 'Missing messageId.'
226
- }));
227
- });
228
- it('Creates a messageBox when it does not exist', async () => {
229
- queryTracker.on('query', (q, step) => {
230
- if (step === 1) {
231
- q.response(0); // Simulate that the messageBox does not exist
232
- }
233
- else if (step === 2) {
234
- q.response([validMessageBox]); // Simulate messageBox being inserted
235
- }
236
- else if (step === 3) {
237
- q.response([validMessageBox]); // Simulate finding a valid messageBoxId
238
- }
239
- else {
240
- q.response([]); // Default response
241
- }
242
- });
243
- await sendMessage.func(validReq, mockRes);
244
- expect(mockRes.status).toHaveBeenCalledWith(200);
245
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
246
- status: 'success'
247
- }));
248
- });
249
- it('Silently ignores duplicate messages via onConflict().ignore()', async () => {
250
- queryTracker.on('query', (q, step) => {
251
- if (step === 1) {
252
- q.response({ messageBoxId: 42, type: 'payment_inbox' }); // messageBox exists
253
- }
254
- else if (step === 2) {
255
- q.response({ messageBoxId: 42 }); // get messageBoxId for insert
256
- }
257
- else if (step === 3) {
258
- q.response(0); // insert with onConflict().ignore() returns 0 rows affected
259
- }
260
- else {
261
- q.response([]);
262
- }
263
- });
264
- await sendMessage.func(validReq, mockRes);
265
- expect(mockRes.status).toHaveBeenCalledWith(200);
266
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
267
- status: 'success'
268
- }));
269
- });
270
- it('Returns internal error if unexpected error occurs', async () => {
271
- jest.spyOn(console, 'error').mockImplementation(() => { });
272
- jest.spyOn(console, 'log').mockImplementation(() => { });
273
- queryTracker.on('query', () => {
274
- throw new Error('Unexpected failure'); // Simulating an unexpected database failure
275
- });
276
- await sendMessage.func(validReq, mockRes);
277
- // Ensure the response status is set
278
- expect(mockRes.status).toHaveBeenCalledTimes(1);
279
- expect(mockRes.status).toHaveBeenCalledWith(500);
280
- // Ensure the response body is set
281
- expect(mockRes.json).toHaveBeenCalledTimes(1);
282
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
283
- status: 'error',
284
- code: 'ERR_INTERNAL'
285
- }));
286
- });
287
- it('creates a new messageBox when one does not exist for recipient', async () => {
288
- queryTracker.on('query', (q, step) => {
289
- if (step === 1)
290
- q.response(undefined); // messageBox not found
291
- else if (step === 2)
292
- q.response(1); // messageBox insert
293
- else if (step === 3)
294
- q.response({ messageBoxId: 42 }); // get messageBoxId for message insert
295
- else if (step === 4)
296
- q.response(1); // insert message
297
- else
298
- q.response([]);
299
- });
300
- await sendMessage.func(validReq, mockRes);
301
- expect(mockRes.status).toHaveBeenCalledWith(200);
302
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
303
- status: 'success'
304
- }));
305
- });
306
- });
307
- //# sourceMappingURL=sendMessage.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sendMessage.test.js","sourceRoot":"","sources":["../../../../src/routes/__tests/sendMessage.test.ts"],"names":[],"mappings":"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"}