From 56de71cbbfc792870dd7d050c25c9409311bb309 Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Fri, 29 Mar 2024 16:51:39 +0800 Subject: [PATCH] refactor: fix test cases --- packages/integration-tests/jest.setup.js | 4 ++ .../integration-tests/src/api/application.ts | 7 ++-- packages/integration-tests/src/api/factory.ts | 30 +++++++++++-- .../src/api/interaction-sso.ts | 1 - .../integration-tests/src/api/interaction.ts | 15 +------ .../integration-tests/src/client/index.ts | 4 ++ .../src/helpers/admin-tenant.ts | 1 + .../integration-tests/src/helpers/index.ts | 10 ++--- .../src/helpers/interactions.ts | 2 +- .../src/tests/api/admin-user.roles.test.ts | 2 +- .../src/tests/api/admin-user.search.test.ts | 16 +++---- .../src/tests/api/admin-user.test.ts | 42 ++++++++++--------- .../application-sign-in-experience.test.ts | 6 +-- ...lication-user-consent-organization.test.ts | 8 ++-- .../application-user-consent-scope.test.ts | 16 +++---- .../api/application/application.roles.test.ts | 4 +- .../tests/api/application/application.test.ts | 8 ++-- .../src/tests/api/callback.test.ts | 1 + .../src/tests/api/connector.test.ts | 8 ++-- .../src/tests/api/dashboard.test.ts | 6 +-- .../src/tests/api/health-check.test.ts | 2 +- .../src/tests/api/hook/hook.test.ts | 18 ++++---- .../src/tests/api/hook/hook.testing.test.ts | 6 +-- .../interaction-details-guard.test.ts | 20 ++++----- .../interaction-results-checking.test.ts | 16 +++---- .../patch-interaction-identifiers.test.ts | 2 +- .../post-send-verification-code.test.ts | 11 +++-- .../put-interaction-event.test.ts | 12 +++--- .../api-counter-cases/put-interaction.test.ts | 16 +++---- .../forgot-password/happy-path.test.ts | 8 ++-- .../forgot-password/sad-path.test.ts | 6 +-- .../api/interaction/mfa/backup-code.test.ts | 4 +- .../tests/api/interaction/mfa/totp.test.ts | 12 +++--- .../happy-path.test.ts | 8 ++-- .../register-with-identifier/sad-path.test.ts | 8 ++-- .../single-sign-on.test.ts | 2 +- .../happy-path.test.ts | 14 +++---- .../sad-path.test.ts | 20 ++++----- .../single-sign-on.test.ts | 2 +- .../happy-path.test.ts | 4 +- .../sad-path.test.ts | 20 ++++----- .../single-sign-on.test.ts | 2 +- .../single-sign-on/happy-path.test.ts | 10 +++-- .../single-sign-on/sad-path.test.ts | 7 ++-- .../social-sign-in/happy-path.test.ts | 18 ++++---- .../social-sign-in/sad-path.test.ts | 30 ++++++------- .../src/tests/api/log.test.ts | 2 +- .../src/tests/api/logto-config.test.ts | 16 +++---- .../src/tests/api/me.test.ts | 10 ++--- .../tests/api/oidc/content-type-json.test.ts | 7 +--- .../api/oidc/refresh-token-grant.test.ts | 19 +++++---- .../organization-invitation.creation.test.ts | 20 ++++----- .../organization-invitation.status.test.ts | 16 ++++--- .../organization/organization-role.test.ts | 9 ++-- .../organization/organization-scope.test.ts | 7 ++-- .../organization/organization-user.test.ts | 4 +- .../src/tests/api/resource.test.ts | 2 +- .../src/tests/api/role.user.test.ts | 2 +- .../src/tests/api/sign-in-experience.test.ts | 2 +- .../src/tests/api/sso-connectors.test.ts | 4 +- .../src/tests/api/swagger-check.test.ts | 2 +- .../src/tests/api/verification-code.test.ts | 16 +++---- .../tests/experience/password-policy.test.ts | 5 +-- packages/integration-tests/src/utils.ts | 8 +--- 64 files changed, 319 insertions(+), 301 deletions(-) diff --git a/packages/integration-tests/jest.setup.js b/packages/integration-tests/jest.setup.js index 38ea7b6caa4a..ff4d9651c147 100644 --- a/packages/integration-tests/jest.setup.js +++ b/packages/integration-tests/jest.setup.js @@ -9,6 +9,10 @@ dotenv.config(); /* eslint-disable @silverhand/fp/no-mutation */ global.TextDecoder = TextDecoder; global.TextEncoder = TextEncoder; +global.fail = (message) => { + throw new Error(message); +}; + /* eslint-enable @silverhand/fp/no-mutation */ // GitHub Actions default runners need more time for UI tests diff --git a/packages/integration-tests/src/api/application.ts b/packages/integration-tests/src/api/application.ts index c6f1d2c99715..91ba032b37aa 100644 --- a/packages/integration-tests/src/api/application.ts +++ b/packages/integration-tests/src/api/application.ts @@ -8,8 +8,6 @@ import { } from '@logto/schemas'; import { conditional } from '@silverhand/essentials'; -import { createFormData } from '#src/utils.js'; - import { authedAdminApi, oidcApi } from './api.js'; export const createApplication = async ( @@ -101,7 +99,10 @@ export const generateM2mLog = async (applicationId: string) => { // This is a token request with insufficient parameters and should fail. We make the request to generate a log for the current machine to machine app. return oidcApi.post('token', { - body: createFormData({ + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: new URLSearchParams({ client_id: id, client_secret: secret, grant_type: 'client_credentials', diff --git a/packages/integration-tests/src/api/factory.ts b/packages/integration-tests/src/api/factory.ts index e2761d66c26f..f7ccbaac498f 100644 --- a/packages/integration-tests/src/api/factory.ts +++ b/packages/integration-tests/src/api/factory.ts @@ -1,5 +1,23 @@ import { authedAdminApi } from './api.js'; +/** + * Transform the data to a new object or array without modifying the original data. + * This is useful since `.json()` returns an object that contains something which makes + * it impossible to use `.toStrictEqual()` directly. + */ +const transform = (data: T): T => { + if (Array.isArray(data)) { + // eslint-disable-next-line no-restricted-syntax + return [...data] as T; + } + + if (typeof data === 'object') { + return { ...data }; + } + + return data; +}; + export class ApiFactory< Schema extends Record, PostData extends Record, @@ -8,19 +26,23 @@ export class ApiFactory< constructor(public readonly path: string) {} async create(data: PostData): Promise { - return authedAdminApi.post(this.path, { json: data }).json(); + return transform(await authedAdminApi.post(this.path, { json: data }).json()); } async getList(params?: URLSearchParams): Promise { - return authedAdminApi.get(this.path + '?' + (params?.toString() ?? '')).json(); + return transform( + await authedAdminApi.get(this.path + '?' + (params?.toString() ?? '')).json() + ); } async get(id: string): Promise { - return authedAdminApi.get(this.path + '/' + id).json(); + return transform(await authedAdminApi.get(this.path + '/' + id).json()); } async update(id: string, data: PatchData): Promise { - return authedAdminApi.patch(this.path + '/' + id, { json: data }).json(); + return transform( + await authedAdminApi.patch(this.path + '/' + id, { json: data }).json() + ); } async delete(id: string): Promise { diff --git a/packages/integration-tests/src/api/interaction-sso.ts b/packages/integration-tests/src/api/interaction-sso.ts index e515f0e9b081..9d2011c5d728 100644 --- a/packages/integration-tests/src/api/interaction-sso.ts +++ b/packages/integration-tests/src/api/interaction-sso.ts @@ -15,7 +15,6 @@ export const getSsoAuthorizationUrl = async ( .post(`interaction/${ssoPath}/${connectorId}/authorization-url`, { headers: { cookie }, json: payload, - redirect: 'manual', }) .json<{ redirectTo: string }>(); }; diff --git a/packages/integration-tests/src/api/interaction.ts b/packages/integration-tests/src/api/interaction.ts index 139e2dd9f44d..977b690e0f10 100644 --- a/packages/integration-tests/src/api/interaction.ts +++ b/packages/integration-tests/src/api/interaction.ts @@ -26,7 +26,6 @@ export const putInteraction = async (cookie: string, payload: InteractionPayload .put('interaction', { headers: { cookie }, json: payload, - redirect: 'manual', }) .json(); @@ -34,7 +33,6 @@ export const deleteInteraction = async (cookie: string) => api .delete('interaction', { headers: { cookie }, - redirect: 'manual', }) .json(); @@ -46,7 +44,6 @@ export const patchInteractionIdentifiers = async (cookie: string, payload: Ident .patch('interaction/identifiers', { headers: { cookie }, json: payload, - redirect: 'manual', }) .json(); @@ -55,7 +52,6 @@ export const patchInteractionProfile = async (cookie: string, payload: Profile) .patch('interaction/profile', { headers: { cookie }, json: payload, - redirect: 'manual', }) .json(); @@ -64,7 +60,6 @@ export const putInteractionProfile = async (cookie: string, payload: Profile) => .put('interaction/profile', { headers: { cookie }, json: payload, - redirect: 'manual', }) .json(); @@ -73,7 +68,6 @@ export const postInteractionBindMfa = async (cookie: string, payload: BindMfaPay .post('interaction/bind-mfa', { headers: { cookie }, json: payload, - redirect: 'manual', }) .json(); @@ -82,7 +76,6 @@ export const putInteractionMfa = async (cookie: string, payload: VerifyMfaPayloa .put('interaction/mfa', { headers: { cookie }, json: payload, - redirect: 'manual', }) .json(); @@ -90,7 +83,6 @@ export const deleteInteractionProfile = async (cookie: string) => api .delete('interaction/profile', { headers: { cookie }, - redirect: 'manual', }) .json(); @@ -106,7 +98,6 @@ export const sendVerificationCode = async ( api.post('interaction/verification/verification-code', { headers: { cookie }, json: payload, - redirect: 'manual', }); export type SocialAuthorizationUriPayload = { @@ -122,7 +113,6 @@ export const createSocialAuthorizationUri = async ( api.post('interaction/verification/social-authorization-uri', { headers: { cookie }, json: payload, - redirect: 'manual', }); export const initTotp = async (cookie: string) => @@ -131,6 +121,7 @@ export const initTotp = async (cookie: string) => headers: { cookie }, json: {}, redirect: 'manual', + throwHttpErrors: false, }) .json<{ secret: string }>(); @@ -140,7 +131,6 @@ export const skipMfaBinding = async (cookie: string) => json: { mfaSkipped: true, }, - redirect: 'manual', }); export const consent = async (api: KyInstance, cookie: string) => @@ -150,6 +140,7 @@ export const consent = async (api: KyInstance, cookie: string) => cookie, }, redirect: 'manual', + throwHttpErrors: false, }) .json(); @@ -157,7 +148,6 @@ export const getConsentInfo = async (cookie: string) => api .get('interaction/consent', { headers: { cookie }, - redirect: 'manual', }) .json(); @@ -168,5 +158,4 @@ export const createSingleSignOnAuthorizationUri = async ( api.post('interaction/verification/sso-authorization-uri', { headers: { cookie }, json: payload, - redirect: 'manual', }); diff --git a/packages/integration-tests/src/client/index.ts b/packages/integration-tests/src/client/index.ts index 5be2873845b7..16d8ce5dd479 100644 --- a/packages/integration-tests/src/client/index.ts +++ b/packages/integration-tests/src/client/index.ts @@ -73,6 +73,7 @@ export default class MockClient { // Mock SDK sign-in navigation const response = await ky(this.navigateUrl, { redirect: 'manual', + throwHttpErrors: false, }); // Note: should redirect to sign-in page @@ -106,6 +107,7 @@ export default class MockClient { cookie: this.interactionCookie, }, redirect: 'manual', + throwHttpErrors: false, }); // Note: Should redirect to logto consent page @@ -182,6 +184,7 @@ export default class MockClient { cookie: this.interactionCookie, }, redirect: 'manual', + throwHttpErrors: false, }); // Consent page should auto consent and redirect to auth endpoint @@ -196,6 +199,7 @@ export default class MockClient { cookie: this.interactionCookie, }, redirect: 'manual', + throwHttpErrors: false, }); // Note: Should redirect to the signInCallbackUri diff --git a/packages/integration-tests/src/helpers/admin-tenant.ts b/packages/integration-tests/src/helpers/admin-tenant.ts index e35f2242613b..d91840c06e55 100644 --- a/packages/integration-tests/src/helpers/admin-tenant.ts +++ b/packages/integration-tests/src/helpers/admin-tenant.ts @@ -63,6 +63,7 @@ export const putInteraction = async (cookie: string, payload: InteractionPayload headers: { cookie }, json: payload, redirect: 'manual', + throwHttpErrors: false, }) .json(); diff --git a/packages/integration-tests/src/helpers/index.ts b/packages/integration-tests/src/helpers/index.ts index 520e1d81d99c..d83decf2451b 100644 --- a/packages/integration-tests/src/helpers/index.ts +++ b/packages/integration-tests/src/helpers/index.ts @@ -77,7 +77,7 @@ export const removeConnectorMessage = async ( type ExpectedErrorInfo = { code: string; - statusCode: number; + status: number; messageIncludes?: string; }; @@ -94,8 +94,8 @@ export const expectRejects = async ( fail(); }; -export const expectRequestError = (error: unknown, expected: ExpectedErrorInfo) => { - const { code, statusCode, messageIncludes } = expected; +const expectRequestError = async (error: unknown, expected: ExpectedErrorInfo) => { + const { code, status, messageIncludes } = expected; if (!(error instanceof HTTPError)) { fail('Error should be an instance of RequestError'); @@ -103,7 +103,7 @@ export const expectRequestError = (error: unknown, expected: ExpectedE // JSON.parse returns `any`. Directly use `as` since we've already know the response body structure. // eslint-disable-next-line no-restricted-syntax - const body = JSON.parse(String(error.response.body)) as { + const body = (await error.response.json()) as { code: string; message: string; data: T; @@ -111,7 +111,7 @@ export const expectRequestError = (error: unknown, expected: ExpectedE expect(body.code).toEqual(code); - expect(error.response.status).toEqual(statusCode); + expect(error.response.status).toEqual(status); if (messageIncludes) { expect(body.message.includes(messageIncludes)).toBeTruthy(); diff --git a/packages/integration-tests/src/helpers/interactions.ts b/packages/integration-tests/src/helpers/interactions.ts index a0dfe1f94b80..a744d8bae951 100644 --- a/packages/integration-tests/src/helpers/interactions.ts +++ b/packages/integration-tests/src/helpers/interactions.ts @@ -80,7 +80,7 @@ export const createNewSocialUserWithUsernameAndPassword = async (connectorId: st await expectRejects(client.submitInteraction(), { code: 'user.identity_not_exist', - statusCode: 422, + status: 422, }); await client.successSend(patchInteractionIdentifiers, { username, password }); await client.successSend(putInteractionProfile, { connectorId }); diff --git a/packages/integration-tests/src/tests/api/admin-user.roles.test.ts b/packages/integration-tests/src/tests/api/admin-user.roles.test.ts index 16f51a8e959b..820bcc70fa7d 100644 --- a/packages/integration-tests/src/tests/api/admin-user.roles.test.ts +++ b/packages/integration-tests/src/tests/api/admin-user.roles.test.ts @@ -21,7 +21,7 @@ describe('admin console user management (roles)', () => { const m2mRole = await createRole({ type: RoleType.MachineToMachine }); await expectRejects(assignRolesToUser(user.id, [m2mRole.id]), { code: 'user.invalid_role_type', - statusCode: 422, + status: 422, }); await assignRolesToUser(user.id, [role1.id, role2.id]); diff --git a/packages/integration-tests/src/tests/api/admin-user.search.test.ts b/packages/integration-tests/src/tests/api/admin-user.search.test.ts index 781bf232b732..23b5f6f75ebb 100644 --- a/packages/integration-tests/src/tests/api/admin-user.search.test.ts +++ b/packages/integration-tests/src/tests/api/admin-user.search.test.ts @@ -9,11 +9,11 @@ import { UserApiTest } from '#src/helpers/user.js'; const getUsers = async ( init: string[][] | Record | URLSearchParams ): Promise<{ headers: Headers; json: T }> => { - const { headers, json } = await authedAdminApi.get('users', { + const response = await authedAdminApi.get('users', { searchParams: new URLSearchParams(init), }); - return { headers, json: (await json()) as T }; + return { headers: response.headers, json: (await response.json()) as T }; }; describe('admin console user search params', () => { @@ -172,7 +172,7 @@ describe('admin console user search params', () => { ['search.primaryEmail', 'jerry_swift_jr_2@geek.best'], ['search.primaryEmail', 'jerry_swift_jr_jr@gmail.com'], ]), - { code: 'request.invalid_input', statusCode: 400, messageIncludes: '`exact`' } + { code: 'request.invalid_input', status: 400, messageIncludes: '`exact`' } ); }); @@ -184,7 +184,7 @@ describe('admin console user search params', () => { ]), { code: 'request.invalid_input', - statusCode: 400, + status: 400, messageIncludes: 'cannot be empty', } ); @@ -198,7 +198,7 @@ describe('admin console user search params', () => { ]), { code: 'request.invalid_input', - statusCode: 400, + status: 400, messageIncludes: 'case-insensitive', } ); @@ -213,13 +213,13 @@ describe('admin console user search params', () => { ]), { code: 'request.invalid_input', - statusCode: 400, + status: 400, messageIncludes: 'is not valid', } ), expectRejects(getUsers([['search.email', '%gmail%']]), { code: 'request.invalid_input', - statusCode: 400, + status: 400, messageIncludes: 'is not valid', }), expectRejects( @@ -229,7 +229,7 @@ describe('admin console user search params', () => { ]), { code: 'request.invalid_input', - statusCode: 400, + status: 400, messageIncludes: 'is not valid', } ), diff --git a/packages/integration-tests/src/tests/api/admin-user.test.ts b/packages/integration-tests/src/tests/api/admin-user.test.ts index 2f17b7003442..9662010b8c95 100644 --- a/packages/integration-tests/src/tests/api/admin-user.test.ts +++ b/packages/integration-tests/src/tests/api/admin-user.test.ts @@ -1,5 +1,3 @@ -import crypto from 'node:crypto'; - import { UsersPasswordEncryptionMethod, ConnectorType } from '@logto/schemas'; import { HTTPError } from 'ky'; @@ -25,9 +23,13 @@ import { import { clearConnectorsByTypes } from '#src/helpers/connector.js'; import { createUserByAdmin, expectRejects } from '#src/helpers/index.js'; import { createNewSocialUserWithUsernameAndPassword } from '#src/helpers/interactions.js'; -import { generateUsername, generateEmail, generatePhone, generatePassword } from '#src/utils.js'; - -const randomString = () => crypto.randomBytes(8).toString('hex'); +import { + generateUsername, + generateEmail, + generatePhone, + generatePassword, + randomString, +} from '#src/utils.js'; describe('admin console user management', () => { beforeAll(async () => { @@ -62,8 +64,8 @@ describe('admin console user management', () => { profile: { gender: 'neutral' }, }); const { customData, profile } = await getUser(user.id); - expect(customData).toStrictEqual({ foo: 'bar' }); - expect(profile).toStrictEqual({ gender: 'neutral' }); + expect({ ...customData }).toStrictEqual({ foo: 'bar' }); + expect({ ...profile }).toStrictEqual({ gender: 'neutral' }); }); it('should fail when create user with conflict identifiers', async () => { @@ -76,22 +78,22 @@ describe('admin console user management', () => { await createUserByAdmin({ username, password, primaryEmail, primaryPhone }); await expectRejects(createUserByAdmin({ username, password }), { code: 'user.username_already_in_use', - statusCode: 422, + status: 422, }); await expectRejects(createUserByAdmin({ primaryEmail }), { code: 'user.email_already_in_use', - statusCode: 422, + status: 422, }); await expectRejects(createUserByAdmin({ primaryPhone }), { code: 'user.phone_already_in_use', - statusCode: 422, + status: 422, }); }); it('should fail when get user by invalid id', async () => { await expectRejects(getUser('invalid-user-id'), { code: 'entity.not_found', - statusCode: 404, + status: 404, }); }); @@ -131,21 +133,21 @@ describe('admin console user management', () => { }; const updatedProfile = await updateUserProfile(user.id, profile); - expect(updatedProfile).toStrictEqual(profile); + expect(updatedProfile).toMatchObject(profile); const patchProfile = { familyName: 'another name', website: 'https://logto.io/', }; const updatedProfile2 = await updateUserProfile(user.id, patchProfile); - expect(updatedProfile2).toStrictEqual({ ...profile, ...patchProfile }); + expect(updatedProfile2).toMatchObject({ ...profile, ...patchProfile }); }); it('should respond 422 when no update data provided', async () => { const user = await createUserByAdmin(); await expectRejects(updateUser(user.id, {}), { code: 'entity.invalid_input', - statusCode: 422, + status: 422, }); }); @@ -160,17 +162,17 @@ describe('admin console user management', () => { await expectRejects(updateUser(anotherUser.id, { username }), { code: 'user.username_already_in_use', - statusCode: 422, + status: 422, }); await expectRejects(updateUser(anotherUser.id, { primaryEmail }), { code: 'user.email_already_in_use', - statusCode: 422, + status: 422, }); await expectRejects(updateUser(anotherUser.id, { primaryPhone }), { code: 'user.phone_already_in_use', - statusCode: 422, + status: 422, }); }); @@ -297,7 +299,7 @@ describe('admin console user management', () => { it('should return 204 if password is correct', async () => { const user = await createUserByAdmin({ password: 'new_password' }); - expect(await verifyUserPassword(user.id, 'new_password')).toHaveProperty('statusCode', 204); + expect(await verifyUserPassword(user.id, 'new_password')).toHaveProperty('status', 204); await deleteUser(user.id); }); @@ -305,7 +307,7 @@ describe('admin console user management', () => { const user = await createUserByAdmin({ password: 'new_password' }); await expectRejects(verifyUserPassword(user.id, 'wrong_password'), { code: 'session.invalid_credentials', - statusCode: 422, + status: 422, }); await deleteUser(user.id); }); @@ -314,7 +316,7 @@ describe('admin console user management', () => { const user = await createUserByAdmin(); await expectRejects(verifyUserPassword(user.id, ''), { code: 'guard.invalid_input', - statusCode: 400, + status: 400, }); }); }); diff --git a/packages/integration-tests/src/tests/api/application/application-sign-in-experience.test.ts b/packages/integration-tests/src/tests/api/application/application-sign-in-experience.test.ts index d7fd80122d24..24966a87eda8 100644 --- a/packages/integration-tests/src/tests/api/application/application-sign-in-experience.test.ts +++ b/packages/integration-tests/src/tests/api/application/application-sign-in-experience.test.ts @@ -51,7 +51,7 @@ describe('application sign in experience', () => { setApplicationSignInExperience('non-existent-application', applicationSignInExperiences), { code: 'entity.not_exists_with_id', - statusCode: 404, + status: 404, } ); }); @@ -64,7 +64,7 @@ describe('application sign in experience', () => { ), { code: 'application.third_party_application_only', - statusCode: 422, + status: 422, } ); }); @@ -112,7 +112,7 @@ describe('application sign in experience', () => { await expectRejects(getApplicationSignInExperience(application.id), { code: 'entity.not_exists_with_id', - statusCode: 404, + status: 404, }); }); }); diff --git a/packages/integration-tests/src/tests/api/application/application-user-consent-organization.test.ts b/packages/integration-tests/src/tests/api/application/application-user-consent-organization.test.ts index 84aaa7c7c3ee..49103a856f83 100644 --- a/packages/integration-tests/src/tests/api/application/application-user-consent-organization.test.ts +++ b/packages/integration-tests/src/tests/api/application/application-user-consent-organization.test.ts @@ -76,7 +76,7 @@ describe('assign user consent organizations to application', () => { }), { code: 'entity.not_exists_with_id', - statusCode: 404, + status: 404, } ); }); @@ -88,7 +88,7 @@ describe('assign user consent organizations to application', () => { }), { code: 'entity.not_found', - statusCode: 404, + status: 404, } ); }); @@ -104,7 +104,7 @@ describe('assign user consent organizations to application', () => { ), { code: 'application.third_party_application_only', - statusCode: 422, + status: 422, } ); }); @@ -120,7 +120,7 @@ describe('assign user consent organizations to application', () => { ), { code: 'organization.require_membership', - statusCode: 422, + status: 422, } ); }); diff --git a/packages/integration-tests/src/tests/api/application/application-user-consent-scope.test.ts b/packages/integration-tests/src/tests/api/application/application-user-consent-scope.test.ts index ef7535c0fa4a..cf574493654a 100644 --- a/packages/integration-tests/src/tests/api/application/application-user-consent-scope.test.ts +++ b/packages/integration-tests/src/tests/api/application/application-user-consent-scope.test.ts @@ -78,7 +78,7 @@ describe('assign user consent scopes to application', () => { }), { code: 'application.third_party_application_only', - statusCode: 422, + status: 422, } ); }); @@ -90,7 +90,7 @@ describe('assign user consent scopes to application', () => { }), { code: 'application.user_consent_scopes_not_found', - statusCode: 422, + status: 422, } ); }); @@ -102,7 +102,7 @@ describe('assign user consent scopes to application', () => { }), { code: 'application.user_consent_scopes_not_found', - statusCode: 422, + status: 422, } ); }); @@ -130,7 +130,7 @@ describe('assign user consent scopes to application', () => { it('should return 404 when trying to get consent scopes from non-existing application', async () => { await expectRejects(getUserConsentScopes('non-existing-application'), { code: 'entity.not_exists_with_id', - statusCode: 404, + status: 404, }); }); @@ -184,7 +184,7 @@ describe('assign user consent scopes to application', () => { ), { code: 'entity.not_exists_with_id', - statusCode: 404, + status: 404, } ); }); @@ -198,7 +198,7 @@ describe('assign user consent scopes to application', () => { ), { code: 'entity.not_found', - statusCode: 404, + status: 404, } ); @@ -210,7 +210,7 @@ describe('assign user consent scopes to application', () => { ), { code: 'entity.not_found', - statusCode: 404, + status: 404, } ); @@ -222,7 +222,7 @@ describe('assign user consent scopes to application', () => { ), { code: 'entity.not_found', - statusCode: 404, + status: 404, } ); }); diff --git a/packages/integration-tests/src/tests/api/application/application.roles.test.ts b/packages/integration-tests/src/tests/api/application/application.roles.test.ts index d136ec7919cd..6fe86b4620bd 100644 --- a/packages/integration-tests/src/tests/api/application/application.roles.test.ts +++ b/packages/integration-tests/src/tests/api/application/application.roles.test.ts @@ -59,7 +59,7 @@ describe('admin console application management (roles)', () => { await assignRolesToApplication(application.id, [role.id]); await expectRejects(assignRolesToApplication(application.id, [role.id]), { code: 'application.role_exists', - statusCode: 422, + status: 422, }); }); @@ -70,7 +70,7 @@ describe('admin console application management (roles)', () => { await expectRejects(assignRolesToApplication(application.id, [role.id]), { code: 'application.invalid_type', - statusCode: 422, + status: 422, }); }); diff --git a/packages/integration-tests/src/tests/api/application/application.test.ts b/packages/integration-tests/src/tests/api/application/application.test.ts index fe8675f811fd..f896188335c6 100644 --- a/packages/integration-tests/src/tests/api/application/application.test.ts +++ b/packages/integration-tests/src/tests/api/application/application.test.ts @@ -31,7 +31,7 @@ describe('admin console application', () => { createApplication('test-create-app', ApplicationType.Native, { isThirdParty: true, }), - { code: 'application.invalid_third_party_application_type', statusCode: 400 } + { code: 'application.invalid_third_party_application_type', status: 400 } ); }); @@ -86,7 +86,7 @@ describe('admin console application', () => { }), { code: 'application.protected_application_subdomain_exists', - statusCode: 422, + status: 422, } ); await deleteApplication(application.id); @@ -95,7 +95,7 @@ describe('admin console application', () => { it('should throw error when creating a protected application with invalid type', async () => { await expectRejects(createApplication('test-create-app', ApplicationType.Protected), { code: 'application.protected_app_metadata_is_required', - statusCode: 400, + status: 400, }); }); @@ -120,7 +120,7 @@ describe('admin console application', () => { expect(updatedApplication.description).toBe(newApplicationDescription); expect(updatedApplication.oidcClientMetadata.redirectUris).toEqual(newRedirectUris); - expect(updatedApplication.customClientMetadata).toStrictEqual({ + expect({ ...updatedApplication.customClientMetadata }).toStrictEqual({ rotateRefreshToken: true, refreshTokenTtlInDays: 10, }); diff --git a/packages/integration-tests/src/tests/api/callback.test.ts b/packages/integration-tests/src/tests/api/callback.test.ts index 4f096e4aeb4e..00cadf01d4e7 100644 --- a/packages/integration-tests/src/tests/api/callback.test.ts +++ b/packages/integration-tests/src/tests/api/callback.test.ts @@ -11,6 +11,7 @@ describe('social connector form post callback', () => { const response = await request.post('callback/some_connector_id', { json: { some: 'data' }, redirect: 'manual', + throwHttpErrors: false, }); expect(response.status).toBe(303); diff --git a/packages/integration-tests/src/tests/api/connector.test.ts b/packages/integration-tests/src/tests/api/connector.test.ts index e20cd0dfdd99..585072f2020e 100644 --- a/packages/integration-tests/src/tests/api/connector.test.ts +++ b/packages/integration-tests/src/tests/api/connector.test.ts @@ -160,7 +160,7 @@ test('create connector with non-exist connectorId', async () => { await cleanUpConnectorTable(); await expectRejects(postConnector({ connectorId: 'non-exist-id' }), { code: 'connector.not_found_with_connector_id', - statusCode: 422, + status: 422, }); }); @@ -170,7 +170,7 @@ test('create non standard social connector with target', async () => { postConnector({ connectorId: mockSocialConnectorId, metadata: { target: 'target' } }), { code: 'connector.cannot_overwrite_metadata_for_non_standard_connector', - statusCode: 400, + status: 400, } ); }); @@ -180,7 +180,7 @@ test('create duplicated social connector', async () => { await postConnector({ connectorId: mockSocialConnectorId }); await expectRejects(postConnector({ connectorId: mockSocialConnectorId }), { code: 'connector.multiple_instances_not_supported', - statusCode: 422, + status: 422, }); }); @@ -189,7 +189,7 @@ test('override metadata for non-standard social connector', async () => { const { id } = await postConnector({ connectorId: mockSocialConnectorId }); await expectRejects(updateConnectorConfig(id, {}, { target: 'target' }), { code: 'connector.cannot_overwrite_metadata_for_non_standard_connector', - statusCode: 400, + status: 400, }); }); diff --git a/packages/integration-tests/src/tests/api/dashboard.test.ts b/packages/integration-tests/src/tests/api/dashboard.test.ts index 1a2a6d356e1b..f6cfda523374 100644 --- a/packages/integration-tests/src/tests/api/dashboard.test.ts +++ b/packages/integration-tests/src/tests/api/dashboard.test.ts @@ -19,15 +19,15 @@ describe('admin console dashboard', () => { it('non authorized request should return 401', async () => { await expectRejects(api.get('dashboard/users/total'), { code: 'auth.authorization_header_missing', - statusCode: 401, + status: 401, }); await expectRejects(api.get('dashboard/users/new'), { code: 'auth.authorization_header_missing', - statusCode: 401, + status: 401, }); await expectRejects(api.get('dashboard/users/active'), { code: 'auth.authorization_header_missing', - statusCode: 401, + status: 401, }); }); diff --git a/packages/integration-tests/src/tests/api/health-check.test.ts b/packages/integration-tests/src/tests/api/health-check.test.ts index cf4c3c1bc8b7..f5577a91e362 100644 --- a/packages/integration-tests/src/tests/api/health-check.test.ts +++ b/packages/integration-tests/src/tests/api/health-check.test.ts @@ -2,6 +2,6 @@ import { api } from '#src/api/index.js'; describe('health check', () => { it('should have a health state', async () => { - expect(await api.get('status')).toHaveProperty('statusCode', 204); + expect(await api.get('status')).toHaveProperty('status', 204); }); }); diff --git a/packages/integration-tests/src/tests/api/hook/hook.test.ts b/packages/integration-tests/src/tests/api/hook/hook.test.ts index dc21d9f1ab6f..4f018dab9035 100644 --- a/packages/integration-tests/src/tests/api/hook/hook.test.ts +++ b/packages/integration-tests/src/tests/api/hook/hook.test.ts @@ -19,10 +19,10 @@ describe('hooks', () => { .patch(`hooks/${created.id}`, { json: { events: [HookEvent.PostSignIn] } }) .json() ).toMatchObject({ ...created, events: [HookEvent.PostSignIn] }); - expect(await authedAdminApi.delete(`hooks/${created.id}`)).toHaveProperty('statusCode', 204); + expect(await authedAdminApi.delete(`hooks/${created.id}`)).toHaveProperty('status', 204); await expectRejects(authedAdminApi.get(`hooks/${created.id}`), { code: 'entity.not_exists_with_id', - statusCode: 404, + status: 404, }); }); @@ -48,10 +48,10 @@ describe('hooks', () => { ...created, event: HookEvent.PostSignIn, }); - expect(await authedAdminApi.delete(`hooks/${created.id}`)).toHaveProperty('statusCode', 204); + expect(await authedAdminApi.delete(`hooks/${created.id}`)).toHaveProperty('status', 204); await expectRejects(authedAdminApi.get(`hooks/${created.id}`), { code: 'entity.not_exists_with_id', - statusCode: 404, + status: 404, }); }); @@ -62,7 +62,7 @@ describe('hooks', () => { const response = await authedAdminApi.get('hooks?page=1&page_size=20'); expect(response.status).toBe(200); - expect(response.headers).toHaveProperty('total-number'); + expect(response.headers.get('total-number')).toEqual(expect.any(String)); // Clean up await authedAdminApi.delete(`hooks/${created.id}`); @@ -78,7 +78,7 @@ describe('hooks', () => { }; await expectRejects(authedAdminApi.post('hooks', { json: payload }), { code: 'guard.invalid_input', - statusCode: 400, + status: 400, }); }); @@ -91,7 +91,7 @@ describe('hooks', () => { }; await expectRejects(authedAdminApi.post('hooks', { json: payload }), { code: 'hook.missing_events', - statusCode: 400, + status: 400, }); }); @@ -102,14 +102,14 @@ describe('hooks', () => { await expectRejects(authedAdminApi.patch('hooks/invalid_id', { json: payload }), { code: 'entity.not_exists', - statusCode: 404, + status: 404, }); }); it('should throw error if regenerate a hook signing key with a invalid hook id', async () => { await expectRejects(authedAdminApi.patch('hooks/invalid_id/signing-key'), { code: 'entity.not_exists', - statusCode: 404, + status: 404, }); }); }); diff --git a/packages/integration-tests/src/tests/api/hook/hook.testing.test.ts b/packages/integration-tests/src/tests/api/hook/hook.testing.test.ts index 6dd637d45623..d4c3d180e673 100644 --- a/packages/integration-tests/src/tests/api/hook/hook.testing.test.ts +++ b/packages/integration-tests/src/tests/api/hook/hook.testing.test.ts @@ -51,7 +51,7 @@ describe('hook testing', () => { }), { code: 'entity.not_exists_with_id', - statusCode: 404, + status: 404, } ); }); @@ -65,7 +65,7 @@ describe('hook testing', () => { }), { code: 'hook.send_test_payload_failed', - statusCode: 422, + status: 422, } ); @@ -82,7 +82,7 @@ describe('hook testing', () => { }), { code: 'hook.endpoint_responded_with_error', - statusCode: 422, + status: 422, } ); diff --git a/packages/integration-tests/src/tests/api/interaction/api-counter-cases/interaction-details-guard.test.ts b/packages/integration-tests/src/tests/api/interaction/api-counter-cases/interaction-details-guard.test.ts index 48b7dc3a5dc4..c9c80b20cb67 100644 --- a/packages/integration-tests/src/tests/api/interaction/api-counter-cases/interaction-details-guard.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/api-counter-cases/interaction-details-guard.test.ts @@ -30,7 +30,7 @@ describe('Interaction details guard checking', () => { }), { code: 'session.not_found', - statusCode: 400, + status: 400, } ); }); @@ -38,7 +38,7 @@ describe('Interaction details guard checking', () => { it('DELETE /interaction', async () => { await expectRejects(client.send(deleteInteraction), { code: 'session.not_found', - statusCode: 400, + status: 400, }); }); @@ -49,7 +49,7 @@ describe('Interaction details guard checking', () => { }), { code: 'session.not_found', - statusCode: 400, + status: 400, } ); }); @@ -62,7 +62,7 @@ describe('Interaction details guard checking', () => { }), { code: 'session.not_found', - statusCode: 400, + status: 400, } ); }); @@ -75,7 +75,7 @@ describe('Interaction details guard checking', () => { }), { code: 'session.not_found', - statusCode: 400, + status: 400, } ); }); @@ -88,7 +88,7 @@ describe('Interaction details guard checking', () => { }), { code: 'session.not_found', - statusCode: 400, + status: 400, } ); }); @@ -96,14 +96,14 @@ describe('Interaction details guard checking', () => { it('DELETE /interaction/profile', async () => { await expectRejects(client.send(deleteInteractionProfile), { code: 'session.not_found', - statusCode: 400, + status: 400, }); }); it('POST /interaction/submit', async () => { await expectRejects(client.submitInteraction(), { code: 'session.not_found', - statusCode: 400, + status: 400, }); }); @@ -116,7 +116,7 @@ describe('Interaction details guard checking', () => { }), { code: 'session.not_found', - statusCode: 400, + status: 400, } ); }); @@ -128,7 +128,7 @@ describe('Interaction details guard checking', () => { }), { code: 'session.not_found', - statusCode: 400, + status: 400, } ); }); diff --git a/packages/integration-tests/src/tests/api/interaction/api-counter-cases/interaction-results-checking.test.ts b/packages/integration-tests/src/tests/api/interaction/api-counter-cases/interaction-results-checking.test.ts index 0100aa594f7c..14b83e93143f 100644 --- a/packages/integration-tests/src/tests/api/interaction/api-counter-cases/interaction-results-checking.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/api-counter-cases/interaction-results-checking.test.ts @@ -26,7 +26,7 @@ describe('Interaction details results checking', () => { }), { code: 'session.verification_session_not_found', - statusCode: 404, + status: 404, } ); }); @@ -41,7 +41,7 @@ describe('Interaction details results checking', () => { }), { code: 'session.verification_session_not_found', - statusCode: 404, + status: 404, } ); }); @@ -55,7 +55,7 @@ describe('Interaction details results checking', () => { }), { code: 'session.verification_session_not_found', - statusCode: 404, + status: 404, } ); }); @@ -69,7 +69,7 @@ describe('Interaction details results checking', () => { }), { code: 'session.verification_session_not_found', - statusCode: 404, + status: 404, } ); }); @@ -78,7 +78,7 @@ describe('Interaction details results checking', () => { const client = await initClient(); await expectRejects(client.send(deleteInteractionProfile), { code: 'session.verification_session_not_found', - statusCode: 404, + status: 404, }); }); @@ -86,7 +86,7 @@ describe('Interaction details results checking', () => { const client = await initClient(); await expectRejects(client.submitInteraction(), { code: 'session.verification_session_not_found', - statusCode: 404, + status: 404, }); }); @@ -100,7 +100,7 @@ describe('Interaction details results checking', () => { }), { code: 'session.verification_session_not_found', - statusCode: 404, + status: 404, } ); }); @@ -113,7 +113,7 @@ describe('Interaction details results checking', () => { }), { code: 'session.verification_session_not_found', - statusCode: 404, + status: 404, } ); }); diff --git a/packages/integration-tests/src/tests/api/interaction/api-counter-cases/patch-interaction-identifiers.test.ts b/packages/integration-tests/src/tests/api/interaction/api-counter-cases/patch-interaction-identifiers.test.ts index ae9d028daf35..02f7f87188f8 100644 --- a/packages/integration-tests/src/tests/api/interaction/api-counter-cases/patch-interaction-identifiers.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/api-counter-cases/patch-interaction-identifiers.test.ts @@ -31,7 +31,7 @@ describe('PATCH /interaction/identifiers', () => { }), { code: 'user.suspended', - statusCode: 401, + status: 401, } ); }); diff --git a/packages/integration-tests/src/tests/api/interaction/api-counter-cases/post-send-verification-code.test.ts b/packages/integration-tests/src/tests/api/interaction/api-counter-cases/post-send-verification-code.test.ts index 8348dfcc4b1e..deebbf922d36 100644 --- a/packages/integration-tests/src/tests/api/interaction/api-counter-cases/post-send-verification-code.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/api-counter-cases/post-send-verification-code.test.ts @@ -1,10 +1,15 @@ -import { InteractionEvent } from '@logto/schemas'; +import { ConnectorType, InteractionEvent } from '@logto/schemas'; import { putInteraction, sendVerificationCode } from '#src/api/interaction.js'; import { initClient } from '#src/helpers/client.js'; +import { clearConnectorsByTypes } from '#src/helpers/connector.js'; import { expectRejects } from '#src/helpers/index.js'; import { generateEmail, generatePhone } from '#src/utils.js'; +beforeAll(async () => { + await clearConnectorsByTypes([ConnectorType.Email, ConnectorType.Sms]); +}); + /** * Note: These test cases are designed to cover exceptional scenarios of API calls that * cannot be covered within the auth flow. @@ -23,7 +28,7 @@ describe('POST /interaction/verification/verification-code', () => { }), { code: 'connector.not_found', - statusCode: 501, + status: 501, } ); }); @@ -41,7 +46,7 @@ describe('POST /interaction/verification/verification-code', () => { }), { code: 'connector.not_found', - statusCode: 501, + status: 501, } ); }); diff --git a/packages/integration-tests/src/tests/api/interaction/api-counter-cases/put-interaction-event.test.ts b/packages/integration-tests/src/tests/api/interaction/api-counter-cases/put-interaction-event.test.ts index 777fb8494609..b25c85d3a419 100644 --- a/packages/integration-tests/src/tests/api/interaction/api-counter-cases/put-interaction-event.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/api-counter-cases/put-interaction-event.test.ts @@ -27,7 +27,7 @@ describe('PUT /interaction/event', () => { }), { code: 'auth.forbidden', - statusCode: 403, + status: 403, } ); @@ -41,7 +41,7 @@ describe('PUT /interaction/event', () => { }), { code: 'auth.forbidden', - statusCode: 403, + status: 403, } ); @@ -65,7 +65,7 @@ describe('PUT /interaction/event', () => { }), { code: 'session.interaction_not_found', - statusCode: 404, + status: 404, } ); @@ -75,7 +75,7 @@ describe('PUT /interaction/event', () => { }), { code: 'session.interaction_not_found', - statusCode: 404, + status: 404, } ); }); @@ -96,7 +96,7 @@ describe('PUT /interaction/event', () => { }), { code: 'session.interaction_not_found', - statusCode: 404, + status: 404, } ); @@ -111,7 +111,7 @@ describe('PUT /interaction/event', () => { }), { code: 'session.interaction_not_found', - statusCode: 404, + status: 404, } ); }); diff --git a/packages/integration-tests/src/tests/api/interaction/api-counter-cases/put-interaction.test.ts b/packages/integration-tests/src/tests/api/interaction/api-counter-cases/put-interaction.test.ts index 536de204bd83..6be7b8a8aed9 100644 --- a/packages/integration-tests/src/tests/api/interaction/api-counter-cases/put-interaction.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/api-counter-cases/put-interaction.test.ts @@ -54,7 +54,7 @@ describe('PUT /interaction', () => { }), { code: 'user.sign_in_method_not_enabled', - statusCode: 422, + status: 422, } ); @@ -69,7 +69,7 @@ describe('PUT /interaction', () => { }), { code: 'user.sign_in_method_not_enabled', - statusCode: 422, + status: 422, } ); @@ -100,7 +100,7 @@ describe('PUT /interaction', () => { }), { code: 'user.sign_in_method_not_enabled', - statusCode: 422, + status: 422, } ); @@ -114,7 +114,7 @@ describe('PUT /interaction', () => { }), { code: 'user.sign_in_method_not_enabled', - statusCode: 422, + status: 422, } ); @@ -140,7 +140,7 @@ describe('PUT /interaction', () => { }), { code: 'verification_code.not_found', - statusCode: 400, + status: 400, } ); @@ -155,7 +155,7 @@ describe('PUT /interaction', () => { }), { code: 'verification_code.not_found', - statusCode: 400, + status: 400, } ); @@ -177,7 +177,7 @@ describe('PUT /interaction', () => { }), { code: 'session.invalid_connector_id', - statusCode: 422, + status: 422, } ); }); @@ -194,7 +194,7 @@ describe('PUT /interaction', () => { }), { code: 'session.connector_session_not_found', - statusCode: 400, + status: 400, } ); }); diff --git a/packages/integration-tests/src/tests/api/interaction/forgot-password/happy-path.test.ts b/packages/integration-tests/src/tests/api/interaction/forgot-password/happy-path.test.ts index 822a6ed5aa15..6417218e83f7 100644 --- a/packages/integration-tests/src/tests/api/interaction/forgot-password/happy-path.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/forgot-password/happy-path.test.ts @@ -64,14 +64,14 @@ describe('reset password', () => { await expectRejects(client.submitInteraction(), { code: 'user.new_password_required_in_profile', - statusCode: 422, + status: 422, }); await client.successSend(putInteractionProfile, { password: userProfile.password }); await expectRejects(client.submitInteraction(), { code: 'user.same_password', - statusCode: 422, + status: 422, }); const newPasswordRecord = generatePassword(); @@ -124,14 +124,14 @@ describe('reset password', () => { await expectRejects(client.submitInteraction(), { code: 'user.new_password_required_in_profile', - statusCode: 422, + status: 422, }); await client.successSend(putInteractionProfile, { password: userProfile.password }); await expectRejects(client.submitInteraction(), { code: 'user.same_password', - statusCode: 422, + status: 422, }); const newPasswordRecord = generatePassword(); diff --git a/packages/integration-tests/src/tests/api/interaction/forgot-password/sad-path.test.ts b/packages/integration-tests/src/tests/api/interaction/forgot-password/sad-path.test.ts index ffd91ac30c01..5a3bb2ff16cc 100644 --- a/packages/integration-tests/src/tests/api/interaction/forgot-password/sad-path.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/forgot-password/sad-path.test.ts @@ -40,7 +40,7 @@ describe('reset password flow sad path', () => { await client.successSend(putInteractionProfile, { password: generatePassword() }); await expectRejects(client.submitInteraction(), { code: 'user.user_not_exist', - statusCode: 404, + status: 404, }); // Clear @@ -68,7 +68,7 @@ describe('reset password flow sad path', () => { await client.successSend(putInteractionProfile, { password: generatePassword() }); await expectRejects(client.submitInteraction(), { code: 'user.user_not_exist', - statusCode: 404, + status: 404, }); // Clear @@ -104,7 +104,7 @@ describe('reset password flow sad path', () => { await client.successSend(putInteractionProfile, { password: generatePassword() }); await expectRejects(client.submitInteraction(), { code: 'user.suspended', - statusCode: 401, + status: 401, }); // Clear diff --git a/packages/integration-tests/src/tests/api/interaction/mfa/backup-code.test.ts b/packages/integration-tests/src/tests/api/interaction/mfa/backup-code.test.ts index 13f3cfb6e42c..2e961e426caf 100644 --- a/packages/integration-tests/src/tests/api/interaction/mfa/backup-code.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/mfa/backup-code.test.ts @@ -39,7 +39,7 @@ const registerWithMfa = async () => { const { codes } = await expectRejects<{ codes: string[] }>(client.submitInteraction(), { code: 'session.mfa.backup_code_required', - statusCode: 400, + status: 400, }); await client.send(postInteractionBindMfa, { @@ -81,7 +81,7 @@ describe('sign in and verify mfa (Backup Code)', () => { await expectRejects(client.submitInteraction(), { code: 'session.mfa.require_mfa_verification', - statusCode: 403, + status: 403, }); await deleteUser(id); diff --git a/packages/integration-tests/src/tests/api/interaction/mfa/totp.test.ts b/packages/integration-tests/src/tests/api/interaction/mfa/totp.test.ts index e1aad0a52e94..db4619779e1e 100644 --- a/packages/integration-tests/src/tests/api/interaction/mfa/totp.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/mfa/totp.test.ts @@ -70,7 +70,7 @@ describe('register with mfa (mandatory TOTP)', () => { await expectRejects(client.submitInteraction(), { code: 'user.missing_mfa', - statusCode: 422, + status: 422, }); }); @@ -94,7 +94,7 @@ describe('register with mfa (mandatory TOTP)', () => { }), { code: 'session.mfa.invalid_totp_code', - statusCode: 400, + status: 400, } ); }); @@ -151,7 +151,7 @@ describe('sign in and fulfill mfa (mandatory TOTP)', () => { await expectRejects(client.submitInteraction(), { code: 'user.missing_mfa', - statusCode: 422, + status: 422, }); await deleteUser(user.id); @@ -187,7 +187,7 @@ describe('sign in and fulfill mfa (user-controlled TOTP)', () => { await expectRejects(client.submitInteraction(), { code: 'user.missing_mfa', - statusCode: 422, + status: 422, }); await deleteUser(user.id); @@ -207,7 +207,7 @@ describe('sign in and fulfill mfa (user-controlled TOTP)', () => { await expectRejects(client.submitInteraction(), { code: 'user.missing_mfa', - statusCode: 422, + status: 422, }); await client.successSend(skipMfaBinding); @@ -241,7 +241,7 @@ describe('sign in and verify mfa (TOTP)', () => { await expectRejects(client.submitInteraction(), { code: 'session.mfa.require_mfa_verification', - statusCode: 403, + status: 403, }); await deleteUser(id); diff --git a/packages/integration-tests/src/tests/api/interaction/register-with-identifier/happy-path.test.ts b/packages/integration-tests/src/tests/api/interaction/register-with-identifier/happy-path.test.ts index 94f7c04e9554..761086c5613e 100644 --- a/packages/integration-tests/src/tests/api/interaction/register-with-identifier/happy-path.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/register-with-identifier/happy-path.test.ts @@ -146,7 +146,7 @@ describe('register with passwordless identifier', () => { await expectRejects(client.submitInteraction(), { code: 'user.missing_profile', - statusCode: 422, + status: 422, }); await client.successSend(patchInteractionProfile, { @@ -251,7 +251,7 @@ describe('register with passwordless identifier', () => { await expectRejects(client.submitInteraction(), { code: 'user.missing_profile', - statusCode: 422, + status: 422, }); await client.successSend(patchInteractionProfile, { @@ -322,7 +322,7 @@ describe('register with passwordless identifier', () => { await expectRejects(client.submitInteraction(), { code: 'user.email_already_in_use', - statusCode: 422, + status: 422, }); await client.successSend(deleteInteractionProfile); @@ -377,7 +377,7 @@ describe('register with passwordless identifier', () => { await expectRejects(client.submitInteraction(), { code: 'user.phone_already_in_use', - statusCode: 422, + status: 422, }); await client.successSend(deleteInteractionProfile); diff --git a/packages/integration-tests/src/tests/api/interaction/register-with-identifier/sad-path.test.ts b/packages/integration-tests/src/tests/api/interaction/register-with-identifier/sad-path.test.ts index dbb18fa97715..db091eaa021b 100644 --- a/packages/integration-tests/src/tests/api/interaction/register-with-identifier/sad-path.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/register-with-identifier/sad-path.test.ts @@ -40,7 +40,7 @@ describe('Register with identifiers sad path', () => { }), { code: 'auth.forbidden', - statusCode: 403, + status: 403, } ); @@ -67,7 +67,7 @@ describe('Register with identifiers sad path', () => { }), { code: 'user.sign_in_method_not_enabled', - statusCode: 422, + status: 422, } ); }); @@ -94,7 +94,7 @@ describe('Register with identifiers sad path', () => { }), { code: 'user.sign_in_method_not_enabled', - statusCode: 422, + status: 422, } ); @@ -125,7 +125,7 @@ describe('Register with identifiers sad path', () => { }), { code: 'user.sign_in_method_not_enabled', - statusCode: 422, + status: 422, } ); diff --git a/packages/integration-tests/src/tests/api/interaction/register-with-identifier/single-sign-on.test.ts b/packages/integration-tests/src/tests/api/interaction/register-with-identifier/single-sign-on.test.ts index c67b6ea8baef..5da4816238cd 100644 --- a/packages/integration-tests/src/tests/api/interaction/register-with-identifier/single-sign-on.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/register-with-identifier/single-sign-on.test.ts @@ -133,7 +133,7 @@ describe('test register with email with SSO feature', () => { }), { code: 'session.sso_enabled', - statusCode: 422, + status: 422, } ); }); diff --git a/packages/integration-tests/src/tests/api/interaction/sign-in-with-passcode-identifier/happy-path.test.ts b/packages/integration-tests/src/tests/api/interaction/sign-in-with-passcode-identifier/happy-path.test.ts index 94182d8bf139..62b3d3572142 100644 --- a/packages/integration-tests/src/tests/api/interaction/sign-in-with-passcode-identifier/happy-path.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/sign-in-with-passcode-identifier/happy-path.test.ts @@ -127,7 +127,7 @@ describe('Sign-in flow using verification-code identifiers', () => { await expectRejects(client.submitInteraction(), { code: 'user.user_not_exist', - statusCode: 404, + status: 404, }); await client.successSend(putInteractionEvent, { event: InteractionEvent.Register }); @@ -169,7 +169,7 @@ describe('Sign-in flow using verification-code identifiers', () => { await expectRejects(client.submitInteraction(), { code: 'user.user_not_exist', - statusCode: 404, + status: 404, }); await client.successSend(putInteractionEvent, { event: InteractionEvent.Register }); @@ -214,7 +214,7 @@ describe('Sign-in flow using verification-code identifiers', () => { await expectRejects(client.submitInteraction(), { code: 'user.missing_profile', - statusCode: 422, + status: 422, }); // Fulfill user profile @@ -276,7 +276,7 @@ describe('Sign-in flow using verification-code identifiers', () => { await expectRejects(client.submitInteraction(), { code: 'user.missing_profile', - statusCode: 422, + status: 422, }); // Fulfill user profile with existing password @@ -287,7 +287,7 @@ describe('Sign-in flow using verification-code identifiers', () => { await expectRejects(client.submitInteraction(), { code: 'user.password_exists_in_profile', - statusCode: 400, + status: 400, }); await client.successSend(putInteractionProfile, { @@ -333,7 +333,7 @@ describe('Sign-in flow using verification-code identifiers', () => { await expectRejects(client.submitInteraction(), { code: 'user.missing_profile', - statusCode: 422, + status: 422, }); // Fulfill user profile with existing password @@ -344,7 +344,7 @@ describe('Sign-in flow using verification-code identifiers', () => { await expectRejects(client.submitInteraction(), { code: 'user.username_already_in_use', - statusCode: 422, + status: 422, }); await client.successSend(putInteractionProfile, { diff --git a/packages/integration-tests/src/tests/api/interaction/sign-in-with-passcode-identifier/sad-path.test.ts b/packages/integration-tests/src/tests/api/interaction/sign-in-with-passcode-identifier/sad-path.test.ts index 3dcaacfc6b4c..d8cd47599273 100644 --- a/packages/integration-tests/src/tests/api/interaction/sign-in-with-passcode-identifier/sad-path.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/sign-in-with-passcode-identifier/sad-path.test.ts @@ -43,7 +43,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => { }), { code: 'auth.forbidden', - statusCode: 403, + status: 403, } ); @@ -81,7 +81,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => { }), { code: 'user.sign_in_method_not_enabled', - statusCode: 422, + status: 422, } ); @@ -99,7 +99,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => { }), { code: 'user.sign_in_method_not_enabled', - statusCode: 422, + status: 422, } ); @@ -130,7 +130,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => { }), { code: 'verification_code.code_mismatch', - statusCode: 400, + status: 400, } ); @@ -141,7 +141,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => { }), { code: 'verification_code.email_mismatch', - statusCode: 400, + status: 400, } ); }); @@ -169,7 +169,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => { }), { code: 'verification_code.code_mismatch', - statusCode: 400, + status: 400, } ); @@ -180,7 +180,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => { }), { code: 'verification_code.phone_mismatch', - statusCode: 400, + status: 400, } ); }); @@ -207,7 +207,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => { await expectRejects(client.submitInteraction(), { code: 'user.user_not_exist', - statusCode: 404, + status: 404, }); }); @@ -233,7 +233,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => { await expectRejects(client.submitInteraction(), { code: 'user.user_not_exist', - statusCode: 404, + status: 404, }); }); @@ -263,7 +263,7 @@ describe('Sign-in flow sad path using verification-code identifiers', () => { await expectRejects(client.submitInteraction(), { code: 'user.suspended', - statusCode: 401, + status: 401, }); }); }); diff --git a/packages/integration-tests/src/tests/api/interaction/sign-in-with-passcode-identifier/single-sign-on.test.ts b/packages/integration-tests/src/tests/api/interaction/sign-in-with-passcode-identifier/single-sign-on.test.ts index a3e58e753801..39b18c2cdb61 100644 --- a/packages/integration-tests/src/tests/api/interaction/sign-in-with-passcode-identifier/single-sign-on.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/sign-in-with-passcode-identifier/single-sign-on.test.ts @@ -100,7 +100,7 @@ describe('test sign-in with email passcode identifier with SSO feature', () => { }), { code: 'session.sso_enabled', - statusCode: 422, + status: 422, } ); diff --git a/packages/integration-tests/src/tests/api/interaction/sign-in-with-password-identifier/happy-path.test.ts b/packages/integration-tests/src/tests/api/interaction/sign-in-with-password-identifier/happy-path.test.ts index dc872ae0c32a..fe66b572a6ee 100644 --- a/packages/integration-tests/src/tests/api/interaction/sign-in-with-password-identifier/happy-path.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/sign-in-with-password-identifier/happy-path.test.ts @@ -161,7 +161,7 @@ describe('Sign-in flow using password identifiers', () => { await expectRejects(client.submitInteraction(), { code: 'user.missing_profile', - statusCode: 422, + status: 422, }); await client.successSend(sendVerificationCode, { @@ -223,7 +223,7 @@ describe('Sign-in flow using password identifiers', () => { await expectRejects(client.submitInteraction(), { code: 'user.missing_profile', - statusCode: 422, + status: 422, }); await client.successSend(sendVerificationCode, { diff --git a/packages/integration-tests/src/tests/api/interaction/sign-in-with-password-identifier/sad-path.test.ts b/packages/integration-tests/src/tests/api/interaction/sign-in-with-password-identifier/sad-path.test.ts index d11d8a1c5dea..293b0e2d77eb 100644 --- a/packages/integration-tests/src/tests/api/interaction/sign-in-with-password-identifier/sad-path.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/sign-in-with-password-identifier/sad-path.test.ts @@ -35,7 +35,7 @@ describe('Sign-in flow sad path using password identifiers', () => { }), { code: 'auth.forbidden', - statusCode: 403, + status: 403, } ); @@ -51,7 +51,7 @@ describe('Sign-in flow sad path using password identifiers', () => { }), { code: 'auth.forbidden', - statusCode: 403, + status: 403, } ); @@ -67,7 +67,7 @@ describe('Sign-in flow sad path using password identifiers', () => { }), { code: 'auth.forbidden', - statusCode: 403, + status: 403, } ); @@ -91,7 +91,7 @@ describe('Sign-in flow sad path using password identifiers', () => { }), { code: 'user.sign_in_method_not_enabled', - statusCode: 422, + status: 422, } ); @@ -107,7 +107,7 @@ describe('Sign-in flow sad path using password identifiers', () => { }), { code: 'user.sign_in_method_not_enabled', - statusCode: 422, + status: 422, } ); @@ -123,7 +123,7 @@ describe('Sign-in flow sad path using password identifiers', () => { }), { code: 'user.sign_in_method_not_enabled', - statusCode: 422, + status: 422, } ); @@ -141,7 +141,7 @@ describe('Sign-in flow sad path using password identifiers', () => { }), { code: 'session.invalid_credentials', - statusCode: 422, + status: 422, } ); }); @@ -159,7 +159,7 @@ describe('Sign-in flow sad path using password identifiers', () => { }), { code: 'session.invalid_credentials', - statusCode: 422, + status: 422, } ); }); @@ -177,7 +177,7 @@ describe('Sign-in flow sad path using password identifiers', () => { }), { code: 'session.invalid_credentials', - statusCode: 422, + status: 422, } ); }); @@ -199,7 +199,7 @@ describe('Sign-in flow sad path using password identifiers', () => { }), { code: 'user.suspended', - statusCode: 401, + status: 401, } ); }); diff --git a/packages/integration-tests/src/tests/api/interaction/sign-in-with-password-identifier/single-sign-on.test.ts b/packages/integration-tests/src/tests/api/interaction/sign-in-with-password-identifier/single-sign-on.test.ts index 19205d1778cc..7d39e7a8bcc8 100644 --- a/packages/integration-tests/src/tests/api/interaction/sign-in-with-password-identifier/single-sign-on.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/sign-in-with-password-identifier/single-sign-on.test.ts @@ -99,7 +99,7 @@ describe('test sign-in with email passcode identifier with SSO feature', () => { }), { code: 'session.sso_enabled', - statusCode: 422, + status: 422, } ); await deleteUser(user.id); diff --git a/packages/integration-tests/src/tests/api/interaction/single-sign-on/happy-path.test.ts b/packages/integration-tests/src/tests/api/interaction/single-sign-on/happy-path.test.ts index cd31ad8de838..966044b3b531 100644 --- a/packages/integration-tests/src/tests/api/interaction/single-sign-on/happy-path.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/single-sign-on/happy-path.test.ts @@ -6,18 +6,20 @@ import { updateSignInExperience } from '#src/api/sign-in-experience.js'; import { createSsoConnector, deleteSsoConnectorById } from '#src/api/sso-connector.js'; import { logtoUrl } from '#src/constants.js'; import { initClient } from '#src/helpers/client.js'; +import { randomString } from '#src/utils.js'; describe('Single Sign On Happy Path', () => { const connectorIdMap = new Map(); const state = 'foo_state'; const redirectUri = 'http://foo.dev/callback'; + const domain = `foo${randomString()}.com`; beforeAll(async () => { const { id, connectorName } = await createSsoConnector({ providerName: SsoProviderName.OIDC, - connectorName: 'test-oidc', - domains: ['foo.com'], + connectorName: `test-oidc-${randomString()}`, + domains: [domain], config: { clientId: 'foo', clientSecret: 'bar', @@ -60,7 +62,7 @@ describe('Single Sign On Happy Path', () => { const client = await initClient(); const response = await client.send(getSsoConnectorsByEmail, { - email: 'bar@foo.com', + email: 'bar@' + domain, }); expect(response.length).toBeGreaterThan(0); @@ -88,7 +90,7 @@ describe('Single Sign On Happy Path', () => { }); const response = await client.send(getSsoConnectorsByEmail, { - email: 'bar@foo.com', + email: 'bar@' + domain, }); expect(response.length).toBe(0); diff --git a/packages/integration-tests/src/tests/api/interaction/single-sign-on/sad-path.test.ts b/packages/integration-tests/src/tests/api/interaction/single-sign-on/sad-path.test.ts index b0acc703be3b..a9fc8ff3e87f 100644 --- a/packages/integration-tests/src/tests/api/interaction/single-sign-on/sad-path.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/single-sign-on/sad-path.test.ts @@ -9,6 +9,7 @@ import { putInteraction } from '#src/api/interaction.js'; import { createSsoConnector, deleteSsoConnectorById } from '#src/api/sso-connector.js'; import { initClient } from '#src/helpers/client.js'; import { expectRejects } from '#src/helpers/index.js'; +import { randomString } from '#src/utils.js'; describe('Single Sign On Sad Path', () => { const state = 'foo_state'; @@ -34,7 +35,7 @@ describe('Single Sign On Sad Path', () => { it('should throw if connector config is invalid', async () => { const { id } = await createSsoConnector({ providerName: SsoProviderName.OIDC, - connectorName: 'test-oidc', + connectorName: `test-oidc-${randomString()}`, }); const client = await initClient(); @@ -82,7 +83,7 @@ describe('Single Sign On Sad Path', () => { postSamlAssertion({ connectorId, RelayState: 'foo', SAMLResponse: samlAssertion }), { code: 'session.not_found', - statusCode: 400, + status: 400, } ); }); @@ -103,7 +104,7 @@ describe('Single Sign On Sad Path', () => { postSamlAssertion({ connectorId, RelayState, SAMLResponse: samlAssertion }), { code: 'connector.authorization_failed', - statusCode: 401, + status: 401, } ); }); diff --git a/packages/integration-tests/src/tests/api/interaction/social-sign-in/happy-path.test.ts b/packages/integration-tests/src/tests/api/interaction/social-sign-in/happy-path.test.ts index 17bbc9525525..a4ee51ac9a6e 100644 --- a/packages/integration-tests/src/tests/api/interaction/social-sign-in/happy-path.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/social-sign-in/happy-path.test.ts @@ -68,7 +68,7 @@ describe('social sign-in', () => { await expectRejects(client.submitInteraction(), { code: 'user.identity_not_exist', - statusCode: 422, + status: 422, }); await client.successSend(putInteractionEvent, { event: InteractionEvent.Register }); @@ -124,7 +124,7 @@ describe('social sign-in', () => { await expectRejects(client.submitInteraction(), { code: 'user.identity_not_exist', - statusCode: 422, + status: 422, }); await client.successSend(putInteractionEvent, { event: InteractionEvent.Register }); @@ -176,7 +176,7 @@ describe('social sign-in', () => { await expectRejects(client.submitInteraction(), { code: 'user.identity_not_exist', - statusCode: 422, + status: 422, }); await client.successSend(putInteractionEvent, { event: InteractionEvent.Register }); @@ -213,7 +213,7 @@ describe('social sign-in', () => { await expectRejects(client.submitInteraction(), { code: 'user.identity_not_exist', - statusCode: 422, + status: 422, }); await client.successSend(putInteractionEvent, { event: InteractionEvent.Register }); @@ -255,7 +255,7 @@ describe('social sign-in', () => { await expectRejects(client.submitInteraction(), { code: 'user.identity_not_exist', - statusCode: 422, + status: 422, }); await client.successSend(patchInteractionIdentifiers, { @@ -319,7 +319,7 @@ describe('social sign-in', () => { await expectRejects(client.submitInteraction(), { code: 'user.identity_not_exist', - statusCode: 422, + status: 422, }); await client.successSend(putInteractionEvent, { event: InteractionEvent.Register }); @@ -327,7 +327,7 @@ describe('social sign-in', () => { await expectRejects(client.submitInteraction(), { code: 'user.missing_profile', - statusCode: 422, + status: 422, }); await client.successSend(patchInteractionProfile, { username: generateUsername() }); @@ -363,7 +363,7 @@ describe('social sign-in', () => { await expectRejects(client.submitInteraction(), { code: 'user.identity_not_exist', - statusCode: 422, + status: 422, }); await client.successSend(putInteractionEvent, { event: InteractionEvent.Register }); @@ -400,7 +400,7 @@ describe('social sign-in', () => { await expectRejects(client.submitInteraction(), { code: 'user.identity_not_exist', - statusCode: 422, + status: 422, }); await client.successSend(putInteractionEvent, { event: InteractionEvent.Register }); diff --git a/packages/integration-tests/src/tests/api/interaction/social-sign-in/sad-path.test.ts b/packages/integration-tests/src/tests/api/interaction/social-sign-in/sad-path.test.ts index 1296a94df836..b9be50cf8157 100644 --- a/packages/integration-tests/src/tests/api/interaction/social-sign-in/sad-path.test.ts +++ b/packages/integration-tests/src/tests/api/interaction/social-sign-in/sad-path.test.ts @@ -73,7 +73,7 @@ describe('Social identifier interaction sad path', () => { await expectRejects(client.submitInteraction(), { code: 'user.identity_not_exist', - statusCode: 422, + status: 422, }); await client.successSend(putInteractionEvent, { event: InteractionEvent.Register }); @@ -101,7 +101,7 @@ describe('Social identifier interaction sad path', () => { }), { code: 'session.insufficient_info', - statusCode: 400, + status: 400, } ); }); @@ -121,7 +121,7 @@ describe('Social identifier interaction sad path', () => { }), { code: 'guard.invalid_input', - statusCode: 400, + status: 400, } ); }); @@ -141,7 +141,7 @@ describe('Social identifier interaction sad path', () => { }), { code: 'connector.unexpected_type', - statusCode: 400, + status: 400, } ); @@ -154,7 +154,7 @@ describe('Social identifier interaction sad path', () => { }), { code: 'connector.unexpected_type', - statusCode: 400, + status: 400, } ); }); @@ -173,7 +173,7 @@ describe('Social identifier interaction sad path', () => { }), { code: 'entity.not_found', - statusCode: 404, + status: 404, } ); }); @@ -195,7 +195,7 @@ describe('Social identifier interaction sad path', () => { }), { code: 'session.invalid_connector_id', - statusCode: 422, + status: 422, } ); }); @@ -217,7 +217,7 @@ describe('Social identifier interaction sad path', () => { }), { code: 'session.invalid_connector_id', - statusCode: 422, + status: 422, } ); }); @@ -240,7 +240,7 @@ describe('Social identifier interaction sad path', () => { }), { code: 'session.connector_session_not_found', - statusCode: 400, + status: 400, } ); @@ -252,7 +252,7 @@ describe('Social identifier interaction sad path', () => { }), { code: 'session.connector_session_not_found', - statusCode: 400, + status: 400, } ); }); @@ -281,7 +281,7 @@ describe('Social identifier interaction sad path', () => { }), { code: 'session.connector_session_not_found', - statusCode: 400, + status: 400, } ); @@ -293,7 +293,7 @@ describe('Social identifier interaction sad path', () => { }), { code: 'session.connector_session_not_found', - statusCode: 400, + status: 400, } ); }); @@ -318,7 +318,7 @@ describe('Social identifier interaction sad path', () => { await expectRejects(client.submitInteraction(), { code: 'user.suspended', - statusCode: 401, + status: 401, }); // Reset @@ -350,7 +350,7 @@ describe('Social identifier interaction sad path', () => { await expectRejects(client.submitInteraction(), { code: 'user.identity_not_exist', - statusCode: 422, + status: 422, }); await client.successSend(putInteractionEvent, { event: InteractionEvent.Register }); @@ -361,7 +361,7 @@ describe('Social identifier interaction sad path', () => { await expectRejects(client.submitInteraction(), { code: 'session.connector_session_not_found', - statusCode: 404, + status: 404, }); }); }); diff --git a/packages/integration-tests/src/tests/api/log.test.ts b/packages/integration-tests/src/tests/api/log.test.ts index a9c06cd2e127..1171eb318f89 100644 --- a/packages/integration-tests/src/tests/api/log.test.ts +++ b/packages/integration-tests/src/tests/api/log.test.ts @@ -22,7 +22,7 @@ describe('logs', () => { it('should throw on getting non-exist log detail', async () => { await expectRejects(getLog('non-exist-log-id'), { code: 'entity.not_exists_with_id', - statusCode: 404, + status: 404, }); }); }); diff --git a/packages/integration-tests/src/tests/api/logto-config.test.ts b/packages/integration-tests/src/tests/api/logto-config.test.ts index 05aaea5199fe..acd566c8d3c7 100644 --- a/packages/integration-tests/src/tests/api/logto-config.test.ts +++ b/packages/integration-tests/src/tests/api/logto-config.test.ts @@ -61,14 +61,14 @@ describe('admin console sign-in experience', () => { expect(privateKeys).toHaveLength(1); await expectRejects(deleteOidcKey(LogtoOidcConfigKeyType.PrivateKeys, privateKeys[0]!.id), { code: 'oidc.key_required', - statusCode: 422, + status: 422, }); const cookieKeys = await getOidcKeys(LogtoOidcConfigKeyType.CookieKeys); expect(cookieKeys).toHaveLength(1); await expectRejects(deleteOidcKey(LogtoOidcConfigKeyType.CookieKeys, cookieKeys[0]!.id), { code: 'oidc.key_required', - statusCode: 422, + status: 422, }); }); @@ -141,11 +141,11 @@ describe('admin console sign-in experience', () => { await expectRejects(getJwtCustomizer('access-token'), { code: 'entity.not_exists', - statusCode: 404, + status: 404, }); await expectRejects(deleteJwtCustomizer('access-token'), { code: 'entity.not_found', - statusCode: 404, + status: 404, }); const accessToken = await upsertJwtCustomizer('access-token', accessTokenJwtCustomizerPayload); expect(accessToken).toMatchObject(accessTokenJwtCustomizerPayload); @@ -164,7 +164,7 @@ describe('admin console sign-in experience', () => { await expect(deleteJwtCustomizer('access-token')).resolves.not.toThrow(); await expectRejects(getJwtCustomizer('access-token'), { code: 'entity.not_exists', - statusCode: 404, + status: 404, }); }); @@ -177,11 +177,11 @@ describe('admin console sign-in experience', () => { await expectRejects(getJwtCustomizer('client-credentials'), { code: 'entity.not_exists', - statusCode: 404, + status: 404, }); await expectRejects(deleteJwtCustomizer('client-credentials'), { code: 'entity.not_found', - statusCode: 404, + status: 404, }); const clientCredentials = await upsertJwtCustomizer( 'client-credentials', @@ -203,7 +203,7 @@ describe('admin console sign-in experience', () => { await expect(deleteJwtCustomizer('client-credentials')).resolves.not.toThrow(); await expectRejects(getJwtCustomizer('client-credentials'), { code: 'entity.not_exists', - statusCode: 404, + status: 404, }); }); }); diff --git a/packages/integration-tests/src/tests/api/me.test.ts b/packages/integration-tests/src/tests/api/me.test.ts index 59b1c541c3c2..f4032002c484 100644 --- a/packages/integration-tests/src/tests/api/me.test.ts +++ b/packages/integration-tests/src/tests/api/me.test.ts @@ -13,7 +13,7 @@ describe('me', () => { it('should only be available in admin tenant', async () => { await expectRejects(ky.get(new URL('/me/custom-data', logtoConsoleUrl)), { code: 'auth.authorization_header_missing', - statusCode: 401, + status: 401, }); // Redirect to UI @@ -31,7 +31,7 @@ describe('me', () => { }), { code: 'auth.unauthorized', - statusCode: 401, + status: 401, } ); @@ -39,7 +39,7 @@ describe('me', () => { ky.get(logtoConsoleUrl + '/me/custom-data', { headers: { authorization: `Bearer ${await client.getAccessToken(resourceMe)}` }, }) - ).resolves.toHaveProperty('statusCode', 200); + ).resolves.toHaveProperty('status', 200); await deleteUser(id); }); @@ -53,9 +53,9 @@ describe('me', () => { .json>(); const newData = await ky .patch(logtoConsoleUrl + '/me/custom-data', { headers, json: { foo: 'bar' } }) - .json(); + .json>(); - expect({ ...data, foo: 'bar' }).toStrictEqual(newData); + expect({ ...data, foo: 'bar' }).toStrictEqual({ ...newData }); await deleteUser(id); }); diff --git a/packages/integration-tests/src/tests/api/oidc/content-type-json.test.ts b/packages/integration-tests/src/tests/api/oidc/content-type-json.test.ts index 33edafc927ea..e33734c5f3ef 100644 --- a/packages/integration-tests/src/tests/api/oidc/content-type-json.test.ts +++ b/packages/integration-tests/src/tests/api/oidc/content-type-json.test.ts @@ -20,14 +20,11 @@ describe('content-type: application/json compatibility', () => { headers, json: payload, }), - (error) => { + async (error) => { if (!(error instanceof HTTPError)) { throw new TypeError('Error is not a HTTPError instance.'); } - expect(JSON.parse(String(error.response.body))).toHaveProperty( - 'error_description', - errorMessage - ); + expect(await error.response.json()).toHaveProperty('error_description', errorMessage); } ); }; diff --git a/packages/integration-tests/src/tests/api/oidc/refresh-token-grant.test.ts b/packages/integration-tests/src/tests/api/oidc/refresh-token-grant.test.ts index 50a8b260ce15..3b5febf62398 100644 --- a/packages/integration-tests/src/tests/api/oidc/refresh-token-grant.test.ts +++ b/packages/integration-tests/src/tests/api/oidc/refresh-token-grant.test.ts @@ -14,12 +14,12 @@ import { processSession } from '#src/helpers/client.js'; import { OrganizationApiTest } from '#src/helpers/organization.js'; import { enableAllPasswordSignInMethods } from '#src/helpers/sign-in-experience.js'; import { UserApiTest } from '#src/helpers/user.js'; -import { generateUsername, generatePassword, createFormData } from '#src/utils.js'; +import { generateUsername, generatePassword } from '#src/utils.js'; /** A helper class to simplify the test on grant errors. */ class GrantError extends Error { constructor( - public readonly statusCode: number, + public readonly status: number, public readonly body: unknown ) { super(); @@ -27,9 +27,9 @@ class GrantError extends Error { } /** Create a grant error matcher that matches certain elements of the error response. */ -const grantErrorContaining = (code: string, description: string, statusCode = 400) => +const grantErrorContaining = (code: string, description: string, status = 400) => new GrantError( - statusCode, + status, expect.objectContaining({ code, error_description: description, @@ -51,11 +51,14 @@ class MockOrganizationClient extends MockClient { try { const json = await ky .post(`${this.config.endpoint}/oidc/token`, { - body: createFormData( + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: new URLSearchParams( removeUndefinedKeys({ grant_type: GrantType.RefreshToken, client_id: this.config.appId, - refresh_token: refreshToken, + refresh_token: refreshToken ?? undefined, organization_id: organizationId, scope: scopes?.join(' '), }) @@ -68,7 +71,9 @@ class MockOrganizationClient extends MockClient { return json; } catch (error) { if (error instanceof HTTPError) { - throw new GrantError(error.response.status, JSON.parse(String(error.response.body))); + const json: unknown = JSON.parse(await error.response.text()); + console.error('HTTPError:', error.response.status, JSON.stringify(json, undefined, 2)); + throw new GrantError(error.response.status, json); } throw error; } diff --git a/packages/integration-tests/src/tests/api/organization/organization-invitation.creation.test.ts b/packages/integration-tests/src/tests/api/organization/organization-invitation.creation.test.ts index f487d0ad2ae9..fee13d6ef1f9 100644 --- a/packages/integration-tests/src/tests/api/organization/organization-invitation.creation.test.ts +++ b/packages/integration-tests/src/tests/api/organization/organization-invitation.creation.test.ts @@ -11,12 +11,10 @@ import { OrganizationApiTest, OrganizationInvitationApiTest } from '#src/helpers const randomId = () => generateStandardId(4); -const expectErrorResponse = (error: unknown, status: number, code: string) => { +const expectErrorResponse = async (error: unknown, statusCode: number, code: string) => { assert(error instanceof HTTPError); - const { status: statusCode, body: raw } = error.response; - const body: unknown = JSON.parse(String(raw)); - expect(statusCode).toBe(status); - expect(body).toMatchObject({ code }); + expect(error.response.status).toBe(statusCode); + expect(await error.response.json()).toMatchObject({ code }); }; describe('organization invitation creation', () => { @@ -105,7 +103,7 @@ describe('organization invitation creation', () => { }) .catch((error: unknown) => error); - expectErrorResponse(error, 501, 'connector.not_found'); + await expectErrorResponse(error, 501, 'connector.not_found'); }); it('should not be able to create invitations with the same email', async () => { @@ -124,7 +122,7 @@ describe('organization invitation creation', () => { }) .catch((error: unknown) => error); - expectErrorResponse(error, 422, 'entity.unique_integrity_violation'); + await expectErrorResponse(error, 422, 'entity.unique_integrity_violation'); }); it('should be able to create invitations with the same email for different organizations', async () => { @@ -157,7 +155,7 @@ describe('organization invitation creation', () => { }) .catch((error: unknown) => error); - expectErrorResponse(error, 400, 'request.invalid_input'); + await expectErrorResponse(error, 400, 'request.invalid_input'); }); it('should not be able to create invitations if the invitee is already a member of the organization', async () => { @@ -174,7 +172,7 @@ describe('organization invitation creation', () => { }) .catch((error: unknown) => error); - expectErrorResponse(error, 422, 'request.invalid_input'); + await expectErrorResponse(error, 422, 'request.invalid_input'); }); it('should not be able to create invitations with an invalid email', async () => { @@ -187,7 +185,7 @@ describe('organization invitation creation', () => { }) .catch((error: unknown) => error); - expectErrorResponse(error, 400, 'guard.invalid_input'); + await expectErrorResponse(error, 400, 'guard.invalid_input'); }); it('should not be able to create invitations with an invalid organization id', async () => { @@ -199,7 +197,7 @@ describe('organization invitation creation', () => { }) .catch((error: unknown) => error); - expectErrorResponse(error, 422, 'entity.relation_foreign_key_not_found'); + await expectErrorResponse(error, 422, 'entity.relation_foreign_key_not_found'); }); it('should be able to create invitations with organization role ids', async () => { diff --git a/packages/integration-tests/src/tests/api/organization/organization-invitation.status.test.ts b/packages/integration-tests/src/tests/api/organization/organization-invitation.status.test.ts index d84b0037e1b9..9ce6b2658864 100644 --- a/packages/integration-tests/src/tests/api/organization/organization-invitation.status.test.ts +++ b/packages/integration-tests/src/tests/api/organization/organization-invitation.status.test.ts @@ -9,12 +9,10 @@ import { UserApiTest } from '#src/helpers/user.js'; const randomId = () => generateStandardId(4); -const expectErrorResponse = (error: unknown, status: number, code: string) => { +const expectErrorResponse = async (error: unknown, statusCode: number, code: string) => { assert(error instanceof HTTPError); - const { status: statusCode, body: raw } = error.response; - const body: unknown = JSON.parse(String(raw)); - expect(statusCode).toBe(status); - expect(body).toMatchObject({ code }); + expect(error.response.status).toBe(statusCode); + expect(await error.response.json()).toMatchObject({ code }); }; describe('organization invitation status update', () => { @@ -50,7 +48,7 @@ describe('organization invitation status update', () => { const error = await invitationApi .updateStatus(invitation.id, OrganizationInvitationStatus.Accepted) .catch((error: unknown) => error); - expectErrorResponse(error, 422, 'request.invalid_input'); + await expectErrorResponse(error, 422, 'request.invalid_input'); }); it('should be able to accept an invitation', async () => { @@ -130,7 +128,7 @@ describe('organization invitation status update', () => { .updateStatus(invitation.id, OrganizationInvitationStatus.Accepted, user.id) .catch((error: unknown) => error); - expectErrorResponse(error, 422, 'request.invalid_input'); + await expectErrorResponse(error, 422, 'request.invalid_input'); }); it('should not be able to accept an invitation with an invalid user id', async () => { @@ -146,7 +144,7 @@ describe('organization invitation status update', () => { .updateStatus(invitation.id, OrganizationInvitationStatus.Accepted, 'invalid') .catch((error: unknown) => error); - expectErrorResponse(error, 404, 'entity.not_found'); + await expectErrorResponse(error, 404, 'entity.not_found'); }); it('should not be able to update the status of an ended invitation', async () => { @@ -164,6 +162,6 @@ describe('organization invitation status update', () => { .updateStatus(invitation.id, OrganizationInvitationStatus.Accepted) .catch((error: unknown) => error); - expectErrorResponse(error, 422, 'request.invalid_input'); + await expectErrorResponse(error, 422, 'request.invalid_input'); }); }); diff --git a/packages/integration-tests/src/tests/api/organization/organization-role.test.ts b/packages/integration-tests/src/tests/api/organization/organization-role.test.ts index e09163598fab..9314286131fc 100644 --- a/packages/integration-tests/src/tests/api/organization/organization-role.test.ts +++ b/packages/integration-tests/src/tests/api/organization/organization-role.test.ts @@ -25,9 +25,8 @@ describe('organization role APIs', () => { assert(response instanceof HTTPError); - const { status: statusCode, body: raw } = response.response; - const body: unknown = JSON.parse(String(raw)); - expect(statusCode).toBe(422); + const body: unknown = await response.response.json(); + expect(response.response.status).toBe(422); expect(isKeyInObject(body, 'code') && body.code).toBe('entity.unique_integrity_violation'); }); @@ -127,7 +126,7 @@ describe('organization role APIs', () => { assert(response instanceof HTTPError); expect(response.response.status).toBe(422); - expect(JSON.parse(String(response.response.body))).toMatchObject( + expect(await response.response.json()).toMatchObject( expect.objectContaining({ code: 'entity.unique_integrity_violation', }) @@ -213,7 +212,7 @@ describe('organization role APIs', () => { assert(response instanceof HTTPError); expect(response.response.status).toBe(422); - expect(JSON.parse(String(response.response.body))).toMatchObject( + expect(await response.response.json()).toMatchObject( expect.objectContaining({ code: 'entity.relation_foreign_key_not_found', }) diff --git a/packages/integration-tests/src/tests/api/organization/organization-scope.test.ts b/packages/integration-tests/src/tests/api/organization/organization-scope.test.ts index da5a64440bb1..146f49979584 100644 --- a/packages/integration-tests/src/tests/api/organization/organization-scope.test.ts +++ b/packages/integration-tests/src/tests/api/organization/organization-scope.test.ts @@ -22,9 +22,8 @@ describe('organization scope APIs', () => { assert(response instanceof HTTPError); - const { status: statusCode, body: raw } = response.response; - const body: unknown = JSON.parse(String(raw)); - expect(statusCode).toBe(422); + const body: unknown = await response.response.json(); + expect(response.response.status).toBe(422); expect(isKeyInObject(body, 'code') && body.code).toBe('entity.unique_integrity_violation'); }); @@ -100,7 +99,7 @@ describe('organization scope APIs', () => { assert(response instanceof HTTPError); expect(response.response.status).toBe(422); - expect(JSON.parse(String(response.response.body))).toMatchObject( + expect(await response.response.json()).toMatchObject( expect.objectContaining({ code: 'entity.unique_integrity_violation', }) diff --git a/packages/integration-tests/src/tests/api/organization/organization-user.test.ts b/packages/integration-tests/src/tests/api/organization/organization-user.test.ts index efb874be24e1..72292542f9b9 100644 --- a/packages/integration-tests/src/tests/api/organization/organization-user.test.ts +++ b/packages/integration-tests/src/tests/api/organization/organization-user.test.ts @@ -102,7 +102,7 @@ describe('organization user APIs', () => { const response = await organizationApi.addUsers('0', ['0']).catch((error: unknown) => error); assert(response instanceof HTTPError); expect(response.response.status).toBe(422); - expect(JSON.parse(String(response.response.body))).toMatchObject( + expect(await response.response.json()).toMatchObject( expect.objectContaining({ code: 'entity.relation_foreign_key_not_found' }) ); }); @@ -147,7 +147,7 @@ describe('organization user APIs', () => { assert(response instanceof HTTPError); expect(response.response.status).toBe(422); - expect(JSON.parse(String(response.response.body))).toMatchObject( + expect(await response.response.json()).toMatchObject( expect.objectContaining({ code: 'organization.require_membership' }) ); diff --git a/packages/integration-tests/src/tests/api/resource.test.ts b/packages/integration-tests/src/tests/api/resource.test.ts index 3c8f5ecfbc82..f4f1219655ea 100644 --- a/packages/integration-tests/src/tests/api/resource.test.ts +++ b/packages/integration-tests/src/tests/api/resource.test.ts @@ -49,7 +49,7 @@ describe('admin console api resources', () => { const resourceName2 = generateResourceName(); await expectRejects(createResource(resourceName2, resourceIndicator), { code: 'resource.resource_identifier_in_use', - statusCode: 422, + status: 422, }); }); diff --git a/packages/integration-tests/src/tests/api/role.user.test.ts b/packages/integration-tests/src/tests/api/role.user.test.ts index 71cd6103f11e..a046839d30cb 100644 --- a/packages/integration-tests/src/tests/api/role.user.test.ts +++ b/packages/integration-tests/src/tests/api/role.user.test.ts @@ -66,7 +66,7 @@ describe('roles users', () => { const user = await createUser(generateNewUserProfile({})); await expectRejects(assignUsersToRole([user.id], m2mRole.id), { code: 'entity.db_constraint_violated', - statusCode: 422, + status: 422, }); const users = await getRoleUsers(m2mRole.id); diff --git a/packages/integration-tests/src/tests/api/sign-in-experience.test.ts b/packages/integration-tests/src/tests/api/sign-in-experience.test.ts index d110a4701ea1..ec369087ac21 100644 --- a/packages/integration-tests/src/tests/api/sign-in-experience.test.ts +++ b/packages/integration-tests/src/tests/api/sign-in-experience.test.ts @@ -45,7 +45,7 @@ describe('admin console sign-in experience', () => { await expectRejects(updateSignInExperience(newSignInExperience), { code: 'sign_in_experiences.username_requires_password', - statusCode: 400, + status: 400, }); }); }); diff --git a/packages/integration-tests/src/tests/api/sso-connectors.test.ts b/packages/integration-tests/src/tests/api/sso-connectors.test.ts index 9a8e46ec0442..03315de7d430 100644 --- a/packages/integration-tests/src/tests/api/sso-connectors.test.ts +++ b/packages/integration-tests/src/tests/api/sso-connectors.test.ts @@ -64,7 +64,7 @@ describe('post sso-connectors', () => { providerName: 'OIDC', connectorName: 'test connector name', }), - { code: 'single_sign_on.duplicate_connector_name', statusCode: 409 } + { code: 'single_sign_on.duplicate_connector_name', status: 409 } ); await deleteSsoConnectorById(id); @@ -202,7 +202,7 @@ describe('patch sso-connector by id', () => { patchSsoConnectorById(id2, { connectorName: 'test connector name', }), - { code: 'single_sign_on.duplicate_connector_name', statusCode: 409 } + { code: 'single_sign_on.duplicate_connector_name', status: 409 } ); await deleteSsoConnectorById(id); diff --git a/packages/integration-tests/src/tests/api/swagger-check.test.ts b/packages/integration-tests/src/tests/api/swagger-check.test.ts index 6124dd2a724f..22b172678897 100644 --- a/packages/integration-tests/src/tests/api/swagger-check.test.ts +++ b/packages/integration-tests/src/tests/api/swagger-check.test.ts @@ -9,7 +9,7 @@ const { default: OpenApiSchemaValidator } = Validator; describe('Swagger check', () => { it('should provide a valid swagger.json', async () => { const response = await api.get('swagger.json'); - expect(response).toHaveProperty('statusCode', 200); + expect(response).toHaveProperty('status', 200); expect(response.headers.get('content-type')).toContain('application/json'); // Use multiple validators to be more confident diff --git a/packages/integration-tests/src/tests/api/verification-code.test.ts b/packages/integration-tests/src/tests/api/verification-code.test.ts index 44c9715c5d94..b8bfd4ea9af3 100644 --- a/packages/integration-tests/src/tests/api/verification-code.test.ts +++ b/packages/integration-tests/src/tests/api/verification-code.test.ts @@ -56,7 +56,7 @@ describe('Generic verification code through management API', () => { it('should fail to create a verification code on server side when the email and phone are not provided', async () => { await expectRejects(requestVerificationCode({ username: 'any_string' }), { code: 'guard.invalid_input', - statusCode: 400, + status: 400, }); await expect(readConnectorMessage('Email')).rejects.toThrow(); @@ -68,14 +68,14 @@ describe('Generic verification code through management API', () => { await clearConnectorsByTypes([ConnectorType.Email]); await expectRejects(requestVerificationCode({ email: emailForTestSendCode }), { code: 'connector.not_found', - statusCode: 501, + status: 501, }); await expect( verifyVerificationCode({ email: emailForTestSendCode, verificationCode: 'any_string' }) ).rejects.toMatchObject({ response: { - statusCode: 400, + status: 400, body: JSON.stringify({ message: 'Invalid verification code.', code: 'verification_code.code_mismatch', @@ -92,14 +92,14 @@ describe('Generic verification code through management API', () => { await clearConnectorsByTypes([ConnectorType.Sms]); await expectRejects(requestVerificationCode({ phone: phoneForTestSendCode }), { code: 'connector.not_found', - statusCode: 501, + status: 501, }); await expect( verifyVerificationCode({ phone: phoneForTestSendCode, verificationCode: 'any_string' }) ).rejects.toMatchObject({ response: { - statusCode: 400, + status: 400, body: JSON.stringify({ message: 'Invalid verification code.', code: 'verification_code.code_mismatch', @@ -136,7 +136,7 @@ describe('Generic verification code through management API', () => { await readConnectorMessage('Sms'); await expectRejects(verifyVerificationCode({ phone: mockPhone, verificationCode: '666' }), { code: 'verification_code.code_mismatch', - statusCode: 400, + status: 400, }); }); @@ -148,7 +148,7 @@ describe('Generic verification code through management API', () => { expect(phoneToGetCode).toEqual(phone); await expectRejects(verifyVerificationCode({ phone: phoneToVerify, verificationCode: code }), { code: 'verification_code.not_found', - statusCode: 400, + status: 400, }); }); @@ -160,7 +160,7 @@ describe('Generic verification code through management API', () => { expect(emailToGetCode).toEqual(address); await expectRejects(verifyVerificationCode({ email: emailToVerify, verificationCode: code }), { code: 'verification_code.not_found', - statusCode: 400, + status: 400, }); }); }); diff --git a/packages/integration-tests/src/tests/experience/password-policy.test.ts b/packages/integration-tests/src/tests/experience/password-policy.test.ts index 8c819844a1ec..b2ea78e895f9 100644 --- a/packages/integration-tests/src/tests/experience/password-policy.test.ts +++ b/packages/integration-tests/src/tests/experience/password-policy.test.ts @@ -1,7 +1,5 @@ /* Test the sign-in with different password policies. */ -import crypto from 'node:crypto'; - import { ConnectorType, SignInIdentifier } from '@logto/schemas'; import { updateSignInExperience } from '#src/api/sign-in-experience.js'; @@ -9,8 +7,7 @@ import { demoAppUrl } from '#src/constants.js'; import { clearConnectorsByTypes, setEmailConnector } from '#src/helpers/connector.js'; import ExpectExperience from '#src/ui-helpers/expect-experience.js'; import { setupUsernameAndEmailExperience } from '#src/ui-helpers/index.js'; - -const randomString = () => crypto.randomBytes(8).toString('hex'); +import { randomString } from '#src/utils.js'; describe('password policy', () => { const username = 'test_' + randomString(); diff --git a/packages/integration-tests/src/utils.ts b/packages/integration-tests/src/utils.ts index 9b6cb559a0dd..259aede9111d 100644 --- a/packages/integration-tests/src/utils.ts +++ b/packages/integration-tests/src/utils.ts @@ -123,10 +123,4 @@ export const dcls = (className: C) => `div${cls(className)}` a */ export const generateTestName = () => `test_${generateStandardId(4)}`; -export const createFormData = (data: Record) => { - const formData = new FormData(); - for (const [key, value] of Object.entries(data)) { - formData.append(key, String(value)); - } - return formData; -}; +export const randomString = () => crypto.randomBytes(8).toString('hex');