0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-30 20:33:54 -05:00

refactor!: update mock connector file paths

This commit is contained in:
Gao Sun 2024-01-29 21:33:12 +08:00
parent 6d0f95739c
commit 6befe60149
No known key found for this signature in database
GPG key ID: 13EBE123E4773688
23 changed files with 122 additions and 91 deletions

View file

@ -0,0 +1,10 @@
---
"@logto/connector-mock-standard-email": major
"@logto/connector-mock-email": major
"@logto/connector-mock-sms": major
---
update `writeFile` path according to the connector type
- SMS connector: `/tmp/logto_mock_sms_record.txt`
- Email connector: `/tmp/logto_mock_email_record.txt`

View file

@ -0,0 +1,5 @@
---
"@logto/connector-kit": minor
---
add `mockConnectorFilePaths` and deprecate `mockSmsVerificationCodeFileName`

View file

@ -1,6 +1,5 @@
import { assert } from '@silverhand/essentials';
import fs from 'node:fs/promises';
import path from 'node:path';
import type {
GetConnectorConfig,
@ -13,6 +12,7 @@ import {
ConnectorErrorCodes,
validateConfig,
ConnectorType,
mockConnectorFilePaths,
} from '@logto/connector-kit';
import { defaultMetadata } from './constant.js';
@ -36,8 +36,8 @@ const sendMessage =
);
await fs.writeFile(
path.join('/tmp', 'logto_mock_verification_code_record.txt'),
JSON.stringify({ address: to, code: payload.code, type }) + '\n'
mockConnectorFilePaths.Email,
JSON.stringify({ address: to, code: payload.code, type, payload }) + '\n'
);
return { address: to, data: payload };

View file

@ -1,6 +1,5 @@
import { assert } from '@silverhand/essentials';
import fs from 'node:fs/promises';
import path from 'node:path';
import type {
GetConnectorConfig,
@ -13,6 +12,7 @@ import {
ConnectorErrorCodes,
validateConfig,
ConnectorType,
mockConnectorFilePaths,
} from '@logto/connector-kit';
import { defaultMetadata } from './constant.js';
@ -36,8 +36,8 @@ const sendMessage =
);
await fs.writeFile(
path.join('/tmp', 'logto_mock_verification_code_record.txt'),
JSON.stringify({ address: to, code: payload.code, type }) + '\n'
mockConnectorFilePaths.Email,
JSON.stringify({ address: to, code: payload.code, type, payload }) + '\n'
);
return { address: to, data: payload };

View file

@ -1,6 +1,5 @@
import { assert } from '@silverhand/essentials';
import fs from 'node:fs/promises';
import path from 'node:path';
import type {
GetConnectorConfig,
@ -13,6 +12,7 @@ import {
ConnectorErrorCodes,
validateConfig,
ConnectorType,
mockConnectorFilePaths,
} from '@logto/connector-kit';
import { defaultMetadata } from './constant.js';
@ -36,8 +36,8 @@ const sendMessage =
);
await fs.writeFile(
path.join('/tmp', 'logto_mock_verification_code_record.txt'),
JSON.stringify({ phone: to, code: payload.code, type }) + '\n'
mockConnectorFilePaths.Sms,
JSON.stringify({ phone: to, code: payload.code, type, payload }) + '\n'
);
return { phone: to, data: payload };

View file

