Task 3-1: Integration Test - Gasless NFT Transfer
Phase: 3 Priority: Medium Module:
biconomyDepends on: task-1-1 Reference: docs/bountyhunter-blockchain-p2/details/feature-evm-integration/SPEC.md
Background
Chưa có integration test cho luồng gasless NFT transfer end-to-end. Luồng này bao gồm nhiều bước: nhận API request, kiểm tra network support, đẩy job vào queue, Processor xử lý job, gọi Biconomy SDK, và callback webhook về Backend. Cần test đủ các nhánh bao gồm gasless, non-gasless, và idempotency khi txHash đã tồn tại.
Tasks
Note: Sử dụng
@nestjs/testingđể tạo test module. MockBullModulequeue bằngbull-mockhoặc in-memory queue. MockBiconomyServicehoặc Biconomy SDK calls để tránh gọi thật lên chain. Dùngsupertestcho API-level test. Đảm bảotask-1-1đã hoàn thành (Logger thay thế console.log) để log output có thể kiểm tra trong test.
- [ ] Tạo test file
biconomy.integration.spec.tshoặcbiconomy.e2e-spec.ts - [ ] Test case 1 — Happy path gasless NFT transfer:
it('POST /biconomy/send-transaction → job queued → processor completes → webhook called', async () => { const mockWebhook = jest.fn().mockResolvedValue({ status: 200 }); // Mock postWithRetry jest.spyOn(httpService, 'post').mockImplementation(mockWebhook); const res = await request(app.getHttpServer()) .post('/biconomy/send-transaction') .send({ chainId: GASLESS_SUPPORTED_CHAIN, ...validPayload }); expect(res.status).toBe(201); // Wait for job processing await waitForJobCompletion(); expect(mockWebhook).toHaveBeenCalledWith( expect.stringContaining('/webhook'), expect.objectContaining({ txHash: expect.any(String) }) ); }); - [ ] Test case 2 — Idempotency: job đã có
data.txHash→ kiểm tra receipt thay vì gửi lại:it('job with existing txHash → checks receipt, does not re-send', async () => { // Pre-populate job with txHash const job = await queue.add({ ...payload, txHash: '0xabc123' }); await processor.handleBiconomySendGaslessNft(job); // Verify: createSmartAccountClient NOT called expect(mockCreateSmartAccount).not.toHaveBeenCalled(); }); - [ ] Test case 3 — Non-gasless path: chain không trong
GASLESS_SUPPORTED_NETWORK→ job vàoGASSLESS_NFTqueue với path thông thường - [ ] Test case 4 — Queue job retry khi Biconomy SDK throw error
- [ ] Test case 5 — Webhook failure: backend webhook trả 500 → retry theo
QUEUE_MAX_RETRY
Verification / Acceptance Criteria
- [ ] Tất cả test cases pass khi chạy
npm run test:e2ehoặcnpm run test:integration - [ ] Coverage cho
biconomy.processor.tsđạt ≥ 80% branch coverage - [ ] Test không gọi thật lên Biconomy API hoặc blockchain (fully mocked)
- [ ] Test idempotency:
createSmartAccountClientkhông được gọi khitxHashđã tồn tại - [ ] Test thất bại khi backend webhook không phản hồi sau max retry
Files to Modify
src/biconomy/tests/biconomy.integration.spec.ts(tạo mới)src/biconomy/tests/biconomy.e2e-spec.ts(tạo mới nếu dùng e2e)