Files
pwap/backend/integration-tests/kyc.live.test.js
T
pezkuwichain 1295c36241 Rebrand: polkadot → pezkuwi build fixes
- Fixed TypeScript type assertion issues
- Updated imports from api-augment/substrate to api-augment/bizinikiwi
- Fixed imgConvert.mjs header and imports
- Added @ts-expect-error for runtime-converted types
- Fixed all @polkadot copyright headers to @pezkuwi
2026-01-07 02:32:54 +03:00

142 lines
5.8 KiB
JavaScript

/**
* @file: kyc.live.test.js
* @description: Live integration tests for the KYC backend API.
*
* @preconditions:
* 1. A local Pezkuwi dev node must be running and accessible at `ws://127.0.0.1:8082`.
* 2. The KYC backend server must be running and accessible at `http://127.0.0.1:8082`.
* 3. The Supabase database must be clean, or the tests will fail on unique constraints.
* 4. The backend's .env file must be correctly configured (SUDO_SEED, FOUNDER_ADDRESS, etc.).
* 5. The backend must be running in a mode that bypasses signature checks for these tests (e.g., NODE_ENV=test).
*
* @execution:
* Run this file with Jest: `npx jest kyc.live.test.js`
*/
import { ApiPromise, WsProvider, Keyring } from '@pezkuwi/api';
import axios from 'axios'; // Using axios for HTTP requests
// ========================================
// TEST CONFIGURATION
// ========================================
const API_BASE_URL = 'http://127.0.0.1:8082/api';
const WS_ENDPOINT = 'ws://127.0.0.1:8082';
// Set a long timeout for all tests in this file
jest.setTimeout(60000); // 60 seconds
// ========================================
// TEST SETUP & TEARDOWN
// ========================================
let api;
let keyring;
let sudo, founder, councilMember, user1, user2;
beforeAll(async () => {
const wsProvider = new WsProvider(WS_ENDPOINT);
api = await ApiPromise.create({ provider: wsProvider });
keyring = new Keyring({ type: 'sr25519' });
// Define accounts from the well-known dev seeds
sudo = keyring.addFromUri('//Alice');
founder = keyring.addFromUri('//Alice'); // Assuming founder is also sudo for tests
councilMember = keyring.addFromUri('//Bob');
user1 = keyring.addFromUri('//Charlie');
user2 = keyring.addFromUri('//Dave');
console.log('Connected to node and initialized accounts.');
});
afterAll(async () => {
if (api) await api.disconnect();
console.log('Disconnected from node.');
});
// Helper to wait for the next finalized block
const nextBlock = () => new Promise(res => api.rpc.chain.subscribeFinalizedHeads(() => res()));
// ========================================
// LIVE INTEGRATION TESTS
// ========================================
describe('Live KYC Workflow', () => {
it('should run a full KYC lifecycle: Setup -> Propose -> Vote -> Approve -> Verify', async () => {
// -----------------------------------------------------------------
// PHASE 1: SETUP
// -----------------------------------------------------------------
console.log('PHASE 1: Setting up initial state...');
// 1a. Clear and set up the council in the database via API
await axios.post(`${API_BASE_URL}/council/add-member`, {
newMemberAddress: councilMember.address,
signature: '0x00', message: `addCouncilMember:${councilMember.address}`
});
// 1b. User1 sets their identity on-chain
await api.tx.identityKyc.setIdentity("User1", "user1@test.com").signAndSend(user1);
// 1c. User1 applies for KYC on-chain
await api.tx.identityKyc.applyForKyc([], "Live test application").signAndSend(user1);
await nextBlock(); // Wait for setup transactions to be finalized
// Verification of setup
let kycStatus = (await api.query.identityKyc.kycStatusOf(user1.address)).toString();
expect(kycStatus).toBe('Pending');
console.log('User1 KYC status is correctly set to Pending.');
// -----------------------------------------------------------------
// PHASE 2: API ACTION (Propose & Vote)
// -----------------------------------------------------------------
console.log('PHASE 2: Council member proposes user via API...');
const proposeResponse = await axios.post(`${API_BASE_URL}/kyc/propose`, {
userAddress: user1.address,
proposerAddress: councilMember.address,
signature: '0x00', message: `proposeKYC:${user1.address}`
});
expect(proposeResponse.status).toBe(201);
console.log('Proposal successful. Backend should now be executing `approve_kyc`...');
// Since we have 1 council member and the threshold is 60%, the proposer's
// automatic "aye" vote is enough to trigger `checkAndExecute`.
// We need to wait for the backend to see the vote, execute the transaction,
// and for that transaction to be finalized on-chain. This can take time.
await new Promise(resolve => setTimeout(resolve, 15000)); // Wait 15s for finalization
// -----------------------------------------------------------------
// PHASE 3: VERIFICATION
// -----------------------------------------------------------------
console.log('PHASE 3: Verifying final state on-chain and in DB...');
// 3a. Verify on-chain status is now 'Approved'
kycStatus = (await api.query.identityKyc.kycStatusOf(user1.address)).toString();
expect(kycStatus).toBe('Approved');
console.log('SUCCESS: On-chain KYC status for User1 is now Approved.');
// 3b. Verify via API that the proposal is no longer pending
const pendingResponse = await axios.get(`${API_BASE_URL}/kyc/pending`);
const pendingForUser1 = pendingResponse.data.pending.find(p => p.userAddress === user1.address);
expect(pendingForUser1).toBeUndefined();
console.log('SUCCESS: Pending proposals list is correctly updated.');
});
it('should reject a proposal from a non-council member', async () => {
console.log('Testing rejection of non-council member proposal...');
const nonCouncilMember = keyring.addFromUri('//Eve');
// Attempt to propose from an address not in the council DB
await expect(axios.post(`${API_BASE_URL}/kyc/propose`, {
userAddress: user2.address,
proposerAddress: nonCouncilMember.address,
signature: '0x00', message: `proposeKYC:${user2.address}`
})).rejects.toThrow('Request failed with status code 403');
console.log('SUCCESS: API correctly returned 403 Forbidden.');
});
});