mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
test: add sad paths for sign-in with passcode flow (#4296)
This commit is contained in:
parent
ae0322621f
commit
2660a1e132
3 changed files with 270 additions and 1 deletions
|
@ -29,6 +29,9 @@ export const updateUser = async (userId: string, payload: Partial<User>) =>
|
||||||
})
|
})
|
||||||
.json<User>();
|
.json<User>();
|
||||||
|
|
||||||
|
export const suspendUser = async (userId: string, isSuspended: boolean) =>
|
||||||
|
authedAdminApi.patch(`users/${userId}/is-suspended`, { json: { isSuspended } }).json<User>();
|
||||||
|
|
||||||
export const deleteUser = async (userId: string) => authedAdminApi.delete(`users/${userId}`);
|
export const deleteUser = async (userId: string) => authedAdminApi.delete(`users/${userId}`);
|
||||||
|
|
||||||
export const updateUserPassword = async (userId: string, password: string) =>
|
export const updateUserPassword = async (userId: string, password: string) =>
|
||||||
|
|
|
@ -20,13 +20,14 @@ import { enableAllVerificationCodeSignInMethods } from '#src/helpers/sign-in-exp
|
||||||
import { generateNewUser, generateNewUserProfile } from '#src/helpers/user.js';
|
import { generateNewUser, generateNewUserProfile } from '#src/helpers/user.js';
|
||||||
import { generateEmail, generatePhone } from '#src/utils.js';
|
import { generateEmail, generatePhone } from '#src/utils.js';
|
||||||
|
|
||||||
describe('Sign-In flow using verification-code identifiers', () => {
|
describe('Sign-in flow using verification-code identifiers', () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await clearConnectorsByTypes([ConnectorType.Email, ConnectorType.Sms]);
|
await clearConnectorsByTypes([ConnectorType.Email, ConnectorType.Sms]);
|
||||||
await setEmailConnector();
|
await setEmailConnector();
|
||||||
await setSmsConnector();
|
await setSmsConnector();
|
||||||
await enableAllVerificationCodeSignInMethods();
|
await enableAllVerificationCodeSignInMethods();
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await clearConnectorsByTypes([ConnectorType.Email, ConnectorType.Sms]);
|
await clearConnectorsByTypes([ConnectorType.Email, ConnectorType.Sms]);
|
||||||
});
|
});
|
|
@ -0,0 +1,265 @@
|
||||||
|
import { ConnectorType } from '@logto/connector-kit';
|
||||||
|
import { InteractionEvent, SignInMode } from '@logto/schemas';
|
||||||
|
|
||||||
|
import { suspendUser } from '#src/api/admin-user.js';
|
||||||
|
import {
|
||||||
|
patchInteractionIdentifiers,
|
||||||
|
putInteraction,
|
||||||
|
sendVerificationCode,
|
||||||
|
} from '#src/api/interaction.js';
|
||||||
|
import { updateSignInExperience } from '#src/api/sign-in-experience.js';
|
||||||
|
import { initClient } from '#src/helpers/client.js';
|
||||||
|
import {
|
||||||
|
clearConnectorsByTypes,
|
||||||
|
setEmailConnector,
|
||||||
|
setSmsConnector,
|
||||||
|
} from '#src/helpers/connector.js';
|
||||||
|
import { expectRejects, readVerificationCode } from '#src/helpers/index.js';
|
||||||
|
import { enableAllVerificationCodeSignInMethods } from '#src/helpers/sign-in-experience.js';
|
||||||
|
import { generateNewUser } from '#src/helpers/user.js';
|
||||||
|
import { generateEmail, generatePhone } from '#src/utils.js';
|
||||||
|
|
||||||
|
describe('Sign-in flow sad path using verification-code identifiers', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await clearConnectorsByTypes([ConnectorType.Email, ConnectorType.Sms]);
|
||||||
|
await setEmailConnector();
|
||||||
|
await setSmsConnector();
|
||||||
|
await enableAllVerificationCodeSignInMethods();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await clearConnectorsByTypes([ConnectorType.Email, ConnectorType.Sms]);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await enableAllVerificationCodeSignInMethods();
|
||||||
|
});
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
await expectRejects(
|
||||||
|
client.send(putInteraction, {
|
||||||
|
event: InteractionEvent.SignIn,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
code: 'auth.forbidden',
|
||||||
|
statusCode: 403,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should fail to sign in if related identifiers are not enabled', async () => {
|
||||||
|
await updateSignInExperience({
|
||||||
|
signIn: {
|
||||||
|
methods: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const client = await initClient();
|
||||||
|
|
||||||
|
const {
|
||||||
|
userProfile: { primaryEmail, primaryPhone },
|
||||||
|
} = await generateNewUser({ primaryEmail: true, primaryPhone: true });
|
||||||
|
|
||||||
|
await client.successSend(putInteraction, {
|
||||||
|
event: InteractionEvent.SignIn,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Email
|
||||||
|
await client.successSend(sendVerificationCode, {
|
||||||
|
email: primaryEmail,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { code: emailVerificationCode } = await readVerificationCode();
|
||||||
|
|
||||||
|
await expectRejects(
|
||||||
|
client.send(patchInteractionIdentifiers, {
|
||||||
|
email: primaryEmail,
|
||||||
|
verificationCode: emailVerificationCode,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
code: 'user.sign_in_method_not_enabled',
|
||||||
|
statusCode: 422,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Phone
|
||||||
|
await client.successSend(sendVerificationCode, {
|
||||||
|
phone: primaryPhone,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { code: phoneVerificationCode } = await readVerificationCode();
|
||||||
|
|
||||||
|
await expectRejects(
|
||||||
|
client.send(patchInteractionIdentifiers, {
|
||||||
|
phone: primaryPhone,
|
||||||
|
verificationCode: phoneVerificationCode,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
code: 'user.sign_in_method_not_enabled',
|
||||||
|
statusCode: 422,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should fail to update sign in email identifier if verification code is incorrect or mismatch', async () => {
|
||||||
|
const {
|
||||||
|
userProfile: { primaryEmail },
|
||||||
|
} = await generateNewUser({ primaryEmail: true });
|
||||||
|
const client = await initClient();
|
||||||
|
|
||||||
|
await client.successSend(putInteraction, {
|
||||||
|
event: InteractionEvent.SignIn,
|
||||||
|
});
|
||||||
|
|
||||||
|
await client.successSend(sendVerificationCode, {
|
||||||
|
email: primaryEmail,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { code: verificationCode } = await readVerificationCode();
|
||||||
|
|
||||||
|
await expectRejects(
|
||||||
|
client.send(patchInteractionIdentifiers, {
|
||||||
|
email: primaryEmail,
|
||||||
|
verificationCode: `${verificationCode}-incorrect`,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
code: 'verification_code.code_mismatch',
|
||||||
|
statusCode: 400,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await expectRejects(
|
||||||
|
client.send(patchInteractionIdentifiers, {
|
||||||
|
email: `${primaryEmail}-incorrect`,
|
||||||
|
verificationCode,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
code: 'verification_code.email_mismatch',
|
||||||
|
statusCode: 400,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should fail to update sign in phone identifier if verification code is incorrect or mismatch', async () => {
|
||||||
|
const {
|
||||||
|
userProfile: { primaryPhone },
|
||||||
|
} = await generateNewUser({ primaryPhone: true });
|
||||||
|
const client = await initClient();
|
||||||
|
|
||||||
|
await client.successSend(putInteraction, {
|
||||||
|
event: InteractionEvent.SignIn,
|
||||||
|
});
|
||||||
|
|
||||||
|
await client.successSend(sendVerificationCode, {
|
||||||
|
phone: primaryPhone,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { code: verificationCode } = await readVerificationCode();
|
||||||
|
|
||||||
|
await expectRejects(
|
||||||
|
client.send(patchInteractionIdentifiers, {
|
||||||
|
phone: primaryPhone,
|
||||||
|
verificationCode: `${verificationCode}-incorrect`,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
code: 'verification_code.code_mismatch',
|
||||||
|
statusCode: 400,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await expectRejects(
|
||||||
|
client.send(patchInteractionIdentifiers, {
|
||||||
|
phone: `${primaryPhone}001`,
|
||||||
|
verificationCode,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
code: 'verification_code.phone_mismatch',
|
||||||
|
statusCode: 400,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should fail to sign in with email and passcode if related user is not exist', async () => {
|
||||||
|
const notExistUserEmail = generateEmail();
|
||||||
|
|
||||||
|
const client = await initClient();
|
||||||
|
|
||||||
|
await client.successSend(putInteraction, {
|
||||||
|
event: InteractionEvent.SignIn,
|
||||||
|
});
|
||||||
|
|
||||||
|
await client.successSend(sendVerificationCode, {
|
||||||
|
email: notExistUserEmail,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { code: verificationCode } = await readVerificationCode();
|
||||||
|
|
||||||
|
await client.successSend(patchInteractionIdentifiers, {
|
||||||
|
email: notExistUserEmail,
|
||||||
|
verificationCode,
|
||||||
|
});
|
||||||
|
|
||||||
|
await expectRejects(client.submitInteraction(), {
|
||||||
|
code: 'user.user_not_exist',
|
||||||
|
statusCode: 404,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should fail to sign in with phone and passcode if related user is not exist', async () => {
|
||||||
|
const notExistUserPhone = generatePhone();
|
||||||
|
|
||||||
|
const client = await initClient();
|
||||||
|
|
||||||
|
await client.successSend(putInteraction, {
|
||||||
|
event: InteractionEvent.SignIn,
|
||||||
|
});
|
||||||
|
|
||||||
|
await client.successSend(sendVerificationCode, {
|
||||||
|
phone: notExistUserPhone,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { code: verificationCode } = await readVerificationCode();
|
||||||
|
|
||||||
|
await client.successSend(patchInteractionIdentifiers, {
|
||||||
|
phone: notExistUserPhone,
|
||||||
|
verificationCode,
|
||||||
|
});
|
||||||
|
|
||||||
|
await expectRejects(client.submitInteraction(), {
|
||||||
|
code: 'user.user_not_exist',
|
||||||
|
statusCode: 404,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should fail to sign in if related user is suspended', async () => {
|
||||||
|
const {
|
||||||
|
userProfile: { primaryEmail },
|
||||||
|
user: { id: userId },
|
||||||
|
} = await generateNewUser({ primaryEmail: true });
|
||||||
|
|
||||||
|
await suspendUser(userId, true);
|
||||||
|
|
||||||
|
const client = await initClient();
|
||||||
|
await client.successSend(putInteraction, {
|
||||||
|
event: InteractionEvent.SignIn,
|
||||||
|
});
|
||||||
|
|
||||||
|
await client.successSend(sendVerificationCode, {
|
||||||
|
email: primaryEmail,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { code: verificationCode } = await readVerificationCode();
|
||||||
|
|
||||||
|
await client.successSend(patchInteractionIdentifiers, {
|
||||||
|
email: primaryEmail,
|
||||||
|
verificationCode,
|
||||||
|
});
|
||||||
|
|
||||||
|
await expectRejects(client.submitInteraction(), {
|
||||||
|
code: 'user.suspended',
|
||||||
|
statusCode: 401,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in a new issue