@ -14,8 +14,6 @@ import type Queries from '#src/tenants/Queries.js';
import { type ConnectorLibrary } from './connector.js';
const invitationLinkPath = '/invitation';
/**
* The ending statuses of an organization invitation per RFC 0003. It means that the invitation
* status cannot be changed anymore.

View file

@ -1,15 +1,12 @@
import fs from 'node:fs/promises';
import { createServer, type RequestListener } from 'node:http';
import path from 'node:path';
import { mockSmsVerificationCodeFileName } from '@logto/connector-kit';
import { mockConnectorFilePaths } from '@logto/connector-kit';
import { RequestError } from 'got';
import { createUser } from '#src/api/index.js';
import { generateUsername } from '#src/utils.js';
const temporaryVerificationCodeFilePath = path.join('/tmp', mockSmsVerificationCodeFileName);
export const createUserByAdmin = async (
username?: string,
password?: string,
@ -33,8 +30,10 @@ type VerificationCodeRecord = {
type: string;
};
export const readVerificationCode = async (): Promise<VerificationCodeRecord> => {
const buffer = await fs.readFile(temporaryVerificationCodeFilePath);
export const readVerificationCode = async (
forType: keyof typeof mockConnectorFilePaths
): Promise<VerificationCodeRecord> => {
const buffer = await fs.readFile(mockConnectorFilePaths[forType]);
const content = buffer.toString();
// For test use only
@ -42,9 +41,11 @@ export const readVerificationCode = async (): Promise<VerificationCodeRecord> =>
return JSON.parse(content) as VerificationCodeRecord;
};
export const removeVerificationCode = async (): Promise<void> => {
export const removeVerificationCode = async (
forType: keyof typeof mockConnectorFilePaths
): Promise<void> => {
try {
await fs.unlink(temporaryVerificationCodeFilePath);
await fs.unlink(mockConnectorFilePaths[forType]);
} catch {
// Do nothing
}

View file

@ -101,7 +101,9 @@ export const resetPassword = async (
...profile,
});
const { code: verificationCode } = await readVerificationCode();
const { code: verificationCode } = await readVerificationCode(
'email' in profile ? 'Email' : 'Sms'
);
await client.successSend(patchInteractionIdentifiers, {
...profile,
verificationCode,

View file

@ -48,7 +48,7 @@ describe('reset password', () => {
email: userProfile.primaryEmail,
});
const verificationCodeRecord = await readVerificationCode();
const verificationCodeRecord = await readVerificationCode('Email');
expect(verificationCodeRecord).toMatchObject({
address: userProfile.primaryEmail,
@ -108,7 +108,7 @@ describe('reset password', () => {
phone: userProfile.primaryPhone,
});
const verificationCodeRecord = await readVerificationCode();
const verificationCodeRecord = await readVerificationCode('Sms');
expect(verificationCodeRecord).toMatchObject({
phone: userProfile.primaryPhone,

View file

@ -31,7 +31,7 @@ describe('reset password flow sad path', () => {
email: primaryEmail,
});
const { code: verificationCode } = await readVerificationCode();
const { code: verificationCode } = await readVerificationCode('Email');
await client.successSend(patchInteractionIdentifiers, {
email: primaryEmail,
verificationCode,
@ -59,7 +59,7 @@ describe('reset password flow sad path', () => {
phone: primaryPhone,
});
const { code: verificationCode } = await readVerificationCode();
const { code: verificationCode } = await readVerificationCode('Sms');
await client.successSend(patchInteractionIdentifiers, {
phone: primaryPhone,
verificationCode,
@ -95,7 +95,7 @@ describe('reset password flow sad path', () => {
phone: primaryPhone,
});
const { code: verificationCode } = await readVerificationCode();
const { code: verificationCode } = await readVerificationCode('Sms');
await client.successSend(patchInteractionIdentifiers, {
phone: primaryPhone,
verificationCode,

View file

@ -79,7 +79,7 @@ describe('register with passwordless identifier', () => {
email: primaryEmail,
});
const verificationCodeRecord = await readVerificationCode();
const verificationCodeRecord = await readVerificationCode('Email');
expect(verificationCodeRecord).toMatchObject({
address: primaryEmail,
@ -125,7 +125,7 @@ describe('register with passwordless identifier', () => {
email: primaryEmail,
});
const verificationCodeRecord = await readVerificationCode();
const verificationCodeRecord = await readVerificationCode('Email');
const { code } = verificationCodeRecord;
@ -186,7 +186,7 @@ describe('register with passwordless identifier', () => {
phone: primaryPhone,
});
const verificationCodeRecord = await readVerificationCode();
const verificationCodeRecord = await readVerificationCode('Sms');
expect(verificationCodeRecord).toMatchObject({
phone: primaryPhone,
@ -232,7 +232,7 @@ describe('register with passwordless identifier', () => {
phone: primaryPhone,
});
const { code } = await readVerificationCode();
const { code } = await readVerificationCode('Sms');
await client.successSend(patchInteractionIdentifiers, {
phone: primaryPhone,
@ -296,7 +296,7 @@ describe('register with passwordless identifier', () => {
email: primaryEmail,
});
const verificationCodeRecord = await readVerificationCode();
const verificationCodeRecord = await readVerificationCode('Email');
expect(verificationCodeRecord).toMatchObject({
address: primaryEmail,
@ -351,7 +351,7 @@ describe('register with passwordless identifier', () => {
phone: primaryPhone,
});
const verificationCodeRecord = await readVerificationCode();
const verificationCodeRecord = await readVerificationCode('Sms');
expect(verificationCodeRecord).toMatchObject({
phone: primaryPhone,

View file

@ -30,7 +30,7 @@ describe('Register with identifiers sad path', () => {
await clearSsoConnectors();
});
it('Should fail to register if sign-in mode is sign-in only', async () => {
it('should fail to register if sign-in mode is sign-in only', async () => {
await updateSignInExperience({ signInMode: SignInMode.SignIn });
const client = await initClient();
@ -48,13 +48,13 @@ describe('Register with identifiers sad path', () => {
await updateSignInExperience({ signInMode: SignInMode.SignInAndRegister });
});
describe('Should fail to register with identifiers if sign-up settings are not enabled', () => {
describe('should fail to register with identifiers if sign-up settings are not enabled', () => {
beforeAll(async () => {
// This function call will disable all sign-up settings by default
await enableAllPasswordSignInMethods();
});
it('Should fail to register with username and password', async () => {
it('should fail to register with username and password', async () => {
const client = await initClient();
await expectRejects(
@ -72,7 +72,7 @@ describe('Register with identifiers sad path', () => {
);
});
it('Should fail to register with email', async () => {
it('should fail to register with email', async () => {
await setEmailConnector();
const { primaryEmail } = generateNewUserProfile({ primaryEmail: true });
const client = await initClient();
@ -85,7 +85,7 @@ describe('Register with identifiers sad path', () => {
email: primaryEmail,
});
const { code: verificationCode } = await readVerificationCode();
const { code: verificationCode } = await readVerificationCode('Email');
await expectRejects(
client.send(patchInteractionIdentifiers, {
@ -102,7 +102,7 @@ describe('Register with identifiers sad path', () => {
await clearConnectorsByTypes([ConnectorType.Email]);
});
it('Should fail to register with phone', async () => {
it('should fail to register with phone', async () => {
await setSmsConnector();
const { primaryPhone } = generateNewUserProfile({ primaryPhone: true });
@ -116,7 +116,7 @@ describe('Register with identifiers sad path', () => {
phone: primaryPhone,
});
const { code: verificationCode } = await readVerificationCode();
const { code: verificationCode } = await readVerificationCode('Sms');
await expectRejects(
client.send(patchInteractionIdentifiers, {

View file

@ -32,7 +32,7 @@ const happyPath = async (email: string) => {
email,
});
const verificationCodeRecord = await readVerificationCode();
const verificationCodeRecord = await readVerificationCode('Email');
expect(verificationCodeRecord).toMatchObject({
address: email,
@ -124,7 +124,7 @@ describe('test register with email with SSO feature', () => {
email,
});
const { code: verificationCode } = await readVerificationCode();
const { code: verificationCode } = await readVerificationCode('Email');
await expectRejects(
client.send(patchInteractionIdentifiers, {

View file

@ -44,7 +44,7 @@ describe('Sign-in flow using verification-code identifiers', () => {
email: userProfile.primaryEmail,
});
const verificationCodeRecord = await readVerificationCode();
const verificationCodeRecord = await readVerificationCode('Email');
expect(verificationCodeRecord).toMatchObject({
address: userProfile.primaryEmail,
@ -77,7 +77,7 @@ describe('Sign-in flow using verification-code identifiers', () => {
phone: userProfile.primaryPhone,
});
const verificationCodeRecord = await readVerificationCode();
const verificationCodeRecord = await readVerificationCode('Sms');
expect(verificationCodeRecord).toMatchObject({
phone: userProfile.primaryPhone,
@ -116,7 +116,7 @@ describe('Sign-in flow using verification-code identifiers', () => {
email: newEmail,
});
const verificationCodeRecord = await readVerificationCode();
const verificationCodeRecord = await readVerificationCode('Email');
const { code } = verificationCodeRecord;
@ -158,7 +158,7 @@ describe('Sign-in flow using verification-code identifiers', () => {
phone: newPhone,
});
const verificationCodeRecord = await readVerificationCode();
const verificationCodeRecord = await readVerificationCode('Sms');
const { code } = verificationCodeRecord;
@ -205,7 +205,7 @@ describe('Sign-in flow using verification-code identifiers', () => {
await client.successSend(sendVerificationCode, {
email: userProfile.primaryEmail,
});
const { code } = await readVerificationCode();
const { code } = await readVerificationCode('Email');
await client.successSend(patchInteractionIdentifiers, {
email: userProfile.primaryEmail,
@ -267,7 +267,7 @@ describe('Sign-in flow using verification-code identifiers', () => {
await client.successSend(sendVerificationCode, {
email: userProfile.primaryEmail,
});
const { code } = await readVerificationCode();
const { code } = await readVerificationCode('Email');
await client.successSend(patchInteractionIdentifiers, {
email: userProfile.primaryEmail,
@ -324,7 +324,7 @@ describe('Sign-in flow using verification-code identifiers', () => {
await client.successSend(sendVerificationCode, {
email: userProfile.primaryEmail,
});
const { code } = await readVerificationCode();
const { code } = await readVerificationCode('Email');
await client.successSend(patchInteractionIdentifiers, {
email: userProfile.primaryEmail,

View file

@ -33,7 +33,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => {
await clearSsoConnectors();
});
it('Should fail to sign in with passcode if sign-in mode is register only', async () => {
it('should fail to sign in with passcode if sign-in mode is register only', async () => {
await updateSignInExperience({ signInMode: SignInMode.Register });
const client = await initClient();
@ -51,7 +51,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => {
await enableAllVerificationCodeSignInMethods();
});
it('Should fail to sign in if related identifiers are not enabled', async () => {
it('should fail to sign in if related identifiers are not enabled', async () => {
await updateSignInExperience({
signIn: {
methods: [],
@ -72,7 +72,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => {
email: primaryEmail,
});
const { code: emailVerificationCode } = await readVerificationCode();
const { code: emailVerificationCode } = await readVerificationCode('Email');
await expectRejects(
client.send(patchInteractionIdentifiers, {
@ -90,7 +90,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => {
phone: primaryPhone,
});
const { code: phoneVerificationCode } = await readVerificationCode();
const { code: phoneVerificationCode } = await readVerificationCode('Sms');
await expectRejects(
client.send(patchInteractionIdentifiers, {
@ -107,7 +107,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => {
await enableAllVerificationCodeSignInMethods();
});
it('Should fail to update sign in email identifier if verification code is incorrect or mismatch', async () => {
it('should fail to update sign in email identifier if verification code is incorrect or mismatch', async () => {
const {
userProfile: { primaryEmail },
} = await generateNewUser({ primaryEmail: true });
@ -121,7 +121,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => {
email: primaryEmail,
});
const { code: verificationCode } = await readVerificationCode();
const { code: verificationCode } = await readVerificationCode('Email');
await expectRejects(
client.send(patchInteractionIdentifiers, {
@ -146,7 +146,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => {
);
});
it('Should fail to update sign in phone identifier if verification code is incorrect or mismatch', async () => {
it('should fail to update sign in phone identifier if verification code is incorrect or mismatch', async () => {
const {
userProfile: { primaryPhone },
} = await generateNewUser({ primaryPhone: true });
@ -160,7 +160,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => {
phone: primaryPhone,
});
const { code: verificationCode } = await readVerificationCode();
const { code: verificationCode } = await readVerificationCode('Sms');
await expectRejects(
client.send(patchInteractionIdentifiers, {
@ -185,7 +185,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => {
);
});
it('Should fail to sign in with email and passcode if related user is not exist', async () => {
it('should fail to sign in with email and passcode if related user is not exist', async () => {
const notExistUserEmail = generateEmail();
const client = await initClient();
@ -198,7 +198,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => {
email: notExistUserEmail,
});
const { code: verificationCode } = await readVerificationCode();
const { code: verificationCode } = await readVerificationCode('Email');
await client.successSend(patchInteractionIdentifiers, {
email: notExistUserEmail,
@ -211,7 +211,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => {
});
});
it('Should fail to sign in with phone and passcode if related user is not exist', async () => {
it('should fail to sign in with phone and passcode if related user is not exist', async () => {
const notExistUserPhone = generatePhone();
const client = await initClient();
@ -224,7 +224,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => {
phone: notExistUserPhone,
});
const { code: verificationCode } = await readVerificationCode();
const { code: verificationCode } = await readVerificationCode('Sms');
await client.successSend(patchInteractionIdentifiers, {
phone: notExistUserPhone,
@ -237,7 +237,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => {
});
});
it('Should fail to sign in if related user is suspended', async () => {
it('should fail to sign in if related user is suspended', async () => {
const {
userProfile: { primaryEmail },
user: { id: userId },
@ -254,7 +254,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => {
email: primaryEmail,
});
const { code: verificationCode } = await readVerificationCode();
const { code: verificationCode } = await readVerificationCode('Email');
await client.successSend(patchInteractionIdentifiers, {
email: primaryEmail,

View file

@ -32,7 +32,7 @@ const happyPath = async (email: string) => {
email,
});
const verificationCodeRecord = await readVerificationCode();
const verificationCodeRecord = await readVerificationCode('Email');
expect(verificationCodeRecord).toMatchObject({
address: email,
@ -70,7 +70,7 @@ describe('test sign-in with email passcode identifier with SSO feature', () => {
await clearSsoConnectors();
});
it('Should fail to sign in with email and passcode if the email domain is enabled for SSO only', async () => {
it('should fail to sign in with email and passcode if the email domain is enabled for SSO only', async () => {
const email = generateEmail('sso-sad-path.io');
const user = await createUser({ primaryEmail: email });
await updateSignInExperience({ singleSignOnEnabled: true });
@ -91,7 +91,7 @@ describe('test sign-in with email passcode identifier with SSO feature', () => {
email,
});
const { code: verificationCode } = await readVerificationCode();
const { code: verificationCode } = await readVerificationCode('Email');
await expectRejects(
client.send(patchInteractionIdentifiers, {
@ -108,7 +108,7 @@ describe('test sign-in with email passcode identifier with SSO feature', () => {
await deleteSsoConnectorById(id);
});
it('Should sign-in with email with SSO disabled', async () => {
it('should sign-in with email with SSO disabled', async () => {
await updateSignInExperience({ singleSignOnEnabled: false });
const { id } = await createSsoConnector({
@ -123,7 +123,7 @@ describe('test sign-in with email passcode identifier with SSO feature', () => {
await deleteSsoConnectorById(id);
});
it('Should sign-in with email with SSO enabled but no connector found', async () => {
it('should sign-in with email with SSO enabled but no connector found', async () => {
await updateSignInExperience({ singleSignOnEnabled: true });
const { id } = await createSsoConnector({

View file

@ -121,7 +121,7 @@ describe('Sign-in flow using password identifiers', () => {
email: primaryEmail,
});
const { code } = await readVerificationCode();
const { code } = await readVerificationCode('Email');
await client.successSend(patchInteractionIdentifiers, {
email: primaryEmail,
@ -183,7 +183,7 @@ describe('Sign-in flow using password identifiers', () => {
phone: primaryPhone,
});
const { code } = await readVerificationCode();
const { code } = await readVerificationCode('Sms');
await client.successSend(patchInteractionIdentifiers, {
phone: primaryPhone,

View file

@ -26,7 +26,7 @@ describe('Generic verification code through management API', () => {
});
afterEach(async () => {
await removeVerificationCode();
await Promise.all([removeVerificationCode('Sms'), removeVerificationCode('Email')]);
});
it('should create an email verification code on server side', async () => {
@ -34,7 +34,7 @@ describe('Generic verification code through management API', () => {
const response = await requestVerificationCode(payload);
expect(response.statusCode).toBe(204);
const { code, type, address } = await readVerificationCode();
const { code, type, address } = await readVerificationCode('Email');
expect(type).toBe(TemplateType.Generic);
expect(address).toBe(mockEmail);
@ -46,7 +46,7 @@ describe('Generic verification code through management API', () => {
const response = await requestVerificationCode(payload);
expect(response.statusCode).toBe(204);
const { code, type, phone } = await readVerificationCode();
const { code, type, phone } = await readVerificationCode('Sms');
expect(type).toBe(TemplateType.Generic);
expect(phone).toBe(mockPhone);
@ -59,7 +59,8 @@ describe('Generic verification code through management API', () => {
statusCode: 400,
});
await expect(readVerificationCode()).rejects.toThrow();
await expect(readVerificationCode('Email')).rejects.toThrow();
await expect(readVerificationCode('Sms')).rejects.toThrow();
});
it('should fail to send a verification code on server side when no email connector has been set', async () => {
@ -113,7 +114,7 @@ describe('Generic verification code through management API', () => {
it('should be able to verify the email verification code', async () => {
await requestVerificationCode({ email: mockEmail });
const { code } = await readVerificationCode();
const { code } = await readVerificationCode('Email');
await expect(
verifyVerificationCode({ email: mockEmail, verificationCode: code })
@ -123,7 +124,7 @@ describe('Generic verification code through management API', () => {
it('should be able to verify the sms verification code', async () => {
await requestVerificationCode({ phone: mockPhone });
const { code } = await readVerificationCode();
const { code } = await readVerificationCode('Sms');
await expect(
verifyVerificationCode({ phone: mockPhone, verificationCode: code })
@ -132,7 +133,7 @@ describe('Generic verification code through management API', () => {
it('should throw when the code is not valid', async () => {
await requestVerificationCode({ phone: mockPhone });
await readVerificationCode();
await readVerificationCode('Sms');
await expectRejects(verifyVerificationCode({ phone: mockPhone, verificationCode: '666' }), {
code: 'verification_code.code_mismatch',
statusCode: 400,
@ -143,7 +144,7 @@ describe('Generic verification code through management API', () => {
const phoneToVerify = '666';
const phoneToGetCode = mockPhone;
await requestVerificationCode({ phone: phoneToGetCode });
const { code, phone } = await readVerificationCode();
const { code, phone } = await readVerificationCode('Sms');
expect(phoneToGetCode).toEqual(phone);
await expectRejects(verifyVerificationCode({ phone: phoneToVerify, verificationCode: code }), {
code: 'verification_code.not_found',
@ -155,7 +156,7 @@ describe('Generic verification code through management API', () => {
const emailToVerify = 'verify_email@mail.com';
const emailToGetCode = mockEmail;
await requestVerificationCode({ email: emailToGetCode });
const { code, address } = await readVerificationCode();
const { code, address } = await readVerificationCode('Email');
expect(emailToGetCode).toEqual(address);
await expectRejects(verifyVerificationCode({ email: emailToVerify, verificationCode: code }), {
code: 'verification_code.not_found',

View file

@ -48,7 +48,7 @@ describe('MFA - TOTP', () => {
const experience = new ExpectTotpExperience(await browser.newPage());
await experience.startWith(demoAppUrl, 'sign-in');
await experience.toFillInput('identifier', userProfile.primaryEmail, { submit: true });
await experience.toCompleteVerification('sign-in');
await experience.toCompleteVerification('sign-in', 'Email');
// Add missing password
await experience.toFillInput('newPassword', 'l0gt0_T3st_P@ssw0rd', { submit: true });
@ -99,7 +99,7 @@ describe('MFA - TOTP', () => {
// Add missing phone number
await waitFor(500);
await experience.toFillInput('identifier', generatePhone(), { submit: true });
await experience.toCompleteVerification('continue');
await experience.toCompleteVerification('continue', 'Sms');
// Bind TOTP
await experience.toBindTotp();
@ -147,7 +147,7 @@ describe('MFA - TOTP', () => {
// Add missing email number
await waitFor(500);
await experience.toFillInput('identifier', generateEmail(), { submit: true });
await experience.toCompleteVerification('continue');
await experience.toCompleteVerification('continue', 'Email');
// Bind TOTP
await experience.toBindTotp();
@ -230,7 +230,7 @@ describe('MFA - TOTP', () => {
// Add missing email
await verificationExperience.toFillInput('identifier', generateEmail(), { submit: true });
await verificationExperience.toCompleteVerification('continue');
await verificationExperience.toCompleteVerification('continue', 'Email');
// Wait for the page to load
await waitFor(500);
await verificationExperience.verifyThenEnd();

View file

@ -67,7 +67,7 @@ describe('MFA - TOTP', () => {
const experience = new ExpectTotpExperience(await browser.newPage());
await experience.startWith(demoAppUrl, 'register');
await experience.toFillInput('id', context.userEmail, { submit: true });
await experience.toCompleteVerification('register');
await experience.toCompleteVerification('register', 'Email');
context.setUpTotpSecret(await experience.toBindTotp());
await experience.verifyThenEnd();
@ -81,7 +81,7 @@ describe('MFA - TOTP', () => {
const experience = new ExpectTotpExperience(await browser.newPage());
await experience.startWith(demoAppUrl, 'sign-in');
await experience.toFillInput('identifier', context.userEmail, { submit: true });
await experience.toCompleteVerification('sign-in');
await experience.toCompleteVerification('sign-in', 'Email');
await experience.toVerifyTotp(context.totpSecret);
const userId = await experience.getUserIdFromDemoAppPage();
await experience.verifyThenEnd();
@ -95,7 +95,7 @@ describe('MFA - TOTP', () => {
const experience = new ExpectTotpExperience(await browser.newPage());
await experience.startWith(demoAppUrl, 'sign-in');
await experience.toFillInput('identifier', userProfile.primaryEmail, { submit: true });
await experience.toCompleteVerification('sign-in');
await experience.toCompleteVerification('sign-in', 'Email');
await experience.toBindTotp();
await experience.verifyThenEnd();
// Clean up
@ -147,7 +147,7 @@ describe('MFA - TOTP', () => {
const experience = new ExpectTotpExperience(await browser.newPage());
await experience.startWith(demoAppUrl, 'register');
await experience.toFillInput('id', context.userPhone, { submit: true });
await experience.toCompleteVerification('register');
await experience.toCompleteVerification('register', 'Sms');
context.setUpTotpSecret(await experience.toBindTotp());
@ -163,7 +163,7 @@ describe('MFA - TOTP', () => {
const experience = new ExpectTotpExperience(await browser.newPage());
await experience.startWith(demoAppUrl, 'sign-in');
await experience.toFillInput('identifier', context.userPhone, { submit: true });
await experience.toCompleteVerification('sign-in');
await experience.toCompleteVerification('sign-in', 'Sms');
await experience.toVerifyTotp(context.totpSecret);
const userId = await experience.getUserIdFromDemoAppPage();
await experience.verifyThenEnd();
@ -179,7 +179,7 @@ describe('MFA - TOTP', () => {
await experience.toFillInput('identifier', userProfile.primaryPhone.slice(1), {
submit: true,
});
await experience.toCompleteVerification('sign-in');
await experience.toCompleteVerification('sign-in', 'Sms');
await experience.toBindTotp();
await experience.verifyThenEnd();

View file

@ -70,7 +70,7 @@ describe('password policy', () => {
// Complete verification code flow
await experience.toFillInput('id', email, { submit: true });
await experience.toCompleteVerification('register');
await experience.toCompleteVerification('register', 'Email');
// Wait for the password page to load
await waitFor(100);
@ -98,7 +98,7 @@ describe('password policy', () => {
await experience.toClickSubmit();
// Complete verification code flow
await experience.toCompleteVerification('forgot-password');
await experience.toCompleteVerification('forgot-password', 'Email');
// Wait for the password page to load
await waitFor(100);

View file

@ -131,9 +131,12 @@ export default class ExpectExperience extends ExpectPage {
*
* @param type The type of experience to expect.
*/
async toCompleteVerification(type: ExperienceType) {
async toCompleteVerification(
type: ExperienceType,
connectorType: Parameters<typeof readVerificationCode>['0']
) {
this.toBeAt(`${type}/verification-code`);
const { code } = await readVerificationCode();
const { code } = await readVerificationCode(connectorType);
await this.toFillVerificationCode(code);
}

View file

@ -5,6 +5,7 @@ import {
ConnectorErrorCodes,
sendMessagePayloadKeys,
type SendMessagePayload,
ConnectorType,
} from './types/index.js';
export * from './types/index.js';
@ -42,8 +43,18 @@ export const parseJsonObject = (...args: Parameters<typeof parseJson>) => {
return parsed;
};
/** @deprecated Use {@link mockConnectorFilePaths} instead. */
export const mockSmsVerificationCodeFileName = 'logto_mock_verification_code_record.txt';
/**
* The file paths for storing the mock sms/email connector records. You can use these file paths to
* read the records for testing.
*/
export const mockConnectorFilePaths = Object.freeze({
[ConnectorType.Sms]: '/tmp/logto_mock_sms_record.txt',
[ConnectorType.Email]: '/tmp/logto_mock_email_record.txt',
});
/**
* Replace all handlebars that match the keys in {@link SendMessagePayload} with the payload
* values. If the payload does not contain the key, the handlebar will be replaced with an empty