fix(tst-005): fix PATCH route (/:id not /:id/evidence), fix mock method names
This commit is contained in:
parent
469adb64fa
commit
8d6a2c2086
1 changed files with 58 additions and 8 deletions
|
|
@ -2,8 +2,9 @@
|
||||||
* TST-005: Transactions API Integration Tests (CC-047)
|
* TST-005: Transactions API Integration Tests (CC-047)
|
||||||
*
|
*
|
||||||
* Tests HTTP contract of TransactionsController:
|
* Tests HTTP contract of TransactionsController:
|
||||||
* - validation of amountMinorUnits as integer
|
* - validation of amountMinorUnits as integer >= 0
|
||||||
* - currency and evidenceStatus validation
|
* - currency length validation (3 chars)
|
||||||
|
* - evidenceStatus enum validation on create + update
|
||||||
* - ParseUUIDPipe on path params
|
* - ParseUUIDPipe on path params
|
||||||
* - response shapes
|
* - response shapes
|
||||||
*/
|
*/
|
||||||
|
|
@ -64,7 +65,8 @@ const mockTxService = {
|
||||||
list: jest.fn().mockResolvedValue([MOCK_TX]),
|
list: jest.fn().mockResolvedValue([MOCK_TX]),
|
||||||
getById: jest.fn().mockResolvedValue(MOCK_TX),
|
getById: jest.fn().mockResolvedValue(MOCK_TX),
|
||||||
create: jest.fn().mockResolvedValue(MOCK_TX),
|
create: jest.fn().mockResolvedValue(MOCK_TX),
|
||||||
updateEvidence: jest.fn().mockResolvedValue({ ...MOCK_TX, evidenceStatus: 'complete' }),
|
update: jest.fn().mockResolvedValue({ ...MOCK_TX, evidenceStatus: 'complete' }),
|
||||||
|
softDelete: jest.fn().mockResolvedValue({ deleted: true }),
|
||||||
};
|
};
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
|
@ -96,6 +98,21 @@ describe('TST-005: Transactions API Integration', () => {
|
||||||
afterAll(() => app.close());
|
afterAll(() => app.close());
|
||||||
beforeEach(() => jest.clearAllMocks());
|
beforeEach(() => jest.clearAllMocks());
|
||||||
|
|
||||||
|
describe('GET /v1/transactions', () => {
|
||||||
|
it('returns 401 without auth', async () => {
|
||||||
|
await request(app.getHttpServer()).get('/v1/transactions').expect(401);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns 200 with array when authenticated', async () => {
|
||||||
|
const res = await request(app.getHttpServer())
|
||||||
|
.get('/v1/transactions')
|
||||||
|
.set('Authorization', AUTH)
|
||||||
|
.expect(200);
|
||||||
|
expect(Array.isArray(res.body)).toBe(true);
|
||||||
|
expect(mockTxService.list).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('POST /v1/transactions', () => {
|
describe('POST /v1/transactions', () => {
|
||||||
const VALID_BODY = {
|
const VALID_BODY = {
|
||||||
organizationId: VALID_ORG_UUID,
|
organizationId: VALID_ORG_UUID,
|
||||||
|
|
@ -103,7 +120,6 @@ describe('TST-005: Transactions API Integration', () => {
|
||||||
amountMinorUnits: 123400,
|
amountMinorUnits: 123400,
|
||||||
currency: 'EUR',
|
currency: 'EUR',
|
||||||
transactionDate: '2026-07-31',
|
transactionDate: '2026-07-31',
|
||||||
evidenceStatus: 'missing',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
it('returns 201 with valid body', async () => {
|
it('returns 201 with valid body', async () => {
|
||||||
|
|
@ -131,7 +147,7 @@ describe('TST-005: Transactions API Integration', () => {
|
||||||
.expect(400);
|
.expect(400);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns 400 when evidenceStatus is invalid', async () => {
|
it('returns 400 when evidenceStatus is invalid enum', async () => {
|
||||||
await request(app.getHttpServer())
|
await request(app.getHttpServer())
|
||||||
.post('/v1/transactions')
|
.post('/v1/transactions')
|
||||||
.set('Authorization', AUTH)
|
.set('Authorization', AUTH)
|
||||||
|
|
@ -147,6 +163,14 @@ describe('TST-005: Transactions API Integration', () => {
|
||||||
.expect(400);
|
.expect(400);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns 400 when currency is not 3 chars', async () => {
|
||||||
|
await request(app.getHttpServer())
|
||||||
|
.post('/v1/transactions')
|
||||||
|
.set('Authorization', AUTH)
|
||||||
|
.send({ ...VALID_BODY, currency: 'EURO' })
|
||||||
|
.expect(400);
|
||||||
|
});
|
||||||
|
|
||||||
it('returns 400 when required field missing (currency)', async () => {
|
it('returns 400 when required field missing (currency)', async () => {
|
||||||
const { currency: _c, ...bodyWithoutCurrency } = VALID_BODY;
|
const { currency: _c, ...bodyWithoutCurrency } = VALID_BODY;
|
||||||
await request(app.getHttpServer())
|
await request(app.getHttpServer())
|
||||||
|
|
@ -157,21 +181,47 @@ describe('TST-005: Transactions API Integration', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('PATCH /v1/transactions/:id/evidence', () => {
|
describe('PATCH /v1/transactions/:id', () => {
|
||||||
it('returns 200 with valid UUID and valid body', async () => {
|
it('returns 200 with valid UUID and valid body', async () => {
|
||||||
await request(app.getHttpServer())
|
await request(app.getHttpServer())
|
||||||
.patch(`/v1/transactions/${VALID_UUID}/evidence`)
|
.patch(`/v1/transactions/${VALID_UUID}`)
|
||||||
.set('Authorization', AUTH)
|
.set('Authorization', AUTH)
|
||||||
.send({ evidenceStatus: 'complete' })
|
.send({ evidenceStatus: 'complete' })
|
||||||
.expect(200);
|
.expect(200);
|
||||||
|
expect(mockTxService.update).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns 400 for non-UUID path param', async () => {
|
it('returns 400 for non-UUID path param', async () => {
|
||||||
await request(app.getHttpServer())
|
await request(app.getHttpServer())
|
||||||
.patch('/v1/transactions/not-a-uuid/evidence')
|
.patch('/v1/transactions/not-a-uuid')
|
||||||
.set('Authorization', AUTH)
|
.set('Authorization', AUTH)
|
||||||
.send({ evidenceStatus: 'complete' })
|
.send({ evidenceStatus: 'complete' })
|
||||||
.expect(400);
|
.expect(400);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns 400 for invalid evidenceStatus in body', async () => {
|
||||||
|
await request(app.getHttpServer())
|
||||||
|
.patch(`/v1/transactions/${VALID_UUID}`)
|
||||||
|
.set('Authorization', AUTH)
|
||||||
|
.send({ evidenceStatus: 'flying' })
|
||||||
|
.expect(400);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('DELETE /v1/transactions/:id', () => {
|
||||||
|
it('returns 200 with valid UUID', async () => {
|
||||||
|
await request(app.getHttpServer())
|
||||||
|
.delete(`/v1/transactions/${VALID_UUID}`)
|
||||||
|
.set('Authorization', AUTH)
|
||||||
|
.expect(200);
|
||||||
|
expect(mockTxService.softDelete).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns 400 for non-UUID path param', async () => {
|
||||||
|
await request(app.getHttpServer())
|
||||||
|
.delete('/v1/transactions/not-a-uuid')
|
||||||
|
.set('Authorization', AUTH)
|
||||||
|
.expect(400);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue