| author | Eric Roberts
<eric@devl.me> 2026-09-15 15:38:54 UTC |
| committer | Eric Roberts
<eric@devl.me> 2026-09-21 17:49:22 UTC |
| parent | 7b5bd51434020fae6b30b79e6982717fcb6022f0 |
| npm/package.json | +2 | -1 |
| test/idb.spec.ts | +2 | -0 |
| test/persistence-factories.ts | +86 | -0 |
| test/persistence-tests.ts | +40 | -0 |
| test/sqlite.spec.ts | +8 | -1 |
diff --git a/npm/package.json b/npm/package.json index 6617be6..e681a4d 100644 --- a/npm/package.json +++ b/npm/package.json @@ -38,11 +38,12 @@ } }, "devDependencies": { + "@faker-js/faker": "^10.6.0", "@sqlite.org/sqlite-wasm": "^3.53.0-build1", "@vitest/browser": "^5.0.0", "@vitest/browser-playwright": "^5.0.0", - "oxlint": "^1.82.0", "oxfmt": "^0.67.0", + "oxlint": "^1.82.0", "playwright": "1.60.0", "typescript": "^5.4.5", "vitest": "^5.0.0" diff --git a/test/idb.spec.ts b/test/idb.spec.ts index 36df8c5..98e71f5 100644 --- a/test/idb.spec.ts +++ b/test/idb.spec.ts @@ -1,5 +1,6 @@ import { expect, test } from "vitest"; import * as borogove from "../playwright/.cache/borogove.js"; +import { createFactories } from "./persistence-factories"; import { sharedPersistenceTests } from "./persistence-tests"; async function idbFixture() { @@ -35,6 +36,7 @@ async function idbFixture() { }); }; return { + factories: createFactories(borogove), borogove, persistence, createChannel, diff --git a/test/persistence-factories.ts b/test/persistence-factories.ts new file mode 100644 index 0000000..53cb915 --- /dev/null +++ b/test/persistence-factories.ts @@ -0,0 +1,86 @@ +import { faker } from "@faker-js/faker"; + +type MakeMessageOpts = { + serverId?: string; + serverIdBy?: string; + localId?: string; + senderId?: string; + to?: any; // JID + from?: any; // JID + direction?: 0 | 1; + sortId?: string; + recipients?: string[]; + replyTo?: string[]; + text?: string; + timestamp?: Date; + versions?: any[]; +}; + +type CorrectionProps = { + text: string; +}; + +export function createFactories(borogove: any) { + const message = ({ + serverId, + serverIdBy, + localId, + senderId, + to, + from, + direction, + sortId, + recipients, + replyTo, + text, + timestamp, + versions, + }: MakeMessageOpts = {}) => { + const toJID = to ?? borogove.JID.parse(faker.internet.email()); + const fromJID = from ?? borogove.JID.parse(faker.internet.email()); + + const builder = new borogove.ChatMessageBuilder({ + serverId: serverId ?? crypto.randomUUID(), + serverIdBy: serverIdBy ?? toJID.asString(), + localId: localId ?? crypto.randomUUID(), + senderId: senderId ?? fromJID.asString(), + direction: direction ?? 0, + }); + builder.sortId = sortId ?? crypto.randomUUID(); + builder.to = toJID; + builder.from = fromJID; + builder.recipients = recipients ?? [toJID]; + builder.replyTo = replyTo ?? [fromJID]; + builder.versions = versions ?? []; + builder.text = text ?? faker.lorem.sentence(); + builder.timestamp = timestamp?.toISOString() ?? new Date().toISOString(); + + return builder.build(); + }; + + const corrections = (original: any, props: CorrectionProps[]) => { + const originalTimestamp = new Date(original.timestamp).getTime(); + + return props.map(({ text }, index) => { + const versionTimestamp = new Date(originalTimestamp + index + 1); + + const version = message({ + to: original.to, + from: original.from, + text, + timestamp: versionTimestamp, + }); + + return message({ + to: original.to, + from: original.from, + localId: original.localId, + versions: [version], + timestamp: versionTimestamp, + text, + }); + }); + }; + + return { message, corrections }; +} diff --git a/test/persistence-tests.ts b/test/persistence-tests.ts index 66f908a..beee6c8 100644 --- a/test/persistence-tests.ts +++ b/test/persistence-tests.ts @@ -1,3 +1,4 @@ +import { faker } from "@faker-js/faker"; import { expect } from "vitest"; export function sharedPersistenceTests(test) { @@ -1937,6 +1938,45 @@ export function sharedPersistenceTests(test) { ]); expect([...stored.reactions.keys()]).toEqual([]); }); + + test("storeMessages properly stores corrected messages", async ({ + factories, + borogove, + persistence, + }) => { + const account = faker.internet.email(); + const to = borogove.JID.parse(account); + const original = factories.message({ to, text: "Original message" }); + await persistence.storeMessages(account, [original]); + + const [correction] = factories.corrections(original, [ + { text: "Corrected message" }, + ]); + const [stored, ...restStored] = await persistence.storeMessages(account, [ + correction, + ]); + + expect(restStored.length).toBe(0); + expect(stored.localId).toBe(original.localId); + expect(stored.serverId).toBe(original.serverId); + expect(stored.text).toBe(correction.text); + + expect(stored.versions.map((version) => version.text)).toEqual([ + correction.text, + original.text, + ]); + const [fetched, ...rest] = await persistence.getMessagesBefore( + account, + original.chatId(), + ); + + expect(rest.length).toBe(0); + expect(fetched?.text).toBe(correction.text); + expect(fetched?.versions.map((version) => version.text)).toEqual([ + correction.text, + original.text, + ]); + }); } type TestKeyPair = { diff --git a/test/sqlite.spec.ts b/test/sqlite.spec.ts index d34b33f..3efcccc 100644 --- a/test/sqlite.spec.ts +++ b/test/sqlite.spec.ts @@ -1,6 +1,7 @@ import { test } from "vitest"; import * as borogove from "../playwright/.cache/borogove.js"; import * as sqlite from "../playwright/.cache/sqlite-wasm.js"; +import { createFactories } from "./persistence-factories"; import { sharedPersistenceTests } from "./persistence-tests"; async function sqliteFixture() { @@ -48,7 +49,13 @@ async function sqliteFixture() { ], ); }; - return { borogove, persistence, createChannel, storeIncompleteMember }; + return { + factories: createFactories(borogove), + borogove, + persistence, + createChannel, + storeIncompleteMember, + }; } const sqlitePersistence = sqliteFixture();