From a8faef27ad917bc932bb09cb26ab78477ecd7559 Mon Sep 17 00:00:00 2001 From: Po-Lin Lai Date: Sat, 18 Apr 2026 10:51:03 +0800 Subject: [PATCH] test(shared): extract push fixtures to packages/shared/src/__tests__/fixtures.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `makeUser`, `makeProblem`, `makeChannel` helpers were duplicated across push pipeline test files. Hoisted to a shared fixtures module so a schema change only touches one file instead of every suite. push.pipeline.test.ts migrated to use the shared fixtures. Other test files (push.pipeline.paused.test.ts, push.worker.test.ts) construct their own specialised mocks and are left untouched for now — they can migrate incrementally without a forcing function. Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/shared/src/__tests__/fixtures.ts | 57 +++++++++++++++++++ .../src/push/__tests__/push.pipeline.test.ts | 39 +------------ 2 files changed, 58 insertions(+), 38 deletions(-) create mode 100644 packages/shared/src/__tests__/fixtures.ts diff --git a/packages/shared/src/__tests__/fixtures.ts b/packages/shared/src/__tests__/fixtures.ts new file mode 100644 index 0000000..5e728e8 --- /dev/null +++ b/packages/shared/src/__tests__/fixtures.ts @@ -0,0 +1,57 @@ +/** + * Shared test fixtures for push-pipeline tests. + * + * Previously duplicated as local `makeUser` / `makeProblem` / `makeChannel` + * functions in individual test files. Centralised here so a schema change + * only needs to touch one place. + */ +import type { PushCandidate, VerifiedChannel } from '../push/push.repository.js' +import type { PushMessage, SelectedProblem } from '../types/push.js' + +export function makeUser(overrides: Partial = {}): PushCandidate { + return { + id: 'user-1', + timezone: 'Asia/Taipei', + active_mode: 'list', + difficulty_min: 0, + difficulty_max: 3000, + topic_filter: null, + line_push_allowed: true, + ...overrides, + } +} + +export function makeProblem(overrides: Partial = {}): SelectedProblem { + return { + problem_id: 42, + leetcode_id: 1, + slug: 'two-sum', + title: 'Two Sum', + difficulty: 'Easy', + explanation: 'Use a hash map.', + ...overrides, + } +} + +export function makeChannel(overrides: Partial = {}): VerifiedChannel { + return { + id: 'ch-1', + user_id: 'user-1', + channel_type: 'telegram', + channel_identifier: '123456', + ...overrides, + } +} + +export function makePushMessage(overrides: Partial = {}): PushMessage { + return { + title: 'Two Sum', + difficulty: 'Easy', + leetcodeId: 1, + explanation: 'Use a hash map.', + url: 'https://caffecode.net/problems/two-sum', + problemSlug: 'two-sum', + problemId: 42, + ...overrides, + } +} diff --git a/packages/shared/src/push/__tests__/push.pipeline.test.ts b/packages/shared/src/push/__tests__/push.pipeline.test.ts index 7b7f713..1da030d 100644 --- a/packages/shared/src/push/__tests__/push.pipeline.test.ts +++ b/packages/shared/src/push/__tests__/push.pipeline.test.ts @@ -14,13 +14,11 @@ import { stampLastPushDate, advanceListPositions, resetChannelFailures, - type PushCandidate, - type VerifiedChannel, } from '../push.repository.js' import { selectProblemForUser } from '../../services/problem-selector.js' import type { SupabaseClient } from '@supabase/supabase-js' -import type { SelectedProblem } from '../../types/push.js' import type { NotificationChannel } from '../channels/registry.js' +import { makeUser, makeProblem, makeChannel } from '../../__tests__/fixtures.js' const mockGetAllCandidates = vi.mocked(getAllCandidates) const mockGetChannels = vi.mocked(getVerifiedChannelsBulk) @@ -35,41 +33,6 @@ const db = {} as SupabaseClient // A p-limit stub that invokes the thunk immediately (no concurrency control needed in tests) const noopLimit = vi.fn((fn: () => unknown) => fn()) as unknown as LimitFunction -function makeUser(overrides: Partial = {}): PushCandidate { - return { - id: 'user-1', - timezone: 'Asia/Taipei', - active_mode: 'list', - difficulty_min: 0, - difficulty_max: 3000, - topic_filter: null, - line_push_allowed: true, - ...overrides, - } -} - -function makeProblem(overrides: Partial = {}): SelectedProblem { - return { - problem_id: 42, - leetcode_id: 1, - slug: 'two-sum', - title: 'Two Sum', - difficulty: 'Easy', - explanation: 'Use a hash map.', - ...overrides, - } -} - -function makeChannel(overrides: Partial = {}): VerifiedChannel { - return { - id: 'ch-1', - user_id: 'user-1', - channel_type: 'telegram', - channel_identifier: '123456', - ...overrides, - } -} - // Channel registry stub: dispatches succeed without real HTTP calls function makeChannelRegistry(channelTypes = ['telegram', 'email', 'line']): Record { const channel: NotificationChannel = vi.fn().mockResolvedValue({ success: true })