@marcoappio/marco-config 2.0.530 → 2.0.532
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/dist/types/UserSettings.d.ts +17 -0
- package/dist/types/UserSettings.d.ts.map +1 -0
- package/dist/types/UserSettings.js +29 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/zero/index.d.ts +22 -38
- package/dist/zero/index.d.ts.map +1 -1
- package/dist/zero/mutatorSchemas.d.ts +5 -30
- package/dist/zero/mutatorSchemas.d.ts.map +1 -1
- package/dist/zero/mutatorSchemas.js +3 -6
- package/dist/zero/mutators.d.ts +13 -8
- package/dist/zero/mutators.d.ts.map +1 -1
- package/dist/zero/mutators.js +14 -5
- package/dist/zero/mutators.test.js +508 -243
- package/dist/zero/queries.d.ts +2 -0
- package/dist/zero/queries.d.ts.map +1 -1
- package/dist/zero/schema.d.ts +3 -0
- package/dist/zero/schema.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it, mock } from 'bun:test';
|
|
2
2
|
import * as v from 'valibot';
|
|
3
|
+
import { CustomViewIcon, USER_SETTINGS_CUSTOM_VIEW_ICONS } from '../types';
|
|
3
4
|
import { mutatorSchemas } from './mutatorSchemas';
|
|
4
5
|
import { mutators } from './mutators';
|
|
5
6
|
const createMockTx = () => ({
|
|
@@ -39,26 +40,26 @@ describe('mutators', () => {
|
|
|
39
40
|
describe('createAccount', () => {
|
|
40
41
|
it('creates an account and primary alias', async () => {
|
|
41
42
|
const args = {
|
|
42
|
-
aliasId: 'alias-1',
|
|
43
|
+
aliasId: 'test-alias-id-1',
|
|
43
44
|
color: '#ff0000',
|
|
44
45
|
emailAddress: 'test@example.com',
|
|
45
|
-
id: 'account-1',
|
|
46
|
+
id: 'test-account-id-1',
|
|
46
47
|
};
|
|
47
48
|
await mutators.account.createAccount.fn({ args, ctx, tx: tx });
|
|
48
49
|
expect(tx.mutate.account.insert).toHaveBeenCalledWith({
|
|
49
50
|
color: '#ff0000',
|
|
50
51
|
displayName: null,
|
|
51
|
-
id: 'account-1',
|
|
52
|
+
id: 'test-account-id-1',
|
|
52
53
|
imapConnectionStatus: 'AWAITING_CONNECTION',
|
|
53
54
|
mailProcessedCount: 0,
|
|
54
55
|
mailTotalCount: 0,
|
|
55
|
-
primaryAliasId: 'alias-1',
|
|
56
|
+
primaryAliasId: 'test-alias-id-1',
|
|
56
57
|
userId: 'test-user-id',
|
|
57
58
|
});
|
|
58
59
|
expect(tx.mutate.accountAlias.insert).toHaveBeenCalledWith({
|
|
59
|
-
accountId: 'account-1',
|
|
60
|
+
accountId: 'test-account-id-1',
|
|
60
61
|
emailAddress: 'test@example.com',
|
|
61
|
-
id: 'alias-1',
|
|
62
|
+
id: 'test-alias-id-1',
|
|
62
63
|
isPrimary: true,
|
|
63
64
|
name: null,
|
|
64
65
|
});
|
|
@@ -67,36 +68,36 @@ describe('mutators', () => {
|
|
|
67
68
|
describe('createAlias', () => {
|
|
68
69
|
it('creates a non-primary alias', async () => {
|
|
69
70
|
const args = {
|
|
70
|
-
accountId: 'account-1',
|
|
71
|
+
accountId: 'test-account-id-1',
|
|
71
72
|
alias: {
|
|
72
73
|
emailAddress: 'alias@example.com',
|
|
73
|
-
id: 'alias-2',
|
|
74
|
-
name: '
|
|
74
|
+
id: 'test-alias-id-2',
|
|
75
|
+
name: 'test-alias-name',
|
|
75
76
|
},
|
|
76
77
|
};
|
|
77
78
|
await mutators.account.createAlias.fn({ args, ctx, tx: tx });
|
|
78
79
|
expect(tx.mutate.accountAlias.insert).toHaveBeenCalledWith({
|
|
79
|
-
accountId: 'account-1',
|
|
80
|
+
accountId: 'test-account-id-1',
|
|
80
81
|
emailAddress: 'alias@example.com',
|
|
81
|
-
id: 'alias-2',
|
|
82
|
+
id: 'test-alias-id-2',
|
|
82
83
|
isPrimary: false,
|
|
83
|
-
name: '
|
|
84
|
+
name: 'test-alias-name',
|
|
84
85
|
});
|
|
85
86
|
});
|
|
86
87
|
it('creates an alias with null name', async () => {
|
|
87
88
|
const args = {
|
|
88
|
-
accountId: 'account-1',
|
|
89
|
+
accountId: 'test-account-id-1',
|
|
89
90
|
alias: {
|
|
90
91
|
emailAddress: 'alias@example.com',
|
|
91
|
-
id: 'alias-2',
|
|
92
|
+
id: 'test-alias-id-2',
|
|
92
93
|
name: null,
|
|
93
94
|
},
|
|
94
95
|
};
|
|
95
96
|
await mutators.account.createAlias.fn({ args, ctx, tx: tx });
|
|
96
97
|
expect(tx.mutate.accountAlias.insert).toHaveBeenCalledWith({
|
|
97
|
-
accountId: 'account-1',
|
|
98
|
+
accountId: 'test-account-id-1',
|
|
98
99
|
emailAddress: 'alias@example.com',
|
|
99
|
-
id: 'alias-2',
|
|
100
|
+
id: 'test-alias-id-2',
|
|
100
101
|
isPrimary: false,
|
|
101
102
|
name: null,
|
|
102
103
|
});
|
|
@@ -104,51 +105,60 @@ describe('mutators', () => {
|
|
|
104
105
|
});
|
|
105
106
|
describe('deleteAccount', () => {
|
|
106
107
|
it('deletes an account', async () => {
|
|
107
|
-
const args = { id: 'account-1' };
|
|
108
|
+
const args = { id: 'test-account-id-1' };
|
|
108
109
|
await mutators.account.deleteAccount.fn({ args, ctx, tx: tx });
|
|
109
|
-
expect(tx.mutate.account.delete).toHaveBeenCalledWith({ id: 'account-1' });
|
|
110
|
+
expect(tx.mutate.account.delete).toHaveBeenCalledWith({ id: 'test-account-id-1' });
|
|
110
111
|
});
|
|
111
112
|
});
|
|
112
113
|
describe('deleteAlias', () => {
|
|
113
114
|
it('deletes a non-primary alias', async () => {
|
|
114
115
|
tx.run = mock(() => Promise.resolve({ isPrimary: false }));
|
|
115
|
-
const args = { accountId: 'account-1', aliasId: 'alias-2' };
|
|
116
|
+
const args = { accountId: 'test-account-id-1', aliasId: 'test-alias-id-2' };
|
|
116
117
|
await mutators.account.deleteAlias.fn({ args, ctx, tx: tx });
|
|
117
|
-
expect(tx.mutate.accountAlias.delete).toHaveBeenCalledWith({ id: 'alias-2' });
|
|
118
|
+
expect(tx.mutate.accountAlias.delete).toHaveBeenCalledWith({ id: 'test-alias-id-2' });
|
|
118
119
|
expect(tx.mutate.accountAlias.update).not.toHaveBeenCalled();
|
|
119
120
|
});
|
|
120
121
|
it('promotes another alias when deleting primary', async () => {
|
|
121
122
|
tx.run = mock()
|
|
122
123
|
.mockResolvedValueOnce({ isPrimary: true })
|
|
123
|
-
.mockResolvedValueOnce([{ id: 'alias-3' }]);
|
|
124
|
-
const args = { accountId: 'account-1', aliasId: 'alias-1' };
|
|
124
|
+
.mockResolvedValueOnce([{ id: 'test-alias-id-3' }]);
|
|
125
|
+
const args = { accountId: 'test-account-id-1', aliasId: 'test-alias-id-1' };
|
|
125
126
|
await mutators.account.deleteAlias.fn({ args, ctx, tx: tx });
|
|
126
|
-
expect(tx.mutate.accountAlias.delete).toHaveBeenCalledWith({ id: 'alias-1' });
|
|
127
|
-
expect(tx.mutate.accountAlias.update).toHaveBeenCalledWith({ id: 'alias-3', isPrimary: true });
|
|
128
|
-
expect(tx.mutate.account.update).toHaveBeenCalledWith({
|
|
127
|
+
expect(tx.mutate.accountAlias.delete).toHaveBeenCalledWith({ id: 'test-alias-id-1' });
|
|
128
|
+
expect(tx.mutate.accountAlias.update).toHaveBeenCalledWith({ id: 'test-alias-id-3', isPrimary: true });
|
|
129
|
+
expect(tx.mutate.account.update).toHaveBeenCalledWith({
|
|
130
|
+
id: 'test-account-id-1',
|
|
131
|
+
primaryAliasId: 'test-alias-id-3',
|
|
132
|
+
});
|
|
129
133
|
});
|
|
130
134
|
it('sets primaryAliasId to null when no remaining aliases', async () => {
|
|
131
135
|
tx.run = mock().mockResolvedValueOnce({ isPrimary: true }).mockResolvedValueOnce([]);
|
|
132
|
-
const args = { accountId: 'account-1', aliasId: 'alias-1' };
|
|
136
|
+
const args = { accountId: 'test-account-id-1', aliasId: 'test-alias-id-1' };
|
|
133
137
|
await mutators.account.deleteAlias.fn({ args, ctx, tx: tx });
|
|
134
|
-
expect(tx.mutate.account.update).toHaveBeenCalledWith({ id: 'account-1', primaryAliasId: null });
|
|
138
|
+
expect(tx.mutate.account.update).toHaveBeenCalledWith({ id: 'test-account-id-1', primaryAliasId: null });
|
|
135
139
|
});
|
|
136
140
|
});
|
|
137
141
|
describe('setAliasName', () => {
|
|
138
142
|
it('updates alias name', async () => {
|
|
139
|
-
const args = { accountId: 'account-1', aliasId: 'alias-1', displayName: '
|
|
143
|
+
const args = { accountId: 'test-account-id-1', aliasId: 'test-alias-id-1', displayName: 'test-alias-new-name' };
|
|
140
144
|
await mutators.account.setAliasName.fn({ args, ctx, tx: tx });
|
|
141
|
-
expect(tx.mutate.accountAlias.update).toHaveBeenCalledWith({
|
|
145
|
+
expect(tx.mutate.accountAlias.update).toHaveBeenCalledWith({
|
|
146
|
+
id: 'test-alias-id-1',
|
|
147
|
+
name: 'test-alias-new-name',
|
|
148
|
+
});
|
|
142
149
|
});
|
|
143
150
|
});
|
|
144
151
|
describe('setAliasPrimary', () => {
|
|
145
152
|
it('sets a new primary alias', async () => {
|
|
146
|
-
tx.run = mock(() => Promise.resolve([{ id: 'alias-1' }, { id: 'alias-2' }]));
|
|
147
|
-
const args = { accountId: 'account-1', aliasId: 'alias-2' };
|
|
153
|
+
tx.run = mock(() => Promise.resolve([{ id: 'test-alias-id-1' }, { id: 'test-alias-id-2' }]));
|
|
154
|
+
const args = { accountId: 'test-account-id-1', aliasId: 'test-alias-id-2' };
|
|
148
155
|
await mutators.account.setAliasPrimary.fn({ args, ctx, tx: tx });
|
|
149
|
-
expect(tx.mutate.accountAlias.update).toHaveBeenCalledWith({ id: 'alias-1', isPrimary: false });
|
|
150
|
-
expect(tx.mutate.accountAlias.update).toHaveBeenCalledWith({ id: 'alias-2', isPrimary: true });
|
|
151
|
-
expect(tx.mutate.account.update).toHaveBeenCalledWith({
|
|
156
|
+
expect(tx.mutate.accountAlias.update).toHaveBeenCalledWith({ id: 'test-alias-id-1', isPrimary: false });
|
|
157
|
+
expect(tx.mutate.accountAlias.update).toHaveBeenCalledWith({ id: 'test-alias-id-2', isPrimary: true });
|
|
158
|
+
expect(tx.mutate.account.update).toHaveBeenCalledWith({
|
|
159
|
+
id: 'test-account-id-1',
|
|
160
|
+
primaryAliasId: 'test-alias-id-2',
|
|
161
|
+
});
|
|
152
162
|
});
|
|
153
163
|
});
|
|
154
164
|
describe('setConnectionConfigImapRaw', () => {
|
|
@@ -156,21 +166,21 @@ describe('mutators', () => {
|
|
|
156
166
|
const args = {
|
|
157
167
|
connectionConfig: {
|
|
158
168
|
imapHost: 'imap.example.com',
|
|
159
|
-
imapPassword: '
|
|
169
|
+
imapPassword: 'test-imap-password',
|
|
160
170
|
imapPort: 993,
|
|
161
171
|
imapSocketType: 'SSL',
|
|
162
|
-
imapUser: 'user',
|
|
172
|
+
imapUser: 'test-imap-user',
|
|
163
173
|
smtpHost: 'smtp.example.com',
|
|
164
|
-
smtpPassword: '
|
|
174
|
+
smtpPassword: 'test-smtp-password',
|
|
165
175
|
smtpPort: 465,
|
|
166
176
|
smtpSocketType: 'SSL',
|
|
167
|
-
smtpUser: 'user',
|
|
177
|
+
smtpUser: 'test-smtp-user',
|
|
168
178
|
},
|
|
169
|
-
id: 'account-1',
|
|
179
|
+
id: 'test-account-id-1',
|
|
170
180
|
};
|
|
171
181
|
await mutators.account.setConnectionConfigImapRaw.fn({ args, ctx, tx: tx });
|
|
172
182
|
expect(tx.mutate.account.update).toHaveBeenCalledWith({
|
|
173
|
-
id: 'account-1',
|
|
183
|
+
id: 'test-account-id-1',
|
|
174
184
|
imapConnectionStatus: 'AWAITING_CONNECTION',
|
|
175
185
|
});
|
|
176
186
|
});
|
|
@@ -178,24 +188,24 @@ describe('mutators', () => {
|
|
|
178
188
|
describe('setConnectionConfigOauth', () => {
|
|
179
189
|
it('updates connection status for oauth', async () => {
|
|
180
190
|
const args = {
|
|
181
|
-
connectionConfig: { code: 'auth-code', provider: 'GOOGLE', user: 'user@example.com' },
|
|
182
|
-
id: 'account-1',
|
|
191
|
+
connectionConfig: { code: 'test-auth-code', provider: 'GOOGLE', user: 'test-user@example.com' },
|
|
192
|
+
id: 'test-account-id-1',
|
|
183
193
|
};
|
|
184
194
|
await mutators.account.setConnectionConfigOauth.fn({ args, ctx, tx: tx });
|
|
185
195
|
expect(tx.mutate.account.update).toHaveBeenCalledWith({
|
|
186
|
-
id: 'account-1',
|
|
196
|
+
id: 'test-account-id-1',
|
|
187
197
|
imapConnectionStatus: 'AWAITING_CONNECTION',
|
|
188
198
|
});
|
|
189
199
|
});
|
|
190
200
|
});
|
|
191
201
|
describe('setSettings', () => {
|
|
192
202
|
it('updates account settings', async () => {
|
|
193
|
-
const args = { color: '#00ff00', displayName: '
|
|
203
|
+
const args = { color: '#00ff00', displayName: 'test-account-display-name', id: 'test-account-id-1' };
|
|
194
204
|
await mutators.account.setSettings.fn({ args, ctx, tx: tx });
|
|
195
205
|
expect(tx.mutate.account.update).toHaveBeenCalledWith({
|
|
196
206
|
color: '#00ff00',
|
|
197
|
-
displayName: '
|
|
198
|
-
id: 'account-1',
|
|
207
|
+
displayName: 'test-account-display-name',
|
|
208
|
+
id: 'test-account-id-1',
|
|
199
209
|
});
|
|
200
210
|
});
|
|
201
211
|
});
|
|
@@ -204,10 +214,10 @@ describe('mutators', () => {
|
|
|
204
214
|
describe('cancelSend', () => {
|
|
205
215
|
it('cancels a scheduled send', async () => {
|
|
206
216
|
tx.run = mock(() => Promise.resolve({ status: 'SEND_REQUESTED' }));
|
|
207
|
-
const args = { id: 'draft-1', updatedAt: 1234567890 };
|
|
217
|
+
const args = { id: 'test-draft-id-1', updatedAt: 1234567890 };
|
|
208
218
|
await mutators.draft.cancelSend.fn({ args, ctx, tx: tx });
|
|
209
219
|
expect(tx.mutate.draft.update).toHaveBeenCalledWith({
|
|
210
|
-
id: 'draft-1',
|
|
220
|
+
id: 'test-draft-id-1',
|
|
211
221
|
scheduledFor: null,
|
|
212
222
|
status: 'DRAFT',
|
|
213
223
|
updatedAt: 1234567890,
|
|
@@ -215,13 +225,13 @@ describe('mutators', () => {
|
|
|
215
225
|
});
|
|
216
226
|
it('does nothing if draft not found', async () => {
|
|
217
227
|
tx.run = mock(() => Promise.resolve(null));
|
|
218
|
-
const args = { id: 'draft-1', updatedAt: 1234567890 };
|
|
228
|
+
const args = { id: 'test-draft-id-1', updatedAt: 1234567890 };
|
|
219
229
|
await mutators.draft.cancelSend.fn({ args, ctx, tx: tx });
|
|
220
230
|
expect(tx.mutate.draft.update).not.toHaveBeenCalled();
|
|
221
231
|
});
|
|
222
232
|
it('does nothing if already confirmed', async () => {
|
|
223
233
|
tx.run = mock(() => Promise.resolve({ status: 'SEND_CONFIRMED' }));
|
|
224
|
-
const args = { id: 'draft-1', updatedAt: 1234567890 };
|
|
234
|
+
const args = { id: 'test-draft-id-1', updatedAt: 1234567890 };
|
|
225
235
|
await mutators.draft.cancelSend.fn({ args, ctx, tx: tx });
|
|
226
236
|
expect(tx.mutate.draft.update).not.toHaveBeenCalled();
|
|
227
237
|
});
|
|
@@ -231,25 +241,25 @@ describe('mutators', () => {
|
|
|
231
241
|
const args = {
|
|
232
242
|
attachment: {
|
|
233
243
|
fileName: 'file.pdf',
|
|
234
|
-
id: 'attachment-1',
|
|
244
|
+
id: 'test-attachment-id-1',
|
|
235
245
|
mimeType: 'application/pdf',
|
|
236
246
|
status: 'PENDING',
|
|
237
247
|
totalSize: 1024,
|
|
238
248
|
},
|
|
239
|
-
id: 'draft-1',
|
|
249
|
+
id: 'test-draft-id-1',
|
|
240
250
|
updatedAt: 1234567890,
|
|
241
251
|
};
|
|
242
252
|
await mutators.draft.createAttachment.fn({ args, ctx, tx: tx });
|
|
243
253
|
expect(tx.mutate.draftAttachment.insert).toHaveBeenCalledWith({
|
|
244
|
-
draftId: 'draft-1',
|
|
254
|
+
draftId: 'test-draft-id-1',
|
|
245
255
|
fileName: 'file.pdf',
|
|
246
|
-
id: 'attachment-1',
|
|
256
|
+
id: 'test-attachment-id-1',
|
|
247
257
|
mimeType: 'application/pdf',
|
|
248
258
|
status: 'PENDING',
|
|
249
259
|
totalSize: 1024,
|
|
250
260
|
});
|
|
251
261
|
expect(tx.mutate.draft.update).toHaveBeenCalledWith({
|
|
252
|
-
id: 'draft-1',
|
|
262
|
+
id: 'test-draft-id-1',
|
|
253
263
|
updatedAt: 1234567890,
|
|
254
264
|
});
|
|
255
265
|
});
|
|
@@ -257,21 +267,27 @@ describe('mutators', () => {
|
|
|
257
267
|
describe('createDraft', () => {
|
|
258
268
|
it('creates a draft with attachments', async () => {
|
|
259
269
|
const args = {
|
|
260
|
-
accountId: 'account-1',
|
|
270
|
+
accountId: 'test-account-id-1',
|
|
261
271
|
attachments: [
|
|
262
272
|
{
|
|
263
|
-
fileName: 'file.pdf',
|
|
264
|
-
id: '
|
|
273
|
+
fileName: 'test-file-name.pdf',
|
|
274
|
+
id: 'test-attachment-id-1',
|
|
265
275
|
mimeType: 'application/pdf',
|
|
266
276
|
status: 'COMPLETE',
|
|
267
277
|
totalSize: 1024,
|
|
268
278
|
},
|
|
269
279
|
],
|
|
270
|
-
body: {
|
|
280
|
+
body: {
|
|
281
|
+
bcc: [],
|
|
282
|
+
cc: ['test-email-1@example.com'],
|
|
283
|
+
content: 'test-content',
|
|
284
|
+
subject: 'test-subject',
|
|
285
|
+
to: ['test-email-2@example.com'],
|
|
286
|
+
},
|
|
271
287
|
error: null,
|
|
272
|
-
from: '
|
|
273
|
-
fromName: '
|
|
274
|
-
id: 'draft-1',
|
|
288
|
+
from: 'test-email-3@example.com',
|
|
289
|
+
fromName: 'test-sender-name',
|
|
290
|
+
id: 'test-draft-id-1',
|
|
275
291
|
referencedMessageId: null,
|
|
276
292
|
scheduledFor: null,
|
|
277
293
|
status: 'DRAFT',
|
|
@@ -280,25 +296,30 @@ describe('mutators', () => {
|
|
|
280
296
|
};
|
|
281
297
|
await mutators.draft.createDraft.fn({ args, ctx, tx: tx });
|
|
282
298
|
expect(tx.mutate.draft.insert).toHaveBeenCalledWith({
|
|
283
|
-
accountId: 'account-1',
|
|
284
|
-
body: {
|
|
299
|
+
accountId: 'test-account-id-1',
|
|
300
|
+
body: {
|
|
301
|
+
bcc: [],
|
|
302
|
+
cc: ['test-email-1@example.com'],
|
|
303
|
+
content: 'test-content',
|
|
304
|
+
to: ['test-email-2@example.com'],
|
|
305
|
+
},
|
|
285
306
|
error: null,
|
|
286
307
|
fromAliasId: null,
|
|
287
|
-
fromEmail: '
|
|
288
|
-
fromName: '
|
|
289
|
-
id: 'draft-1',
|
|
308
|
+
fromEmail: 'test-email-3@example.com',
|
|
309
|
+
fromName: 'test-sender-name',
|
|
310
|
+
id: 'test-draft-id-1',
|
|
290
311
|
referencedMessageId: null,
|
|
291
312
|
scheduledFor: null,
|
|
292
313
|
status: 'DRAFT',
|
|
293
|
-
subject: '
|
|
314
|
+
subject: 'test-subject',
|
|
294
315
|
type: 'NEW',
|
|
295
316
|
updatedAt: 1234567890,
|
|
296
317
|
userId: 'test-user-id',
|
|
297
318
|
});
|
|
298
319
|
expect(tx.mutate.draftAttachment.insert).toHaveBeenCalledWith({
|
|
299
|
-
draftId: 'draft-1',
|
|
300
|
-
fileName: 'file.pdf',
|
|
301
|
-
id: '
|
|
320
|
+
draftId: 'test-draft-id-1',
|
|
321
|
+
fileName: 'test-file-name.pdf',
|
|
322
|
+
id: 'test-attachment-id-1',
|
|
302
323
|
mimeType: 'application/pdf',
|
|
303
324
|
status: 'COMPLETE',
|
|
304
325
|
totalSize: 1024,
|
|
@@ -307,35 +328,35 @@ describe('mutators', () => {
|
|
|
307
328
|
});
|
|
308
329
|
describe('deleteAttachment', () => {
|
|
309
330
|
it('deletes an attachment and updates draft', async () => {
|
|
310
|
-
const args = { attachmentId: '
|
|
331
|
+
const args = { attachmentId: 'test-attachment-id-1', id: 'test-draft-id-1', updatedAt: 1234567890 };
|
|
311
332
|
await mutators.draft.deleteAttachment.fn({ args, ctx, tx: tx });
|
|
312
|
-
expect(tx.mutate.draftAttachment.delete).toHaveBeenCalledWith({ id: '
|
|
313
|
-
expect(tx.mutate.draft.update).toHaveBeenCalledWith({ id: 'draft-1', updatedAt: 1234567890 });
|
|
333
|
+
expect(tx.mutate.draftAttachment.delete).toHaveBeenCalledWith({ id: 'test-attachment-id-1' });
|
|
334
|
+
expect(tx.mutate.draft.update).toHaveBeenCalledWith({ id: 'test-draft-id-1', updatedAt: 1234567890 });
|
|
314
335
|
});
|
|
315
336
|
});
|
|
316
337
|
describe('deleteDraft', () => {
|
|
317
338
|
it('deletes a draft', async () => {
|
|
318
|
-
const args = { id: 'draft-1' };
|
|
339
|
+
const args = { id: 'test-draft-id-1' };
|
|
319
340
|
await mutators.draft.deleteDraft.fn({ args, ctx, tx: tx });
|
|
320
|
-
expect(tx.mutate.draft.delete).toHaveBeenCalledWith({ id: 'draft-1' });
|
|
341
|
+
expect(tx.mutate.draft.delete).toHaveBeenCalledWith({ id: 'test-draft-id-1' });
|
|
321
342
|
});
|
|
322
343
|
});
|
|
323
344
|
describe('scheduleSend', () => {
|
|
324
345
|
it('schedules an immediate send with undo delay', async () => {
|
|
325
|
-
const args = { id: 'draft-1', kind: 'IMMEDIATE', undoMs: 5000, updatedAt: 1000000 };
|
|
346
|
+
const args = { id: 'test-draft-id-1', kind: 'IMMEDIATE', undoMs: 5000, updatedAt: 1000000 };
|
|
326
347
|
await mutators.draft.scheduleSend.fn({ args, ctx, tx: tx });
|
|
327
348
|
expect(tx.mutate.draft.update).toHaveBeenCalledWith({
|
|
328
|
-
id: 'draft-1',
|
|
349
|
+
id: 'test-draft-id-1',
|
|
329
350
|
scheduledFor: 1005000,
|
|
330
351
|
status: 'SEND_REQUESTED',
|
|
331
352
|
updatedAt: 1000000,
|
|
332
353
|
});
|
|
333
354
|
});
|
|
334
355
|
it('schedules a future send', async () => {
|
|
335
|
-
const args = { id: 'draft-1', kind: 'SCHEDULED', scheduledFor: 2000000, updatedAt: 1000000 };
|
|
356
|
+
const args = { id: 'test-draft-id-1', kind: 'SCHEDULED', scheduledFor: 2000000, updatedAt: 1000000 };
|
|
336
357
|
await mutators.draft.scheduleSend.fn({ args, ctx, tx: tx });
|
|
337
358
|
expect(tx.mutate.draft.update).toHaveBeenCalledWith({
|
|
338
|
-
id: 'draft-1',
|
|
359
|
+
id: 'test-draft-id-1',
|
|
339
360
|
scheduledFor: 2000000,
|
|
340
361
|
status: 'SEND_REQUESTED',
|
|
341
362
|
updatedAt: 1000000,
|
|
@@ -344,39 +365,49 @@ describe('mutators', () => {
|
|
|
344
365
|
});
|
|
345
366
|
describe('setContent', () => {
|
|
346
367
|
it('applies a content patch', async () => {
|
|
347
|
-
tx.run = mock(() => Promise.resolve({ body: { bcc: [], cc: [], content: '
|
|
368
|
+
tx.run = mock(() => Promise.resolve({ body: { bcc: [], cc: [], content: 'test-content', to: [] } }));
|
|
348
369
|
const args = {
|
|
349
|
-
id: 'draft-1',
|
|
350
|
-
patch: [{ index:
|
|
370
|
+
id: 'test-draft-id-1',
|
|
371
|
+
patch: [{ index: 12, type: 'INSERTION', value: ' test-value' }],
|
|
351
372
|
updatedAt: 1234567890,
|
|
352
373
|
};
|
|
353
374
|
await mutators.draft.setContent.fn({ args, ctx, tx: tx });
|
|
354
375
|
expect(tx.mutate.draft.update).toHaveBeenCalledWith({
|
|
355
|
-
body: { bcc: [], cc: [], content: '
|
|
356
|
-
id: 'draft-1',
|
|
376
|
+
body: { bcc: [], cc: [], content: 'test-content test-value', to: [] },
|
|
377
|
+
id: 'test-draft-id-1',
|
|
357
378
|
updatedAt: 1234567890,
|
|
358
379
|
});
|
|
359
380
|
});
|
|
360
381
|
it('does nothing if draft not found', async () => {
|
|
361
382
|
tx.run = mock(() => Promise.resolve(null));
|
|
362
|
-
const args = { id: 'draft-1', patch: [], updatedAt: 1234567890 };
|
|
383
|
+
const args = { id: 'test-draft-id-1', patch: [], updatedAt: 1234567890 };
|
|
363
384
|
await mutators.draft.setContent.fn({ args, ctx, tx: tx });
|
|
364
385
|
expect(tx.mutate.draft.update).not.toHaveBeenCalled();
|
|
365
386
|
});
|
|
366
387
|
});
|
|
367
388
|
describe('setEnvelope', () => {
|
|
368
389
|
it('updates envelope fields', async () => {
|
|
369
|
-
tx.run = mock(() => Promise.resolve({ body: { content: '
|
|
390
|
+
tx.run = mock(() => Promise.resolve({ body: { content: 'test-content' } }));
|
|
370
391
|
const args = {
|
|
371
|
-
envelope: {
|
|
372
|
-
|
|
392
|
+
envelope: {
|
|
393
|
+
bcc: ['test-email-1@example.com'],
|
|
394
|
+
cc: [],
|
|
395
|
+
subject: 'test-subject',
|
|
396
|
+
to: ['test-email-2@example.com'],
|
|
397
|
+
},
|
|
398
|
+
id: 'test-draft-id-1',
|
|
373
399
|
updatedAt: 1234567890,
|
|
374
400
|
};
|
|
375
401
|
await mutators.draft.setEnvelope.fn({ args, ctx, tx: tx });
|
|
376
402
|
expect(tx.mutate.draft.update).toHaveBeenCalledWith({
|
|
377
|
-
body: {
|
|
378
|
-
|
|
379
|
-
|
|
403
|
+
body: {
|
|
404
|
+
bcc: ['test-email-1@example.com'],
|
|
405
|
+
cc: [],
|
|
406
|
+
content: 'test-content',
|
|
407
|
+
to: ['test-email-2@example.com'],
|
|
408
|
+
},
|
|
409
|
+
id: 'test-draft-id-1',
|
|
410
|
+
subject: 'test-subject',
|
|
380
411
|
updatedAt: 1234567890,
|
|
381
412
|
});
|
|
382
413
|
});
|
|
@@ -384,20 +415,20 @@ describe('mutators', () => {
|
|
|
384
415
|
describe('setFrom', () => {
|
|
385
416
|
it('updates from fields', async () => {
|
|
386
417
|
const args = {
|
|
387
|
-
accountId: 'account-2',
|
|
388
|
-
aliasId: 'alias-2',
|
|
389
|
-
from: '
|
|
390
|
-
fromName: '
|
|
391
|
-
id: 'draft-1',
|
|
418
|
+
accountId: 'test-account-id-2',
|
|
419
|
+
aliasId: 'test-alias-id-2',
|
|
420
|
+
from: 'test-email-3@example.com',
|
|
421
|
+
fromName: 'test-alias-new-name',
|
|
422
|
+
id: 'test-draft-id-1',
|
|
392
423
|
updatedAt: 1234567890,
|
|
393
424
|
};
|
|
394
425
|
await mutators.draft.setFrom.fn({ args, ctx, tx: tx });
|
|
395
426
|
expect(tx.mutate.draft.update).toHaveBeenCalledWith({
|
|
396
|
-
accountId: 'account-2',
|
|
397
|
-
fromAliasId: 'alias-2',
|
|
398
|
-
fromEmail: '
|
|
399
|
-
fromName: '
|
|
400
|
-
id: 'draft-1',
|
|
427
|
+
accountId: 'test-account-id-2',
|
|
428
|
+
fromAliasId: 'test-alias-id-2',
|
|
429
|
+
fromEmail: 'test-email-3@example.com',
|
|
430
|
+
fromName: 'test-alias-new-name',
|
|
431
|
+
id: 'test-draft-id-1',
|
|
401
432
|
updatedAt: 1234567890,
|
|
402
433
|
});
|
|
403
434
|
});
|
|
@@ -407,35 +438,35 @@ describe('mutators', () => {
|
|
|
407
438
|
describe('addLabel', () => {
|
|
408
439
|
it('adds a label to threads', async () => {
|
|
409
440
|
tx.run = mock()
|
|
410
|
-
.mockResolvedValueOnce({ id: 'label-1', uidValidity: 1, unreadCount: 0 })
|
|
441
|
+
.mockResolvedValueOnce({ id: 'test-label-id-1', uidValidity: 1, unreadCount: 0 })
|
|
411
442
|
.mockResolvedValueOnce({
|
|
412
|
-
id: 'thread-1',
|
|
413
|
-
labelIdList: ' label-2 ',
|
|
443
|
+
id: 'test-thread-id-1',
|
|
444
|
+
labelIdList: ' test-label-id-2 ',
|
|
414
445
|
latestMessageDate: 1234567890,
|
|
415
446
|
seen: true,
|
|
416
447
|
})
|
|
417
|
-
.mockResolvedValueOnce([{ id: 'message-1' }])
|
|
448
|
+
.mockResolvedValueOnce([{ id: 'test-message-id-1' }])
|
|
418
449
|
.mockResolvedValueOnce(null);
|
|
419
450
|
const args = {
|
|
420
|
-
accounts: { 'account-1': { threadIds: ['thread-1'] } },
|
|
451
|
+
accounts: { 'test-account-id-1': { threadIds: ['test-thread-id-1'] } },
|
|
421
452
|
labelPath: 'INBOX',
|
|
422
453
|
};
|
|
423
454
|
await mutators.thread.addLabel.fn({ args, ctx, tx: tx });
|
|
424
455
|
expect(tx.mutate.threadByLabel.insert).toHaveBeenCalledWith({
|
|
425
|
-
labelId: 'label-1',
|
|
456
|
+
labelId: 'test-label-id-1',
|
|
426
457
|
latestMessageDate: 1234567890,
|
|
427
|
-
threadId: 'thread-1',
|
|
458
|
+
threadId: 'test-thread-id-1',
|
|
428
459
|
});
|
|
429
460
|
expect(tx.mutate.threadLabel.insert).toHaveBeenCalled();
|
|
430
461
|
expect(tx.mutate.thread.update).toHaveBeenCalledWith({
|
|
431
|
-
id: 'thread-1',
|
|
432
|
-
labelIdList: expect.stringContaining('label-1'),
|
|
462
|
+
id: 'test-thread-id-1',
|
|
463
|
+
labelIdList: expect.stringContaining('test-label-id-1'),
|
|
433
464
|
});
|
|
434
465
|
});
|
|
435
466
|
it('does nothing if label not found', async () => {
|
|
436
467
|
tx.run = mock(() => Promise.resolve(null));
|
|
437
468
|
const args = {
|
|
438
|
-
accounts: { 'account-1': { threadIds: ['thread-1'] } },
|
|
469
|
+
accounts: { 'test-account-id-1': { threadIds: ['test-thread-id-1'] } },
|
|
439
470
|
labelPath: 'NONEXISTENT',
|
|
440
471
|
};
|
|
441
472
|
await mutators.thread.addLabel.fn({ args, ctx, tx: tx });
|
|
@@ -446,50 +477,54 @@ describe('mutators', () => {
|
|
|
446
477
|
describe('delete', () => {
|
|
447
478
|
it('deletes threads and updates unread counts', async () => {
|
|
448
479
|
tx.run = mock()
|
|
449
|
-
.mockResolvedValueOnce({ id: 'thread-1', labelIdList: ' label-1 ', seen: false })
|
|
450
|
-
.mockResolvedValueOnce([{ id: 'label-1', unreadCount: 5 }]);
|
|
451
|
-
const args = { accounts: { 'account-1': { threadIds: ['thread-1'] } } };
|
|
480
|
+
.mockResolvedValueOnce({ id: 'test-thread-id-1', labelIdList: ' test-label-id-1 ', seen: false })
|
|
481
|
+
.mockResolvedValueOnce([{ id: 'test-label-id-1', unreadCount: 5 }]);
|
|
482
|
+
const args = { accounts: { 'test-account-id-1': { threadIds: ['test-thread-id-1'] } } };
|
|
452
483
|
await mutators.thread.delete.fn({ args, ctx, tx: tx });
|
|
453
|
-
expect(tx.mutate.accountLabel.update).toHaveBeenCalledWith({ id: 'label-1', unreadCount: 4 });
|
|
454
|
-
expect(tx.mutate.thread.delete).toHaveBeenCalledWith({ id: 'thread-1' });
|
|
484
|
+
expect(tx.mutate.accountLabel.update).toHaveBeenCalledWith({ id: 'test-label-id-1', unreadCount: 4 });
|
|
485
|
+
expect(tx.mutate.thread.delete).toHaveBeenCalledWith({ id: 'test-thread-id-1' });
|
|
455
486
|
});
|
|
456
487
|
it('skips unread count update for seen threads', async () => {
|
|
457
|
-
tx.run = mock(() => Promise.resolve({ id: 'thread-1', labelIdList: '', seen: true }));
|
|
458
|
-
const args = { accounts: { 'account-1': { threadIds: ['thread-1'] } } };
|
|
488
|
+
tx.run = mock(() => Promise.resolve({ id: 'test-thread-id-1', labelIdList: '', seen: true }));
|
|
489
|
+
const args = { accounts: { 'test-account-id-1': { threadIds: ['test-thread-id-1'] } } };
|
|
459
490
|
await mutators.thread.delete.fn({ args, ctx, tx: tx });
|
|
460
491
|
expect(tx.mutate.accountLabel.update).not.toHaveBeenCalled();
|
|
461
|
-
expect(tx.mutate.thread.delete).toHaveBeenCalledWith({ id: 'thread-1' });
|
|
492
|
+
expect(tx.mutate.thread.delete).toHaveBeenCalledWith({ id: 'test-thread-id-1' });
|
|
462
493
|
});
|
|
463
494
|
});
|
|
464
495
|
describe('removeLabel', () => {
|
|
465
496
|
it('removes a label from threads', async () => {
|
|
466
497
|
tx.run = mock()
|
|
467
|
-
.mockResolvedValueOnce({ id: 'label-1', unreadCount: 5 })
|
|
468
|
-
.mockResolvedValueOnce({
|
|
469
|
-
|
|
498
|
+
.mockResolvedValueOnce({ id: 'test-label-id-1', unreadCount: 5 })
|
|
499
|
+
.mockResolvedValueOnce({
|
|
500
|
+
id: 'test-thread-id-1',
|
|
501
|
+
labelIdList: ' test-label-id-1 test-label-id-2 ',
|
|
502
|
+
seen: false,
|
|
503
|
+
})
|
|
504
|
+
.mockResolvedValueOnce([{ id: 'test-message-id-1' }]);
|
|
470
505
|
const args = {
|
|
471
|
-
accounts: { 'account-1': { threadIds: ['thread-1'] } },
|
|
506
|
+
accounts: { 'test-account-id-1': { threadIds: ['test-thread-id-1'] } },
|
|
472
507
|
labelPath: 'INBOX',
|
|
473
508
|
};
|
|
474
509
|
await mutators.thread.removeLabel.fn({ args, ctx, tx: tx });
|
|
475
510
|
expect(tx.mutate.threadLabel.delete).toHaveBeenCalledWith({
|
|
476
|
-
accountId: 'account-1',
|
|
477
|
-
labelId: 'label-1',
|
|
478
|
-
threadMessageId: 'message-1',
|
|
511
|
+
accountId: 'test-account-id-1',
|
|
512
|
+
labelId: 'test-label-id-1',
|
|
513
|
+
threadMessageId: 'test-message-id-1',
|
|
479
514
|
});
|
|
480
515
|
expect(tx.mutate.threadByLabel.delete).toHaveBeenCalledWith({
|
|
481
|
-
labelId: 'label-1',
|
|
482
|
-
threadId: 'thread-1',
|
|
516
|
+
labelId: 'test-label-id-1',
|
|
517
|
+
threadId: 'test-thread-id-1',
|
|
483
518
|
});
|
|
484
|
-
expect(tx.mutate.accountLabel.update).toHaveBeenCalledWith({ id: 'label-1', unreadCount: 4 });
|
|
519
|
+
expect(tx.mutate.accountLabel.update).toHaveBeenCalledWith({ id: 'test-label-id-1', unreadCount: 4 });
|
|
485
520
|
});
|
|
486
521
|
it('does nothing if thread does not have label', async () => {
|
|
487
522
|
tx.run = mock()
|
|
488
|
-
.mockResolvedValueOnce({ id: 'label-1' })
|
|
489
|
-
.mockResolvedValueOnce({ id: 'thread-1', labelIdList: ' label-2 ' })
|
|
523
|
+
.mockResolvedValueOnce({ id: 'test-label-id-1' })
|
|
524
|
+
.mockResolvedValueOnce({ id: 'test-thread-id-1', labelIdList: ' test-label-id-2 ' })
|
|
490
525
|
.mockResolvedValueOnce([]);
|
|
491
526
|
const args = {
|
|
492
|
-
accounts: { 'account-1': { threadIds: ['thread-1'] } },
|
|
527
|
+
accounts: { 'test-account-id-1': { threadIds: ['test-thread-id-1'] } },
|
|
493
528
|
labelPath: 'INBOX',
|
|
494
529
|
};
|
|
495
530
|
await mutators.thread.removeLabel.fn({ args, ctx, tx: tx });
|
|
@@ -499,34 +534,37 @@ describe('mutators', () => {
|
|
|
499
534
|
});
|
|
500
535
|
describe('setFlagged', () => {
|
|
501
536
|
it('sets flagged status', async () => {
|
|
502
|
-
const args = {
|
|
537
|
+
const args = {
|
|
538
|
+
accounts: { 'test-account-id-1': { threadIds: ['test-thread-id-1', 'test-thread-id-2'] } },
|
|
539
|
+
flagged: true,
|
|
540
|
+
};
|
|
503
541
|
await mutators.thread.setFlagged.fn({ args, ctx, tx: tx });
|
|
504
|
-
expect(tx.mutate.thread.update).toHaveBeenCalledWith({ flagged: true, id: 'thread-1' });
|
|
505
|
-
expect(tx.mutate.thread.update).toHaveBeenCalledWith({ flagged: true, id: 'thread-2' });
|
|
542
|
+
expect(tx.mutate.thread.update).toHaveBeenCalledWith({ flagged: true, id: 'test-thread-id-1' });
|
|
543
|
+
expect(tx.mutate.thread.update).toHaveBeenCalledWith({ flagged: true, id: 'test-thread-id-2' });
|
|
506
544
|
});
|
|
507
545
|
});
|
|
508
546
|
describe('setSeen', () => {
|
|
509
547
|
it('marks threads as seen and updates label counts', async () => {
|
|
510
548
|
tx.run = mock()
|
|
511
|
-
.mockResolvedValueOnce([{ id: 'thread-1', labelIdList: ' label-1 ', seen: false }])
|
|
512
|
-
.mockResolvedValueOnce([{ id: 'label-1', unreadCount: 5 }]);
|
|
513
|
-
const args = { accounts: { 'account-1': { threadIds: ['thread-1'] } }, seen: true };
|
|
549
|
+
.mockResolvedValueOnce([{ id: 'test-thread-id-1', labelIdList: ' test-label-id-1 ', seen: false }])
|
|
550
|
+
.mockResolvedValueOnce([{ id: 'test-label-id-1', unreadCount: 5 }]);
|
|
551
|
+
const args = { accounts: { 'test-account-id-1': { threadIds: ['test-thread-id-1'] } }, seen: true };
|
|
514
552
|
await mutators.thread.setSeen.fn({ args, ctx, tx: tx });
|
|
515
|
-
expect(tx.mutate.accountLabel.update).toHaveBeenCalledWith({ id: 'label-1', unreadCount: 4 });
|
|
516
|
-
expect(tx.mutate.thread.update).toHaveBeenCalledWith({ id: 'thread-1', seen: true });
|
|
553
|
+
expect(tx.mutate.accountLabel.update).toHaveBeenCalledWith({ id: 'test-label-id-1', unreadCount: 4 });
|
|
554
|
+
expect(tx.mutate.thread.update).toHaveBeenCalledWith({ id: 'test-thread-id-1', seen: true });
|
|
517
555
|
});
|
|
518
556
|
it('marks threads as unseen and increments label counts', async () => {
|
|
519
557
|
tx.run = mock()
|
|
520
|
-
.mockResolvedValueOnce([{ id: 'thread-1', labelIdList: ' label-1 ', seen: true }])
|
|
521
|
-
.mockResolvedValueOnce([{ id: 'label-1', unreadCount: 5 }]);
|
|
522
|
-
const args = { accounts: { 'account-1': { threadIds: ['thread-1'] } }, seen: false };
|
|
558
|
+
.mockResolvedValueOnce([{ id: 'test-thread-id-1', labelIdList: ' test-label-id-1 ', seen: true }])
|
|
559
|
+
.mockResolvedValueOnce([{ id: 'test-label-id-1', unreadCount: 5 }]);
|
|
560
|
+
const args = { accounts: { 'test-account-id-1': { threadIds: ['test-thread-id-1'] } }, seen: false };
|
|
523
561
|
await mutators.thread.setSeen.fn({ args, ctx, tx: tx });
|
|
524
|
-
expect(tx.mutate.accountLabel.update).toHaveBeenCalledWith({ id: 'label-1', unreadCount: 6 });
|
|
525
|
-
expect(tx.mutate.thread.update).toHaveBeenCalledWith({ id: 'thread-1', seen: false });
|
|
562
|
+
expect(tx.mutate.accountLabel.update).toHaveBeenCalledWith({ id: 'test-label-id-1', unreadCount: 6 });
|
|
563
|
+
expect(tx.mutate.thread.update).toHaveBeenCalledWith({ id: 'test-thread-id-1', seen: false });
|
|
526
564
|
});
|
|
527
565
|
it('skips label update when thread seen status unchanged', async () => {
|
|
528
|
-
tx.run = mock(() => Promise.resolve([{ id: 'thread-1', labelIdList: ' label-1 ', seen: true }]));
|
|
529
|
-
const args = { accounts: { 'account-1': { threadIds: ['thread-1'] } }, seen: true };
|
|
566
|
+
tx.run = mock(() => Promise.resolve([{ id: 'test-thread-id-1', labelIdList: ' test-label-id-1 ', seen: true }]));
|
|
567
|
+
const args = { accounts: { 'test-account-id-1': { threadIds: ['test-thread-id-1'] } }, seen: true };
|
|
530
568
|
await mutators.thread.setSeen.fn({ args, ctx, tx: tx });
|
|
531
569
|
expect(tx.mutate.accountLabel.update).not.toHaveBeenCalled();
|
|
532
570
|
});
|
|
@@ -542,26 +580,29 @@ describe('mutators', () => {
|
|
|
542
580
|
it(`moves thread to ${specialUse} label`, async () => {
|
|
543
581
|
tx.run = mock()
|
|
544
582
|
.mockResolvedValueOnce({
|
|
545
|
-
accountId: 'account-1',
|
|
546
|
-
id: 'thread-1',
|
|
547
|
-
labelIdList: '
|
|
583
|
+
accountId: 'test-account-id-1',
|
|
584
|
+
id: 'test-thread-id-1',
|
|
585
|
+
labelIdList: ' test-label-id-1 ',
|
|
548
586
|
latestMessageDate: 1234567890,
|
|
549
587
|
seen: true,
|
|
550
588
|
})
|
|
551
|
-
.mockResolvedValueOnce({ id: '
|
|
552
|
-
.mockResolvedValueOnce([{ id: 'message-1' }])
|
|
553
|
-
.mockResolvedValueOnce([{ id: '
|
|
554
|
-
const args = { accounts: { 'account-1': { threadIds: ['thread-1'] } } };
|
|
589
|
+
.mockResolvedValueOnce({ id: 'test-label-id-2', uidValidity: 1 })
|
|
590
|
+
.mockResolvedValueOnce([{ id: 'test-message-id-1' }])
|
|
591
|
+
.mockResolvedValueOnce([{ id: 'test-label-id-1', unreadCount: 0 }]);
|
|
592
|
+
const args = { accounts: { 'test-account-id-1': { threadIds: ['test-thread-id-1'] } } };
|
|
555
593
|
await mutators.thread[mutatorName].fn({ args, ctx, tx: tx });
|
|
556
|
-
expect(tx.mutate.threadByLabel.delete).toHaveBeenCalledWith({
|
|
594
|
+
expect(tx.mutate.threadByLabel.delete).toHaveBeenCalledWith({
|
|
595
|
+
labelId: 'test-label-id-1',
|
|
596
|
+
threadId: 'test-thread-id-1',
|
|
597
|
+
});
|
|
557
598
|
expect(tx.mutate.threadByLabel.insert).toHaveBeenCalledWith({
|
|
558
|
-
labelId: '
|
|
599
|
+
labelId: 'test-label-id-2',
|
|
559
600
|
latestMessageDate: 1234567890,
|
|
560
|
-
threadId: 'thread-1',
|
|
601
|
+
threadId: 'test-thread-id-1',
|
|
561
602
|
});
|
|
562
603
|
expect(tx.mutate.thread.update).toHaveBeenCalledWith({
|
|
563
|
-
id: 'thread-1',
|
|
564
|
-
labelIdList: expect.stringContaining('
|
|
604
|
+
id: 'test-thread-id-1',
|
|
605
|
+
labelIdList: expect.stringContaining('test-label-id-2'),
|
|
565
606
|
});
|
|
566
607
|
});
|
|
567
608
|
});
|
|
@@ -570,38 +611,38 @@ describe('mutators', () => {
|
|
|
570
611
|
describe('user', () => {
|
|
571
612
|
describe('deleteSettingsPushNotificationToken', () => {
|
|
572
613
|
it('deletes a push notification token', async () => {
|
|
573
|
-
const args = { id: 'token-1', token: '
|
|
614
|
+
const args = { id: 'test-token-id-1', token: 'test-token-1' };
|
|
574
615
|
await mutators.user.deleteSettingsPushNotificationToken.fn({ args, ctx, tx: tx });
|
|
575
|
-
expect(tx.mutate.userPushNotificationToken.delete).toHaveBeenCalledWith({ id: 'token-1' });
|
|
616
|
+
expect(tx.mutate.userPushNotificationToken.delete).toHaveBeenCalledWith({ id: 'test-token-id-1' });
|
|
576
617
|
});
|
|
577
618
|
});
|
|
578
619
|
describe('setSettingsName', () => {
|
|
579
620
|
it('updates user name', async () => {
|
|
580
|
-
const args = { id: 'user-1', name: '
|
|
621
|
+
const args = { id: 'test-user-id-1', name: 'test-user-new-name' };
|
|
581
622
|
await mutators.user.setSettingsName.fn({ args, ctx, tx: tx });
|
|
582
|
-
expect(tx.mutate.user.update).toHaveBeenCalledWith({ id: 'user-1', name: '
|
|
623
|
+
expect(tx.mutate.user.update).toHaveBeenCalledWith({ id: 'test-user-id-1', name: 'test-user-new-name' });
|
|
583
624
|
});
|
|
584
625
|
});
|
|
585
626
|
describe('setSettingsPushNotificationToken', () => {
|
|
586
627
|
it('inserts a new push notification token', async () => {
|
|
587
628
|
tx.run = mock(() => Promise.resolve(null));
|
|
588
629
|
const args = {
|
|
589
|
-
id: 'user-1',
|
|
590
|
-
pushNotificationToken: { createdAt: 1234567890, id: 'token-1', token: '
|
|
630
|
+
id: 'test-user-id-1',
|
|
631
|
+
pushNotificationToken: { createdAt: 1234567890, id: 'test-token-id-1', token: 'test-token-1' },
|
|
591
632
|
};
|
|
592
633
|
await mutators.user.setSettingsPushNotificationToken.fn({ args, ctx, tx: tx });
|
|
593
634
|
expect(tx.mutate.userPushNotificationToken.insert).toHaveBeenCalledWith({
|
|
594
635
|
createdAt: 1234567890,
|
|
595
|
-
id: 'token-1',
|
|
596
|
-
token: '
|
|
597
|
-
userId: 'user-1',
|
|
636
|
+
id: 'test-token-id-1',
|
|
637
|
+
token: 'test-token-1',
|
|
638
|
+
userId: 'test-user-id-1',
|
|
598
639
|
});
|
|
599
640
|
});
|
|
600
641
|
it('skips insert if token already exists', async () => {
|
|
601
642
|
tx.run = mock(() => Promise.resolve({ id: 'existing-token' }));
|
|
602
643
|
const args = {
|
|
603
|
-
id: 'user-1',
|
|
604
|
-
pushNotificationToken: { createdAt: 1234567890, id: 'token-1', token: '
|
|
644
|
+
id: 'test-user-id-1',
|
|
645
|
+
pushNotificationToken: { createdAt: 1234567890, id: 'test-token-id-1', token: 'test-token-1' },
|
|
605
646
|
};
|
|
606
647
|
await mutators.user.setSettingsPushNotificationToken.fn({ args, ctx, tx: tx });
|
|
607
648
|
expect(tx.mutate.userPushNotificationToken.insert).not.toHaveBeenCalled();
|
|
@@ -609,78 +650,151 @@ describe('mutators', () => {
|
|
|
609
650
|
});
|
|
610
651
|
describe('createView', () => {
|
|
611
652
|
it('creates a new view', async () => {
|
|
612
|
-
tx.run = mock(() => Promise.resolve({ id: 'user-1', views: [] }));
|
|
653
|
+
tx.run = mock(() => Promise.resolve({ id: 'test-user-id-1', views: [] }));
|
|
613
654
|
const args = {
|
|
614
|
-
id: 'user-1',
|
|
615
|
-
view: {
|
|
655
|
+
id: 'test-user-id-1',
|
|
656
|
+
view: {
|
|
657
|
+
aliasEmails: ['test-email-1@example.com', 'test-email-2@example.com'],
|
|
658
|
+
icon: null,
|
|
659
|
+
id: 'test-view-id-1',
|
|
660
|
+
name: 'test-view-name-1',
|
|
661
|
+
},
|
|
616
662
|
};
|
|
617
663
|
await mutators.user.createView.fn({ args, ctx, tx: tx });
|
|
618
664
|
expect(tx.mutate.user.update).toHaveBeenCalledWith({
|
|
619
|
-
id: 'user-1',
|
|
620
|
-
views: [
|
|
665
|
+
id: 'test-user-id-1',
|
|
666
|
+
views: [
|
|
667
|
+
{
|
|
668
|
+
aliasEmails: ['test-email-1@example.com', 'test-email-2@example.com'],
|
|
669
|
+
icon: null,
|
|
670
|
+
id: 'test-view-id-1',
|
|
671
|
+
name: 'test-view-name-1',
|
|
672
|
+
},
|
|
673
|
+
],
|
|
621
674
|
});
|
|
622
675
|
});
|
|
623
676
|
it('deduplicates aliasEmails', async () => {
|
|
624
|
-
tx.run = mock(() => Promise.resolve({ id: 'user-1', views: [] }));
|
|
677
|
+
tx.run = mock(() => Promise.resolve({ id: 'test-user-id-1', views: [] }));
|
|
678
|
+
const args = {
|
|
679
|
+
id: 'test-user-id-1',
|
|
680
|
+
view: {
|
|
681
|
+
aliasEmails: ['test-email-1@example.com', 'test-email-2@example.com', 'test-email-1@example.com'],
|
|
682
|
+
icon: null,
|
|
683
|
+
id: 'test-view-id-1',
|
|
684
|
+
name: 'test-view-name-1',
|
|
685
|
+
},
|
|
686
|
+
};
|
|
687
|
+
await mutators.user.createView.fn({ args, ctx, tx: tx });
|
|
688
|
+
expect(tx.mutate.user.update).toHaveBeenCalledWith({
|
|
689
|
+
id: 'test-user-id-1',
|
|
690
|
+
views: [
|
|
691
|
+
{
|
|
692
|
+
aliasEmails: ['test-email-1@example.com', 'test-email-2@example.com'],
|
|
693
|
+
icon: null,
|
|
694
|
+
id: 'test-view-id-1',
|
|
695
|
+
name: 'test-view-name-1',
|
|
696
|
+
},
|
|
697
|
+
],
|
|
698
|
+
});
|
|
699
|
+
});
|
|
700
|
+
it('creates a view with an icon', async () => {
|
|
701
|
+
tx.run = mock(() => Promise.resolve({ id: 'test-user-id-1', views: [] }));
|
|
625
702
|
const args = {
|
|
626
|
-
id: 'user-1',
|
|
627
|
-
view: {
|
|
703
|
+
id: 'test-user-id-1',
|
|
704
|
+
view: {
|
|
705
|
+
aliasEmails: ['test-email-1@example.com'],
|
|
706
|
+
icon: CustomViewIcon.STAR,
|
|
707
|
+
id: 'test-view-id-1',
|
|
708
|
+
name: 'test-view-name-1',
|
|
709
|
+
},
|
|
628
710
|
};
|
|
629
711
|
await mutators.user.createView.fn({ args, ctx, tx: tx });
|
|
630
712
|
expect(tx.mutate.user.update).toHaveBeenCalledWith({
|
|
631
|
-
id: 'user-1',
|
|
632
|
-
views: [
|
|
713
|
+
id: 'test-user-id-1',
|
|
714
|
+
views: [
|
|
715
|
+
{
|
|
716
|
+
aliasEmails: ['test-email-1@example.com'],
|
|
717
|
+
icon: CustomViewIcon.STAR,
|
|
718
|
+
id: 'test-view-id-1',
|
|
719
|
+
name: 'test-view-name-1',
|
|
720
|
+
},
|
|
721
|
+
],
|
|
633
722
|
});
|
|
634
723
|
});
|
|
635
724
|
it('appends to existing views', async () => {
|
|
636
725
|
tx.run = mock(() => Promise.resolve({
|
|
637
|
-
id: 'user-1',
|
|
638
|
-
views: [
|
|
726
|
+
id: 'test-user-id-1',
|
|
727
|
+
views: [
|
|
728
|
+
{ aliasEmails: ['test-email-1@example.com'], icon: null, id: 'test-view-id-1', name: 'test-view-name-1' },
|
|
729
|
+
],
|
|
639
730
|
}));
|
|
640
731
|
const args = {
|
|
641
|
-
id: 'user-1',
|
|
642
|
-
view: {
|
|
732
|
+
id: 'test-user-id-1',
|
|
733
|
+
view: {
|
|
734
|
+
aliasEmails: ['test-email-2@example.com'],
|
|
735
|
+
icon: null,
|
|
736
|
+
id: 'test-view-id-2',
|
|
737
|
+
name: 'test-view-name-2',
|
|
738
|
+
},
|
|
643
739
|
};
|
|
644
740
|
await mutators.user.createView.fn({ args, ctx, tx: tx });
|
|
645
741
|
expect(tx.mutate.user.update).toHaveBeenCalledWith({
|
|
646
|
-
id: 'user-1',
|
|
742
|
+
id: 'test-user-id-1',
|
|
647
743
|
views: [
|
|
648
|
-
{ aliasEmails: ['
|
|
649
|
-
{ aliasEmails: ['
|
|
744
|
+
{ aliasEmails: ['test-email-1@example.com'], icon: null, id: 'test-view-id-1', name: 'test-view-name-1' },
|
|
745
|
+
{ aliasEmails: ['test-email-2@example.com'], icon: null, id: 'test-view-id-2', name: 'test-view-name-2' },
|
|
650
746
|
],
|
|
651
747
|
});
|
|
652
748
|
});
|
|
653
749
|
it('does nothing if user not found', async () => {
|
|
654
750
|
tx.run = mock(() => Promise.resolve(null));
|
|
655
751
|
const args = {
|
|
656
|
-
id: 'user-1',
|
|
657
|
-
view: {
|
|
752
|
+
id: 'test-user-id-1',
|
|
753
|
+
view: {
|
|
754
|
+
aliasEmails: ['test-email-1@example.com'],
|
|
755
|
+
icon: null,
|
|
756
|
+
id: 'test-view-id-1',
|
|
757
|
+
name: 'test-view-name-1',
|
|
758
|
+
},
|
|
658
759
|
};
|
|
659
760
|
await mutators.user.createView.fn({ args, ctx, tx: tx });
|
|
660
761
|
expect(tx.mutate.user.update).not.toHaveBeenCalled();
|
|
661
762
|
});
|
|
662
763
|
it('does nothing if view with same id already exists', async () => {
|
|
663
764
|
tx.run = mock(() => Promise.resolve({
|
|
664
|
-
id: 'user-1',
|
|
665
|
-
views: [
|
|
765
|
+
id: 'test-user-id-1',
|
|
766
|
+
views: [
|
|
767
|
+
{ aliasEmails: ['test-email-1@example.com'], icon: null, id: 'test-view-id-1', name: 'test-view-name-1' },
|
|
768
|
+
],
|
|
666
769
|
}));
|
|
667
770
|
const args = {
|
|
668
|
-
id: 'user-1',
|
|
669
|
-
view: {
|
|
771
|
+
id: 'test-user-id-1',
|
|
772
|
+
view: {
|
|
773
|
+
aliasEmails: ['test-email-2@example.com'],
|
|
774
|
+
icon: null,
|
|
775
|
+
id: 'test-view-id-1',
|
|
776
|
+
name: 'test-view-name-2',
|
|
777
|
+
},
|
|
670
778
|
};
|
|
671
779
|
await mutators.user.createView.fn({ args, ctx, tx: tx });
|
|
672
780
|
expect(tx.mutate.user.update).not.toHaveBeenCalled();
|
|
673
781
|
});
|
|
674
782
|
it('does nothing if max views limit reached', async () => {
|
|
675
783
|
const existingViews = Array.from({ length: 25 }, (_, i) => ({
|
|
676
|
-
aliasEmails: [`email
|
|
677
|
-
|
|
678
|
-
|
|
784
|
+
aliasEmails: [`test-email-${i}@example.com`],
|
|
785
|
+
icon: null,
|
|
786
|
+
id: `test-view-id-${i}`,
|
|
787
|
+
name: `test-view-name-${i}`,
|
|
679
788
|
}));
|
|
680
|
-
tx.run = mock(() => Promise.resolve({ id: 'user-1', views: existingViews }));
|
|
789
|
+
tx.run = mock(() => Promise.resolve({ id: 'test-user-id-1', views: existingViews }));
|
|
681
790
|
const args = {
|
|
682
|
-
id: 'user-1',
|
|
683
|
-
view: {
|
|
791
|
+
id: 'test-user-id-1',
|
|
792
|
+
view: {
|
|
793
|
+
aliasEmails: ['test-email-1@example.com'],
|
|
794
|
+
icon: null,
|
|
795
|
+
id: 'test-view-id-1',
|
|
796
|
+
name: 'test-view-name-1',
|
|
797
|
+
},
|
|
684
798
|
};
|
|
685
799
|
await mutators.user.createView.fn({ args, ctx, tx: tx });
|
|
686
800
|
expect(tx.mutate.user.update).not.toHaveBeenCalled();
|
|
@@ -689,22 +803,24 @@ describe('mutators', () => {
|
|
|
689
803
|
describe('deleteView', () => {
|
|
690
804
|
it('deletes a view', async () => {
|
|
691
805
|
tx.run = mock(() => Promise.resolve({
|
|
692
|
-
id: 'user-1',
|
|
806
|
+
id: 'test-user-id-1',
|
|
693
807
|
views: [
|
|
694
|
-
{ aliasEmails: ['
|
|
695
|
-
{ aliasEmails: ['
|
|
808
|
+
{ aliasEmails: ['test-email-1@example.com'], icon: null, id: 'test-view-id-1', name: 'test-view-name-1' },
|
|
809
|
+
{ aliasEmails: ['test-email-2@example.com'], icon: null, id: 'test-view-id-2', name: 'test-view-name-2' },
|
|
696
810
|
],
|
|
697
811
|
}));
|
|
698
|
-
const args = { id: 'user-1', viewId: 'view-1' };
|
|
812
|
+
const args = { id: 'test-user-id-1', viewId: 'test-view-id-1' };
|
|
699
813
|
await mutators.user.deleteView.fn({ args, ctx, tx: tx });
|
|
700
814
|
expect(tx.mutate.user.update).toHaveBeenCalledWith({
|
|
701
|
-
id: 'user-1',
|
|
702
|
-
views: [
|
|
815
|
+
id: 'test-user-id-1',
|
|
816
|
+
views: [
|
|
817
|
+
{ aliasEmails: ['test-email-2@example.com'], icon: null, id: 'test-view-id-2', name: 'test-view-name-2' },
|
|
818
|
+
],
|
|
703
819
|
});
|
|
704
820
|
});
|
|
705
821
|
it('does nothing if user not found', async () => {
|
|
706
822
|
tx.run = mock(() => Promise.resolve(null));
|
|
707
|
-
const args = { id: 'user-1', viewId: 'view-1' };
|
|
823
|
+
const args = { id: 'test-user-id-1', viewId: 'test-view-id-1' };
|
|
708
824
|
await mutators.user.deleteView.fn({ args, ctx, tx: tx });
|
|
709
825
|
expect(tx.mutate.user.update).not.toHaveBeenCalled();
|
|
710
826
|
});
|
|
@@ -712,95 +828,244 @@ describe('mutators', () => {
|
|
|
712
828
|
describe('updateView', () => {
|
|
713
829
|
it('updates view name', async () => {
|
|
714
830
|
tx.run = mock(() => Promise.resolve({
|
|
715
|
-
id: 'user-1',
|
|
716
|
-
views: [
|
|
831
|
+
id: 'test-user-id-1',
|
|
832
|
+
views: [
|
|
833
|
+
{ aliasEmails: ['test-email-1@example.com'], icon: null, id: 'test-view-id-1', name: 'test-view-name-1' },
|
|
834
|
+
],
|
|
717
835
|
}));
|
|
718
|
-
const args = {
|
|
836
|
+
const args = {
|
|
837
|
+
id: 'test-user-id-1',
|
|
838
|
+
view: {
|
|
839
|
+
aliasEmails: ['test-email-1@example.com'],
|
|
840
|
+
icon: null,
|
|
841
|
+
id: 'test-view-id-1',
|
|
842
|
+
name: 'test-updated-name',
|
|
843
|
+
},
|
|
844
|
+
};
|
|
719
845
|
await mutators.user.updateView.fn({ args, ctx, tx: tx });
|
|
720
846
|
expect(tx.mutate.user.update).toHaveBeenCalledWith({
|
|
721
|
-
id: 'user-1',
|
|
722
|
-
views: [
|
|
847
|
+
id: 'test-user-id-1',
|
|
848
|
+
views: [
|
|
849
|
+
{ aliasEmails: ['test-email-1@example.com'], icon: null, id: 'test-view-id-1', name: 'test-updated-name' },
|
|
850
|
+
],
|
|
723
851
|
});
|
|
724
852
|
});
|
|
725
853
|
it('updates view aliasEmails', async () => {
|
|
726
854
|
tx.run = mock(() => Promise.resolve({
|
|
727
|
-
id: 'user-1',
|
|
728
|
-
views: [
|
|
855
|
+
id: 'test-user-id-1',
|
|
856
|
+
views: [
|
|
857
|
+
{ aliasEmails: ['test-email-1@example.com'], icon: null, id: 'test-view-id-1', name: 'test-view-name-1' },
|
|
858
|
+
],
|
|
729
859
|
}));
|
|
730
|
-
const args = {
|
|
860
|
+
const args = {
|
|
861
|
+
id: 'test-user-id-1',
|
|
862
|
+
view: {
|
|
863
|
+
aliasEmails: ['test-email-1@example.com', 'test-email-2@example.com'],
|
|
864
|
+
icon: null,
|
|
865
|
+
id: 'test-view-id-1',
|
|
866
|
+
name: 'test-view-name-1',
|
|
867
|
+
},
|
|
868
|
+
};
|
|
731
869
|
await mutators.user.updateView.fn({ args, ctx, tx: tx });
|
|
732
870
|
expect(tx.mutate.user.update).toHaveBeenCalledWith({
|
|
733
|
-
id: 'user-1',
|
|
734
|
-
views: [
|
|
871
|
+
id: 'test-user-id-1',
|
|
872
|
+
views: [
|
|
873
|
+
{
|
|
874
|
+
aliasEmails: ['test-email-1@example.com', 'test-email-2@example.com'],
|
|
875
|
+
icon: null,
|
|
876
|
+
id: 'test-view-id-1',
|
|
877
|
+
name: 'test-view-name-1',
|
|
878
|
+
},
|
|
879
|
+
],
|
|
735
880
|
});
|
|
736
881
|
});
|
|
737
882
|
it('deduplicates aliasEmails on update', async () => {
|
|
738
883
|
tx.run = mock(() => Promise.resolve({
|
|
739
|
-
id: 'user-1',
|
|
740
|
-
views: [
|
|
884
|
+
id: 'test-user-id-1',
|
|
885
|
+
views: [
|
|
886
|
+
{ aliasEmails: ['test-email-1@example.com'], icon: null, id: 'test-view-id-1', name: 'test-view-name-1' },
|
|
887
|
+
],
|
|
741
888
|
}));
|
|
742
889
|
const args = {
|
|
743
|
-
id: 'user-1',
|
|
744
|
-
|
|
745
|
-
|
|
890
|
+
id: 'test-user-id-1',
|
|
891
|
+
view: {
|
|
892
|
+
aliasEmails: ['test-email-1@example.com', 'test-email-2@example.com', 'test-email-1@example.com'],
|
|
893
|
+
icon: null,
|
|
894
|
+
id: 'test-view-id-1',
|
|
895
|
+
name: 'test-view-name-1',
|
|
896
|
+
},
|
|
746
897
|
};
|
|
747
898
|
await mutators.user.updateView.fn({ args, ctx, tx: tx });
|
|
748
899
|
expect(tx.mutate.user.update).toHaveBeenCalledWith({
|
|
749
|
-
id: 'user-1',
|
|
750
|
-
views: [
|
|
900
|
+
id: 'test-user-id-1',
|
|
901
|
+
views: [
|
|
902
|
+
{
|
|
903
|
+
aliasEmails: ['test-email-1@example.com', 'test-email-2@example.com'],
|
|
904
|
+
icon: null,
|
|
905
|
+
id: 'test-view-id-1',
|
|
906
|
+
name: 'test-view-name-1',
|
|
907
|
+
},
|
|
908
|
+
],
|
|
909
|
+
});
|
|
910
|
+
});
|
|
911
|
+
it('updates view icon', async () => {
|
|
912
|
+
tx.run = mock(() => Promise.resolve({
|
|
913
|
+
id: 'test-user-id-1',
|
|
914
|
+
views: [
|
|
915
|
+
{ aliasEmails: ['test-email-1@example.com'], icon: null, id: 'test-view-id-1', name: 'test-view-name-1' },
|
|
916
|
+
],
|
|
917
|
+
}));
|
|
918
|
+
const args = {
|
|
919
|
+
id: 'test-user-id-1',
|
|
920
|
+
view: {
|
|
921
|
+
aliasEmails: ['test-email-1@example.com'],
|
|
922
|
+
icon: CustomViewIcon.HEART,
|
|
923
|
+
id: 'test-view-id-1',
|
|
924
|
+
name: 'test-view-name-1',
|
|
925
|
+
},
|
|
926
|
+
};
|
|
927
|
+
await mutators.user.updateView.fn({ args, ctx, tx: tx });
|
|
928
|
+
expect(tx.mutate.user.update).toHaveBeenCalledWith({
|
|
929
|
+
id: 'test-user-id-1',
|
|
930
|
+
views: [
|
|
931
|
+
{
|
|
932
|
+
aliasEmails: ['test-email-1@example.com'],
|
|
933
|
+
icon: CustomViewIcon.HEART,
|
|
934
|
+
id: 'test-view-id-1',
|
|
935
|
+
name: 'test-view-name-1',
|
|
936
|
+
},
|
|
937
|
+
],
|
|
751
938
|
});
|
|
752
939
|
});
|
|
753
940
|
it('updates both name and aliasEmails', async () => {
|
|
754
941
|
tx.run = mock(() => Promise.resolve({
|
|
755
|
-
id: 'user-1',
|
|
756
|
-
views: [
|
|
942
|
+
id: 'test-user-id-1',
|
|
943
|
+
views: [
|
|
944
|
+
{ aliasEmails: ['test-email-1@example.com'], icon: null, id: 'test-view-id-1', name: 'test-view-name-1' },
|
|
945
|
+
],
|
|
757
946
|
}));
|
|
758
947
|
const args = {
|
|
759
|
-
id: 'user-1',
|
|
760
|
-
|
|
761
|
-
|
|
948
|
+
id: 'test-user-id-1',
|
|
949
|
+
view: {
|
|
950
|
+
aliasEmails: ['test-email-1@example.com'],
|
|
951
|
+
icon: null,
|
|
952
|
+
id: 'test-view-id-1',
|
|
953
|
+
name: 'test-updated-name',
|
|
954
|
+
},
|
|
762
955
|
};
|
|
763
956
|
await mutators.user.updateView.fn({ args, ctx, tx: tx });
|
|
764
957
|
expect(tx.mutate.user.update).toHaveBeenCalledWith({
|
|
765
|
-
id: 'user-1',
|
|
766
|
-
views: [
|
|
958
|
+
id: 'test-user-id-1',
|
|
959
|
+
views: [
|
|
960
|
+
{ aliasEmails: ['test-email-1@example.com'], icon: null, id: 'test-view-id-1', name: 'test-updated-name' },
|
|
961
|
+
],
|
|
767
962
|
});
|
|
768
963
|
});
|
|
769
964
|
it('does nothing if user not found', async () => {
|
|
770
965
|
tx.run = mock(() => Promise.resolve(null));
|
|
771
|
-
const args = {
|
|
966
|
+
const args = {
|
|
967
|
+
id: 'test-user-id-1',
|
|
968
|
+
view: {
|
|
969
|
+
aliasEmails: ['test-email-1@example.com'],
|
|
970
|
+
icon: null,
|
|
971
|
+
id: 'test-view-id-1',
|
|
972
|
+
name: 'test-updated-name',
|
|
973
|
+
},
|
|
974
|
+
};
|
|
772
975
|
await mutators.user.updateView.fn({ args, ctx, tx: tx });
|
|
773
976
|
expect(tx.mutate.user.update).not.toHaveBeenCalled();
|
|
774
977
|
});
|
|
775
978
|
it('does nothing if view does not exist', async () => {
|
|
776
979
|
tx.run = mock(() => Promise.resolve({
|
|
777
|
-
id: 'user-1',
|
|
778
|
-
views: [
|
|
980
|
+
id: 'test-user-id-1',
|
|
981
|
+
views: [
|
|
982
|
+
{ aliasEmails: ['test-email-1@example.com'], icon: null, id: 'test-view-id-1', name: 'test-view-name-1' },
|
|
983
|
+
],
|
|
779
984
|
}));
|
|
780
|
-
const args = {
|
|
985
|
+
const args = {
|
|
986
|
+
id: 'test-user-id-1',
|
|
987
|
+
view: {
|
|
988
|
+
aliasEmails: ['test-email-1@example.com'],
|
|
989
|
+
icon: null,
|
|
990
|
+
id: 'test-view-id-nonexistent',
|
|
991
|
+
name: 'test-updated-name',
|
|
992
|
+
},
|
|
993
|
+
};
|
|
781
994
|
await mutators.user.updateView.fn({ args, ctx, tx: tx });
|
|
782
995
|
expect(tx.mutate.user.update).not.toHaveBeenCalled();
|
|
783
996
|
});
|
|
784
997
|
it('leaves non-matching views unchanged', async () => {
|
|
785
998
|
tx.run = mock(() => Promise.resolve({
|
|
786
|
-
id: 'user-1',
|
|
999
|
+
id: 'test-user-id-1',
|
|
787
1000
|
views: [
|
|
788
|
-
{ aliasEmails: ['
|
|
789
|
-
{ aliasEmails: ['
|
|
1001
|
+
{ aliasEmails: ['test-email-1@example.com'], icon: null, id: 'test-view-id-1', name: 'test-view-name-1' },
|
|
1002
|
+
{ aliasEmails: ['test-email-2@example.com'], icon: null, id: 'test-view-id-2', name: 'test-view-name-2' },
|
|
790
1003
|
],
|
|
791
1004
|
}));
|
|
792
|
-
const args = {
|
|
1005
|
+
const args = {
|
|
1006
|
+
id: 'test-user-id-1',
|
|
1007
|
+
view: {
|
|
1008
|
+
aliasEmails: ['test-email-1@example.com'],
|
|
1009
|
+
icon: null,
|
|
1010
|
+
id: 'test-view-id-1',
|
|
1011
|
+
name: 'test-view-updated-name',
|
|
1012
|
+
},
|
|
1013
|
+
};
|
|
793
1014
|
await mutators.user.updateView.fn({ args, ctx, tx: tx });
|
|
794
1015
|
expect(tx.mutate.user.update).toHaveBeenCalledWith({
|
|
795
|
-
id: 'user-1',
|
|
1016
|
+
id: 'test-user-id-1',
|
|
796
1017
|
views: [
|
|
797
|
-
{
|
|
798
|
-
|
|
1018
|
+
{
|
|
1019
|
+
aliasEmails: ['test-email-1@example.com'],
|
|
1020
|
+
icon: null,
|
|
1021
|
+
id: 'test-view-id-1',
|
|
1022
|
+
name: 'test-view-updated-name',
|
|
1023
|
+
},
|
|
1024
|
+
{ aliasEmails: ['test-email-2@example.com'], icon: null, id: 'test-view-id-2', name: 'test-view-name-2' },
|
|
799
1025
|
],
|
|
800
1026
|
});
|
|
801
1027
|
});
|
|
802
1028
|
it('schema rejects empty aliasEmails array', () => {
|
|
803
|
-
const args = {
|
|
1029
|
+
const args = {
|
|
1030
|
+
id: 'test-user-id-1',
|
|
1031
|
+
view: { aliasEmails: [], icon: null, id: 'test-view-id-1', name: 'test-view-name-1' },
|
|
1032
|
+
};
|
|
1033
|
+
const result = v.safeParse(mutatorSchemas.user.updateView, args);
|
|
1034
|
+
expect(result.success).toBe(false);
|
|
1035
|
+
});
|
|
1036
|
+
for (const icon of USER_SETTINGS_CUSTOM_VIEW_ICONS) {
|
|
1037
|
+
it(`schema accepts valid icon value: ${icon}`, () => {
|
|
1038
|
+
const args = {
|
|
1039
|
+
id: 'test-user-id-1',
|
|
1040
|
+
view: { aliasEmails: ['test-email-1@example.com'], icon, id: 'test-view-id-1', name: 'test-view-name-1' },
|
|
1041
|
+
};
|
|
1042
|
+
const result = v.safeParse(mutatorSchemas.user.updateView, args);
|
|
1043
|
+
expect(result.success).toBe(true);
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
it('schema accepts null icon value', () => {
|
|
1047
|
+
const args = {
|
|
1048
|
+
id: 'test-user-id-1',
|
|
1049
|
+
view: {
|
|
1050
|
+
aliasEmails: ['test-email-1@example.com'],
|
|
1051
|
+
icon: null,
|
|
1052
|
+
id: 'test-view-id-1',
|
|
1053
|
+
name: 'test-view-name-1',
|
|
1054
|
+
},
|
|
1055
|
+
};
|
|
1056
|
+
const result = v.safeParse(mutatorSchemas.user.updateView, args);
|
|
1057
|
+
expect(result.success).toBe(true);
|
|
1058
|
+
});
|
|
1059
|
+
it('schema rejects invalid icon value', () => {
|
|
1060
|
+
const args = {
|
|
1061
|
+
id: 'test-user-id-1',
|
|
1062
|
+
view: {
|
|
1063
|
+
aliasEmails: ['test-email-1@example.com'],
|
|
1064
|
+
icon: 'INVALID_ICON',
|
|
1065
|
+
id: 'test-view-id-1',
|
|
1066
|
+
name: 'test-view-name-1',
|
|
1067
|
+
},
|
|
1068
|
+
};
|
|
804
1069
|
const result = v.safeParse(mutatorSchemas.user.updateView, args);
|
|
805
1070
|
expect(result.success).toBe(false);
|
|
806
1071
|
});
|