diff --git a/packages/core/src/routes/custom-phrase.test.ts b/packages/core/src/routes/custom-phrase.test.ts index fd8347849..6e6f30e11 100644 --- a/packages/core/src/routes/custom-phrase.test.ts +++ b/packages/core/src/routes/custom-phrase.test.ts @@ -140,7 +140,7 @@ describe('customPhraseRoutes', () => { const response = await customPhraseRequest .put(`/custom-phrases/${mockLanguageTag}`) .send(translation); - expect(response.status).toEqual(400); + expect(response.status).toEqual(422); }); it('should call upsertCustomPhrase with specified language tag', async () => { @@ -183,9 +183,9 @@ describe('customPhraseRoutes', () => { expect(response.status).toEqual(404); }); - it('should return 400 status code when specified custom phrase is used as fallback language in sign-in experience', async () => { + it('should return 409 status code when specified custom phrase is used as fallback language in sign-in experience', async () => { const response = await customPhraseRequest.delete(`/custom-phrases/${mockFallbackLanguage}`); - expect(response.status).toEqual(400); + expect(response.status).toEqual(409); }); it('should return 400 status code when the language tag is invalid', async () => { diff --git a/packages/core/src/routes/custom-phrase.ts b/packages/core/src/routes/custom-phrase.ts index d1c4dcc72..cf79afdff 100644 --- a/packages/core/src/routes/custom-phrase.ts +++ b/packages/core/src/routes/custom-phrase.ts @@ -48,7 +48,7 @@ export default function customPhraseRoutes( koaGuard({ params: object({ languageTag: languageTagGuard }), response: CustomPhrases.guard, - status: [200], + status: [200, 404], }), async (ctx, next) => { const { @@ -67,7 +67,7 @@ export default function customPhraseRoutes( params: object({ languageTag: languageTagGuard }), body: translationGuard, response: CustomPhrases.guard, - status: [200], + status: [200, 422], }), async (ctx, next) => { const { @@ -79,7 +79,7 @@ export default function customPhraseRoutes( assertThat( isStrictlyPartial(resource.en.translation, translation), - new RequestError('localization.invalid_translation_structure') + new RequestError({ code: 'localization.invalid_translation_structure', status: 422 }) ); ctx.body = await upsertCustomPhrase(languageTag, translation); @@ -92,7 +92,7 @@ export default function customPhraseRoutes( '/custom-phrases/:languageTag', koaGuard({ params: object({ languageTag: languageTagGuard }), - status: [204], + status: [204, 404, 409], }), async (ctx, next) => { const { @@ -106,6 +106,7 @@ export default function customPhraseRoutes( if (fallbackLanguage === languageTag) { throw new RequestError({ code: 'localization.cannot_delete_default_language', + status: 409, languageTag, }); } diff --git a/packages/core/src/routes/logto-config.ts b/packages/core/src/routes/logto-config.ts index 7f6bbc3b0..8fc13547d 100644 --- a/packages/core/src/routes/logto-config.ts +++ b/packages/core/src/routes/logto-config.ts @@ -11,7 +11,7 @@ export default function logtoConfigRoutes( router.get( '/configs/admin-console', - koaGuard({ response: adminConsoleDataGuard, status: 200 }), + koaGuard({ response: adminConsoleDataGuard, status: [200, 404] }), async (ctx, next) => { const { value } = await getAdminConsoleConfig(); ctx.body = value; @@ -25,7 +25,7 @@ export default function logtoConfigRoutes( koaGuard({ body: adminConsoleDataGuard.partial(), response: adminConsoleDataGuard, - status: 200, + status: [200, 404], }), async (ctx, next) => { const { value } = await updateAdminConsoleConfig(ctx.guard.body); diff --git a/packages/core/src/routes/sign-in-experience/index.ts b/packages/core/src/routes/sign-in-experience/index.ts index a7cdbfb21..068c61acb 100644 --- a/packages/core/src/routes/sign-in-experience/index.ts +++ b/packages/core/src/routes/sign-in-experience/index.ts @@ -25,7 +25,7 @@ export default function signInExperiencesRoutes( '/sign-in-exp', koaGuard({ response: SignInExperiences.guard, - status: [200], + status: [200, 404], }), async (ctx, next) => { ctx.body = await findDefaultSignInExperience(); @@ -48,7 +48,7 @@ export default function signInExperiencesRoutes( ) .partial(), response: SignInExperiences.guard, - status: [200], + status: [200, 400, 404, 422], }), async (ctx, next) => { const { 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 133605f7b..be8b9c244 100644 --- a/packages/integration-tests/src/tests/api/custom-phrase.test.ts +++ b/packages/integration-tests/src/tests/api/custom-phrase.test.ts @@ -60,6 +60,12 @@ describe('custom-phrase flow', () => { expect(zhTranslationNew).toEqual(mockZhTranslationUpdated); }); + it('fail to update an existing custom phrase with invalid translation keys', async () => { + await expect( + createOrUpdateCustomPhrase('zh', { ...mockZhTranslationUpdated, invalidKey: 'invalid value' }) + ).rejects.toThrow(HTTPError); + }); + it('failed to get a custom phrase with invalid language tag (zh-ZH)', async () => { await expect(getCustomPhrase('zh-ZH')).rejects.toThrow(HTTPError); }); @@ -86,6 +92,10 @@ describe('custom-phrase flow', () => { await expect(deleteCustomPhrase('zh-TW')).rejects.toThrow(HTTPError); }); + it('fail to delete a custom phrase which has been set as fallback language', async () => { + await expect(deleteCustomPhrase('en')).rejects.toThrow(HTTPError); + }); + it('delete all custom phrases', async () => { await deleteCustomPhrase('zh'); await deleteCustomPhrase('en-US'); 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 7a55f4bf8..06021e38f 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 @@ -1,4 +1,7 @@ +import { SignInIdentifier } from '@logto/schemas'; + import { getSignInExperience, updateSignInExperience } from '#src/api/index.js'; +import { createResponseWithCode } from '#src/helpers/admin-tenant.js'; describe('admin console sign-in experience', () => { it('should get sign-in experience successfully', async () => { @@ -25,4 +28,18 @@ describe('admin console sign-in experience', () => { const updatedSignInExperience = await updateSignInExperience(newSignInExperience); expect(updatedSignInExperience).toMatchObject(newSignInExperience); }); + + it('throw 400 when fail to validate SIE', async () => { + const newSignInExperience = { + signUp: { + identifiers: [SignInIdentifier.Username], + password: false, + verify: false, + }, + }; + + await expect(updateSignInExperience(newSignInExperience)).rejects.toMatchObject( + createResponseWithCode(400) + ); + }); });