mirror of
https://github.com/pezkuwichain/pwap.git
synced 2026-04-21 23:47:56 +00:00
1295c36241
- 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
142 lines
5.8 KiB
JavaScript
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.');
|
|
});
|
|
});
|