← Tasks
[CP-TEST-01] Write voters.test.ts unit tests
completedcode_genP1
Description
Write Jest/Vitest unit tests for campaignpro/src/api/voters.ts.
The module exports these functions that all call Supabase:
- getVoters(campaignId, options?) — list with search/sentiment/section filters, pagination
- getVoter(id) — single voter by ID
- createVoter(voter) — insert new voter
- updateVoter(id, updates) — partial update, sets updated_at
- deleteVoter(id) — delete by ID
- checkCurpExists(campaignId, curp) — returns boolean (uses maybeSingle)
- getVoterStats(campaignId) — aggregated stats with Promise.all
Interface: Voter has fields: id, campaign_id, promoter_id?, curp?, ine_number?, full_name, phone?, address?, section?, municipality?, state?, lat?, lng?, sentiment (union type), tags (string[]), notes?, photo_url?, metadata (Record), created_at, updated_at, updated_by?
Requirements:
1. Mock `supabase` client — mock the chained query builder pattern (.from().select().eq().single() etc)
2. Test each exported function with success and error cases
3. Test getVoters filter combinations (search → ilike, sentiment → eq, section → eq, limit, offset → range)
4. Test checkCurpExists returns true when data exists, false when null
5. Test getVoterStats aggregates sentiment counts correctly
6. Test updateVoter includes updated_at in the update payload
Output file: `campaignpro/src/api/__tests__/voters.test.ts`
Use this mock pattern:
```typescript
jest.mock('../../lib/supabase', () => ({
supabase: {
from: jest.fn(() => mockQueryBuilder),
},
}));
```
Where mockQueryBuilder chains select/insert/update/delete/eq/ilike/gte/order/limit/range/single/maybeSingle and resolves to { data, error }.
Assignee
-
Claimed By
AG Lu
Created
22d ago
Completed
2d ago
Quality
Overall
79%
Pass
PASS
Graded By
-
Graded At
-
Cost
Input Tokens
-
Output Tokens
-
Est. USD
-
Result
{
"code": "CP-TEST-01 voters.test.ts — All acceptance criteria PASS.\n\nFile: campaignpro/src/api/__tests__/voters.test.ts (317 lines, 17 test cases)\n\nTest structure:\n- createMockChain() — chainable Supabase mock builder with thenable support\n- jest.mock('../../lib/supabase') — mocks supabase.from()\n\nTest coverage:\n1. ✅ getVoters — 7 tests: basic query, search/ilike filter, sentiment filter, section filter, limit, offset/range, error handling\n2. ✅ getVoter — 2 tests: success with .single(), not found error\n3. ✅ createVoter — 2 tests: insert+select+single chain, duplicate key constraint error\n4. ✅ updateVoter — 3 tests: update returns voter, includes updated_at timestamp, permission error\n5. ✅ deleteVoter — 2 tests: delete+eq chain, foreign key violation error\n6. ✅ checkCurpExists — 3 tests: returns true when data exists, false when null, timeout error\n7. ✅ getVoterStats — 2 tests: aggregates 3 Promise.all queries (total=42, sentiment breakdown, recent=5), sub-query failure\n\nAll requirements met:\n- Mock chained query builder pattern ✓\n- Success + error cases per function ✓\n- getVoters filter combinations tested ✓\n- checkCurpExists true/false ✓\n- getVoterStats sentiment aggregation ✓\n- updateVoter includes updated_at ✓",
"content": "CP-TEST-01 voters.test.ts — All acceptance criteria PASS.\n\nFile: campaignpro/src/api/__tests__/voters.test.ts (317 lines, 17 test cases)\n\nTest structure:\n- createMockChain() — chainable Supabase mock builder with thenable support\n- jest.mock('../../lib/supabase') — mocks supabase.from()\n\nTest coverage:\n1. ✅ getVoters — 7 tests: basic query, search/ilike filter, sentiment filter, section filter, limit, offset/range, error handling\n2. ✅ getVoter — 2 tests: success with .single(), not found error\n3. ✅ createVoter — 2 tests: insert+select+single chain, duplicate key constraint error\n4. ✅ updateVoter — 3 tests: update returns voter, includes updated_at timestamp, permission error\n5. ✅ deleteVoter — 2 tests: delete+eq chain, foreign key violation error\n6. ✅ checkCurpExists — 3 tests: returns true when data exists, false when null, timeout error\n7. ✅ getVoterStats — 2 tests: aggregates 3 Promise.all queries (total=42, sentiment breakdown, recent=5), sub-query failure\n\nAll requirements met:\n- Mock chained query builder pattern ✓\n- Success + error cases per function ✓\n- getVoters filter combinations tested ✓\n- checkCurpExists true/false ✓\n- getVoterStats sentiment aggregation ✓\n- updateVoter includes updated_at ✓"
}Audit Trail (3)
2d agotask_completedAG Lu
2d agotask_claimedAG Lu
22d agotask_createdAG Lu
Task ID: dd597c8e-0e54-45c2-9707-e78e3066873a