@remit/data-ports 0.0.82 → 0.0.84

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 (174) hide show
  1. package/dist/account-settings.d.ts +371 -0
  2. package/dist/account-settings.js +114 -0
  3. package/dist/conformance/account.d.ts +3 -0
  4. package/dist/conformance/account.js +118 -0
  5. package/dist/conformance/calendar-collection.d.ts +3 -0
  6. package/dist/conformance/calendar-collection.js +251 -0
  7. package/dist/conformance/calendar-event-index.d.ts +3 -0
  8. package/dist/conformance/calendar-event-index.js +114 -0
  9. package/dist/conformance/calendar-feed-token.d.ts +3 -0
  10. package/dist/conformance/calendar-feed-token.js +97 -0
  11. package/dist/conformance/calendar-object.d.ts +3 -0
  12. package/dist/conformance/calendar-object.js +156 -0
  13. package/dist/conformance/calendar-suggestion.d.ts +3 -0
  14. package/dist/conformance/calendar-suggestion.js +255 -0
  15. package/{src/conformance/harness.ts → dist/conformance/harness.d.ts} +4 -4
  16. package/dist/conformance/harness.js +1 -0
  17. package/dist/conformance/index.js +8 -0
  18. package/dist/conformance/label.d.ts +3 -0
  19. package/dist/conformance/label.js +92 -0
  20. package/dist/conformance/sender-signer-standing.d.ts +3 -0
  21. package/dist/conformance/sender-signer-standing.js +81 -0
  22. package/dist/display-name.d.ts +1 -0
  23. package/dist/display-name.js +26 -0
  24. package/dist/errors.d.ts +150 -0
  25. package/dist/errors.js +181 -0
  26. package/dist/filter-ttl.d.ts +7 -0
  27. package/{src/filter-ttl.ts → dist/filter-ttl.js} +8 -11
  28. package/dist/folder-role.d.ts +239 -0
  29. package/dist/folder-role.js +276 -0
  30. package/dist/id.d.ts +124 -0
  31. package/{src/id.ts → dist/id.js} +41 -127
  32. package/dist/index.d.ts +37 -0
  33. package/dist/index.js +5 -0
  34. package/dist/interfaces/account-config.d.ts +15 -0
  35. package/dist/interfaces/account-config.js +1 -0
  36. package/dist/interfaces/account-export-request.d.ts +10 -0
  37. package/dist/interfaces/account-export-request.js +1 -0
  38. package/dist/interfaces/account-setting.d.ts +7 -0
  39. package/dist/interfaces/account-setting.js +1 -0
  40. package/dist/interfaces/account.d.ts +29 -0
  41. package/dist/interfaces/account.js +1 -0
  42. package/dist/interfaces/address.d.ts +69 -0
  43. package/dist/interfaces/address.js +1 -0
  44. package/dist/interfaces/calendar-collection.d.ts +38 -0
  45. package/dist/interfaces/calendar-collection.js +1 -0
  46. package/dist/interfaces/calendar-event-index.d.ts +19 -0
  47. package/dist/interfaces/calendar-event-index.js +1 -0
  48. package/dist/interfaces/calendar-feed-token.d.ts +31 -0
  49. package/dist/interfaces/calendar-feed-token.js +1 -0
  50. package/dist/interfaces/calendar-object.d.ts +36 -0
  51. package/dist/interfaces/calendar-object.js +1 -0
  52. package/dist/interfaces/calendar-store.d.ts +93 -0
  53. package/dist/interfaces/calendar-store.js +1 -0
  54. package/dist/interfaces/calendar-suggestion.d.ts +62 -0
  55. package/dist/interfaces/calendar-suggestion.js +1 -0
  56. package/dist/interfaces/config-import.d.ts +8 -0
  57. package/dist/interfaces/config-import.js +1 -0
  58. package/dist/interfaces/envelope.d.ts +24 -0
  59. package/dist/interfaces/envelope.js +1 -0
  60. package/dist/interfaces/filter.d.ts +28 -0
  61. package/dist/interfaces/filter.js +1 -0
  62. package/dist/interfaces/label.d.ts +17 -0
  63. package/dist/interfaces/label.js +1 -0
  64. package/dist/interfaces/mailbox-lock.d.ts +12 -0
  65. package/dist/interfaces/mailbox-lock.js +1 -0
  66. package/dist/interfaces/mailbox-special-use.d.ts +54 -0
  67. package/dist/interfaces/mailbox-special-use.js +1 -0
  68. package/dist/interfaces/mailbox.d.ts +79 -0
  69. package/dist/interfaces/mailbox.js +1 -0
  70. package/dist/interfaces/message-flag-push.d.ts +9 -0
  71. package/dist/interfaces/message-flag-push.js +1 -0
  72. package/dist/interfaces/message-flag.d.ts +14 -0
  73. package/dist/interfaces/message-flag.js +1 -0
  74. package/dist/interfaces/message-label.d.ts +21 -0
  75. package/dist/interfaces/message-label.js +1 -0
  76. package/dist/interfaces/message-placement-move.d.ts +8 -0
  77. package/dist/interfaces/message-placement-move.js +1 -0
  78. package/dist/interfaces/message.d.ts +60 -0
  79. package/dist/interfaces/message.js +1 -0
  80. package/dist/interfaces/organize-job-request.d.ts +10 -0
  81. package/dist/interfaces/organize-job-request.js +1 -0
  82. package/dist/interfaces/outbox-attachment.d.ts +101 -0
  83. package/dist/interfaces/outbox-attachment.js +7 -0
  84. package/dist/interfaces/outbox-message.d.ts +70 -0
  85. package/dist/interfaces/outbox-message.js +20 -0
  86. package/dist/interfaces/quarantine.d.ts +20 -0
  87. package/dist/interfaces/quarantine.js +1 -0
  88. package/dist/interfaces/sender-signer-standing.d.ts +26 -0
  89. package/dist/interfaces/sender-signer-standing.js +1 -0
  90. package/dist/interfaces/sync-warning.d.ts +11 -0
  91. package/dist/interfaces/sync-warning.js +1 -0
  92. package/dist/interfaces/thread-message.d.ts +202 -0
  93. package/dist/interfaces/thread-message.js +1 -0
  94. package/dist/mailbox-name.d.ts +35 -0
  95. package/dist/mailbox-name.js +68 -0
  96. package/dist/message-parts.d.ts +22 -0
  97. package/dist/message-parts.js +18 -0
  98. package/dist/message-settlement.d.ts +35 -0
  99. package/{src/message-settlement.ts → dist/message-settlement.js} +5 -19
  100. package/dist/mutation-events.d.ts +19 -0
  101. package/{src/mutation-events.ts → dist/mutation-events.js} +2 -5
  102. package/dist/sender-mute.d.ts +26 -0
  103. package/{src/sender-mute.ts → dist/sender-mute.js} +12 -34
  104. package/dist/sync-warning-state.d.ts +3 -0
  105. package/dist/sync-warning-state.js +5 -0
  106. package/dist/types.d.ts +491 -0
  107. package/dist/types.js +1 -0
  108. package/dist/update-manifest.d.ts +24 -0
  109. package/dist/update-manifest.js +20 -0
  110. package/dist/virtual-copy.d.ts +8 -0
  111. package/{src/virtual-copy.ts → dist/virtual-copy.js} +10 -15
  112. package/dist/wellknown.d.ts +47 -0
  113. package/{src/wellknown.ts → dist/wellknown.js} +26 -49
  114. package/package.json +44 -79
  115. package/src/account-settings.ts +0 -194
  116. package/src/conformance/account.ts +0 -104
  117. package/src/conformance/calendar-collection.ts +0 -342
  118. package/src/conformance/calendar-event-index.ts +0 -203
  119. package/src/conformance/calendar-feed-token.ts +0 -148
  120. package/src/conformance/calendar-object.ts +0 -269
  121. package/src/conformance/calendar-suggestion.ts +0 -490
  122. package/src/conformance/label.ts +0 -136
  123. package/src/conformance/sender-signer-standing.ts +0 -117
  124. package/src/display-name.test.ts +0 -101
  125. package/src/display-name.ts +0 -40
  126. package/src/errors.ts +0 -226
  127. package/src/folder-role.test.ts +0 -422
  128. package/src/folder-role.ts +0 -447
  129. package/src/id.test.ts +0 -352
  130. package/src/index.ts +0 -170
  131. package/src/interfaces/account-config.ts +0 -25
  132. package/src/interfaces/account-export-request.ts +0 -21
  133. package/src/interfaces/account-setting.ts +0 -14
  134. package/src/interfaces/account.ts +0 -43
  135. package/src/interfaces/address.ts +0 -122
  136. package/src/interfaces/calendar-collection.ts +0 -60
  137. package/src/interfaces/calendar-event-index.ts +0 -34
  138. package/src/interfaces/calendar-feed-token.ts +0 -38
  139. package/src/interfaces/calendar-object.ts +0 -58
  140. package/src/interfaces/calendar-suggestion.ts +0 -93
  141. package/src/interfaces/calendar-unit-of-work.ts +0 -47
  142. package/src/interfaces/config-import.ts +0 -16
  143. package/src/interfaces/envelope.ts +0 -32
  144. package/src/interfaces/filter-anchor-transaction.ts +0 -23
  145. package/src/interfaces/filter-anchor.ts +0 -11
  146. package/src/interfaces/filter.ts +0 -41
  147. package/src/interfaces/label.ts +0 -30
  148. package/src/interfaces/mailbox-lock.ts +0 -32
  149. package/src/interfaces/mailbox-special-use.ts +0 -60
  150. package/src/interfaces/mailbox.ts +0 -115
  151. package/src/interfaces/message-flag-push.ts +0 -17
  152. package/src/interfaces/message-flag.ts +0 -15
  153. package/src/interfaces/message-label.ts +0 -25
  154. package/src/interfaces/message-placement-move.ts +0 -15
  155. package/src/interfaces/message.ts +0 -56
  156. package/src/interfaces/organize-job-request.ts +0 -19
  157. package/src/interfaces/outbox-attachment.ts +0 -132
  158. package/src/interfaces/outbox-message.ts +0 -106
  159. package/src/interfaces/quarantine.ts +0 -22
  160. package/src/interfaces/sender-signer-standing.ts +0 -37
  161. package/src/interfaces/thread-message.ts +0 -264
  162. package/src/interfaces/unit-of-work.ts +0 -28
  163. package/src/mailbox-name.test.ts +0 -106
  164. package/src/mailbox-name.ts +0 -90
  165. package/src/mailbox-state-doors.test.ts +0 -104
  166. package/src/message-placement-doors.test.ts +0 -100
  167. package/src/message-settlement.test.ts +0 -132
  168. package/src/sender-mute.test.ts +0 -76
  169. package/src/types.ts +0 -820
  170. package/src/update-manifest.test.ts +0 -130
  171. package/src/update-manifest.ts +0 -22
  172. package/src/virtual-copy.test.ts +0 -34
  173. package/tsconfig.json +0 -8
  174. /package/{src/conformance/index.ts → dist/conformance/index.d.ts} +0 -0
