@remit/drizzle-service 0.0.63 → 0.0.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remit/drizzle-service",
3
- "version": "0.0.63",
3
+ "version": "0.0.65",
4
4
  "description": "Drizzle ORM service over SQLite",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -1,10 +1,17 @@
1
1
  import assert from "node:assert/strict";
2
2
  import { readFileSync } from "node:fs";
3
3
  import { after, before, beforeEach, describe, test } from "node:test";
4
+ import { composeFolderRoleAppointmentName } from "@remit/data-ports/folder-role";
5
+ import { CanonicalMailboxRole } from "@remit/domain-enums";
4
6
  import Database from "better-sqlite3";
7
+ import { drizzle } from "drizzle-orm/better-sqlite3";
8
+ import { AccountSettingRepo } from "../repos/i4-account-setting.js";
9
+ import { MailboxSpecialUseRepo } from "../repos/i4-mailbox-special-use.js";
5
10
  import { shippedTableDdl } from "../test-shipped-sqlite-schema.js";
6
11
  import {
7
12
  type JunkOnlyRepairClient,
13
+ type JunkOnlyRepairMode,
14
+ type JunkOnlyReport,
8
15
  sweepJunkOnlyAddresses,
9
16
  } from "./junk-only-address.js";
10
17
 
@@ -22,8 +29,47 @@ interface AddressRow {
22
29
 
23
30
  describe("addresses standing only on mail in Junk", () => {
24
31
  let sqlite: Database.Database;
32
+ let specialUse: MailboxSpecialUseRepo;
33
+ let accountSetting: AccountSettingRepo;
34
+
35
+ /**
36
+ * Which folder holds Junk is resolved through the repository seam every
37
+ * other special-folder lookup reads, so the sweep honours an appointment and
38
+ * cannot disagree with the sync that harvested the address.
39
+ */
40
+ const sweep = async (
41
+ mode: JunkOnlyRepairMode = "repair",
42
+ ): Promise<JunkOnlyReport> =>
43
+ sweepJunkOnlyAddresses(
44
+ clientOver(sqlite),
45
+ mode,
46
+ await specialUse.resolveJunkRolesForInstance(),
47
+ );
25
48
 
26
- const mailbox = (mailboxId: string, specialUse: string | null): void => {
49
+ const account = (accountId: string): void => {
50
+ sqlite
51
+ .prepare(
52
+ `INSERT OR IGNORE INTO account (
53
+ account_id, account_config_id, username, email, imap_host,
54
+ imap_port, imap_tls, imap_start_tls, smtp_port, is_active,
55
+ connection_state, created_at, updated_at
56
+ ) VALUES (?, 'cfg-1', 'user', 'user@example.com', 'imap.example.com',
57
+ 993, 1, 0, 465, 1, 'disconnected', 0, 0)`,
58
+ )
59
+ .run(accountId);
60
+ };
61
+
62
+ const mailbox = (
63
+ mailboxId: string,
64
+ designation: string | null,
65
+ folder: {
66
+ accountId?: string;
67
+ fullPath?: string;
68
+ hierarchyDelimiter?: string;
69
+ } = {},
70
+ ): void => {
71
+ const accountId = folder.accountId ?? "acc";
72
+ account(accountId);
27
73
  sqlite
28
74
  .prepare(
29
75
  `INSERT INTO mailbox (
@@ -32,9 +78,29 @@ describe("addresses standing only on mail in Junk", () => {
32
78
  unseen_count, deleted_count, total_size, last_sync_uid,
33
79
  high_water_mark_uid, last_message_sync_at, special_use,
34
80
  created_at, updated_at
35
- ) VALUES (?, 'acc', '', '/', ?, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, ?, 0, 0)`,
81
+ ) VALUES (?, ?, '', ?, ?, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, ?, 0, 0)`,
36
82
  )
37
- .run(mailboxId, mailboxId, specialUse);
83
+ .run(
84
+ mailboxId,
85
+ accountId,
86
+ folder.hierarchyDelimiter ?? "/",
87
+ folder.fullPath ?? mailboxId,
88
+ designation,
89
+ );
90
+ };
91
+
92
+ const appointJunk = async (
93
+ accountId: string,
94
+ mailboxId: string,
95
+ ): Promise<void> => {
96
+ await accountSetting.upsert({
97
+ accountConfigId: "cfg-1",
98
+ name: composeFolderRoleAppointmentName(
99
+ accountId,
100
+ CanonicalMailboxRole.Junk,
101
+ ),
102
+ value: { kind: "String", value: mailboxId },
103
+ });
38
104
  };
39
105
 
40
106
  const specialUseEntry = (mailboxId: string, specialUse: string): void => {
@@ -117,12 +183,17 @@ describe("addresses standing only on mail in Junk", () => {
117
183
 
118
184
  before(() => {
119
185
  sqlite = new Database(":memory:");
186
+ const db = drizzle(sqlite);
187
+ specialUse = new MailboxSpecialUseRepo(db as never);
188
+ accountSetting = new AccountSettingRepo(db as never);
120
189
  for (const table of [
121
190
  "address",
122
191
  "envelope_address",
123
192
  "message",
124
193
  "mailbox",
125
194
  "mailbox_special_use_entry",
195
+ "account_setting",
196
+ "account",
126
197
  ]) {
127
198
  sqlite.exec(shippedTableDdl(DDL_TAG, table));
128
199
  }
@@ -148,6 +219,8 @@ describe("addresses standing only on mail in Junk", () => {
148
219
  "message",
149
220
  "mailbox",
150
221
  "mailbox_special_use_entry",
222
+ "account_setting",
223
+ "account",
151
224
  ]) {
152
225
  sqlite.exec(`DELETE FROM ${table}`);
153
226
  }
@@ -167,7 +240,7 @@ describe("addresses standing only on mail in Junk", () => {
167
240
  sighting("spammer", "spam-1");
168
241
  sighting("spammer", "spam-2");
169
242
 
170
- const report = await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
243
+ const report = await sweep();
171
244
 
172
245
  assert.equal(report.withholdable, 1);
173
246
  assert.equal(report.withheld, 1);
@@ -181,7 +254,7 @@ describe("addresses standing only on mail in Junk", () => {
181
254
  sighting("colleague", "spam-1");
182
255
  sighting("colleague", "mail-1");
183
256
 
184
- const report = await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
257
+ const report = await sweep();
185
258
 
186
259
  assert.equal(report.withholdable, 0);
187
260
  assert.equal(withheld("colleague"), false);
@@ -194,7 +267,7 @@ describe("addresses standing only on mail in Junk", () => {
194
267
  .prepare("UPDATE message SET mailbox_id = 'junk' WHERE message_id = ?")
195
268
  .run("mail-1");
196
269
 
197
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
270
+ await sweep();
198
271
 
199
272
  assert.equal(withheld("newsletter"), true);
200
273
  });
@@ -202,13 +275,13 @@ describe("addresses standing only on mail in Junk", () => {
202
275
  test("restores an address whose message moved out of Junk", async () => {
203
276
  address("misfiled");
204
277
  sighting("misfiled", "spam-1");
205
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
278
+ await sweep();
206
279
  assert.equal(withheld("misfiled"), true);
207
280
 
208
281
  sqlite
209
282
  .prepare("UPDATE message SET mailbox_id = 'inbox' WHERE message_id = ?")
210
283
  .run("spam-1");
211
- const report = await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
284
+ const report = await sweep();
212
285
 
213
286
  assert.equal(report.restorable, 1);
214
287
  assert.equal(report.restored, 1);
@@ -219,7 +292,7 @@ describe("addresses standing only on mail in Junk", () => {
219
292
  address("client", { outbound: 1 });
220
293
  sighting("client", "spam-1");
221
294
 
222
- const report = await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
295
+ const report = await sweep();
223
296
 
224
297
  assert.equal(report.withholdable, 0);
225
298
  assert.equal(withheld("client"), false);
@@ -229,7 +302,7 @@ describe("addresses standing only on mail in Junk", () => {
229
302
  address("friend", { reply: 2 });
230
303
  sighting("friend", "spam-1");
231
304
 
232
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
305
+ await sweep();
233
306
 
234
307
  assert.equal(withheld("friend"), false);
235
308
  });
@@ -238,7 +311,7 @@ describe("addresses standing only on mail in Junk", () => {
238
311
  address("boss", {}, '{"vip":{"value":true,"setAt":1}}');
239
312
  sighting("boss", "spam-1");
240
313
 
241
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
314
+ await sweep();
242
315
 
243
316
  assert.equal(withheld("boss"), false);
244
317
  });
@@ -247,13 +320,13 @@ describe("addresses standing only on mail in Junk", () => {
247
320
  address("reformed", {}, '{"junkOnly":{"value":true,"setAt":1}}');
248
321
  sighting("reformed", "spam-1");
249
322
 
250
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
323
+ await sweep();
251
324
  assert.equal(withheld("reformed"), true);
252
325
 
253
326
  sqlite
254
327
  .prepare("UPDATE address SET outbound_count = 1 WHERE address_id = ?")
255
328
  .run("reformed");
256
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
329
+ await sweep();
257
330
 
258
331
  assert.equal(withheld("reformed"), false);
259
332
  });
@@ -262,7 +335,7 @@ describe("addresses standing only on mail in Junk", () => {
262
335
  address("ex-colleague");
263
336
  sighting("ex-colleague", "bin-1");
264
337
 
265
- const report = await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
338
+ const report = await sweep();
266
339
 
267
340
  assert.equal(report.withholdable, 0);
268
341
  assert.equal(withheld("ex-colleague"), false);
@@ -273,7 +346,7 @@ describe("addresses standing only on mail in Junk", () => {
273
346
  sighting("spammer", "spam-1");
274
347
  sighting("spammer", "bin-1");
275
348
 
276
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
349
+ await sweep();
277
350
 
278
351
  assert.equal(withheld("spammer"), true);
279
352
  });
@@ -282,14 +355,14 @@ describe("addresses standing only on mail in Junk", () => {
282
355
  address("junk-then-bin");
283
356
  address("bin-then-junk");
284
357
  sighting("junk-then-bin", "spam-1");
285
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
358
+ await sweep();
286
359
  sighting("junk-then-bin", "bin-1");
287
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
360
+ await sweep();
288
361
 
289
362
  sighting("bin-then-junk", "bin-1");
290
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
363
+ await sweep();
291
364
  sighting("bin-then-junk", "spam-1");
292
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
365
+ await sweep();
293
366
 
294
367
  assert.equal(withheld("junk-then-bin"), true);
295
368
  assert.equal(withheld("bin-then-junk"), true);
@@ -299,12 +372,12 @@ describe("addresses standing only on mail in Junk", () => {
299
372
  address("spammer");
300
373
  sighting("spammer", "spam-1");
301
374
  sighting("spammer", "bin-1");
302
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
375
+ await sweep();
303
376
 
304
377
  sqlite
305
378
  .prepare("UPDATE address SET flags = '{}' WHERE address_id = ?")
306
379
  .run("spammer");
307
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
380
+ await sweep();
308
381
 
309
382
  assert.equal(withheld("spammer"), true);
310
383
  });
@@ -312,12 +385,12 @@ describe("addresses standing only on mail in Junk", () => {
312
385
  test("deleting every spam message leaves the mark standing", async () => {
313
386
  address("spammer");
314
387
  sighting("spammer", "spam-1");
315
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
388
+ await sweep();
316
389
 
317
390
  sqlite
318
391
  .prepare("UPDATE message SET mailbox_id = 'trash' WHERE message_id = ?")
319
392
  .run("spam-1");
320
- const report = await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
393
+ const report = await sweep();
321
394
 
322
395
  assert.equal(report.restorable, 0);
323
396
  assert.equal(withheld("spammer"), true);
@@ -326,12 +399,12 @@ describe("addresses standing only on mail in Junk", () => {
326
399
  test("deleting the spam does not put its sender back", async () => {
327
400
  address("spammer");
328
401
  sighting("spammer", "spam-1");
329
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
402
+ await sweep();
330
403
 
331
404
  sqlite
332
405
  .prepare("UPDATE message SET mailbox_id = 'trash' WHERE message_id = ?")
333
406
  .run("spam-1");
334
- const report = await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
407
+ const report = await sweep();
335
408
 
336
409
  assert.equal(report.restorable, 0);
337
410
  assert.equal(withheld("spammer"), true);
@@ -340,10 +413,10 @@ describe("addresses standing only on mail in Junk", () => {
340
413
  test("purging the spam does not put its sender back", async () => {
341
414
  address("spammer");
342
415
  sighting("spammer", "spam-1");
343
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
416
+ await sweep();
344
417
 
345
418
  sqlite.prepare("DELETE FROM message WHERE message_id = ?").run("spam-1");
346
- const report = await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
419
+ const report = await sweep();
347
420
 
348
421
  assert.equal(report.restorable, 0);
349
422
  assert.equal(withheld("spammer"), true);
@@ -355,7 +428,7 @@ describe("addresses standing only on mail in Junk", () => {
355
428
  sighting("reported", "spam-1");
356
429
  sighting("hushed", "spam-1");
357
430
 
358
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
431
+ await sweep();
359
432
 
360
433
  assert.equal(withheld("reported"), true);
361
434
  assert.equal(withheld("hushed"), true);
@@ -364,7 +437,7 @@ describe("addresses standing only on mail in Junk", () => {
364
437
  test("blocking a withheld sender never lifts the mark", async () => {
365
438
  address("spammer");
366
439
  sighting("spammer", "spam-1");
367
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
440
+ await sweep();
368
441
 
369
442
  sqlite
370
443
  .prepare(
@@ -373,96 +446,172 @@ describe("addresses standing only on mail in Junk", () => {
373
446
  WHERE address_id = ?`,
374
447
  )
375
448
  .run("spammer");
376
- const report = await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
449
+ const report = await sweep();
377
450
 
378
451
  assert.equal(report.restorable, 0);
379
452
  assert.equal(withheld("spammer"), true);
380
453
  });
381
454
 
382
455
  test("reads a Junk folder a server does not designate", async () => {
383
- mailbox("named-spam", null);
456
+ mailbox("named-spam", null, { accountId: "acc-named", fullPath: "Spam" });
384
457
  message("spam-5", "named-spam");
385
458
  address("by-name");
386
459
  sighting("by-name", "spam-5");
387
- sqlite
388
- .prepare("UPDATE mailbox SET full_path = 'Spam' WHERE mailbox_id = ?")
389
- .run("named-spam");
390
460
 
391
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
461
+ await sweep();
392
462
 
393
463
  assert.equal(withheld("by-name"), true);
394
464
  });
395
465
 
396
466
  test("reads a Junk folder nested under any prefix", async () => {
397
- mailbox("nested-spam", null);
467
+ mailbox("nested-spam", null, {
468
+ accountId: "acc-nested",
469
+ fullPath: "INBOX/Spam",
470
+ });
398
471
  message("spam-6", "nested-spam");
399
472
  address("nested");
400
473
  sighting("nested", "spam-6");
401
- sqlite
402
- .prepare(
403
- "UPDATE mailbox SET full_path = 'INBOX/Spam' WHERE mailbox_id = ?",
404
- )
405
- .run("nested-spam");
406
474
 
407
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
475
+ await sweep();
408
476
 
409
477
  assert.equal(withheld("nested"), true);
410
478
  });
411
479
 
412
480
  test("reads a Junk folder under a delimiter that is not a slash", async () => {
413
- mailbox("dotted-spam", null);
481
+ mailbox("dotted-spam", null, {
482
+ accountId: "acc-dotted",
483
+ fullPath: "Mail.Junk E-mail",
484
+ hierarchyDelimiter: ".",
485
+ });
414
486
  message("spam-7", "dotted-spam");
415
487
  address("dotted");
416
488
  sighting("dotted", "spam-7");
417
- sqlite
418
- .prepare(
419
- `UPDATE mailbox SET full_path = 'Mail.Junk E-mail',
420
- hierarchy_delimiter = '.' WHERE mailbox_id = ?`,
421
- )
422
- .run("dotted-spam");
423
489
 
424
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
490
+ await sweep();
425
491
 
426
492
  assert.equal(withheld("dotted"), true);
427
493
  });
428
494
 
429
495
  test("never reads a prefix as the folder it names", async () => {
430
- mailbox("spam-parent", null);
496
+ mailbox("spam-parent", null, {
497
+ accountId: "acc-parent",
498
+ fullPath: "Spam/Receipts",
499
+ });
431
500
  message("mail-2", "spam-parent");
432
501
  address("under-spam");
433
502
  sighting("under-spam", "mail-2");
434
- sqlite
435
- .prepare(
436
- "UPDATE mailbox SET full_path = 'Spam/Receipts' WHERE mailbox_id = ?",
437
- )
438
- .run("spam-parent");
439
503
 
440
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
504
+ await sweep();
441
505
 
442
506
  assert.equal(withheld("under-spam"), false);
443
507
  });
444
508
 
445
- test("reads the designation from either place it is stored", async () => {
446
- mailbox("column-only", '["Junk"]');
447
- mailbox("entry-only", null);
509
+ test("reads the designation the mailbox sync stored", async () => {
510
+ mailbox("entry-only", null, {
511
+ accountId: "acc-entry",
512
+ fullPath: "Bulk",
513
+ });
448
514
  specialUseEntry("entry-only", "Junk");
449
- message("spam-3", "column-only");
450
515
  message("spam-4", "entry-only");
451
- address("by-column");
452
516
  address("by-entry");
453
- sighting("by-column", "spam-3");
454
517
  sighting("by-entry", "spam-4");
455
518
 
456
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
519
+ await sweep();
457
520
 
458
- assert.equal(withheld("by-column"), true);
459
521
  assert.equal(withheld("by-entry"), true);
460
522
  });
461
523
 
524
+ test("a second folder named Spam never claims the role", async () => {
525
+ mailbox("second-spam", null, { fullPath: "Archive/Spam" });
526
+ message("spam-3", "second-spam");
527
+ address("filed-away");
528
+ sighting("filed-away", "spam-3");
529
+
530
+ await sweep();
531
+
532
+ assert.equal(withheld("filed-away"), false);
533
+ });
534
+
535
+ test("withholds on the Junk folder the account appointed", async () => {
536
+ mailbox("rubbish", null, {
537
+ accountId: "acc-appointed",
538
+ fullPath: "INBOX/Rubbish",
539
+ });
540
+ await appointJunk("acc-appointed", "rubbish");
541
+ message("spam-8", "rubbish");
542
+ address("appointed-spammer");
543
+ sighting("appointed-spammer", "spam-8");
544
+
545
+ await sweep();
546
+
547
+ assert.equal(withheld("appointed-spammer"), true);
548
+ });
549
+
550
+ test("leaves the same folder alone when nobody appointed it", async () => {
551
+ mailbox("unclaimed-rubbish", null, {
552
+ accountId: "acc-unappointed",
553
+ fullPath: "INBOX/Rubbish",
554
+ });
555
+ message("spam-9", "unclaimed-rubbish");
556
+ address("stranger");
557
+ sighting("stranger", "spam-9");
558
+
559
+ await sweep();
560
+
561
+ assert.equal(withheld("stranger"), false);
562
+ });
563
+
564
+ /**
565
+ * No folder holds Junk anywhere, so nothing is known about any sighting. The
566
+ * predicate must be silent in both directions: an empty id list read as "no
567
+ * message is in Junk" would make every sighting live mail and hand back
568
+ * every mark the instance had earned.
569
+ */
570
+ test("an instance with no Junk folder neither withholds nor restores", async () => {
571
+ for (const table of [
572
+ "envelope_address",
573
+ "message",
574
+ "mailbox",
575
+ "mailbox_special_use_entry",
576
+ ]) {
577
+ sqlite.exec(`DELETE FROM ${table}`);
578
+ }
579
+ mailbox("plain-inbox", null, { fullPath: "INBOX" });
580
+ message("mail-9", "plain-inbox");
581
+ address("colleague");
582
+ address("misfiled", {}, '{"junkOnly":{"value":true,"setAt":1}}');
583
+ sighting("colleague", "mail-9");
584
+ sighting("misfiled", "mail-9");
585
+
586
+ const report = await sweep();
587
+
588
+ assert.equal(report.withholdable, 0);
589
+ assert.equal(report.restorable, 0);
590
+ assert.equal(withheld("colleague"), false);
591
+ assert.equal(withheld("misfiled"), true);
592
+ });
593
+
594
+ test("standing the account gave an address lifts its mark regardless", async () => {
595
+ for (const table of ["mailbox", "mailbox_special_use_entry"]) {
596
+ sqlite.exec(`DELETE FROM ${table}`);
597
+ }
598
+ mailbox("plain-inbox", null, { fullPath: "INBOX" });
599
+ address(
600
+ "reformed",
601
+ { outbound: 1 },
602
+ '{"junkOnly":{"value":true,"setAt":1}}',
603
+ );
604
+
605
+ const report = await sweep();
606
+
607
+ assert.equal(report.restorable, 1);
608
+ assert.equal(withheld("reformed"), false);
609
+ });
610
+
462
611
  test("leaves an address no message has ever carried alone", async () => {
463
612
  address("orphan");
464
613
 
465
- const report = await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
614
+ const report = await sweep();
466
615
 
467
616
  assert.equal(report.withholdable, 0);
468
617
  assert.equal(withheld("orphan"), false);
@@ -476,7 +625,7 @@ describe("addresses standing only on mail in Junk", () => {
476
625
  sighting("colleague", "mail-1");
477
626
  sighting("client", "spam-2");
478
627
 
479
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
628
+ await sweep();
480
629
 
481
630
  assert.equal(addressCount(), 3);
482
631
  });
@@ -485,7 +634,7 @@ describe("addresses standing only on mail in Junk", () => {
485
634
  address("noisy", {}, '{"muted":{"value":true,"setAt":7}}');
486
635
  sighting("noisy", "spam-1");
487
636
 
488
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
637
+ await sweep();
489
638
 
490
639
  assert.deepEqual(JSON.parse(read("noisy").flags).muted, {
491
640
  value: true,
@@ -496,10 +645,10 @@ describe("addresses standing only on mail in Junk", () => {
496
645
  test("a second run writes nothing", async () => {
497
646
  address("spammer");
498
647
  sighting("spammer", "spam-1");
499
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
648
+ await sweep();
500
649
  const first = read("spammer");
501
650
 
502
- const report = await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
651
+ const report = await sweep();
503
652
 
504
653
  assert.equal(report.withholdable, 0);
505
654
  assert.equal(report.restorable, 0);
@@ -514,7 +663,7 @@ describe("addresses standing only on mail in Junk", () => {
514
663
  address("misfiled", {}, '{"junkOnly":{"value":true,"setAt":1}}');
515
664
  sighting("misfiled", "mail-1");
516
665
 
517
- const report = await sweepJunkOnlyAddresses(clientOver(sqlite), "check");
666
+ const report = await sweep("check");
518
667
 
519
668
  assert.equal(report.withholdable, 1);
520
669
  assert.equal(report.restorable, 1);
@@ -528,7 +677,7 @@ describe("addresses standing only on mail in Junk", () => {
528
677
  address("legacy", {}, "");
529
678
  sighting("legacy", "spam-1");
530
679
 
531
- await sweepJunkOnlyAddresses(clientOver(sqlite), "repair");
680
+ await sweep();
532
681
 
533
682
  assert.equal(withheld("legacy"), true);
534
683
  });