From 14d0a478af5e195f33991f49f72708d8a0f55978 Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Thu, 28 Mar 2024 23:18:37 +0800 Subject: [PATCH 1/4] refactor: use ky in integration tests --- packages/console/package.json | 2 +- packages/experience/package.json | 2 +- packages/integration-tests/package.json | 2 +- packages/integration-tests/src/api/api.ts | 10 ++--- .../integration-tests/src/api/application.ts | 6 ++- .../integration-tests/src/api/connector.ts | 14 +++--- .../src/api/custom-phrase.ts | 4 +- .../src/api/interaction-sso.ts | 2 +- .../integration-tests/src/api/interaction.ts | 42 +++++++++--------- .../integration-tests/src/api/organization.ts | 2 +- .../integration-tests/src/api/resource.ts | 4 +- packages/integration-tests/src/api/scope.ts | 4 +- .../integration-tests/src/client/index.ts | 43 ++++++++++--------- .../src/helpers/admin-tenant.ts | 2 +- .../integration-tests/src/helpers/index.ts | 8 ++-- .../src/tests/api/admin-user.roles.test.ts | 4 +- .../src/tests/api/admin-user.search.test.ts | 36 ++++++++-------- .../src/tests/api/admin-user.test.ts | 4 +- .../api/application/application.roles.test.ts | 6 +-- .../tests/api/application/application.test.ts | 4 +- .../src/tests/api/callback.test.ts | 10 ++--- .../src/tests/api/connector.test.ts | 2 +- .../src/tests/api/custom-phrase.test.ts | 2 +- .../src/tests/api/domains.test.ts | 8 ++-- .../src/tests/api/hook/hook.test.ts | 2 +- .../src/tests/api/hook/hook.testing.test.ts | 2 +- .../src/tests/api/me.test.ts | 18 ++++---- .../tests/api/oidc/content-type-json.test.ts | 7 +-- .../api/oidc/refresh-token-grant.test.ts | 24 ++++++----- .../organization-invitation.creation.test.ts | 4 +- .../organization-invitation.status.test.ts | 4 +- .../organization/organization-role.test.ts | 16 +++---- .../organization/organization-scope.test.ts | 12 +++--- .../organization/organization-user.test.ts | 12 +++--- .../api/organization/organization.test.ts | 8 ++-- .../src/tests/api/resource.scope.test.ts | 18 ++++---- .../src/tests/api/resource.test.ts | 12 +++--- .../src/tests/api/role.application.test.ts | 16 +++---- .../src/tests/api/role.scope.test.ts | 22 +++++----- .../src/tests/api/role.test.ts | 20 ++++----- .../src/tests/api/role.user.test.ts | 16 +++---- .../src/tests/api/sso-connectors.test.ts | 2 +- .../src/tests/api/swagger-check.test.ts | 4 +- .../src/tests/api/verification-code.test.ts | 4 +- .../src/tests/api/well-known.test.ts | 4 +- packages/integration-tests/src/utils.ts | 8 ++++ pnpm-lock.yaml | 36 ++++++++++++---- 47 files changed, 258 insertions(+), 236 deletions(-) diff --git a/packages/console/package.json b/packages/console/package.json index 18674ba94ef..467323fbccf 100644 --- a/packages/console/package.json +++ b/packages/console/package.json @@ -84,7 +84,7 @@ "jest-transform-stub": "^2.0.0", "jest-transformer-svg": "^2.0.0", "just-kebab-case": "^4.2.0", - "ky": "^1.0.0", + "ky": "^1.2.3", "libphonenumber-js": "^1.10.51", "lint-staged": "^15.0.0", "nanoid": "^5.0.1", diff --git a/packages/experience/package.json b/packages/experience/package.json index 0a8b0980403..2905929de30 100644 --- a/packages/experience/package.json +++ b/packages/experience/package.json @@ -67,7 +67,7 @@ "jest-transform-stub": "^2.0.0", "jest-transformer-svg": "^2.0.0", "js-base64": "^3.7.5", - "ky": "^1.0.0", + "ky": "^1.2.3", "libphonenumber-js": "^1.10.51", "lint-staged": "^15.0.0", "parcel": "2.9.3", diff --git a/packages/integration-tests/package.json b/packages/integration-tests/package.json index d30fca9fc20..b37a2a824e9 100644 --- a/packages/integration-tests/package.json +++ b/packages/integration-tests/package.json @@ -38,11 +38,11 @@ "dotenv": "^16.0.0", "eslint": "^8.44.0", "expect-puppeteer": "^10.0.0", - "got": "^14.0.0", "jest": "^29.7.0", "jest-matcher-specific-error": "^1.0.0", "jest-puppeteer": "^10.0.1", "jose": "^5.0.0", + "ky": "^1.2.3", "node-fetch": "^3.3.0", "openapi-schema-validator": "^12.1.3", "openapi-types": "^12.1.3", diff --git a/packages/integration-tests/src/api/api.ts b/packages/integration-tests/src/api/api.ts index ca0a903b1f5..e3993997681 100644 --- a/packages/integration-tests/src/api/api.ts +++ b/packages/integration-tests/src/api/api.ts @@ -1,9 +1,9 @@ import { appendPath } from '@silverhand/essentials'; -import { got } from 'got'; +import ky from 'ky'; import { logtoConsoleUrl, logtoUrl, logtoCloudUrl } from '#src/constants.js'; -const api = got.extend({ +const api = ky.extend({ prefixUrl: appendPath(new URL(logtoUrl), 'api'), }); @@ -16,7 +16,7 @@ export const authedAdminApi = api.extend({ }, }); -export const adminTenantApi = got.extend({ +export const adminTenantApi = ky.extend({ prefixUrl: appendPath(new URL(logtoConsoleUrl), 'api'), }); @@ -26,10 +26,10 @@ export const authedAdminTenantApi = adminTenantApi.extend({ }, }); -export const cloudApi = got.extend({ +export const cloudApi = ky.extend({ prefixUrl: appendPath(new URL(logtoCloudUrl), 'api'), }); -export const oidcApi = got.extend({ +export const oidcApi = ky.extend({ prefixUrl: appendPath(new URL(logtoUrl), 'oidc'), }); diff --git a/packages/integration-tests/src/api/application.ts b/packages/integration-tests/src/api/application.ts index 29112c3e090..c6f1d2c9971 100644 --- a/packages/integration-tests/src/api/application.ts +++ b/packages/integration-tests/src/api/application.ts @@ -8,6 +8,8 @@ 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 ( @@ -99,10 +101,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', { - form: { + body: createFormData({ client_id: id, client_secret: secret, grant_type: 'client_credentials', - }, + }), }); }; diff --git a/packages/integration-tests/src/api/connector.ts b/packages/integration-tests/src/api/connector.ts index 33a263c23dc..0a151d7cdca 100644 --- a/packages/integration-tests/src/api/connector.ts +++ b/packages/integration-tests/src/api/connector.ts @@ -31,14 +31,13 @@ export const postConnector = async ( payload: Pick ) => authedAdminApi - .post({ - url: `connectors`, + .post('connectors', { json: payload, }) .json(); export const deleteConnectorById = async (id: string) => - authedAdminApi.delete({ url: `connectors/${id}` }).json(); + authedAdminApi.delete(`connectors/${id}`).json(); export const updateConnectorConfig = async ( id: string, @@ -46,8 +45,7 @@ export const updateConnectorConfig = async ( metadata?: Record ) => authedAdminApi - .patch({ - url: `connectors/${id}`, + .patch(`connectors/${id}`, { json: { config, metadata }, }) .json(); @@ -70,8 +68,7 @@ const sendTestMessage = async ( receiver: string, config: Record ) => - authedAdminApi.post({ - url: `connectors/${connectorFactoryId}/test`, + authedAdminApi.post(`connectors/${connectorFactoryId}/test`, { json: { [receiverType]: receiver, config }, }); @@ -81,8 +78,7 @@ export const getConnectorAuthorizationUri = async ( redirectUri: string ) => authedAdminApi - .post({ - url: `connectors/${connectorId}/authorization-uri`, + .post(`connectors/${connectorId}/authorization-uri`, { json: { state, redirectUri }, }) .json<{ redirectTo: string }>(); diff --git a/packages/integration-tests/src/api/custom-phrase.ts b/packages/integration-tests/src/api/custom-phrase.ts index 6e2beb26489..0a3da252a52 100644 --- a/packages/integration-tests/src/api/custom-phrase.ts +++ b/packages/integration-tests/src/api/custom-phrase.ts @@ -9,9 +9,7 @@ export const getCustomPhrase = async (languageTag: string) => authedAdminApi.get(`custom-phrases/${languageTag}`).json(); export const createOrUpdateCustomPhrase = async (languageTag: string, translation: Translation) => - authedAdminApi - .put({ url: `custom-phrases/${languageTag}`, json: translation }) - .json(); + authedAdminApi.put(`custom-phrases/${languageTag}`, { json: translation }).json(); export const deleteCustomPhrase = async (languageTag: string) => authedAdminApi.delete(`custom-phrases/${languageTag}`).json(); diff --git a/packages/integration-tests/src/api/interaction-sso.ts b/packages/integration-tests/src/api/interaction-sso.ts index 474b9e6852f..e515f0e9b08 100644 --- a/packages/integration-tests/src/api/interaction-sso.ts +++ b/packages/integration-tests/src/api/interaction-sso.ts @@ -15,7 +15,7 @@ export const getSsoAuthorizationUrl = async ( .post(`interaction/${ssoPath}/${connectorId}/authorization-url`, { headers: { cookie }, json: payload, - followRedirect: false, + redirect: 'manual', }) .json<{ redirectTo: string }>(); }; diff --git a/packages/integration-tests/src/api/interaction.ts b/packages/integration-tests/src/api/interaction.ts index 555067d96d7..139e2dd9f44 100644 --- a/packages/integration-tests/src/api/interaction.ts +++ b/packages/integration-tests/src/api/interaction.ts @@ -7,7 +7,7 @@ import type { VerifyMfaPayload, ConsentInfoResponse, } from '@logto/schemas'; -import type { Got } from 'got'; +import { type KyInstance } from 'ky'; import api from './api.js'; @@ -26,7 +26,7 @@ export const putInteraction = async (cookie: string, payload: InteractionPayload .put('interaction', { headers: { cookie }, json: payload, - followRedirect: false, + redirect: 'manual', }) .json(); @@ -34,21 +34,19 @@ export const deleteInteraction = async (cookie: string) => api .delete('interaction', { headers: { cookie }, - followRedirect: false, + redirect: 'manual', }) .json(); export const putInteractionEvent = async (cookie: string, payload: { event: InteractionEvent }) => - api - .put('interaction/event', { headers: { cookie }, json: payload, followRedirect: false }) - .json(); + api.put('interaction/event', { headers: { cookie }, json: payload, redirect: 'manual' }).json(); export const patchInteractionIdentifiers = async (cookie: string, payload: IdentifierPayload) => api .patch('interaction/identifiers', { headers: { cookie }, json: payload, - followRedirect: false, + redirect: 'manual', }) .json(); @@ -57,7 +55,7 @@ export const patchInteractionProfile = async (cookie: string, payload: Profile) .patch('interaction/profile', { headers: { cookie }, json: payload, - followRedirect: false, + redirect: 'manual', }) .json(); @@ -66,7 +64,7 @@ export const putInteractionProfile = async (cookie: string, payload: Profile) => .put('interaction/profile', { headers: { cookie }, json: payload, - followRedirect: false, + redirect: 'manual', }) .json(); @@ -75,7 +73,7 @@ export const postInteractionBindMfa = async (cookie: string, payload: BindMfaPay .post('interaction/bind-mfa', { headers: { cookie }, json: payload, - followRedirect: false, + redirect: 'manual', }) .json(); @@ -84,7 +82,7 @@ export const putInteractionMfa = async (cookie: string, payload: VerifyMfaPayloa .put('interaction/mfa', { headers: { cookie }, json: payload, - followRedirect: false, + redirect: 'manual', }) .json(); @@ -92,13 +90,13 @@ export const deleteInteractionProfile = async (cookie: string) => api .delete('interaction/profile', { headers: { cookie }, - followRedirect: false, + redirect: 'manual', }) .json(); -export const submitInteraction = async (api: Got, cookie: string) => +export const submitInteraction = async (api: KyInstance, cookie: string) => api - .post('interaction/submit', { headers: { cookie }, followRedirect: false }) + .post('interaction/submit', { headers: { cookie }, redirect: 'manual' }) .json(); export const sendVerificationCode = async ( @@ -108,7 +106,7 @@ export const sendVerificationCode = async ( api.post('interaction/verification/verification-code', { headers: { cookie }, json: payload, - followRedirect: false, + redirect: 'manual', }); export type SocialAuthorizationUriPayload = { @@ -124,7 +122,7 @@ export const createSocialAuthorizationUri = async ( api.post('interaction/verification/social-authorization-uri', { headers: { cookie }, json: payload, - followRedirect: false, + redirect: 'manual', }); export const initTotp = async (cookie: string) => @@ -132,7 +130,7 @@ export const initTotp = async (cookie: string) => .post('interaction/verification/totp', { headers: { cookie }, json: {}, - followRedirect: false, + redirect: 'manual', }) .json<{ secret: string }>(); @@ -142,16 +140,16 @@ export const skipMfaBinding = async (cookie: string) => json: { mfaSkipped: true, }, - followRedirect: false, + redirect: 'manual', }); -export const consent = async (api: Got, cookie: string) => +export const consent = async (api: KyInstance, cookie: string) => api .post('interaction/consent', { headers: { cookie, }, - followRedirect: false, + redirect: 'manual', }) .json(); @@ -159,7 +157,7 @@ export const getConsentInfo = async (cookie: string) => api .get('interaction/consent', { headers: { cookie }, - followRedirect: false, + redirect: 'manual', }) .json(); @@ -170,5 +168,5 @@ export const createSingleSignOnAuthorizationUri = async ( api.post('interaction/verification/sso-authorization-uri', { headers: { cookie }, json: payload, - followRedirect: false, + redirect: 'manual', }); diff --git a/packages/integration-tests/src/api/organization.ts b/packages/integration-tests/src/api/organization.ts index 5adc40d597d..776ffbeb6ee 100644 --- a/packages/integration-tests/src/api/organization.ts +++ b/packages/integration-tests/src/api/organization.ts @@ -37,7 +37,7 @@ export class OrganizationApi extends ApiFactory< query?: Query ): Promise<[rows: UserWithOrganizationRoles[], totalCount: number]> { const got = await authedAdminApi.get(`${this.path}/${id}/users`, { searchParams: query }); - return [JSON.parse(got.body), Number(got.headers['total-number'] ?? 0)]; + return [await got.json(), Number(got.headers.get('total-number') ?? 0)]; } async deleteUser(id: string, userId: string): Promise { diff --git a/packages/integration-tests/src/api/resource.ts b/packages/integration-tests/src/api/resource.ts index fd47632d667..66bdaa4f0ed 100644 --- a/packages/integration-tests/src/api/resource.ts +++ b/packages/integration-tests/src/api/resource.ts @@ -1,5 +1,5 @@ import type { Resource, CreateResource } from '@logto/schemas'; -import type { OptionsOfTextResponseBody } from 'got'; +import { type Options } from 'ky'; import { generateResourceIndicator, generateResourceName } from '#src/utils.js'; @@ -17,7 +17,7 @@ export const createResource = async (name?: string, indicator?: string) => export const getResources = async () => authedAdminApi.get('resources').json(); -export const getResource = async (resourceId: string, options?: OptionsOfTextResponseBody) => +export const getResource = async (resourceId: string, options?: Options) => authedAdminApi.get(`resources/${resourceId}`, options).json(); export const updateResource = async ( diff --git a/packages/integration-tests/src/api/scope.ts b/packages/integration-tests/src/api/scope.ts index e0edbe52442..27141ab5278 100644 --- a/packages/integration-tests/src/api/scope.ts +++ b/packages/integration-tests/src/api/scope.ts @@ -1,11 +1,11 @@ import type { Scope, CreateScope } from '@logto/schemas'; -import type { OptionsOfTextResponseBody } from 'got'; +import { type Options } from 'ky'; import { generateScopeName } from '#src/utils.js'; import { authedAdminApi } from './api.js'; -export const getScopes = async (resourceId: string, options?: OptionsOfTextResponseBody) => +export const getScopes = async (resourceId: string, options?: Options) => authedAdminApi.get(`resources/${resourceId}/scopes`, options).json(); export const createScope = async (resourceId: string, name?: string) => { diff --git a/packages/integration-tests/src/client/index.ts b/packages/integration-tests/src/client/index.ts index c5f396a57ca..5be2873845b 100644 --- a/packages/integration-tests/src/client/index.ts +++ b/packages/integration-tests/src/client/index.ts @@ -3,8 +3,7 @@ import LogtoClient from '@logto/node'; import { demoAppApplicationId } from '@logto/schemas'; import type { Nullable, Optional } from '@silverhand/essentials'; import { assert } from '@silverhand/essentials'; -import type { Got } from 'got'; -import { got } from 'got'; +import ky, { type KyInstance } from 'ky'; import { submitInteraction } from '#src/api/index.js'; import { demoAppRedirectUri, logtoUrl } from '#src/constants.js'; @@ -23,12 +22,12 @@ export default class MockClient { protected readonly logto: LogtoClient; private navigateUrl?: string; - private readonly api: Got; + private readonly api: KyInstance; constructor(config?: Partial) { this.storage = new MemoryStorage(); this.config = { ...defaultConfig, ...config }; - this.api = got.extend({ prefixUrl: this.config.endpoint + '/api' }); + this.api = ky.extend({ prefixUrl: this.config.endpoint + '/api' }); this.logto = new LogtoClient(this.config, { navigate: (url: string) => { @@ -72,19 +71,21 @@ export default class MockClient { ); // Mock SDK sign-in navigation - const response = await got(this.navigateUrl, { - followRedirect: false, + const response = await ky(this.navigateUrl, { + redirect: 'manual', }); // Note: should redirect to sign-in page assert( - response.statusCode === 303 && - response.headers.location?.startsWith(options.directSignIn ? '/direct/' : '/sign-in'), + response.status === 303 && + response.headers + .get('location') + ?.startsWith(options.directSignIn ? '/direct/' : '/sign-in'), new Error('Visit sign in uri failed') ); // Get session cookie - this.rawCookies = response.headers['set-cookie'] ?? []; + this.rawCookies = response.headers.getSetCookie(); assert(this.interactionCookie, new Error('Get cookie from authorization endpoint failed')); } @@ -100,20 +101,20 @@ export default class MockClient { new Error('SignIn or Register failed') ); - const authResponse = await got.get(redirectTo, { + const authResponse = await ky.get(redirectTo, { headers: { cookie: this.interactionCookie, }, - followRedirect: false, + redirect: 'manual', }); // Note: Should redirect to logto consent page assert( - authResponse.statusCode === 303 && authResponse.headers.location === '/consent', + authResponse.status === 303 && authResponse.headers.get('location') === '/consent', new Error('Invoke auth before consent failed') ); - this.rawCookies = authResponse.headers['set-cookie'] ?? []; + this.rawCookies = authResponse.headers.getSetCookie(); // Manually handle the consent flow if (!consent) { @@ -138,7 +139,7 @@ export default class MockClient { } await this.logto.signOut(postSignOutRedirectUri); - await got(this.navigateUrl); + await ky(this.navigateUrl); } public async isAuthenticated() { @@ -176,30 +177,30 @@ export default class MockClient { assert(this.interactionCookie, new Error('Session not found')); assert(this.interactionCookie.includes('_session.sig'), new Error('Session not found')); - const consentResponse = await got.get(`${this.config.endpoint}/consent`, { + const consentResponse = await ky.get(`${this.config.endpoint}/consent`, { headers: { cookie: this.interactionCookie, }, - followRedirect: false, + redirect: 'manual', }); // Consent page should auto consent and redirect to auth endpoint - const redirectTo = consentResponse.headers.location; + const redirectTo = consentResponse.headers.get('location'); if (!redirectTo?.startsWith(`${this.config.endpoint}/oidc/auth`)) { throw new Error('Consent failed'); } - const authCodeResponse = await got.get(redirectTo, { + const authCodeResponse = await ky.get(redirectTo, { headers: { cookie: this.interactionCookie, }, - followRedirect: false, + redirect: 'manual', }); // Note: Should redirect to the signInCallbackUri - assert(authCodeResponse.statusCode === 303, new Error('Complete auth failed')); - const signInCallbackUri = authCodeResponse.headers.location; + assert(authCodeResponse.status === 303, new Error('Complete auth failed')); + const signInCallbackUri = authCodeResponse.headers.get('location'); assert(signInCallbackUri, new Error('Get sign in callback uri failed')); return signInCallbackUri; diff --git a/packages/integration-tests/src/helpers/admin-tenant.ts b/packages/integration-tests/src/helpers/admin-tenant.ts index 6e75c57db70..e35f2242613 100644 --- a/packages/integration-tests/src/helpers/admin-tenant.ts +++ b/packages/integration-tests/src/helpers/admin-tenant.ts @@ -62,7 +62,7 @@ export const putInteraction = async (cookie: string, payload: InteractionPayload .put('interaction', { headers: { cookie }, json: payload, - followRedirect: false, + redirect: 'manual', }) .json(); diff --git a/packages/integration-tests/src/helpers/index.ts b/packages/integration-tests/src/helpers/index.ts index d31c5ddf6a1..520e1d81d99 100644 --- a/packages/integration-tests/src/helpers/index.ts +++ b/packages/integration-tests/src/helpers/index.ts @@ -7,7 +7,7 @@ import { type JsonObject, type UsersPasswordEncryptionMethod, } from '@logto/schemas'; -import { RequestError } from 'got'; +import { HTTPError } from 'ky'; import { createUser } from '#src/api/index.js'; import { generateUsername } from '#src/utils.js'; @@ -97,13 +97,13 @@ export const expectRejects = async ( export const expectRequestError = (error: unknown, expected: ExpectedErrorInfo) => { const { code, statusCode, messageIncludes } = expected; - if (!(error instanceof RequestError)) { + if (!(error instanceof HTTPError)) { fail('Error should be an instance of RequestError'); } // 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 = JSON.parse(String(error.response.body)) 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?.statusCode).toEqual(statusCode); + expect(error.response.status).toEqual(statusCode); if (messageIncludes) { expect(body.message.includes(messageIncludes)).toBeTruthy(); 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 dd44bea2718..16f51a8e959 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 @@ -1,5 +1,5 @@ import { RoleType } from '@logto/schemas'; -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import { assignRolesToUser, getUserRoles, deleteRoleFromUser } from '#src/api/index.js'; import { createRole } from '#src/api/role.js'; @@ -65,6 +65,6 @@ describe('admin console user management (roles)', () => { const role = await createRole({}); const response = await deleteRoleFromUser(user.id, role.id).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode === 404).toBe(true); + expect(response instanceof HTTPError && response.response.status === 404).toBe(true); }); }); 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 268f71d2904..781bf232b73 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 @@ -1,5 +1,3 @@ -import type { IncomingHttpHeaders } from 'node:http'; - import type { Role, User } from '@logto/schemas'; import { assignRolesToUser, authedAdminApi, createUser, deleteUser } from '#src/api/index.js'; @@ -10,12 +8,12 @@ import { UserApiTest } from '#src/helpers/user.js'; const getUsers = async ( init: string[][] | Record | URLSearchParams -): Promise<{ headers: IncomingHttpHeaders; json: T }> => { - const { headers, body } = await authedAdminApi.get('users', { +): Promise<{ headers: Headers; json: T }> => { + const { headers, json } = await authedAdminApi.get('users', { searchParams: new URLSearchParams(init), }); - return { headers, json: JSON.parse(body) as T }; + return { headers, json: (await json()) as T }; }; describe('admin console user search params', () => { @@ -64,21 +62,21 @@ describe('admin console user search params', () => { it('should return all users if nothing specified', async () => { const { headers } = await getUsers([]); - expect(Number(headers['total-number'])).toBeGreaterThanOrEqual(10); + expect(Number(headers.get('total-number'))).toBeGreaterThanOrEqual(10); }); describe('falling back to `like` mode and matches all available fields if only `search` is specified', () => { it('should search username', async () => { const { headers, json } = await getUsers([['search', '%search_tom%']]); - expect(headers['total-number']).toEqual('5'); + expect(headers.get('total-number')).toEqual('5'); expect(json.length === 5 && json.every((user) => user.name === 'Tom Scott')).toBeTruthy(); }); it('should search primaryPhone', async () => { const { headers, json } = await getUsers([['search', '%0000%']]); - expect(headers['total-number']).toEqual('10'); + expect(headers.get('total-number')).toEqual('10'); expect( json.length === 10 && json.every((user) => user.username?.startsWith('search_')) ).toBeTruthy(); @@ -92,7 +90,7 @@ describe('admin console user search params', () => { ['isCaseSensitive', 'true'], ]); - expect(headers['total-number']).toEqual('0'); + expect(headers.get('total-number')).toEqual('0'); expect(json.length === 0).toBeTruthy(); }); @@ -102,7 +100,7 @@ describe('admin console user search params', () => { ['mode.name', 'exact'], ]); - expect(headers['total-number']).toEqual('2'); + expect(headers.get('total-number')).toEqual('2'); expect(json.length === 2 && json.every((user) => user.name === 'Jerry Swift')).toBeTruthy(); }); @@ -117,7 +115,7 @@ describe('admin console user search params', () => { ['isCaseSensitive', 'true'], ]); - expect(headers['total-number']).toEqual('2'); + expect(headers.get('total-number')).toEqual('2'); expect(json.length === 2 && json.every((user) => user.name === 'Jerry Swift Jr')).toBeTruthy(); }); @@ -130,7 +128,7 @@ describe('admin console user search params', () => { ['isCaseSensitive', 'true'], ]); - expect(headers['total-number']).toEqual('5'); + expect(headers.get('total-number')).toEqual('5'); expect( json.length === 5 && json.every((user) => user.username?.startsWith('search_')) ).toBeTruthy(); @@ -144,7 +142,7 @@ describe('admin console user search params', () => { ['mode.primaryEmail', 'exact'], ]); - expect(headers['total-number']).toEqual('3'); + expect(headers.get('total-number')).toEqual('3'); expect( json.length === 3 && json.every((user) => user.name?.startsWith('Jerry Swift Jr')) ).toBeTruthy(); @@ -161,7 +159,7 @@ describe('admin console user search params', () => { ['isCaseSensitive', 'true'], ]); - expect(headers['total-number']).toEqual('3'); + expect(headers.get('total-number')).toEqual('3'); expect( json.length === 3 && json.every((user) => user.username?.startsWith('search_')) ).toBeTruthy(); @@ -283,7 +281,7 @@ describe('admin console user search params - excludeRoleId', () => { ['excludeRoleId', roles[0]!.id], ]); - expect(headers['total-number']).toEqual('2'); + expect(headers.get('total-number')).toEqual('2'); expect(json).toHaveLength(2); expect(json).toContainEqual(expect.objectContaining({ id: users[1]!.id })); expect(json).toContainEqual(expect.objectContaining({ id: users[2]!.id })); @@ -295,7 +293,7 @@ describe('admin console user search params - excludeRoleId', () => { ['excludeRoleId', roles[1]!.id], ]); - expect(headers['total-number']).toEqual('1'); + expect(headers.get('total-number')).toEqual('1'); expect(json).toHaveLength(1); expect(json).toContainEqual(expect.objectContaining({ id: users[2]!.id })); }); @@ -341,7 +339,7 @@ describe('admin console user search params - excludeOrganizationId', () => { ['excludeOrganizationId', organizationApi.organizations[0]!.id], ]); - expect(headers['total-number']).toEqual('1'); + expect(headers.get('total-number')).toEqual('1'); expect(json).toHaveLength(1); expect(json).toContainEqual(expect.objectContaining({ id: userApi.users[2]!.id })); }); @@ -352,7 +350,7 @@ describe('admin console user search params - excludeOrganizationId', () => { ['excludeOrganizationId', organizationApi.organizations[1]!.id], ]); - expect(headers['total-number']).toEqual('1'); + expect(headers.get('total-number')).toEqual('1'); expect(json).toHaveLength(1); expect(json).toContainEqual(expect.objectContaining({ id: userApi.users[0]!.id })); }); @@ -363,7 +361,7 @@ describe('admin console user search params - excludeOrganizationId', () => { ['excludeOrganizationId', organizationApi.organizations[2]!.id], ]); - expect(headers['total-number']).toEqual('2'); + expect(headers.get('total-number')).toEqual('2'); expect(json).toHaveLength(2); expect(json).toContainEqual(expect.objectContaining({ id: userApi.users[0]!.id })); expect(json).toContainEqual(expect.objectContaining({ id: userApi.users[1]!.id })); 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 b8b04231a41..2f17b700344 100644 --- a/packages/integration-tests/src/tests/api/admin-user.test.ts +++ b/packages/integration-tests/src/tests/api/admin-user.test.ts @@ -1,7 +1,7 @@ import crypto from 'node:crypto'; import { UsersPasswordEncryptionMethod, ConnectorType } from '@logto/schemas'; -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import { mockSocialConnectorConfig, @@ -183,7 +183,7 @@ describe('admin console user management', () => { await deleteUser(user.id); const response = await getUser(user.id).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode === 404).toBe(true); + expect(response instanceof HTTPError && response.response.status === 404).toBe(true); }); it('should update user password successfully', async () => { 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 ea5a9331c9e..d136ec7919c 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 @@ -1,6 +1,6 @@ import { ApplicationType, RoleType } from '@logto/schemas'; import { generateStandardId } from '@logto/shared'; -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import { createApplication, @@ -27,7 +27,7 @@ describe('admin console application management (roles)', () => { const application = await createApplication(generateStandardId(), applicationType); const response = await getApplicationRoles(application.id).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode === 422).toBe(true); + expect(response instanceof HTTPError && response.response.status === 422).toBe(true); }); it('should assign roles to app and get list successfully', async () => { @@ -114,7 +114,7 @@ describe('admin console application management (roles)', () => { const response = await deleteRoleFromApplication(application.id, role.id).catch( (error: unknown) => error ); - expect(response instanceof HTTPError && response.response.statusCode === 404).toBe(true); + expect(response instanceof HTTPError && response.response.status === 404).toBe(true); }); // This case tests GET operation on applications and filter by `types` parameter and `search` parameter. 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 8f2d56517f3..fe8675f811f 100644 --- a/packages/integration-tests/src/tests/api/application/application.test.ts +++ b/packages/integration-tests/src/tests/api/application/application.test.ts @@ -1,5 +1,5 @@ import { ApplicationType } from '@logto/schemas'; -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import { createApplication, @@ -256,6 +256,6 @@ describe('admin console application', () => { await deleteApplication(application.id); const response = await getApplication(application.id).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode === 404).toBe(true); + expect(response instanceof HTTPError && response.response.status === 404).toBe(true); }); }); diff --git a/packages/integration-tests/src/tests/api/callback.test.ts b/packages/integration-tests/src/tests/api/callback.test.ts index 3a3f344172f..4f096e4aeb4 100644 --- a/packages/integration-tests/src/tests/api/callback.test.ts +++ b/packages/integration-tests/src/tests/api/callback.test.ts @@ -1,19 +1,19 @@ -import { got } from 'got'; +import ky from 'ky'; import { logtoConsoleUrl } from '#src/constants.js'; describe('social connector form post callback', () => { - const request = got.extend({ + const request = ky.extend({ prefixUrl: new URL(logtoConsoleUrl), }); it('should redirect to the same path with query string', async () => { const response = await request.post('callback/some_connector_id', { json: { some: 'data' }, - followRedirect: false, + redirect: 'manual', }); - expect(response.statusCode).toBe(303); - expect(response.headers.location).toBe('/callback/some_connector_id?some=data'); + expect(response.status).toBe(303); + expect(response.headers.get('location')).toBe('/callback/some_connector_id?some=data'); }); }); diff --git a/packages/integration-tests/src/tests/api/connector.test.ts b/packages/integration-tests/src/tests/api/connector.test.ts index 240945a6ba0..e20cd0dfdd9 100644 --- a/packages/integration-tests/src/tests/api/connector.test.ts +++ b/packages/integration-tests/src/tests/api/connector.test.ts @@ -1,4 +1,4 @@ -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import { mockEmailConnectorConfig, diff --git a/packages/integration-tests/src/tests/api/custom-phrase.test.ts b/packages/integration-tests/src/tests/api/custom-phrase.test.ts index be8b9c244d9..b8edd0ecf00 100644 --- a/packages/integration-tests/src/tests/api/custom-phrase.test.ts +++ b/packages/integration-tests/src/tests/api/custom-phrase.test.ts @@ -1,4 +1,4 @@ -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import { listCustomPhrases, diff --git a/packages/integration-tests/src/tests/api/domains.test.ts b/packages/integration-tests/src/tests/api/domains.test.ts index ccb63d4e015..43d45fb7658 100644 --- a/packages/integration-tests/src/tests/api/domains.test.ts +++ b/packages/integration-tests/src/tests/api/domains.test.ts @@ -1,4 +1,4 @@ -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import { createDomain, deleteDomain, getDomain, getDomains } from '#src/api/domain.js'; import { generateDomain } from '#src/utils.js'; @@ -27,7 +27,7 @@ describe('domains', () => { await createDomain(); const response = await createDomain().catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(422); + expect(response instanceof HTTPError && response.response.status).toBe(422); }); it('should get domain detail successfully', async () => { @@ -40,7 +40,7 @@ describe('domains', () => { it('should return 404 if domain does not exist', async () => { const response = await getDomain('non_existent_domain').catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should delete domain successfully', async () => { @@ -49,6 +49,6 @@ describe('domains', () => { await deleteDomain(domain.id); const response = await getDomain(domain.id).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); }); 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 3b2d0f95538..dc21d9f1ab6 100644 --- a/packages/integration-tests/src/tests/api/hook/hook.test.ts +++ b/packages/integration-tests/src/tests/api/hook/hook.test.ts @@ -61,7 +61,7 @@ describe('hooks', () => { const response = await authedAdminApi.get('hooks?page=1&page_size=20'); - expect(response.statusCode).toBe(200); + expect(response.status).toBe(200); expect(response.headers).toHaveProperty('total-number'); // Clean up 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 889e5f7103e..6dd637d4562 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 @@ -37,7 +37,7 @@ describe('hook testing', () => { const response = await authedAdminApi.post(`hooks/${created.id}/test`, { json: { events: [HookEvent.PostSignIn], config: { url: responseSuccessEndpoint } }, }); - expect(response.statusCode).toBe(204); + expect(response.status).toBe(204); // Clean Up await authedAdminApi.delete(`hooks/${created.id}`); diff --git a/packages/integration-tests/src/tests/api/me.test.ts b/packages/integration-tests/src/tests/api/me.test.ts index 6c01f8c1ff0..59b1c541c3c 100644 --- a/packages/integration-tests/src/tests/api/me.test.ts +++ b/packages/integration-tests/src/tests/api/me.test.ts @@ -1,4 +1,4 @@ -import { got } from 'got'; +import ky from 'ky'; import { logtoConsoleUrl, logtoUrl } from '#src/constants.js'; import { @@ -11,22 +11,22 @@ import { expectRejects } from '#src/helpers/index.js'; describe('me', () => { it('should only be available in admin tenant', async () => { - await expectRejects(got.get(new URL('/me/custom-data', logtoConsoleUrl)), { + await expectRejects(ky.get(new URL('/me/custom-data', logtoConsoleUrl)), { code: 'auth.authorization_header_missing', statusCode: 401, }); // Redirect to UI - const response = await got.get(new URL('/me/custom-data', logtoUrl)); - expect(response.statusCode).toBe(200); - expect(response.headers['content-type']?.startsWith('text/html;')).toBeTruthy(); + const response = await ky.get(new URL('/me/custom-data', logtoUrl)); + expect(response.status).toBe(200); + expect(response.headers.get('content-type')?.startsWith('text/html;')).toBeTruthy(); }); it('should only recognize the access token with correct resource and scope', async () => { const { id, client } = await createUserWithAllRolesAndSignInToClient(); await expectRejects( - got.get(logtoConsoleUrl + '/me/custom-data', { + ky.get(logtoConsoleUrl + '/me/custom-data', { headers: { authorization: `Bearer ${await client.getAccessToken(resourceDefault)}` }, }), { @@ -36,7 +36,7 @@ describe('me', () => { ); await expect( - got.get(logtoConsoleUrl + '/me/custom-data', { + ky.get(logtoConsoleUrl + '/me/custom-data', { headers: { authorization: `Bearer ${await client.getAccessToken(resourceMe)}` }, }) ).resolves.toHaveProperty('statusCode', 200); @@ -48,10 +48,10 @@ describe('me', () => { const { id, client } = await createUserWithAllRolesAndSignInToClient(); const headers = { authorization: `Bearer ${await client.getAccessToken(resourceMe)}` }; - const data = await got + const data = await ky .get(logtoConsoleUrl + '/me/custom-data', { headers }) .json>(); - const newData = await got + const newData = await ky .patch(logtoConsoleUrl + '/me/custom-data', { headers, json: { foo: 'bar' } }) .json(); 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 c423d8e8a90..33edafc927e 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 @@ -1,18 +1,19 @@ import { demoAppApplicationId } from '@logto/schemas'; import { trySafe } from '@silverhand/essentials'; -import { HTTPError, type Headers, got } from 'got'; +import ky, { HTTPError } from 'ky'; +import { type KyHeadersInit } from 'node_modules/ky/distribution/types/options.js'; import { logtoUrl } from '#src/constants.js'; describe('content-type: application/json compatibility', () => { - const api = got.extend({ + const api = ky.extend({ prefixUrl: new URL('/oidc', logtoUrl), }); const expectErrorMessageForPayload = async ( payload: Record, errorMessage: string, - headers: Headers = {} + headers: KyHeadersInit = {} ) => { return trySafe( api.post('token', { 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 08fda3b4ee5..50a8b260ce1 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 @@ -4,8 +4,8 @@ import { decodeAccessToken } from '@logto/js'; import { type LogtoConfig, Prompt, PersistKey } from '@logto/node'; import { GrantType, InteractionEvent, demoAppApplicationId } from '@logto/schemas'; import { isKeyInObject, removeUndefinedKeys } from '@silverhand/essentials'; -import { HTTPError, got } from 'got'; import { createRemoteJWKSet, jwtVerify } from 'jose'; +import ky, { HTTPError } from 'ky'; import { putInteraction } from '#src/api/index.js'; import MockClient, { defaultConfig } from '#src/client/index.js'; @@ -14,7 +14,7 @@ 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 } from '#src/utils.js'; +import { generateUsername, generatePassword, createFormData } from '#src/utils.js'; /** A helper class to simplify the test on grant errors. */ class GrantError extends Error { @@ -49,15 +49,17 @@ class MockOrganizationClient extends MockClient { async fetchOrganizationToken(organizationId?: string, scopes?: string[]) { const refreshToken = await this.getRefreshToken(); try { - const json = await got + const json = await ky .post(`${this.config.endpoint}/oidc/token`, { - form: removeUndefinedKeys({ - grant_type: GrantType.RefreshToken, - client_id: this.config.appId, - refresh_token: refreshToken, - organization_id: organizationId, - scope: scopes?.join(' '), - }), + body: createFormData( + removeUndefinedKeys({ + grant_type: GrantType.RefreshToken, + client_id: this.config.appId, + refresh_token: refreshToken, + organization_id: organizationId, + scope: scopes?.join(' '), + }) + ), }) .json(); if (isKeyInObject(json, 'refresh_token')) { @@ -66,7 +68,7 @@ class MockOrganizationClient extends MockClient { return json; } catch (error) { if (error instanceof HTTPError) { - throw new GrantError(error.response.statusCode, JSON.parse(String(error.response.body))); + throw new GrantError(error.response.status, JSON.parse(String(error.response.body))); } 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 4df4c7b88f5..f487d0ad2ae 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 @@ -2,7 +2,7 @@ import assert from 'node:assert'; import { ConnectorType } from '@logto/connector-kit'; import { generateStandardId } from '@logto/shared'; -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import { createUser } from '#src/api/admin-user.js'; import { clearConnectorsByTypes, setEmailConnector } from '#src/helpers/connector.js'; @@ -13,7 +13,7 @@ const randomId = () => generateStandardId(4); const expectErrorResponse = (error: unknown, status: number, code: string) => { assert(error instanceof HTTPError); - const { statusCode, body: raw } = error.response; + const { status: statusCode, body: raw } = error.response; const body: unknown = JSON.parse(String(raw)); expect(statusCode).toBe(status); expect(body).toMatchObject({ code }); 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 d9082ee5fcc..d84b0037e1b 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 @@ -2,7 +2,7 @@ import assert from 'node:assert'; import { OrganizationInvitationStatus } from '@logto/schemas'; import { generateStandardId } from '@logto/shared'; -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import { OrganizationApiTest, OrganizationInvitationApiTest } from '#src/helpers/organization.js'; import { UserApiTest } from '#src/helpers/user.js'; @@ -11,7 +11,7 @@ const randomId = () => generateStandardId(4); const expectErrorResponse = (error: unknown, status: number, code: string) => { assert(error instanceof HTTPError); - const { statusCode, body: raw } = error.response; + const { status: statusCode, body: raw } = error.response; const body: unknown = JSON.parse(String(raw)); expect(statusCode).toBe(status); expect(body).toMatchObject({ code }); 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 328d473758b..e09163598fa 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 @@ -2,7 +2,7 @@ import assert from 'node:assert'; import { generateStandardId } from '@logto/shared'; import { isKeyInObject, pick } from '@silverhand/essentials'; -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import { OrganizationRoleApiTest, OrganizationScopeApiTest } from '#src/helpers/organization.js'; @@ -25,7 +25,7 @@ describe('organization role APIs', () => { assert(response instanceof HTTPError); - const { statusCode, body: raw } = response.response; + const { status: statusCode, body: raw } = response.response; const body: unknown = JSON.parse(String(raw)); expect(statusCode).toBe(422); expect(isKeyInObject(body, 'code') && body.code).toBe('entity.unique_integrity_violation'); @@ -97,7 +97,7 @@ describe('organization role APIs', () => { it('should fail when try to get an organization role that does not exist', async () => { const response = await roleApi.get('0').catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should be able to update organization role', async () => { @@ -126,7 +126,7 @@ describe('organization role APIs', () => { .catch((error: unknown) => error); assert(response instanceof HTTPError); - expect(response.response.statusCode).toBe(422); + expect(response.response.status).toBe(422); expect(JSON.parse(String(response.response.body))).toMatchObject( expect.objectContaining({ code: 'entity.unique_integrity_violation', @@ -138,12 +138,12 @@ describe('organization role APIs', () => { const createdRole = await roleApi.create({ name: 'test' + randomId() }); await roleApi.delete(createdRole.id); const response = await roleApi.get(createdRole.id).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should fail when try to delete an organization role that does not exist', async () => { const response = await roleApi.delete('0').catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); }); @@ -212,7 +212,7 @@ describe('organization role APIs', () => { .catch((error: unknown) => error); assert(response instanceof HTTPError); - expect(response.response.statusCode).toBe(422); + expect(response.response.status).toBe(422); expect(JSON.parse(String(response.response.body))).toMatchObject( expect.objectContaining({ code: 'entity.relation_foreign_key_not_found', @@ -248,7 +248,7 @@ describe('organization role APIs', () => { const response = await roleApi.deleteScope(role.id, '0').catch((error: unknown) => error); assert(response instanceof HTTPError); - expect(response.response.statusCode).toBe(404); + expect(response.response.status).toBe(404); }); }); }); 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 264683424ea..da5a64440bb 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 @@ -2,7 +2,7 @@ import assert from 'node:assert'; import { generateStandardId } from '@logto/shared'; import { isKeyInObject } from '@silverhand/essentials'; -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import { OrganizationScopeApiTest } from '#src/helpers/organization.js'; @@ -22,7 +22,7 @@ describe('organization scope APIs', () => { assert(response instanceof HTTPError); - const { statusCode, body: raw } = response.response; + const { status: statusCode, body: raw } = response.response; const body: unknown = JSON.parse(String(raw)); expect(statusCode).toBe(422); expect(isKeyInObject(body, 'code') && body.code).toBe('entity.unique_integrity_violation'); @@ -70,7 +70,7 @@ describe('organization scope APIs', () => { it('should fail when try to get an organization scope that does not exist', async () => { const response = await scopeApi.get('0').catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should be able to update organization scope', async () => { @@ -99,7 +99,7 @@ describe('organization scope APIs', () => { .catch((error: unknown) => error); assert(response instanceof HTTPError); - expect(response.response.statusCode).toBe(422); + expect(response.response.status).toBe(422); expect(JSON.parse(String(response.response.body))).toMatchObject( expect.objectContaining({ code: 'entity.unique_integrity_violation', @@ -111,11 +111,11 @@ describe('organization scope APIs', () => { const createdScope = await scopeApi.create({ name: 'test' + randomId() }); await scopeApi.delete(createdScope.id); const response = await scopeApi.get(createdScope.id).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should fail when try to delete an organization scope that does not exist', async () => { const response = await scopeApi.delete('0').catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); }); 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 2c5d9866442..efb874be24e 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 @@ -1,6 +1,6 @@ import assert from 'node:assert'; -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import { OrganizationApiTest } from '#src/helpers/organization.js'; import { UserApiTest } from '#src/helpers/user.js'; @@ -95,13 +95,13 @@ describe('organization user APIs', () => { const response = await organizationApi .addUsers(organization.id, []) .catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(400); + expect(response instanceof HTTPError && response.response.status).toBe(400); }); it('should fail when try to add user to an organization that does not exist', async () => { const response = await organizationApi.addUsers('0', ['0']).catch((error: unknown) => error); assert(response instanceof HTTPError); - expect(response.response.statusCode).toBe(422); + expect(response.response.status).toBe(422); expect(JSON.parse(String(response.response.body))).toMatchObject( expect.objectContaining({ code: 'entity.relation_foreign_key_not_found' }) ); @@ -120,7 +120,7 @@ describe('organization user APIs', () => { it('should fail when try to delete user from an organization that does not exist', async () => { const response = await organizationApi.deleteUser('0', '0').catch((error: unknown) => error); assert(response instanceof HTTPError); - expect(response.response.statusCode).toBe(404); + expect(response.response.status).toBe(404); }); }); @@ -146,7 +146,7 @@ describe('organization user APIs', () => { .catch((error: unknown) => error); assert(response instanceof HTTPError); - expect(response.response.statusCode).toBe(422); + expect(response.response.status).toBe(422); expect(JSON.parse(String(response.response.body))).toMatchObject( expect.objectContaining({ code: 'organization.require_membership' }) ); @@ -244,7 +244,7 @@ describe('organization user APIs', () => { const response = await organizationApi .getUserRoles(organization.id, user.id) .catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(422); // Require membership + expect(response instanceof HTTPError && response.response.status).toBe(422); // Require membership }); }); }); diff --git a/packages/integration-tests/src/tests/api/organization/organization.test.ts b/packages/integration-tests/src/tests/api/organization/organization.test.ts index 107b8c110b2..892a98ba57b 100644 --- a/packages/integration-tests/src/tests/api/organization/organization.test.ts +++ b/packages/integration-tests/src/tests/api/organization/organization.test.ts @@ -1,4 +1,4 @@ -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import { OrganizationApiTest } from '#src/helpers/organization.js'; import { UserApiTest } from '#src/helpers/user.js'; @@ -95,7 +95,7 @@ describe('organization APIs', () => { it('should fail when try to get an organization that does not exist', async () => { const response = await organizationApi.get('0').catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should be able to update organization', async () => { @@ -117,11 +117,11 @@ describe('organization APIs', () => { const response = await organizationApi .get(createdOrganization.id) .catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should fail when try to delete an organization that does not exist', async () => { const response = await organizationApi.delete('0').catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); }); diff --git a/packages/integration-tests/src/tests/api/resource.scope.test.ts b/packages/integration-tests/src/tests/api/resource.scope.test.ts index f098f9907f7..96eaeb747d2 100644 --- a/packages/integration-tests/src/tests/api/resource.scope.test.ts +++ b/packages/integration-tests/src/tests/api/resource.scope.test.ts @@ -1,7 +1,7 @@ import assert from 'node:assert'; import { defaultManagementApi } from '@logto/schemas'; -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import { createResource } from '#src/api/index.js'; import { createScope, deleteScope, getScopes, updateScope } from '#src/api/scope.js'; @@ -32,28 +32,28 @@ describe('scopes', () => { const response = await createScope(resource.id, createdScope.name).catch( (error: unknown) => error ); - expect(response instanceof HTTPError && response.response.statusCode === 422).toBe(true); + expect(response instanceof HTTPError && response.response.status === 422).toBe(true); }); it('should return 404 when create scope with invalid resource id', async () => { const response = await createScope('invalid_resource_id', 'invalid_scope_name').catch( (error: unknown) => error ); - expect(response instanceof HTTPError && response.response.statusCode === 404).toBe(true); + expect(response instanceof HTTPError && response.response.status === 404).toBe(true); }); it('should return 400 if scope name is empty', async () => { const resource = await createResource(); const response = await createScope(resource.id, '').catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode === 400).toBe(true); + expect(response instanceof HTTPError && response.response.status === 400).toBe(true); }); it('should return 400 if scope name has empty space', async () => { const resource = await createResource(); const response = await createScope(resource.id, 'scope id').catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode === 400).toBe(true); + expect(response instanceof HTTPError && response.response.status === 400).toBe(true); }); it('should update scope successfully', async () => { @@ -82,7 +82,7 @@ describe('scopes', () => { const response = await updateScope(resource.id, createdScope2.id, { name: createdScope.name, }).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode === 422).toBe(true); + expect(response instanceof HTTPError && response.response.status === 422).toBe(true); }); it('should return 400 if update scope name that has empty space', async () => { @@ -93,7 +93,7 @@ describe('scopes', () => { }).catch((error: unknown) => error); assert(response instanceof HTTPError); - expect(response.response.statusCode).toBe(400); + expect(response.response.status).toBe(400); }); it('should return 404 when update scope with invalid resource id', async () => { @@ -101,7 +101,7 @@ describe('scopes', () => { name: 'scope', }).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode === 404).toBe(true); + expect(response instanceof HTTPError && response.response.status === 404).toBe(true); }); it('should return 404 when update scope with invalid scope id', async () => { @@ -111,7 +111,7 @@ describe('scopes', () => { name: 'scope', }).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode === 404).toBe(true); + expect(response instanceof HTTPError && response.response.status === 404).toBe(true); }); it('should delete scope successfully', async () => { diff --git a/packages/integration-tests/src/tests/api/resource.test.ts b/packages/integration-tests/src/tests/api/resource.test.ts index b83469a07db..3c8f5ecfbc8 100644 --- a/packages/integration-tests/src/tests/api/resource.test.ts +++ b/packages/integration-tests/src/tests/api/resource.test.ts @@ -1,5 +1,5 @@ import { defaultManagementApi } from '@logto/schemas'; -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import { createResource, @@ -21,7 +21,7 @@ describe('admin console api resources', () => { it('should return 404 if resource not found', async () => { const response = await getResource('not_found').catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode === 404).toBe(true); + expect(response instanceof HTTPError && response.response.status === 404).toBe(true); }); it('should create api resource successfully', async () => { @@ -93,7 +93,7 @@ describe('admin console api resources', () => { name: 123, }).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode === 400).toBe(true); + expect(response instanceof HTTPError && response.response.status === 400).toBe(true); }); it('should not update api resource indicator', async () => { @@ -119,19 +119,19 @@ describe('admin console api resources', () => { await deleteResource(createdResource.id); const response = await getResource(createdResource.id).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode === 404).toBe(true); + expect(response instanceof HTTPError && response.response.status === 404).toBe(true); }); it('should throw when deleting management api resource', async () => { const response = await deleteResource(defaultManagementApi.resource.id).catch( (error: unknown) => error ); - expect(response instanceof HTTPError && response.response.statusCode === 400).toBe(true); + expect(response instanceof HTTPError && response.response.status === 400).toBe(true); }); it('should throw 404 when delete api resource not found', async () => { const response = await deleteResource('dummy_id').catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode === 404).toBe(true); + expect(response instanceof HTTPError && response.response.status === 404).toBe(true); }); it('be able to set only one default api resource', async () => { diff --git a/packages/integration-tests/src/tests/api/role.application.test.ts b/packages/integration-tests/src/tests/api/role.application.test.ts index 4939ae1e154..c53fb6df616 100644 --- a/packages/integration-tests/src/tests/api/role.application.test.ts +++ b/packages/integration-tests/src/tests/api/role.application.test.ts @@ -1,6 +1,6 @@ import { ApplicationType, RoleType } from '@logto/schemas'; import { generateStandardId } from '@logto/shared'; -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import { assignRolesToApplication, createApplication } from '#src/api/index.js'; import { @@ -27,7 +27,7 @@ describe('roles applications', () => { it('should return 404 if role not found', async () => { const response = await getRoleApplications('not-found').catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should assign applications to role successfully', async () => { @@ -52,13 +52,13 @@ describe('roles applications', () => { it('should fail when try to assign empty applications', async () => { const role = await createRole({ type: RoleType.MachineToMachine }); const response = await assignApplicationsToRole([], role.id).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(400); + expect(response instanceof HTTPError && response.response.status).toBe(400); }); it('should fail with invalid application input', async () => { const role = await createRole({ type: RoleType.MachineToMachine }); const response = await assignApplicationsToRole([''], role.id).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(400); + expect(response instanceof HTTPError && response.response.status).toBe(400); }); it('should fail if role not found', async () => { @@ -66,7 +66,7 @@ describe('roles applications', () => { const response = await assignApplicationsToRole([m2mApp.id], 'not-found').catch( (error: unknown) => error ); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should fail if application not found', async () => { @@ -74,7 +74,7 @@ describe('roles applications', () => { const response = await assignApplicationsToRole(['not-found'], role.id).catch( (error: unknown) => error ); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should remove application from role successfully', async () => { @@ -95,7 +95,7 @@ describe('roles applications', () => { const response = await deleteApplicationFromRole(m2mApp.id, 'not-found').catch( (error: unknown) => error ); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should fail if application not found when trying to remove application from role', async () => { @@ -103,7 +103,7 @@ describe('roles applications', () => { const response = await deleteApplicationFromRole('not-found', role.id).catch( (error: unknown) => error ); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); // This case tests GET operation on roles and filter by `type` parameter and `search` parameter. diff --git a/packages/integration-tests/src/tests/api/role.scope.test.ts b/packages/integration-tests/src/tests/api/role.scope.test.ts index c154ff17b54..1b4f6a4ef59 100644 --- a/packages/integration-tests/src/tests/api/role.scope.test.ts +++ b/packages/integration-tests/src/tests/api/role.scope.test.ts @@ -1,5 +1,5 @@ import { defaultManagementApi } from '@logto/schemas'; -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import { createResource } from '#src/api/index.js'; import { @@ -24,7 +24,7 @@ describe('roles scopes', () => { it('should return 404 if role not found', async () => { const response = await getRoleScopes('not-found').catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should return empty if role has no scopes', async () => { @@ -46,13 +46,13 @@ describe('roles scopes', () => { it('should fail when try to assign empty scopes', async () => { const role = await createRole({}); const response = await assignScopesToRole([], role.id).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(400); + expect(response instanceof HTTPError && response.response.status).toBe(400); }); it('should fail with invalid scope input', async () => { const role = await createRole({}); const response = await assignScopesToRole([''], role.id).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(400); + expect(response instanceof HTTPError && response.response.status).toBe(400); }); it('should fail if role not found', async () => { @@ -61,7 +61,7 @@ describe('roles scopes', () => { const response = await assignScopesToRole([scope.id], 'not-found').catch( (error: unknown) => error ); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should fail if scope not found', async () => { @@ -69,7 +69,7 @@ describe('roles scopes', () => { const response = await assignScopesToRole(['not-found'], role.id).catch( (error: unknown) => error ); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should fail if scope already assigned to role', async () => { @@ -81,7 +81,7 @@ describe('roles scopes', () => { const response = await assignScopesToRole([scope1.id, scope2.id], role.id).catch( (error: unknown) => error ); - expect(response instanceof HTTPError && response.response.statusCode).toBe(422); + expect(response instanceof HTTPError && response.response.status).toBe(422); }); it('should fail if try to assign management API scope(s) to user role', async () => { @@ -91,7 +91,7 @@ describe('roles scopes', () => { [defaultManagementApi.scopes[0]!.id], userRole.id ).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(400); + expect(response instanceof HTTPError && response.response.status).toBe(400); }); it('should remove scope from role successfully', async () => { @@ -113,7 +113,7 @@ describe('roles scopes', () => { const resource = await createResource(); const scope = await createScope(resource.id); const response = await deleteScopeFromRole(scope.id, role.id).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should fail when try to remove scope from role that is not found', async () => { @@ -122,7 +122,7 @@ describe('roles scopes', () => { const response = await deleteScopeFromRole(scope.id, 'not-found').catch( (error: unknown) => error ); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should fail when try to assign a scope to an internal role', async () => { @@ -132,6 +132,6 @@ describe('roles scopes', () => { (error: unknown) => error ); - expect(response instanceof HTTPError && response.response.statusCode).toBe(403); + expect(response instanceof HTTPError && response.response.status).toBe(403); }); }); diff --git a/packages/integration-tests/src/tests/api/role.test.ts b/packages/integration-tests/src/tests/api/role.test.ts index 0526866e698..7cc163ddc1e 100644 --- a/packages/integration-tests/src/tests/api/role.test.ts +++ b/packages/integration-tests/src/tests/api/role.test.ts @@ -1,5 +1,5 @@ import { defaultManagementApi } from '@logto/schemas'; -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import { createResource } from '#src/api/resource.js'; import { @@ -49,13 +49,13 @@ describe('roles', () => { const { name } = await createRole({}); const response = await createRole({ name }).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(422); + expect(response instanceof HTTPError && response.response.status).toBe(422); }); it('should fail when try to create an internal role', async () => { const response = await createRole({ name: '#internal:foo' }).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(403); + expect(response instanceof HTTPError && response.response.status).toBe(403); }); it('should fail when try to create role with management API scope(s)', async () => { @@ -63,7 +63,7 @@ describe('roles', () => { (error: unknown) => error ); - expect(response instanceof HTTPError && response.response.statusCode).toBe(400); + expect(response instanceof HTTPError && response.response.status).toBe(400); }); it('should get role detail successfully', async () => { @@ -77,7 +77,7 @@ describe('roles', () => { it('should return 404 if role does not exist', async () => { const response = await getRole('non_existent_role').catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should update role details successfully', async () => { @@ -103,14 +103,14 @@ describe('roles', () => { const response = await updateRole(role2.id, { name: role1.name, }).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(422); + expect(response instanceof HTTPError && response.response.status).toBe(422); }); it('should fail when update a non-existent role', async () => { const response = await updateRole('non_existent_role', { name: 'new_name', }).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should fail when try to update an internal role', async () => { @@ -120,7 +120,7 @@ describe('roles', () => { name: '#internal:foo', }).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(403); + expect(response instanceof HTTPError && response.response.status).toBe(403); }); it('should delete role successfully', async () => { @@ -129,12 +129,12 @@ describe('roles', () => { await deleteRole(role.id); const response = await getRole(role.id).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should return 404 if role does not exist', async () => { const response = await deleteRole('non_existent_role').catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); }); 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 dfa2f8cecf2..71cd6103f11 100644 --- a/packages/integration-tests/src/tests/api/role.user.test.ts +++ b/packages/integration-tests/src/tests/api/role.user.test.ts @@ -1,5 +1,5 @@ import { RoleType } from '@logto/schemas'; -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import { createUser } from '#src/api/index.js'; import { @@ -28,7 +28,7 @@ describe('roles users', () => { it('should return 404 if role not found', async () => { const response = await getRoleUsers('not-found').catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should assign users to role successfully', async () => { @@ -76,13 +76,13 @@ describe('roles users', () => { it('should fail when try to assign empty users', async () => { const role = await createRole({}); const response = await assignUsersToRole([], role.id).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(400); + expect(response instanceof HTTPError && response.response.status).toBe(400); }); it('should fail with invalid user input', async () => { const role = await createRole({}); const response = await assignUsersToRole([''], role.id).catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode).toBe(400); + expect(response instanceof HTTPError && response.response.status).toBe(400); }); it('should fail if role not found', async () => { @@ -90,7 +90,7 @@ describe('roles users', () => { const response = await assignUsersToRole([user.id], 'not-found').catch( (error: unknown) => error ); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should fail if user not found', async () => { @@ -98,7 +98,7 @@ describe('roles users', () => { const response = await assignUsersToRole(['not-found'], role.id).catch( (error: unknown) => error ); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should remove user from role successfully', async () => { @@ -119,7 +119,7 @@ describe('roles users', () => { const response = await deleteUserFromRole(user.id, 'not-found').catch( (error: unknown) => error ); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); it('should fail if user not found when trying to remove user from role', async () => { @@ -127,6 +127,6 @@ describe('roles users', () => { const response = await deleteUserFromRole('not-found', role.id).catch( (error: unknown) => error ); - expect(response instanceof HTTPError && response.response.statusCode).toBe(404); + expect(response instanceof HTTPError && response.response.status).toBe(404); }); }); 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 edb368523b2..9a8e46ec044 100644 --- a/packages/integration-tests/src/tests/api/sso-connectors.test.ts +++ b/packages/integration-tests/src/tests/api/sso-connectors.test.ts @@ -1,5 +1,5 @@ import { SsoProviderName } from '@logto/schemas'; -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import { providerNames, 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 fadd7a8ca04..6124dd2a724 100644 --- a/packages/integration-tests/src/tests/api/swagger-check.test.ts +++ b/packages/integration-tests/src/tests/api/swagger-check.test.ts @@ -10,10 +10,10 @@ 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.headers['content-type']).toContain('application/json'); + expect(response.headers.get('content-type')).toContain('application/json'); // Use multiple validators to be more confident - const object: unknown = JSON.parse(response.body); + const object: unknown = await response.json(); const validator = new OpenApiSchemaValidator({ version: 3 }); const result = validator.validate(object as OpenAPI.Document); 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 cd131d62000..44c9715c5d9 100644 --- a/packages/integration-tests/src/tests/api/verification-code.test.ts +++ b/packages/integration-tests/src/tests/api/verification-code.test.ts @@ -32,7 +32,7 @@ describe('Generic verification code through management API', () => { it('should create an email verification code on server side', async () => { const payload: RequestVerificationCodePayload = { email: mockEmail }; const response = await requestVerificationCode(payload); - expect(response.statusCode).toBe(204); + expect(response.status).toBe(204); const { code, type, address } = await readConnectorMessage('Email'); @@ -44,7 +44,7 @@ describe('Generic verification code through management API', () => { it('should create an SMS verification code on server side', async () => { const payload: RequestVerificationCodePayload = { phone: mockPhone }; const response = await requestVerificationCode(payload); - expect(response.statusCode).toBe(204); + expect(response.status).toBe(204); const { code, type, phone } = await readConnectorMessage('Sms'); diff --git a/packages/integration-tests/src/tests/api/well-known.test.ts b/packages/integration-tests/src/tests/api/well-known.test.ts index d2529a43699..4aaf7ce7589 100644 --- a/packages/integration-tests/src/tests/api/well-known.test.ts +++ b/packages/integration-tests/src/tests/api/well-known.test.ts @@ -1,5 +1,5 @@ import { type SignInExperience, type Translation, type SsoConnectorMetadata } from '@logto/schemas'; -import { HTTPError } from 'got'; +import { HTTPError } from 'ky'; import api, { adminTenantApi, authedAdminApi } from '#src/api/api.js'; import { updateSignInExperience } from '#src/api/index.js'; @@ -15,7 +15,7 @@ describe('.well-known api', () => { it('should not found API route in non-admin tenant', async () => { const response = await api.get('.well-known/endpoints/123').catch((error: unknown) => error); - expect(response instanceof HTTPError && response.response.statusCode === 404).toBe(true); + expect(response instanceof HTTPError && response.response.status === 404).toBe(true); }); it('get /.well-known/sign-in-exp for console', async () => { diff --git a/packages/integration-tests/src/utils.ts b/packages/integration-tests/src/utils.ts index 31c6b884126..9b6cb559a0d 100644 --- a/packages/integration-tests/src/utils.ts +++ b/packages/integration-tests/src/utils.ts @@ -122,3 +122,11 @@ 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; +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8fe494d769e..229f1928f3e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2883,8 +2883,8 @@ importers: specifier: ^4.2.0 version: 4.2.0 ky: - specifier: ^1.0.0 - version: 1.0.0 + specifier: ^1.2.3 + version: 1.2.3 libphonenumber-js: specifier: ^1.10.51 version: 1.10.51 @@ -3535,8 +3535,8 @@ importers: specifier: ^3.7.5 version: 3.7.5 ky: - specifier: ^1.0.0 - version: 1.0.0 + specifier: ^1.2.3 + version: 1.2.3 libphonenumber-js: specifier: ^1.10.51 version: 1.10.51 @@ -3667,9 +3667,6 @@ importers: expect-puppeteer: specifier: ^10.0.0 version: 10.0.0 - got: - specifier: ^14.0.0 - version: 14.0.0 jest: specifier: ^29.7.0 version: 29.7.0(@types/node@20.10.4) @@ -3682,6 +3679,9 @@ importers: jose: specifier: ^5.0.0 version: 5.0.1 + ky: + specifier: ^1.2.3 + version: 1.2.3 node-fetch: specifier: ^3.3.0 version: 3.3.0 @@ -9465,6 +9465,7 @@ packages: /@sindresorhus/is@6.1.0: resolution: {integrity: sha512-BuvU07zq3tQ/2SIgBsEuxKYDyDjC0n7Zir52bpHy2xnBbW81+po43aLFPLbeV3HRAheFbGud1qgcqSYfhtHMAg==} engines: {node: '>=16'} + dev: false /@sinonjs/commons@2.0.0: resolution: {integrity: sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==} @@ -9773,6 +9774,7 @@ packages: engines: {node: '>=14.16'} dependencies: defer-to-connect: 2.0.1 + dev: false /@testing-library/dom@9.0.0: resolution: {integrity: sha512-+/TLgKNFsYUshOY/zXsQOk+PlFQK+eyJ9T13IDVNJEi+M+Un7xlJK+FZKkbGSnf0+7E1G6PlDhkSYQ/GFiruBQ==} @@ -10012,6 +10014,7 @@ packages: /@types/http-cache-semantics@4.0.4: resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} + dev: false /@types/http-errors@1.8.2: resolution: {integrity: sha512-EqX+YQxINb+MeXaIqYDASb6U6FCHbWjkj4a1CKDBks3d/QiB2+PqBLyO72vLDgAO1wUI4O+9gweRcQK11bTL/w==} @@ -11338,6 +11341,7 @@ packages: /cacheable-lookup@7.0.0: resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} engines: {node: '>=14.16'} + dev: false /cacheable-request@10.2.14: resolution: {integrity: sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==} @@ -11350,6 +11354,7 @@ packages: mimic-response: 4.0.0 normalize-url: 8.0.0 responselike: 3.0.0 + dev: false /call-bind@1.0.2: resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} @@ -12263,6 +12268,7 @@ packages: engines: {node: '>=10'} dependencies: mimic-response: 3.1.0 + dev: false /dedent@1.5.1: resolution: {integrity: sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==} @@ -12307,6 +12313,7 @@ packages: /defer-to-connect@2.0.1: resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} engines: {node: '>=10'} + dev: false /define-lazy-prop@2.0.0: resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} @@ -13664,6 +13671,7 @@ packages: /form-data-encoder@4.0.2: resolution: {integrity: sha512-KQVhvhK8ZkWzxKxOr56CPulAhH3dobtuQ4+hNQ+HekH/Wp5gSOafqRAeTphQUJAIk0GBvHZgJ2ZGRWd5kphMuw==} engines: {node: '>= 18'} + dev: false /form-data@3.0.1: resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} @@ -14082,6 +14090,7 @@ packages: lowercase-keys: 3.0.0 p-cancelable: 4.0.1 responselike: 3.0.0 + dev: false /graceful-fs@4.2.10: resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} @@ -14382,6 +14391,7 @@ packages: /http-cache-semantics@4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + dev: false /http-errors@1.4.0: resolution: {integrity: sha512-oLjPqve1tuOl5aRhv8GK5eHpqP1C9fb+Ol+XTLjKfLltE44zdDbEdjPSbU7Ch5rSNsVFqZn97SrMmZLdu1/YMw==} @@ -14459,6 +14469,7 @@ packages: dependencies: quick-lru: 5.1.1 resolve-alpn: 1.2.1 + dev: false /https-proxy-agent@5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} @@ -16225,8 +16236,8 @@ packages: - supports-color dev: false - /ky@1.0.0: - resolution: {integrity: sha512-ptUup6btycj2IXLL/L5Bh/QC9ghYC2k/BsnnSf0ccEap8FpCvJ32FL5s5Potb8NkH6HOTdnVGmyI1wkHZ3mfEQ==} + /ky@1.2.3: + resolution: {integrity: sha512-2IM3VssHfG2zYz2FsHRUqIp8chhLc9uxDMcK2THxgFfv8pQhnMfN8L0ul+iW4RdBl5AglF8ooPIflRm3yNH0IA==} engines: {node: '>=18'} dev: true @@ -16597,6 +16608,7 @@ packages: /lowercase-keys@3.0.0: resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: false /lowlight@1.20.0: resolution: {integrity: sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==} @@ -17241,10 +17253,12 @@ packages: /mimic-response@3.1.0: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} + dev: false /mimic-response@4.0.0: resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: false /min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} @@ -17600,6 +17614,7 @@ packages: /normalize-url@8.0.0: resolution: {integrity: sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==} engines: {node: '>=14.16'} + dev: false /npm-run-path@4.0.1: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} @@ -17879,6 +17894,7 @@ packages: /p-cancelable@4.0.1: resolution: {integrity: sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg==} engines: {node: '>=14.16'} + dev: false /p-defer@4.0.0: resolution: {integrity: sha512-Vb3QRvQ0Y5XnF40ZUWW7JfLogicVh/EnA5gBIvKDJoYpeI82+1E3AlB9yOcKFS0AhHrWVnAQO39fbR0G99IVEQ==} @@ -19496,6 +19512,7 @@ packages: /resolve-alpn@1.2.1: resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + dev: false /resolve-cwd@3.0.0: resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} @@ -19557,6 +19574,7 @@ packages: engines: {node: '>=14.16'} dependencies: lowercase-keys: 3.0.0 + dev: false /restore-cursor@4.0.0: resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} From 1246ad6fb7ed7bc08f6dc768776b82eab68237d4 Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Fri, 29 Mar 2024 11:15:49 +0800 Subject: [PATCH 2/4] refactor: remove node-fetch --- packages/integration-tests/jest.setup.js | 2 - packages/integration-tests/package.json | 1 - .../src/include.d/node-fetch.d.ts | 4 -- .../tests/api/oidc/get-access-token.test.ts | 1 - pnpm-lock.yaml | 42 ------------------- 5 files changed, 50 deletions(-) delete mode 100644 packages/integration-tests/src/include.d/node-fetch.d.ts diff --git a/packages/integration-tests/jest.setup.js b/packages/integration-tests/jest.setup.js index f85fe37425e..38ea7b6caa4 100644 --- a/packages/integration-tests/jest.setup.js +++ b/packages/integration-tests/jest.setup.js @@ -1,6 +1,5 @@ import dotenv from 'dotenv'; import { setDefaultOptions } from 'expect-puppeteer'; -import fetch from 'node-fetch'; import { TextDecoder, TextEncoder } from 'text-encoder'; const { jest } = import.meta; @@ -8,7 +7,6 @@ const { jest } = import.meta; dotenv.config(); /* eslint-disable @silverhand/fp/no-mutation */ -global.fetch = fetch; global.TextDecoder = TextDecoder; global.TextEncoder = TextEncoder; /* eslint-enable @silverhand/fp/no-mutation */ diff --git a/packages/integration-tests/package.json b/packages/integration-tests/package.json index b37a2a824e9..1f21f309ed0 100644 --- a/packages/integration-tests/package.json +++ b/packages/integration-tests/package.json @@ -43,7 +43,6 @@ "jest-puppeteer": "^10.0.1", "jose": "^5.0.0", "ky": "^1.2.3", - "node-fetch": "^3.3.0", "openapi-schema-validator": "^12.1.3", "openapi-types": "^12.1.3", "prettier": "^3.0.0", diff --git a/packages/integration-tests/src/include.d/node-fetch.d.ts b/packages/integration-tests/src/include.d/node-fetch.d.ts deleted file mode 100644 index dd1a8efbe98..00000000000 --- a/packages/integration-tests/src/include.d/node-fetch.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module 'node-fetch' { - const nodeFetch: typeof fetch; - export = nodeFetch; -} diff --git a/packages/integration-tests/src/tests/api/oidc/get-access-token.test.ts b/packages/integration-tests/src/tests/api/oidc/get-access-token.test.ts index e91a5012e81..63da8bb4f22 100644 --- a/packages/integration-tests/src/tests/api/oidc/get-access-token.test.ts +++ b/packages/integration-tests/src/tests/api/oidc/get-access-token.test.ts @@ -4,7 +4,6 @@ import { fetchTokenByRefreshToken } from '@logto/js'; import { InteractionEvent, type Resource, RoleType } from '@logto/schemas'; import { assert } from '@silverhand/essentials'; import { createRemoteJWKSet, jwtVerify } from 'jose'; -import fetch from 'node-fetch'; import { createResource, deleteResource, deleteUser, putInteraction } from '#src/api/index.js'; import { assignUsersToRole, createRole, deleteRole } from '#src/api/role.js'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 229f1928f3e..7748494e148 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3682,9 +3682,6 @@ importers: ky: specifier: ^1.2.3 version: 1.2.3 - node-fetch: - specifier: ^3.3.0 - version: 3.3.0 openapi-schema-validator: specifier: ^12.1.3 version: 12.1.3 @@ -12173,11 +12170,6 @@ packages: engines: {node: '>=12'} dev: true - /data-uri-to-buffer@4.0.0: - resolution: {integrity: sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==} - engines: {node: '>= 12'} - dev: true - /data-uri-to-buffer@5.0.1: resolution: {integrity: sha512-a9l6T1qqDogvvnw0nKlfZzqsyikEBZBClF39V3TFoKhDtGBqHu2HkuomJc02j5zft8zrUaXEuoicLeW54RkzPg==} engines: {node: '>= 14'} @@ -13513,14 +13505,6 @@ packages: pend: 1.2.0 dev: true - /fetch-blob@3.2.0: - resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} - engines: {node: ^12.20 || >= 14.13} - dependencies: - node-domexception: 1.0.0 - web-streams-polyfill: 3.2.1 - dev: true - /figures@5.0.0: resolution: {integrity: sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==} engines: {node: '>=14'} @@ -13695,13 +13679,6 @@ packages: engines: {node: '>=0.4.x'} dev: true - /formdata-polyfill@4.0.10: - resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} - engines: {node: '>=12.20.0'} - dependencies: - fetch-blob: 3.2.0 - dev: true - /formidable@2.0.1: resolution: {integrity: sha512-rjTMNbp2BpfQShhFbR3Ruk3qk2y9jKpvMW78nJgx8QKtxjDVrwbZG+wvDOmVbifHyOUOQJXxqEy6r0faRrPzTQ==} dependencies: @@ -17455,11 +17432,6 @@ packages: resolution: {integrity: sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==} dev: true - /node-domexception@1.0.0: - resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} - engines: {node: '>=10.5.0'} - dev: true - /node-fetch@2.6.7: resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} engines: {node: 4.x || >=6.0.0} @@ -17484,15 +17456,6 @@ packages: whatwg-url: 5.0.0 dev: false - /node-fetch@3.3.0: - resolution: {integrity: sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - data-uri-to-buffer: 4.0.0 - fetch-blob: 3.2.0 - formdata-polyfill: 4.0.10 - dev: true - /node-forge@1.3.1: resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} engines: {node: '>= 6.13.0'} @@ -21606,11 +21569,6 @@ packages: resolution: {integrity: sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==} dev: true - /web-streams-polyfill@3.2.1: - resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==} - engines: {node: '>= 8'} - dev: true - /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} dev: false From ee39885989ecca2783db21af5fc07db7535cfcb5 Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Fri, 29 Mar 2024 17:18:49 +0800 Subject: [PATCH 3/4] 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 | 22 ++++---- .../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 | 50 ++++++++----------- .../tests/experience/password-policy.test.ts | 5 +- packages/integration-tests/src/utils.ts | 8 +-- 64 files changed, 335 insertions(+), 323 deletions(-) diff --git a/packages/integration-tests/jest.setup.js b/packages/integration-tests/jest.setup.js index 38ea7b6caa4..ff4d9651c14 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 c6f1d2c9971..91ba032b37a 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 e2761d66c26..f7ccbaac498 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 e515f0e9b08..9d2011c5d72 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 139e2dd9f44..977b690e0f1 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 5be2873845b..16d8ce5dd47 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 e35f2242613..d91840c06e5 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 520e1d81d99..d83decf2451 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 a0dfe1f94b8..a744d8bae95 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 16f51a8e959..820bcc70fa7 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 781bf232b73..23b5f6f75eb 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 2f17b700344..9662010b8c9 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 d7fd80122d2..24966a87eda 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 84aaa7c7c3e..49103a856f8 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 ef7535c0fa4..cf574493654 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 d136ec7919c..6fe86b4620b 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 fe8675f811f..f896188335c 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 4f096e4aeb4..00cadf01d4e 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 e20cd0dfdd9..585072f2020 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 1a2a6d356e1..f6cfda52337 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 cf4c3c1bc8b..f5577a91e36 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 dc21d9f1ab6..4f018dab903 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 6dd637d4562..d4c3d180e67 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 48b7dc3a5dc..c9c80b20cb6 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 0100aa594f7..14b83e93143 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 ae9d028daf3..02f7f87188f 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 8348dfcc4b1..deebbf922d3 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 777fb849460..b25c85d3a41 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 536de204bd8..6be7b8a8aed 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 822a6ed5aa1..6417218e83f 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 ffd91ac30c0..5a3bb2ff16c 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 13f3cfb6e42..2e961e426ca 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 e1aad0a52e9..db4619779e1 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 94f7c04e955..761086c5613 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 dbb18fa9771..db091eaa021 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 c67b6ea8bae..5da4816238c 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 94182d8bf13..62b3d357214 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 3dcaacfc6b4..d8cd4759927 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 a3e58e75380..39b18c2cdb6 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 dc872ae0c32..fe66b572a6e 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 d11d8a1c5de..293b0e2d77e 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 19205d1778c..7d39e7a8bcc 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 cd31ad8de83..966044b3b53 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 b0acc703be3..a9fc8ff3e87 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 17bbc952552..7eca5f1a742 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 @@ -47,7 +47,7 @@ describe('social sign-in', () => { await clearConnectorsByTypes([ConnectorType.Social, ConnectorType.Email, ConnectorType.Sms]); }); - describe.only('register and sign-in', () => { + describe('register and sign-in', () => { const socialUserId = generateUserId(); it('register with social', async () => { @@ -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 }); @@ -137,7 +137,7 @@ describe('social sign-in', () => { const { primaryEmail, identities } = await getUser(uid); expect(primaryEmail).toBe(socialEmail); /* eslint-disable @typescript-eslint/no-unsafe-assignment */ - expect(identities[mockSocialConnectorTarget]).toStrictEqual({ + expect(identities[mockSocialConnectorTarget]).toMatchObject({ details: { email: expect.any(String), id: expect.any(String), @@ -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 1296a94df83..b9be50cf815 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 a9c06cd2e12..1171eb318f8 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 05aaea5199f..acd566c8d3c 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 59b1c541c3c..f4032002c48 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 33edafc927e..e33734c5f3e 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 50a8b260ce1..3b5febf6239 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 f487d0ad2ae..fee13d6ef1f 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 d84b0037e1b..9ce6b265886 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 e09163598fa..9314286131f 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 da5a64440bb..146f4997958 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 efb874be24e..72292542f9b 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 3c8f5ecfbc8..f4f1219655e 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 71cd6103f11..a046839d30c 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 d110a4701ea..ec369087ac2 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 9a8e46ec044..03315de7d43 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 6124dd2a724..22b17267889 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 44c9715c5d9..95719459c22 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,20 +68,17 @@ 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, - body: JSON.stringify({ - message: 'Invalid verification code.', - code: 'verification_code.code_mismatch', - }), - }, - }); + await expectRejects( + verifyVerificationCode({ email: emailForTestSendCode, verificationCode: 'any_string' }), + { + messageIncludes: 'Invalid verification code.', + code: 'verification_code.code_mismatch', + status: 400, + } + ); // Restore the email connector await setEmailConnector(); @@ -92,20 +89,17 @@ 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, - body: JSON.stringify({ - message: 'Invalid verification code.', - code: 'verification_code.code_mismatch', - }), - }, - }); + await expectRejects( + verifyVerificationCode({ phone: phoneForTestSendCode, verificationCode: 'any_string' }), + { + messageIncludes: 'Invalid verification code.', + code: 'verification_code.code_mismatch', + status: 400, + } + ); // Restore the SMS connector await setSmsConnector(); @@ -136,7 +130,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 +142,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 +154,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 8c819844a1e..b2ea78e895f 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 9b6cb559a0d..259aede9111 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'); From 0973506ffa67207082e7f5e0843c1149c7b58740 Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Fri, 29 Mar 2024 17:38:37 +0800 Subject: [PATCH 4/4] refactor: remove waitFor after each test --- packages/integration-tests/jest.setup.api.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/packages/integration-tests/jest.setup.api.js b/packages/integration-tests/jest.setup.api.js index 8f0fcd63c65..d31c2670de6 100644 --- a/packages/integration-tests/jest.setup.api.js +++ b/packages/integration-tests/jest.setup.api.js @@ -5,13 +5,3 @@ import { authedAdminTenantApi } from './lib/api/api.js'; await authedAdminTenantApi.patch('sign-in-exp', { json: { signInMode: 'SignInAndRegister' }, }); - -const waitFor = async (ms) => - new Promise((resolve) => { - setTimeout(resolve, ms); - }); - -global.afterEach(async () => { - // Try to mitigate the issue of "Socket hang up". See https://github.com/nodejs/node/issues/47130 - await waitFor(1); -});