mirror of
https://github.com/pezkuwichain/pwap.git
synced 2026-04-22 21:47:56 +00:00
db05f21e52
Created complete testing framework for web and mobile frontends based on 437 test scenarios extracted from 12 blockchain pallet test files. Test Infrastructure: - Mock data generators for all 12 pallets (Identity, Perwerde, Rewards, Treasury, etc.) - Test helper utilities (async, blockchain mocks, validation, custom matchers) - Example unit tests for web (KYC Application) and mobile (Education Course List) - Example E2E tests using Cypress (web) and Detox (mobile) - Executable test runner scripts with colored output - Comprehensive documentation with all 437 test scenarios Coverage: - pallet-identity-kyc: 39 test scenarios - pallet-perwerde: 30 test scenarios - pallet-pez-rewards: 44 test scenarios - pallet-pez-treasury: 58 test scenarios - pallet-presale: 24 test scenarios - pallet-referral: 17 test scenarios - pallet-staking-score: 23 test scenarios - pallet-tiki: 66 test scenarios - pallet-token-wrapper: 18 test scenarios - pallet-trust: 26 test scenarios - pallet-validator-pool: 27 test scenarios - pallet-welati: 65 test scenarios Files created: - tests/utils/mockDataGenerators.ts (550+ lines) - tests/utils/testHelpers.ts (400+ lines) - tests/web/unit/citizenship/KYCApplication.test.tsx - tests/mobile/unit/education/CourseList.test.tsx - tests/web/e2e/cypress/citizenship-kyc.cy.ts - tests/mobile/e2e/detox/education-flow.e2e.ts - tests/run-web-tests.sh (executable) - tests/run-mobile-tests.sh (executable) - tests/README.md (800+ lines of documentation)
299 lines
10 KiB
TypeScript
299 lines
10 KiB
TypeScript
/**
|
|
* Cypress E2E Test: Full Citizenship & KYC Flow
|
|
* Based on pallet-identity-kyc integration tests
|
|
*
|
|
* Flow:
|
|
* 1. Set Identity → 2. Apply for KYC → 3. Admin Approval → 4. Citizen NFT Minted
|
|
* Alternative: Self-Confirmation flow
|
|
*/
|
|
|
|
describe('Citizenship & KYC Flow (E2E)', () => {
|
|
const testUser = {
|
|
name: 'Test Citizen',
|
|
email: 'testcitizen@pezkuwi.com',
|
|
wallet: '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
|
|
};
|
|
|
|
const testAdmin = {
|
|
wallet: '5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY',
|
|
};
|
|
|
|
beforeEach(() => {
|
|
// Visit the citizenship page
|
|
cy.visit('/citizenship');
|
|
|
|
// Mock wallet connection
|
|
cy.window().then((win) => {
|
|
(win as any).mockPolkadotWallet = {
|
|
address: testUser.wallet,
|
|
connected: true,
|
|
};
|
|
});
|
|
});
|
|
|
|
describe('Happy Path: Full KYC Approval Flow', () => {
|
|
it('should complete full citizenship flow', () => {
|
|
// STEP 1: Set Identity
|
|
cy.log('Step 1: Setting identity');
|
|
cy.get('[data-testid="identity-name-input"]').type(testUser.name);
|
|
cy.get('[data-testid="identity-email-input"]').type(testUser.email);
|
|
cy.get('[data-testid="submit-identity-btn"]').click();
|
|
|
|
// Wait for transaction confirmation
|
|
cy.contains('Identity set successfully', { timeout: 10000 }).should('be.visible');
|
|
|
|
// STEP 2: Apply for KYC
|
|
cy.log('Step 2: Applying for KYC');
|
|
cy.get('[data-testid="kyc-cid-input"]').type('QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG');
|
|
cy.get('[data-testid="kyc-notes-input"]').type('My citizenship documents');
|
|
|
|
// Check deposit amount is displayed
|
|
cy.contains('Deposit required: 10 HEZ').should('be.visible');
|
|
|
|
cy.get('[data-testid="submit-kyc-btn"]').click();
|
|
|
|
// Wait for transaction
|
|
cy.contains('KYC application submitted', { timeout: 10000 }).should('be.visible');
|
|
|
|
// Verify status changed to Pending
|
|
cy.get('[data-testid="kyc-status-badge"]').should('contain', 'Pending');
|
|
|
|
// STEP 3: Admin Approval (switch to admin account)
|
|
cy.log('Step 3: Admin approving KYC');
|
|
cy.window().then((win) => {
|
|
(win as any).mockPolkadotWallet.address = testAdmin.wallet;
|
|
});
|
|
|
|
cy.visit('/admin/kyc-applications');
|
|
cy.get(`[data-testid="approve-kyc-${testUser.wallet}"]`).click();
|
|
|
|
// Confirm approval
|
|
cy.get('[data-testid="confirm-approval-btn"]').click();
|
|
|
|
cy.contains('KYC approved successfully', { timeout: 10000 }).should('be.visible');
|
|
|
|
// STEP 4: Verify Citizen Status
|
|
cy.log('Step 4: Verifying citizenship status');
|
|
cy.window().then((win) => {
|
|
(win as any).mockPolkadotWallet.address = testUser.wallet;
|
|
});
|
|
|
|
cy.visit('/citizenship');
|
|
|
|
// Should show Approved status
|
|
cy.get('[data-testid="kyc-status-badge"]').should('contain', 'Approved');
|
|
|
|
// Should show Citizen NFT
|
|
cy.contains('Citizen NFT').should('be.visible');
|
|
|
|
// Should show Welati role
|
|
cy.contains('Welati').should('be.visible');
|
|
|
|
// Deposit should be refunded (check balance increased)
|
|
});
|
|
});
|
|
|
|
describe('Alternative: Self-Confirmation Flow', () => {
|
|
it('should allow self-confirmation for Welati NFT holders', () => {
|
|
// User already has Welati NFT (mock this state)
|
|
cy.window().then((win) => {
|
|
(win as any).mockPolkadotState = {
|
|
hasWelatiNFT: true,
|
|
};
|
|
});
|
|
|
|
// STEP 1: Set Identity
|
|
cy.get('[data-testid="identity-name-input"]').type(testUser.name);
|
|
cy.get('[data-testid="identity-email-input"]').type(testUser.email);
|
|
cy.get('[data-testid="submit-identity-btn"]').click();
|
|
|
|
cy.wait(2000);
|
|
|
|
// STEP 2: Apply for KYC
|
|
cy.get('[data-testid="kyc-cid-input"]').type('QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG');
|
|
cy.get('[data-testid="submit-kyc-btn"]').click();
|
|
|
|
cy.wait(2000);
|
|
|
|
// STEP 3: Self-Confirm (should be available for Welati holders)
|
|
cy.get('[data-testid="self-confirm-btn"]').should('be.visible');
|
|
cy.get('[data-testid="self-confirm-btn"]').click();
|
|
|
|
// Confirm action
|
|
cy.contains('Self-confirm citizenship?').should('be.visible');
|
|
cy.get('[data-testid="confirm-self-confirm"]').click();
|
|
|
|
// Wait for confirmation
|
|
cy.contains('Citizenship confirmed!', { timeout: 10000 }).should('be.visible');
|
|
|
|
// Verify status
|
|
cy.get('[data-testid="kyc-status-badge"]').should('contain', 'Approved');
|
|
});
|
|
});
|
|
|
|
describe('Error Cases', () => {
|
|
it('should prevent KYC application without identity', () => {
|
|
// Try to submit KYC without setting identity first
|
|
cy.get('[data-testid="kyc-cid-input"]').should('be.disabled');
|
|
|
|
// Should show message
|
|
cy.contains('Please set your identity first').should('be.visible');
|
|
});
|
|
|
|
it('should prevent duplicate KYC application', () => {
|
|
// Mock existing pending application
|
|
cy.window().then((win) => {
|
|
(win as any).mockPolkadotState = {
|
|
kycStatus: 'Pending',
|
|
};
|
|
});
|
|
|
|
cy.reload();
|
|
|
|
// KYC form should be disabled
|
|
cy.get('[data-testid="submit-kyc-btn"]').should('be.disabled');
|
|
|
|
// Should show current status
|
|
cy.contains('Application already submitted').should('be.visible');
|
|
cy.get('[data-testid="kyc-status-badge"]').should('contain', 'Pending');
|
|
});
|
|
|
|
it('should show insufficient balance error', () => {
|
|
// Mock low balance
|
|
cy.window().then((win) => {
|
|
(win as any).mockPolkadotState = {
|
|
balance: 5_000_000_000_000n, // 5 HEZ (less than 10 required)
|
|
};
|
|
});
|
|
|
|
// Set identity first
|
|
cy.get('[data-testid="identity-name-input"]').type(testUser.name);
|
|
cy.get('[data-testid="identity-email-input"]').type(testUser.email);
|
|
cy.get('[data-testid="submit-identity-btn"]').click();
|
|
|
|
cy.wait(2000);
|
|
|
|
// Try to submit KYC
|
|
cy.get('[data-testid="kyc-cid-input"]').type('QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG');
|
|
cy.get('[data-testid="submit-kyc-btn"]').click();
|
|
|
|
// Should show error
|
|
cy.contains('Insufficient balance').should('be.visible');
|
|
cy.contains('You need at least 10 HEZ').should('be.visible');
|
|
});
|
|
|
|
it('should validate identity name length (max 50 chars)', () => {
|
|
const longName = 'a'.repeat(51);
|
|
|
|
cy.get('[data-testid="identity-name-input"]').type(longName);
|
|
cy.get('[data-testid="submit-identity-btn"]').click();
|
|
|
|
// Should show validation error
|
|
cy.contains(/name must be 50 characters or less/i).should('be.visible');
|
|
});
|
|
|
|
it('should validate IPFS CID format', () => {
|
|
// Set identity first
|
|
cy.get('[data-testid="identity-name-input"]').type(testUser.name);
|
|
cy.get('[data-testid="identity-email-input"]').type(testUser.email);
|
|
cy.get('[data-testid="submit-identity-btn"]').click();
|
|
|
|
cy.wait(2000);
|
|
|
|
// Enter invalid CID
|
|
const invalidCIDs = ['invalid', 'Qm123', 'notacid'];
|
|
|
|
invalidCIDs.forEach((cid) => {
|
|
cy.get('[data-testid="kyc-cid-input"]').clear().type(cid);
|
|
cy.get('[data-testid="submit-kyc-btn"]').click();
|
|
|
|
cy.contains(/invalid IPFS CID/i).should('be.visible');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Citizenship Renunciation', () => {
|
|
it('should allow approved citizens to renounce', () => {
|
|
// Mock approved citizen state
|
|
cy.window().then((win) => {
|
|
(win as any).mockPolkadotState = {
|
|
kycStatus: 'Approved',
|
|
citizenNFTId: 123,
|
|
};
|
|
});
|
|
|
|
cy.visit('/citizenship');
|
|
|
|
// Should show renounce button
|
|
cy.get('[data-testid="renounce-btn"]').should('be.visible');
|
|
cy.get('[data-testid="renounce-btn"]').click();
|
|
|
|
// Confirm renunciation (should show strong warning)
|
|
cy.contains(/are you sure/i).should('be.visible');
|
|
cy.contains(/this action cannot be undone/i).should('be.visible');
|
|
cy.get('[data-testid="confirm-renounce"]').click();
|
|
|
|
// Wait for transaction
|
|
cy.contains('Citizenship renounced', { timeout: 10000 }).should('be.visible');
|
|
|
|
// Status should reset to NotStarted
|
|
cy.get('[data-testid="kyc-status-badge"]').should('contain', 'Not Started');
|
|
});
|
|
|
|
it('should allow reapplication after renunciation', () => {
|
|
// After renouncing (status: NotStarted)
|
|
cy.window().then((win) => {
|
|
(win as any).mockPolkadotState = {
|
|
kycStatus: 'NotStarted',
|
|
previouslyRenounced: true,
|
|
};
|
|
});
|
|
|
|
cy.visit('/citizenship');
|
|
|
|
// Identity and KYC forms should be available again
|
|
cy.get('[data-testid="identity-name-input"]').should('not.be.disabled');
|
|
cy.contains(/you can reapply/i).should('be.visible');
|
|
});
|
|
});
|
|
|
|
describe('Admin KYC Management', () => {
|
|
beforeEach(() => {
|
|
// Switch to admin account
|
|
cy.window().then((win) => {
|
|
(win as any).mockPolkadotWallet.address = testAdmin.wallet;
|
|
});
|
|
|
|
cy.visit('/admin/kyc-applications');
|
|
});
|
|
|
|
it('should display pending KYC applications', () => {
|
|
cy.get('[data-testid="kyc-application-row"]').should('have.length.greaterThan', 0);
|
|
|
|
// Each row should show:
|
|
cy.contains(testUser.name).should('be.visible');
|
|
cy.contains('Pending').should('be.visible');
|
|
});
|
|
|
|
it('should approve KYC application', () => {
|
|
cy.get(`[data-testid="approve-kyc-${testUser.wallet}"]`).first().click();
|
|
cy.get('[data-testid="confirm-approval-btn"]').click();
|
|
|
|
cy.contains('KYC approved', { timeout: 10000 }).should('be.visible');
|
|
|
|
// Application should disappear from pending list
|
|
cy.get(`[data-testid="approve-kyc-${testUser.wallet}"]`).should('not.exist');
|
|
});
|
|
|
|
it('should reject KYC application', () => {
|
|
cy.get(`[data-testid="reject-kyc-${testUser.wallet}"]`).first().click();
|
|
|
|
// Enter rejection reason
|
|
cy.get('[data-testid="rejection-reason"]').type('Incomplete documents');
|
|
cy.get('[data-testid="confirm-rejection-btn"]').click();
|
|
|
|
cy.contains('KYC rejected', { timeout: 10000 }).should('be.visible');
|
|
});
|
|
});
|
|
});
|