ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto
16
fork

Configure Feed

Select the types of activity you want to include in your feed.

test(worker): add cleanup job integration tests

byarielm.fyi fb581466 edf4c3e4

verified
+122
+103
packages/worker/__tests__/cleanupJob.test.ts
··· 1 + /** 2 + * Cleanup Job Integration Tests 3 + * 4 + * Inserts real rows into the test database, calls handleCleanupJob(), 5 + * and verifies the PostgreSQL cleanup_transient_data() function removed 6 + * exactly the expired rows (and kept the fresh ones). 7 + * 8 + * Column names match the actual schema in scripts/init-db.sql: 9 + * oauth_states: state (PK), data (JSONB), created_at 10 + * user_sessions: session_id (PK), did, fingerprint, expires_at 11 + */ 12 + 13 + import { describe, it, expect, beforeAll, afterAll, beforeEach } from "vitest"; 14 + import type { Job } from "bullmq"; 15 + import { sql } from "kysely"; 16 + import { db, closeConnection } from "../src/db/client"; 17 + import { handleCleanupJob } from "../src/jobs/cleanupJob"; 18 + import type { CleanupJobData } from "../src/jobs/cleanupJob"; 19 + 20 + /** Minimal mock of a BullMQ Job — only the fields our handler accesses */ 21 + function mockJob(id: string): Job<CleanupJobData> { 22 + return { id, attemptsMade: 0 } as Job<CleanupJobData>; 23 + } 24 + 25 + describe("Cleanup Job", () => { 26 + beforeAll(async () => { 27 + // Smoke-test the DB connection before running tests 28 + await sql`SELECT 1`.execute(db); 29 + }); 30 + 31 + afterAll(async () => { 32 + await closeConnection(); 33 + }); 34 + 35 + beforeEach(async () => { 36 + // Remove test rows left from a previous run 37 + await sql`DELETE FROM oauth_states WHERE state LIKE 'test-%'`.execute(db); 38 + await sql`DELETE FROM user_sessions WHERE session_id LIKE 'test-%'`.execute(db); 39 + }); 40 + 41 + it("removes expired OAuth states and keeps fresh ones", async () => { 42 + // Expired: created 2 hours ago (threshold is 1 hour) 43 + await sql` 44 + INSERT INTO oauth_states (state, data, created_at) 45 + VALUES ('test-expired-state', '{}', NOW() - INTERVAL '2 hours') 46 + `.execute(db); 47 + 48 + // Fresh: created 30 seconds ago — must survive cleanup 49 + await sql` 50 + INSERT INTO oauth_states (state, data, created_at) 51 + VALUES ('test-fresh-state', '{}', NOW() - INTERVAL '30 seconds') 52 + `.execute(db); 53 + 54 + const result = await handleCleanupJob(mockJob("test-job-1")); 55 + 56 + expect(result.cleaned).toBe(true); 57 + expect(result.timestamp).toBeDefined(); 58 + 59 + const rows = await sql<{ state: string }>` 60 + SELECT state FROM oauth_states WHERE state LIKE 'test-%' 61 + `.execute(db); 62 + 63 + expect(rows.rows).toHaveLength(1); 64 + expect(rows.rows[0].state).toBe("test-fresh-state"); 65 + }); 66 + 67 + it("removes expired user sessions and keeps valid ones", async () => { 68 + // Expired: expires_at in the past 69 + await sql` 70 + INSERT INTO user_sessions (session_id, did, fingerprint, expires_at) 71 + VALUES ('test-expired-session', 'did:plc:test-cleanup-1', 'fp', NOW() - INTERVAL '1 day') 72 + `.execute(db); 73 + 74 + // Valid: expires_at in the future 75 + await sql` 76 + INSERT INTO user_sessions (session_id, did, fingerprint, expires_at) 77 + VALUES ('test-valid-session', 'did:plc:test-cleanup-2', 'fp', NOW() + INTERVAL '7 days') 78 + `.execute(db); 79 + 80 + await handleCleanupJob(mockJob("test-job-2")); 81 + 82 + const rows = await sql<{ session_id: string }>` 83 + SELECT session_id FROM user_sessions WHERE session_id LIKE 'test-%' 84 + `.execute(db); 85 + 86 + expect(rows.rows).toHaveLength(1); 87 + expect(rows.rows[0].session_id).toBe("test-valid-session"); 88 + }); 89 + 90 + it("completes successfully when there is nothing to clean", async () => { 91 + const result = await handleCleanupJob(mockJob("test-job-3")); 92 + 93 + expect(result.cleaned).toBe(true); 94 + expect(result.timestamp).toBeDefined(); 95 + }); 96 + 97 + it("returns a valid ISO timestamp", async () => { 98 + const result = await handleCleanupJob(mockJob("test-job-4")); 99 + 100 + expect(() => new Date(result.timestamp)).not.toThrow(); 101 + expect(new Date(result.timestamp).toISOString()).toBe(result.timestamp); 102 + }); 103 + });
+19
packages/worker/__tests__/setup.ts
··· 1 + /** 2 + * Worker Test Setup 3 + * Runs before all tests to configure the environment. 4 + */ 5 + 6 + import { config } from "dotenv"; 7 + 8 + // Load .env.test if present (overrides are fine — test env wins) 9 + config({ path: ".env.test" }); 10 + 11 + if (!process.env.DATABASE_URL) { 12 + process.env.DATABASE_URL = 13 + "postgresql://atlast:localdev@localhost:5432/atlast"; 14 + } 15 + 16 + if (!process.env.REDIS_URL) { 17 + // Use Redis DB index 1 for tests to avoid colliding with dev data 18 + process.env.REDIS_URL = "redis://localhost:6379/1"; 19 + }