// @vitest-environment jsdom // // An audit row whose server summary is a fixed English line ("log_level = DEBUG", "rss_poll → 15 // min/run", "Background sync paused") reads in the reader's language, rebuilt from the row's // data through the REAL catalog. A row whose summary is data (an e-mail, a URL) keeps it. import { readFileSync } from "node:fs"; import { resolve } from "node:path"; import { afterEach, describe, expect, it } from "vitest"; import i18n, { setLanguage } from "../i18n"; import type { AuditRow } from "./api"; import { auditText } from "./auditText"; afterEach(() => { setLanguage("en"); }); const row = (over: Partial): AuditRow => ({ id: 1, created_at: null, actor_id: null, action: "sync_pause", target_type: null, target_id: null, summary: null, before: null, after: null, request_id: null, log_lines: 0, ...over, }); function details(r: AuditRow): string { setLanguage("hu"); const t = i18n.getFixedT("hu"); const { head, sub } = auditText(t, r, "hu"); return [head, sub].filter(Boolean).join(" | "); } describe("an audit row's details", () => { it("name a config change's field and values", () => { const set = row({ action: "config_set", target_type: "config", target_id: "plex_enabled", summary: "plex_enabled = True", before: { value: false }, after: { value: true }, }); expect(details(set)).toMatch(/ \| Ki → Be$/); expect(details(set)).not.toContain("plex_enabled"); const reset = row({ action: "config_reset", target_type: "config", target_id: "download_upload_max_bytes", summary: "download_upload_max_bytes → default", before: { value: 5242880 }, }); expect(details(reset)).toMatch(/ \| 5\s242\s880 → alapérték$/); const secret = row({ action: "config_set", target_type: "config", target_id: "youtube_api_key", summary: "youtube_api_key = (secret updated)", }); expect(details(secret)).toMatch(/ \| titok frissítve/); }); it("tell a secret's reset from its update, and name a choice", () => { const reset = row({ action: "config_reset", target_type: "config", target_id: "tmdb_api_key", summary: "tmdb_api_key → default", }); expect(details(reset)).toMatch(/ \| titok visszaállítva/); const choice = row({ action: "config_set", target_type: "config", target_id: "plex_transcode_hw", before: { value: "auto" }, after: { value: "on" }, }); expect(details(choice)).toMatch(/ \| Automatikus → GPU$/); }); it("name an interval, a batch and a count in the reader's language", () => { expect( details( row({ action: "scheduler_interval", target_type: "job", target_id: "rss_poll", summary: "rss_poll → 15 min/run", after: { interval_minutes: 15 }, }), ), ).toBe("RSS-lekérdezés (új feltöltések) | 15 percenként"); expect( details(row({ action: "maintenance_tune", after: { revalidate_batch: 50000 } })), ).toMatch(/^Futásonként újraellenőrzött videók \| 50\s000$/); expect( details( row({ action: "audit_clear", summary: "Cleared 12 audit entries", after: { cleared: 12 } }), ), ).not.toContain("Cleared"); }); it("add nothing to a pause, whose action already says it", () => { expect(details(row({ action: "sync_pause", summary: "Background sync paused" }))).toBe(""); }); it("say a token revoke and a token's file work in the reader's language", () => { const revoke = details( row({ action: "api_token_revoke", target_type: "api_token", target_id: "11", summary: "revoked with every session of the account", }), ); expect(revoke).not.toMatch(/revoked/); expect(revoke).toMatch(/munkamenet/); const upload = details( row({ action: "file_upload", target_type: "file", summary: "api token sfl_Q3qXFfcv…" }), ); expect(upload).not.toMatch(/api token/); expect(upload).toContain("sfl_Q3qXFfcv…"); // The line read above is the one the server writes. const apitokens = readFileSync( resolve(__dirname, "../../../backend/app/apitokens.py"), "utf-8", ); expect(apitokens).toContain('f"api token {self.token_prefix}…"'); }); it("keep a summary that is data", () => { expect(details(row({ action: "invite_add", summary: "someone@example.com" }))).toBe( "someone@example.com", ); }); });