diff --git a/backend/src/__tests__/addresses.test.js b/backend/src/__tests__/addresses.test.js index ad099e3..8f63329 100644 --- a/backend/src/__tests__/addresses.test.js +++ b/backend/src/__tests__/addresses.test.js @@ -1,72 +1,92 @@ -const { test } = require('node:test'); -const assert = require('node:assert'); -const sinon = require('sinon'); -const router = require('../routes/addresses'); +import { test } from 'node:test'; +import assert from 'node:assert'; +import { app } from '../app.js'; +import { pool } from '../db/connection.js'; +import { encryptText } from '../services/encryption.js'; -// Mock the database pool -const mockPool = { - query: sinon.stub(), - getConnection: sinon.stub() +// Mock user for testing +const mockUser = { + userId: 1, + email: 'test@example.com' }; -// Mock the route functions with the mocked pool -const mockReq = { user: { userId: 1 }, pool: mockPool }; -const mockRes = { - status: sinon.stub().returnsThis(), - json: sinon.stub() -}; - -test('POST /change-request should validate input and handle existing address check', async () => { - // Test valid input - const validReq = { - ...mockReq, - body: { newAddress: '123 Main St, Anytown, USA' } +// Helper to create a test request +function createTestRequest(path, method, body = {}, headers = {}) { + return { + method, + path, + headers: { + 'Content-Type': 'application/json', + ...headers + }, + body }; +} - mockPool.query.onCall(0).resolves([{ id: 1 }]); // Existing address check - mockPool.query.onCall(1).resolves({ insertId: 1 }); // Insert request +test('POST /addresses/change-request - valid address change request', async () => { + // Mock existing address in DB + await pool.query( + `INSERT INTO addresses (user_id, address_encrypted, postal_verified_at) + VALUES (?, ?, CURRENT_TIMESTAMP)`, + [mockUser.userId, encryptText('Old Address')] + ); - await router.post('/change-request', validReq, mockRes); + const req = createTestRequest('/addresses/change-request', 'POST', { + newAddress: 'New Test Address' + }); - assert.strictEqual(mockRes.status.calledWith(201), true); - assert.strictEqual(mockRes.json.calledOnce, true); + const res = await app.request(req); + + assert.strictEqual(res.status, 201); + const data = await res.json(); + assert.ok(data.requestId); + assert.strictEqual(data.postalDispatch, 'pending_letter'); + assert.ok(data.verificationCode); }); -test('POST /change-request should reject invalid input', async () => { - const invalidReq = { - ...mockReq, - body: { newAddress: 'Invalid' } // Too short - }; +test('POST /addresses/change-request - invalid address (too short)', async () => { + const req = createTestRequest('/addresses/change-request', 'POST', { + newAddress: 'Short' + }); - await router.post('/change-request', invalidReq, mockRes); + const res = await app.request(req); - assert.strictEqual(mockRes.status.calledWith(400), true); + assert.strictEqual(res.status, 400); + const data = await res.json(); + assert.ok(data.error); }); -test('POST /verify should validate input and handle verification flow', async () => { - const validReq = { - ...mockReq, - body: { requestId: 1, code: '123456' } - }; +test('POST /addresses/verify - valid verification', async () => { + // Mock a change request first + const code = '123456'; + const codeHash = 'hashed_code'; + await pool.query( + `INSERT INTO address_change_requests (user_id, new_address_encrypted, verification_code_hash, status) + VALUES (?, ?, ?, 'pending_letter')`, + [mockUser.userId, encryptText('New Address'), codeHash] + ); - mockPool.query.onCall(0).resolves([{ id: 1, user_id: 1, new_address_encrypted: 'encrypted', verification_code_hash: 'hash', status: 'pending_letter' }]); - mockPool.query.onCall(1).resolves(); // Update request - mockPool.query.onCall(2).resolves(); // Insert address + const req = createTestRequest('/addresses/verify', 'POST', { + requestId: 1, + code + }); - await router.post('/verify', validReq, mockRes); + const res = await app.request(req); - assert.strictEqual(mockRes.json.calledWith({ status: 'verified' }), true); + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.status, 'verified'); }); -test('POST /verify should reject invalid verification code', async () => { - const invalidReq = { - ...mockReq, - body: { requestId: 1, code: '000000' } // Wrong code - }; +test('POST /addresses/verify - invalid verification code', async () => { + const req = createTestRequest('/addresses/verify', 'POST', { + requestId: 1, + code: 'wrongcode' + }); - mockPool.query.onCall(0).resolves([{ id: 1, user_id: 1, new_address_encrypted: 'encrypted', verification_code_hash: 'hash', status: 'pending_letter' }]); + const res = await app.request(req); - await router.post('/verify', invalidReq, mockRes); - - assert.strictEqual(mockRes.status.calledWith(400), true); + assert.strictEqual(res.status, 400); + const data = await res.json(); + assert.ok(data.error); }); \ No newline at end of file diff --git a/docs/runtime/pick_next_task_state.env b/docs/runtime/pick_next_task_state.env index e987593..5b07377 100644 --- a/docs/runtime/pick_next_task_state.env +++ b/docs/runtime/pick_next_task_state.env @@ -1,2 +1,2 @@ -LAST_ROUTE=reviews.js -UPDATED_AT=2026-03-06T19:51:18Z +LAST_ROUTE=addresses.js +UPDATED_AT=2026-03-06T19:52:37Z