Skip to content

Task 3-1: Integration Test - Admin Sell NFT & Gasless Buy

Phase: 3 Priority: Medium Module: marketplace Depends on: task-1-1 Reference: docs/bountyhunter-blockchain-p2/details/feature-marketplace/SPEC.md

Background

Luồng Admin Sell NFT và Gasless Buy là các luồng phức tạp nhất trong Marketplace — kết hợp nhiều bước: queue job, on-chain execution (EVM/Solana/ImmutableX), và webhook callback. Chưa có integration test đảm bảo các bước này hoạt động đúng end-to-end. Đặc biệt cần test max-retry webhook failure path để đảm bảo Backend được notify khi tx fail.

Tasks

Note: Sử dụng @nestjs/testing để tạo test module. Mock ethers.js, Biconomy SDK, và ImmutableUtil. Mock postWithRetry để capture webhook calls. Đảm bảo task-1-1 (Logger) đã hoàn thành để test không bị break bởi console.log vs Logger discrepancy. Dùng bull-mock hoặc in-memory queue.

  • [ ] Test case 1 — Happy path Admin Sell NFT:
    it('POST /marketplace/admin-sell-nft → job queued → processor executes → webhook success', async () => {
      const mockTxHash = '0xdeadbeef';
      mockBlockchainUtil.sellNft.mockResolvedValue({ hash: mockTxHash });
      const mockWebhook = jest.fn().mockResolvedValue({ status: 200 });
    
      const res = await request(app.getHttpServer())
        .post('/marketplace/admin-sell-nft')
        .send(validAdminSellPayload);
    
      expect(res.status).toBe(201);
      await waitForJobCompletion('ADMIN_SELL_NFT');
      expect(mockWebhook).toHaveBeenCalledWith(
        expect.any(String),
        expect.objectContaining({ status: 'SUCCESS', txHash: mockTxHash })
      );
    });
    
  • [ ] Test case 2 — Biconomy gasless buy path (chain trong GASLESS_SUPPORTED_NETWORK):
  • Mock SmartAccountClient → success
  • Verify webhook gọi với { status: 'SUCCESS', txHash: ... }
  • [ ] Test case 3 — Webhook failure khi max retries exceeded:
    it('job fails 3 times → failure webhook called on last attempt', async () => {
      mockBlockchainUtil.sellNft.mockRejectedValue(new Error('RPC error'));
      // Simulate QUEUE_MAX_RETRY retries
      // Final attempt → failure webhook called
      expect(mockWebhook).toHaveBeenCalledWith(
        expect.any(String),
        expect.objectContaining({ status: 'FAILED' })
      );
    });
    
  • [ ] Test case 4 — Idempotency: job với txHash đã có → receipt check, không gửi tx mới

Verification / Acceptance Criteria

  • [ ] Happy path: webhook success được gọi với txHash từ on-chain tx
  • [ ] Gasless path: SmartAccountClient được tạo (hoặc dùng cache) và tx được gửi qua Biconomy
  • [ ] Max retry exceeded: failure webhook được gọi đúng 1 lần sau QUEUE_MAX_RETRY lần thất bại
  • [ ] Idempotency: gửi lại job với txHash đã có → blockchainUtil.sellNft không được gọi thêm
  • [ ] Test pass khi chạy npm run test

Files to Modify

  • src/marketplace/tests/marketplace-admin-sell.integration.spec.ts (tạo mới)