tests: couverture des interfaces postMessage; jest: mappers CSS/?raw et alias ~; mocks
This commit is contained in:
parent
941bfb3b67
commit
5791d960c4
@ -20,7 +20,10 @@ module.exports = {
|
|||||||
setupFilesAfterEnv: ['<rootDir>/tests/setup.ts'],
|
setupFilesAfterEnv: ['<rootDir>/tests/setup.ts'],
|
||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
'^@/(.*)$': '<rootDir>/src/$1',
|
'^@/(.*)$': '<rootDir>/src/$1',
|
||||||
'^pkg/(.*)$': '<rootDir>/pkg/$1'
|
'^~/(.*)$': '<rootDir>/src/$1',
|
||||||
|
'^pkg/(.*)$': '<rootDir>/pkg/$1',
|
||||||
|
'^(.*)\\?raw$': '<rootDir>/tests/rawFileMock.js',
|
||||||
|
'\\.(css|less|sass|scss)$': '<rootDir>/tests/styleMock.js'
|
||||||
},
|
},
|
||||||
testTimeout: 10000,
|
testTimeout: 10000,
|
||||||
transform: {
|
transform: {
|
||||||
|
1
tests/rawFileMock.js
Normal file
1
tests/rawFileMock.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
module.exports = '';
|
1
tests/styleMock.js
Normal file
1
tests/styleMock.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
module.exports = {};
|
155
tests/unit/channel-messages.test.ts
Normal file
155
tests/unit/channel-messages.test.ts
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
import { registerAllListeners } from '../../src/router';
|
||||||
|
import { MessageType } from '../../src/models/process.model';
|
||||||
|
|
||||||
|
// Mocks TokenService
|
||||||
|
jest.mock('../../src/services/token', () => {
|
||||||
|
class TokenServiceMock {
|
||||||
|
static async getInstance() { return new TokenServiceMock(); }
|
||||||
|
async generateSessionToken(origin: string) {
|
||||||
|
return { accessToken: `access-${origin}`, refreshToken: `refresh-${origin}` };
|
||||||
|
}
|
||||||
|
async validateToken(token: string, origin: string) { return true; }
|
||||||
|
async refreshAccessToken(refreshToken: string, origin: string) { return `new-access-${origin}`; }
|
||||||
|
}
|
||||||
|
return { __esModule: true, default: TokenServiceMock };
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mocks Services
|
||||||
|
jest.mock('../../src/services/service', () => {
|
||||||
|
class ServicesMock {
|
||||||
|
static instance: any;
|
||||||
|
static async getInstance() {
|
||||||
|
if (!ServicesMock.instance) ServicesMock.instance = new ServicesMock();
|
||||||
|
return ServicesMock.instance;
|
||||||
|
}
|
||||||
|
isPaired() { return true; }
|
||||||
|
async confirmPairing() { /* no-op */ }
|
||||||
|
getPairingProcessId() { return 'pair-123'; }
|
||||||
|
async getProcesses() { return { 'p1': { id: 'p1' } as any }; }
|
||||||
|
async getMyProcesses() { return ['p1', 'p2']; }
|
||||||
|
async getProcess(id: string) { return { states: [{ state_id: 'a'.repeat(64), public_data: {}, pcd_commitment: {}, validation_tokens: [] }] } as any; }
|
||||||
|
async decryptAttribute() { return null; }
|
||||||
|
decodeValue(v: any) { return v; }
|
||||||
|
getHashForFile() { return 'hash-abc'; }
|
||||||
|
getMerkleProofForFile() { return { proof: true } as any; }
|
||||||
|
validateMerkleProof() { return true; }
|
||||||
|
async createPrdUpdate() { return {}; }
|
||||||
|
async approveChange() { return { updated_process: { id: 'p1' } }; }
|
||||||
|
async updateProcess() { return { updated_process: { id: 'p1' } }; }
|
||||||
|
async createProcess() { return { updated_process: { process_id: 'pid', current_process: { states: [{ state_id: 'a'.repeat(64) }] } } } as any; }
|
||||||
|
async handleApiReturn() { /* no-op */ }
|
||||||
|
}
|
||||||
|
return { __esModule: true, default: ServicesMock };
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mocks ModalService (used by REQUEST_LINK)
|
||||||
|
jest.mock('../../src/services/modal.service', () => {
|
||||||
|
class ModalServiceMock {
|
||||||
|
static async getInstance() { return new ModalServiceMock(); }
|
||||||
|
async showConfirmationModal() { return true; }
|
||||||
|
}
|
||||||
|
return { __esModule: true, default: ModalServiceMock };
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('postMessage interfaces (registerAllListeners)', () => {
|
||||||
|
const ORIGIN = 'https://host.test';
|
||||||
|
let postSpy: jest.SpyInstance;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
postSpy = jest.spyOn(window.parent, 'postMessage');
|
||||||
|
await registerAllListeners();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
postSpy.mockClear();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
postSpy.mockRestore();
|
||||||
|
});
|
||||||
|
|
||||||
|
function dispatch(data: any) {
|
||||||
|
window.dispatchEvent(new MessageEvent('message', { data, origin: ORIGIN }));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function waitForLastCall(expectedType?: string, prevCount?: number) {
|
||||||
|
const start = Date.now();
|
||||||
|
const timeoutMs = 1000;
|
||||||
|
// eslint-disable-next-line no-constant-condition
|
||||||
|
while (true) {
|
||||||
|
const calls = postSpy.mock.calls;
|
||||||
|
const countOk = prevCount === undefined ? calls.length > 0 : calls.length > (prevCount || 0);
|
||||||
|
if (countOk) {
|
||||||
|
const last = calls[calls.length - 1] as any;
|
||||||
|
const payload = last && last[0];
|
||||||
|
if (!expectedType || (payload && payload.type === expectedType)) {
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Date.now() - start > timeoutMs) throw new Error('Timeout waiting for postMessage');
|
||||||
|
await new Promise(r => setTimeout(r, 10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it('REQUEST_LINK -> LINK_ACCEPTED avec tokens', async () => {
|
||||||
|
const prev = postSpy.mock.calls.length;
|
||||||
|
dispatch({ type: MessageType.REQUEST_LINK, messageId: 'm1' });
|
||||||
|
const [payload, targetOrigin] = (await waitForLastCall(MessageType.LINK_ACCEPTED, prev)) as any;
|
||||||
|
expect(targetOrigin).toBe(ORIGIN);
|
||||||
|
expect(payload.type).toBe(MessageType.LINK_ACCEPTED);
|
||||||
|
expect(payload.accessToken).toContain('access-');
|
||||||
|
expect(payload.refreshToken).toContain('refresh-');
|
||||||
|
expect(payload.messageId).toBe('m1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('VALIDATE_TOKEN -> VALIDATE_TOKEN avec isValid=true', async () => {
|
||||||
|
const prev = postSpy.mock.calls.length;
|
||||||
|
dispatch({ type: MessageType.VALIDATE_TOKEN, accessToken: 'a', refreshToken: 'r', messageId: 'm2' });
|
||||||
|
const [payload, targetOrigin] = (await waitForLastCall(MessageType.VALIDATE_TOKEN, prev)) as any;
|
||||||
|
expect(targetOrigin).toBe(ORIGIN);
|
||||||
|
expect(payload.type).toBe(MessageType.VALIDATE_TOKEN);
|
||||||
|
expect(payload.isValid).toBe(true);
|
||||||
|
expect(payload.messageId).toBe('m2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('RENEW_TOKEN -> RENEW_TOKEN avec nouveau accessToken', async () => {
|
||||||
|
const prev = postSpy.mock.calls.length;
|
||||||
|
dispatch({ type: MessageType.RENEW_TOKEN, refreshToken: 'r', messageId: 'm3' });
|
||||||
|
const [payload, targetOrigin] = (await waitForLastCall(MessageType.RENEW_TOKEN, prev)) as any;
|
||||||
|
expect(targetOrigin).toBe(ORIGIN);
|
||||||
|
expect(payload.type).toBe(MessageType.RENEW_TOKEN);
|
||||||
|
expect(typeof payload.accessToken).toBe('string');
|
||||||
|
expect(payload.refreshToken).toBe('r');
|
||||||
|
expect(payload.messageId).toBe('m3');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET_PAIRING_ID -> GET_PAIRING_ID avec userPairingId', async () => {
|
||||||
|
const prev = postSpy.mock.calls.length;
|
||||||
|
dispatch({ type: MessageType.GET_PAIRING_ID, accessToken: 'a', messageId: 'm4' });
|
||||||
|
const [payload, targetOrigin] = (await waitForLastCall(MessageType.GET_PAIRING_ID, prev)) as any;
|
||||||
|
expect(targetOrigin).toBe(ORIGIN);
|
||||||
|
expect(payload.type).toBe(MessageType.GET_PAIRING_ID);
|
||||||
|
expect(payload.userPairingId).toBe('pair-123');
|
||||||
|
expect(payload.messageId).toBe('m4');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET_MY_PROCESSES -> GET_MY_PROCESSES avec liste', async () => {
|
||||||
|
const prev = postSpy.mock.calls.length;
|
||||||
|
dispatch({ type: MessageType.GET_MY_PROCESSES, accessToken: 'a', messageId: 'm5' });
|
||||||
|
const [payload, targetOrigin] = (await waitForLastCall(MessageType.GET_MY_PROCESSES, prev)) as any;
|
||||||
|
expect(targetOrigin).toBe(ORIGIN);
|
||||||
|
expect(payload.type).toBe(MessageType.GET_MY_PROCESSES);
|
||||||
|
expect(Array.isArray(payload.myProcesses)).toBe(true);
|
||||||
|
expect(payload.messageId).toBe('m5');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('HASH_VALUE -> VALUE_HASHED avec hash', async () => {
|
||||||
|
const prev = postSpy.mock.calls.length;
|
||||||
|
dispatch({ type: MessageType.HASH_VALUE, accessToken: 'a', commitedIn: 'c', label: 'L', fileBlob: { type: 'application/octet-stream', data: new Uint8Array([1]) }, messageId: 'm6' });
|
||||||
|
const [payload, targetOrigin] = (await waitForLastCall(MessageType.VALUE_HASHED, prev)) as any;
|
||||||
|
expect(targetOrigin).toBe(ORIGIN);
|
||||||
|
expect(payload.type).toBe(MessageType.VALUE_HASHED);
|
||||||
|
expect(payload.hash).toBe('hash-abc');
|
||||||
|
expect(payload.messageId).toBe('m6');
|
||||||
|
});
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user