import { test } from 'node:test'; import assert from 'node:assert/strict'; import { AuthType, IAuthData, UIAFlow } from 'matrix-js-sdk'; import { getSupportedUIAFlows, getUIACompleted, getUIAParams, getUIASession, getUIAErrorCode, getUIAError, getUIAFlowForStages, hasStageInFlows, requiredStageInFlows, getLoginTermUrl, } from './matrix-uia'; const flows = (...stageLists: string[][]): UIAFlow[] => stageLists.map((stages) => ({ stages })) as UIAFlow[]; const auth = (data: Record): IAuthData => data as unknown as IAuthData; test('getSupportedUIAFlows keeps only fully-supported flows', () => { const f = flows(['a', 'b'], ['a', 'c']); assert.deepEqual(getSupportedUIAFlows(f, ['a', 'b']), [{ stages: ['a', 'b'] }]); assert.deepEqual(getSupportedUIAFlows(f, ['a', 'b', 'c']), f); assert.deepEqual(getSupportedUIAFlows(f, ['x']), []); }); test('getUIACompleted / Params / Session default sensibly', () => { assert.deepEqual(getUIACompleted(auth({ completed: ['m.login.password'] })), [ 'm.login.password', ]); assert.deepEqual(getUIACompleted(auth({})), []); assert.deepEqual(getUIAParams(auth({ params: { x: { y: 1 } } })), { x: { y: 1 } }); assert.deepEqual(getUIAParams(auth({})), {}); assert.equal(getUIASession(auth({ session: 'abc' })), 'abc'); assert.equal(getUIASession(auth({})), undefined); }); test('getUIAErrorCode / getUIAError read string fields only', () => { assert.equal(getUIAErrorCode(auth({ errcode: 'M_FORBIDDEN' })), 'M_FORBIDDEN'); assert.equal(getUIAErrorCode(auth({ errcode: 42 })), undefined); assert.equal(getUIAErrorCode(auth({})), undefined); assert.equal(getUIAError(auth({ error: 'Bad' })), 'Bad'); assert.equal(getUIAError(auth({})), undefined); }); test('getUIAFlowForStages: exact match and no match', () => { const f = flows(['m.login.password'], ['m.login.recaptcha', 'm.login.password']); assert.deepEqual(getUIAFlowForStages(f, ['m.login.password']), { stages: ['m.login.password'] }); assert.equal(getUIAFlowForStages(f, ['m.login.sso']), undefined); }); test('getUIAFlowForStages allows a single extra m.login.dummy stage', () => { const f = flows(['m.login.recaptcha', AuthType.Dummy]); assert.deepEqual(getUIAFlowForStages(f, ['m.login.recaptcha']), { stages: ['m.login.recaptcha', AuthType.Dummy], }); // two extra stages (more than dummy) → no match assert.equal(getUIAFlowForStages(flows(['a', 'b', AuthType.Dummy]), ['a']), undefined); }); test('hasStageInFlows / requiredStageInFlows', () => { const f = flows(['m.login.password'], ['m.login.recaptcha', 'm.login.password']); assert.equal(hasStageInFlows(f, 'm.login.recaptcha'), true); assert.equal(hasStageInFlows(f, 'm.login.sso'), false); assert.equal(requiredStageInFlows(f, 'm.login.password'), true); assert.equal(requiredStageInFlows(f, 'm.login.recaptcha'), false); }); test('getLoginTermUrl prefers en, else the first language', () => { const base = (policies: unknown) => ({ [AuthType.Terms]: { policies } }); assert.equal( getLoginTermUrl( base({ privacy_policy: { en: { url: 'https://en' }, fr: { url: 'https://fr' } } }), ), 'https://en', ); assert.equal( getLoginTermUrl(base({ privacy_policy: { fr: { url: 'https://fr' } } })), 'https://fr', ); assert.equal(getLoginTermUrl({}), undefined); assert.equal(getLoginTermUrl(base(null)), undefined); });