@@ -1,422 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { describe, it } from "node:test";
3
- import {
4
- CanonicalMailboxRole,
5
- FolderAppointmentSource,
6
- MailboxSpecialUse,
7
- MailboxSyncStatus,
8
- } from "@remit/domain-enums";
9
- import {
10
- composeFolderRoleAppointmentLabelName,
11
- composeFolderRoleAppointmentName,
12
- isReservedFolderName,
13
- meetsTrashAssurance,
14
- parseFolderRoleAppointmentLabelName,
15
- parseFolderRoleAppointmentName,
16
- type RoleMailboxCandidate,
17
- resolveConfirmedMailboxForRole,
18
- resolveMailboxForRole,
19
- resolveRoleForAccount,
20
- trashSourceMeetsAssurance,
21
- } from "./folder-role.js";
22
-
23
- const mailbox = (
24
- mailboxId: string,
25
- fullPath: string,
26
- specialUse: readonly string[] = [],
27
- hierarchyDelimiter = "/",
28
- ): RoleMailboxCandidate => ({
29
- mailboxId,
30
- fullPath,
31
- hierarchyDelimiter,
32
- specialUse,
33
- });
34
-
35
- describe("resolveMailboxForRole precedence", () => {
36
- const mailboxes = [
37
- mailbox("mb-inbox", "INBOX"),
38
- mailbox("mb-spam", "INBOX/Spam"),
39
- mailbox("mb-junk", "Junk", [MailboxSpecialUse.Junk]),
40
- mailbox("mb-project", "INBOX/Project X"),
41
- ];
42
-
43
- it("puts the user's appointment above both the flag and the name", () => {
44
- assert.equal(
45
- resolveMailboxForRole(CanonicalMailboxRole.Junk, mailboxes, "mb-project")
46
- ?.mailboxId,
47
- "mb-project",
48
- );
49
- });
50
-
51
- it("takes the server's SPECIAL-USE flag when nothing is appointed", () => {
52
- assert.equal(
53
- resolveMailboxForRole(CanonicalMailboxRole.Junk, mailboxes)?.mailboxId,
54
- "mb-junk",
55
- );
56
- });
57
-
58
- it("falls back to the name only when no flag is present", () => {
59
- const unflagged = mailboxes.filter((m) => m.mailboxId !== "mb-junk");
60
- assert.equal(
61
- resolveMailboxForRole(CanonicalMailboxRole.Junk, unflagged)?.mailboxId,
62
- "mb-spam",
63
- );
64
- });
65
-
66
- it("reads the leaf against the mailbox's own delimiter, not a hardcoded slash", () => {
67
- const dotted = [
68
- mailbox("mb-inbox", "INBOX", [], "."),
69
- mailbox("mb-trash", "INBOX.Deleted Items", [], "."),
70
- ];
71
- assert.equal(
72
- resolveMailboxForRole(CanonicalMailboxRole.Trash, dotted)?.mailboxId,
73
- "mb-trash",
74
- );
75
- });
76
-
77
- it("matches the reserved INBOX name for Inbox", () => {
78
- assert.equal(
79
- resolveMailboxForRole(CanonicalMailboxRole.Inbox, mailboxes)?.mailboxId,
80
- "mb-inbox",
81
- );
82
- });
83
-
84
- it("returns null rather than guessing when nothing matches", () => {
85
- assert.equal(
86
- resolveMailboxForRole(CanonicalMailboxRole.Archive, mailboxes),
87
- null,
88
- );
89
- });
90
-
91
- it("re-proposes when the appointment names a mailbox that is gone", () => {
92
- assert.equal(
93
- resolveMailboxForRole(
94
- CanonicalMailboxRole.Junk,
95
- mailboxes,
96
- "mb-deleted-last-week",
97
- )?.mailboxId,
98
- "mb-junk",
99
- );
100
- });
101
- });
102
-
103
- describe("resolveMailboxForRole on [Gmail]/Trash beside a top-level Bin", () => {
104
- // #837: joining Trash to the leaf-name resolver made depth outrank the name,
105
- // so a top-level `Bin` beat `[Gmail]/Trash` and deletes landed in the wrong
106
- // folder. `bin` is no longer a hint — Gmail flags both \Trash — so the name
107
- // rule reaches `[Gmail]/Trash` and nothing reaches `Bin`.
108
- const mailboxes = [
109
- mailbox("mb-inbox", "INBOX"),
110
- mailbox("mb-bin", "Bin"),
111
- mailbox("mb-gmail-trash", "[Gmail]/Trash"),
112
- ];
113
-
114
- it("proposes [Gmail]/Trash, never the folder called Bin", () => {
115
- assert.equal(
116
- resolveMailboxForRole(CanonicalMailboxRole.Trash, mailboxes)?.mailboxId,
117
- "mb-gmail-trash",
118
- );
119
- });
120
-
121
- it("resolves to whichever folder the user appointed", () => {
122
- assert.equal(
123
- resolveMailboxForRole(CanonicalMailboxRole.Trash, mailboxes, "mb-bin")
124
- ?.mailboxId,
125
- "mb-bin",
126
- );
127
- });
128
-
129
- it("still takes the SPECIAL-USE flag over the name when nothing is appointed", () => {
130
- const flagged = [
131
- mailbox("mb-inbox", "INBOX"),
132
- mailbox("mb-bin", "Bin"),
133
- mailbox("mb-gmail-trash", "[Gmail]/Trash", [MailboxSpecialUse.Trash]),
134
- ];
135
- assert.equal(
136
- resolveMailboxForRole(CanonicalMailboxRole.Trash, flagged)?.mailboxId,
137
- "mb-gmail-trash",
138
- );
139
- });
140
- });
141
-
142
- describe("resolveConfirmedMailboxForRole", () => {
143
- // What Empty Trash resolves through: an expunge may only touch a folder
144
- // somebody actually designated (audit #841).
145
- const mailboxes = [
146
- mailbox("mb-inbox", "INBOX"),
147
- mailbox("mb-deleted", "Deleted"),
148
- mailbox("mb-gmail-trash", "[Gmail]/Trash"),
149
- ];
150
-
151
- it("refuses a folder that only matches by name", () => {
152
- assert.equal(
153
- resolveConfirmedMailboxForRole(CanonicalMailboxRole.Trash, mailboxes),
154
- null,
155
- );
156
- });
157
-
158
- it("takes the appointment over the folder the name rule would have picked", () => {
159
- assert.equal(
160
- resolveConfirmedMailboxForRole(
161
- CanonicalMailboxRole.Trash,
162
- mailboxes,
163
- "mb-gmail-trash",
164
- )?.mailboxId,
165
- "mb-gmail-trash",
166
- );
167
- });
168
-
169
- it("takes the server flag when nothing is appointed", () => {
170
- const flagged = [
171
- mailbox("mb-deleted", "Deleted"),
172
- mailbox("mb-trash", "[Gmail]/Trash", [MailboxSpecialUse.Trash]),
173
- ];
174
- assert.equal(
175
- resolveConfirmedMailboxForRole(CanonicalMailboxRole.Trash, flagged)
176
- ?.mailboxId,
177
- "mb-trash",
178
- );
179
- });
180
- });
181
-
182
- describe("resolveRoleForAccount", () => {
183
- it("resolves an appointment naming a mailbox whose last sync failed", () => {
184
- // `failed` means the folder exists at `fullPath` and the last rename or
185
- // delete intent did not land (folder-rename-and-delete.md D7), so the row
186
- // names a path the server really holds.
187
- const failed: RoleMailboxCandidate & { syncStatus: string } = {
188
- ...mailbox("mb-trash", "INBOX/Prullenbak"),
189
- syncStatus: MailboxSyncStatus.failed,
190
- };
191
- assert.deepEqual(
192
- resolveRoleForAccount(
193
- CanonicalMailboxRole.Trash,
194
- [mailbox("mb-inbox", "INBOX"), failed],
195
- "mb-trash",
196
- ),
197
- { kind: "appointed", mailbox: failed },
198
- );
199
- });
200
-
201
- it("answers none when nothing names a Trash folder", () => {
202
- // #887 Done item 4: an account whose folders happen to include a Dutch
203
- // "Prullenbak" has no Trash reader may act on — no flag, no appointment,
204
- // and "prullenbak" is not a hint.
205
- const mailboxes = [
206
- mailbox("mb-inbox", "INBOX"),
207
- mailbox("mb-werk", "Werk"),
208
- mailbox("mb-prullenbak", "Prullenbak"),
209
- ];
210
- assert.deepEqual(
211
- resolveRoleForAccount(CanonicalMailboxRole.Trash, mailboxes),
212
- { kind: "none" },
213
- );
214
- });
215
-
216
- it("proposes a folder named Trash, and that is not enough to empty it", () => {
217
- // #887 Done item 1: the name is a guess. It files a delete somewhere
218
- // retrievable; it never authorises an expunge.
219
- const mailboxes = [
220
- mailbox("mb-inbox", "INBOX"),
221
- mailbox("mb-werk", "Werk"),
222
- mailbox("mb-trash", "Trash"),
223
- ];
224
- const resolution = resolveRoleForAccount(
225
- CanonicalMailboxRole.Trash,
226
- mailboxes,
227
- );
228
- assert.deepEqual(resolution, {
229
- kind: "proposed",
230
- mailbox: mailboxes[2],
231
- });
232
- assert.equal(meetsTrashAssurance(resolution, "confirmed"), false);
233
- assert.equal(meetsTrashAssurance(resolution, "resolved"), true);
234
- });
235
-
236
- it("names the appointment that went stale, and what took its place", () => {
237
- const mailboxes = [
238
- mailbox("mb-inbox", "INBOX"),
239
- mailbox("mb-trash", "[Gmail]/Trash", [MailboxSpecialUse.Trash]),
240
- ];
241
- const resolution = resolveRoleForAccount(
242
- CanonicalMailboxRole.Trash,
243
- mailboxes,
244
- "mb-rubbish-deleted-by-apple-mail",
245
- );
246
- assert.deepEqual(resolution, {
247
- kind: "appointment_stale",
248
- appointedMailboxId: "mb-rubbish-deleted-by-apple-mail",
249
- fallback: { kind: "flagged", mailbox: mailboxes[1] },
250
- });
251
- assert.equal(meetsTrashAssurance(resolution, "confirmed"), false);
252
- assert.equal(meetsTrashAssurance(resolution, "resolved"), false);
253
- });
254
-
255
- it("tags the appointment the user made and the flag the server set apart", () => {
256
- const mailboxes = [
257
- mailbox("mb-inbox", "INBOX"),
258
- mailbox("mb-trash", "[Gmail]/Trash", [MailboxSpecialUse.Trash]),
259
- ];
260
- assert.equal(
261
- resolveRoleForAccount(CanonicalMailboxRole.Trash, mailboxes).kind,
262
- "flagged",
263
- );
264
- assert.equal(
265
- resolveRoleForAccount(CanonicalMailboxRole.Trash, mailboxes, "mb-inbox")
266
- .kind,
267
- "appointed",
268
- );
269
- assert.equal(
270
- resolveRoleForAccount(CanonicalMailboxRole.Inbox, mailboxes).kind,
271
- "reserved",
272
- );
273
- });
274
- });
275
-
276
- describe("the adapters over resolveRoleForAccount", () => {
277
- const mailboxes = [
278
- mailbox("mb-inbox", "INBOX"),
279
- mailbox("mb-trash", "[Gmail]/Trash", [MailboxSpecialUse.Trash]),
280
- ];
281
-
282
- it("withholds a stale appointment's fallback from the confirmed answer only", () => {
283
- // A vanished appointment is not confirmation of anything, so the expunge
284
- // gate sees nothing. Filing mail still works: the fallback is a fine place
285
- // to put a message the user can move back.
286
- assert.equal(
287
- resolveConfirmedMailboxForRole(
288
- CanonicalMailboxRole.Trash,
289
- mailboxes,
290
- "mb-gone",
291
- ),
292
- null,
293
- );
294
- assert.equal(
295
- resolveMailboxForRole(CanonicalMailboxRole.Trash, mailboxes, "mb-gone")
296
- ?.mailboxId,
297
- "mb-trash",
298
- );
299
- });
300
-
301
- it("keeps a stale appointment on the flag, never on a folder named like one", () => {
302
- // The confirmed adapter is not built on top of the other one: were it,
303
- // null-on-stale would drop the seven non-Trash roles past their
304
- // SPECIAL-USE flag and into the name hint, and a folder somebody called
305
- // "Sent" would start collecting this account's sent mail.
306
- const sent = [
307
- mailbox("mb-inbox", "INBOX"),
308
- mailbox("mb-sent-copy", "Sent"),
309
- mailbox("mb-sent", "[Gmail]/Sent Mail", [MailboxSpecialUse.Sent]),
310
- ];
311
- assert.equal(
312
- resolveMailboxForRole(CanonicalMailboxRole.Sent, sent, "mb-gone")
313
- ?.mailboxId,
314
- "mb-sent",
315
- );
316
- });
317
-
318
- it("keeps the name guess out of the confirmed answer", () => {
319
- const unflagged = [
320
- mailbox("mb-inbox", "INBOX"),
321
- mailbox("mb-bak", "Trash"),
322
- ];
323
- assert.equal(
324
- resolveConfirmedMailboxForRole(CanonicalMailboxRole.Trash, unflagged),
325
- null,
326
- );
327
- assert.equal(
328
- resolveMailboxForRole(CanonicalMailboxRole.Trash, unflagged)?.mailboxId,
329
- "mb-bak",
330
- );
331
- });
332
- });
333
-
334
- describe("trashSourceMeetsAssurance", () => {
335
- it("confirms the user's appointment and the server's flag, and nothing else", () => {
336
- // The set a client may word an expunge from. `Reserved` reads as
337
- // designated and is not: it is the INBOX name rule, which nobody chose.
338
- const confirmed = Object.values(FolderAppointmentSource).filter((source) =>
339
- trashSourceMeetsAssurance(source, "confirmed"),
340
- );
341
- assert.deepEqual(confirmed, [
342
- FolderAppointmentSource.Appointed,
343
- FolderAppointmentSource.Flagged,
344
- ]);
345
- });
346
-
347
- it("adds the name guess at `resolved`, where a wrong guess only misfiles", () => {
348
- const resolved = Object.values(FolderAppointmentSource).filter((source) =>
349
- trashSourceMeetsAssurance(source, "resolved"),
350
- );
351
- assert.deepEqual(resolved, [
352
- FolderAppointmentSource.Appointed,
353
- FolderAppointmentSource.Flagged,
354
- FolderAppointmentSource.Proposed,
355
- ]);
356
- });
357
- });
358
-
359
- describe("the appointment name and its label sibling", () => {
360
- it("never lets the label row parse as an appointment", () => {
361
- // The label is display only. If the appointment parser matched it, a path
362
- // string would be read back as a mailboxId and resolution would follow it.
363
- const label = composeFolderRoleAppointmentLabelName(
364
- "acc-1",
365
- CanonicalMailboxRole.Trash,
366
- );
367
- assert.equal(parseFolderRoleAppointmentName(label), undefined);
368
- assert.deepEqual(parseFolderRoleAppointmentLabelName(label), {
369
- accountId: "acc-1",
370
- role: CanonicalMailboxRole.Trash,
371
- });
372
- });
373
-
374
- it("never lets an appointment row parse as a label", () => {
375
- const appointment = composeFolderRoleAppointmentName(
376
- "acc-1",
377
- CanonicalMailboxRole.Trash,
378
- );
379
- assert.equal(parseFolderRoleAppointmentLabelName(appointment), undefined);
380
- assert.deepEqual(parseFolderRoleAppointmentName(appointment), {
381
- accountId: "acc-1",
382
- role: CanonicalMailboxRole.Trash,
383
- });
384
- });
385
- });
386
-
387
- describe("isReservedFolderName", () => {
388
- /**
389
- * The sweep's own predicate. A folder whose leaf name is a role's
390
- * conventional name but which lacks the server's flag is read as a duplicate
391
- * and its row is deleted — under D8, with the folder's mail — as soon as
392
- * another folder holds the flag. A rename to one of these settles `synced`
393
- * and is then reaped, which is why the API refuses it (D5).
394
- */
395
- for (const name of [
396
- "archive",
397
- "Archive",
398
- "ARCHIVES",
399
- "trash",
400
- "Deleted Items",
401
- "drafts",
402
- "Sent Mail",
403
- "junk",
404
- "Spam",
405
- "All Mail",
406
- ]) {
407
- it(`reserves "${name}"`, () => {
408
- assert.equal(isReservedFolderName(name), true);
409
- });
410
- }
411
-
412
- /**
413
- * #843 dropped a bare "Deleted" and "Bin" from the Trash hints precisely
414
- * because they are ordinary folder names a user keeps mail in. Reserving
415
- * them here would refuse a rename nothing would ever have reaped.
416
- */
417
- for (const name of ["Deleted", "Bin", "Receipts", "Work", "Inbox 2024"]) {
418
- it(`leaves "${name}" alone`, () => {
419
- assert.equal(isReservedFolderName(name), false);
420
- });
421
- }
422
- });