Files
archy/docker/gashboard/apps/api/tests/chat.test.ts
T

51 lines
2.6 KiB
TypeScript

import { after, test } from "node:test";
import assert from "node:assert/strict";
import { mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
process.env.JWT_SECRET = "local-test-only-secret-32-characters-long";
process.env.DATUM_ADMIN_PASSWORD = "local-test-only";
process.env.NOSTR_OWNER_PUBKEYS = "a".repeat(64);
const { ChatStore } = await import("../src/chat/store.js");
const dir = mkdtempSync(join(tmpdir(), "gashboard-chat-"));
after(() => rmSync(dir, { recursive: true, force: true }));
const owner = "a".repeat(64);
const viewer = "b".repeat(64);
const newcomer = "c".repeat(64);
test("encrypted history, reactions and key wraps survive restart with private permissions", () => {
const file = join(dir, "chat.json");
const store = new ChatStore(file);
store.shareKey(owner, [{ recipientPubkey: owner, ciphertext: "encrypted-key" }]);
const message = store.addMessage({ pubkey: owner, content: "encrypted-message" });
store.addReaction({ pubkey: owner, messageId: message.id, content: "encrypted-reaction" });
assert.deepEqual(new ChatStore(file).list(), store.list());
assert.equal(statSync(file).mode & 0o777, 0o600);
const copy = store.list();
copy.keyWraps[0]!.ciphertext = "changed";
assert.equal(store.list().keyWraps[0]!.ciphertext, "encrypted-key");
writeFileSync(file, "{}");
assert.throws(() => new ChatStore(file));
});
test("new invitations and simultaneous first visits cannot overwrite the room key", () => {
const store = new ChatStore(join(dir, "invites.json"));
store.shareKey(owner, [{ recipientPubkey: owner, ciphertext: "original-key" }]);
assert.throws(() => store.shareKey(viewer, [{ recipientPubkey: viewer, ciphertext: "different-key" }]), /existing chat member/);
store.shareKey(owner, [{ recipientPubkey: viewer, ciphertext: "same-key-for-viewer" }]);
assert.throws(() => store.shareKey(viewer, [{ recipientPubkey: viewer, ciphertext: "replacement-key" }]), /already shared/);
store.shareKey(viewer, [{ recipientPubkey: newcomer, ciphertext: "same-key-for-newcomer" }]);
assert.equal(store.list().keyWraps[0]!.ciphertext, "original-key");
assert.equal(store.list().keyWraps.length, 3);
});
test("failed persistence does not report or retain an unsaved message", () => {
const parent = join(dir, "blocked");
const store = new ChatStore(join(parent, "chat.json"));
writeFileSync(parent, "not a directory");
assert.throws(() => store.addMessage({ pubkey: owner, content: "ciphertext" }));
assert.deepEqual(store.list().messages, []);
assert.equal(readFileSync(parent, "utf8"), "not a directory");
});