Batch of four reader-facing improvements (TODO "Compat lecteurs + dedup"): - JSON Feed at /json/:feedId (feed lib .json1()); all formats cross-link - OPML export at /admin/opml (admin-protected; the registry lists every feed URL, so it must not be public) - Conditional GET on /rss + /atom: strong ETag + Last-Modified, 304 on If-None-Match/If-Modified-Since, validators shared via http-cache.ts - Duplicate-send dedup in ingestion: match by Message-ID, fall back to a SHA-256 of normalized subject+content; a duplicate is a no-op and bumps the new emails_deduplicated counter (status page + /api/v1/stats) 429 tests green, tsc clean, build dry-run OK. Docs (README/CLAUDE/TODO + landing cards) updated. Co-Authored-By: Claude Opus 4.7 <[email protected]>
24 lines
751 B
TypeScript
24 lines
751 B
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { createMockEnv } from "../test/setup";
|
|
import { CountersRepository } from "./counters-repository";
|
|
import type { Env } from "../types";
|
|
|
|
const mockEnv = () => createMockEnv() as unknown as Env;
|
|
|
|
describe("CountersRepository", () => {
|
|
it("round-trips the counters singleton", async () => {
|
|
const repo = new CountersRepository(mockEnv().EMAIL_STORAGE);
|
|
expect(await repo.getRaw()).toBeNull();
|
|
await repo.put({
|
|
feeds_created: 1,
|
|
feeds_deleted: 0,
|
|
emails_received: 2,
|
|
emails_rejected: 0,
|
|
emails_forwarded: 0,
|
|
emails_deduplicated: 0,
|
|
unsubscribes_sent: 0,
|
|
});
|
|
expect(await repo.getRaw()).toMatchObject({ emails_received: 2 });
|
|
});
|
|
});
|