mirror of
https://github.com/logto-io/logto.git
synced 2024-12-30 20:33:54 -05:00
chore(core,test): add status code guard for SIE, custom phrase and config APIs (#3813)
This commit is contained in:
parent
4d475bfa3b
commit
520e0c3df3
6 changed files with 39 additions and 11 deletions
|
@ -140,7 +140,7 @@ describe('customPhraseRoutes', () => {
|
||||||
const response = await customPhraseRequest
|
const response = await customPhraseRequest
|
||||||
.put(`/custom-phrases/${mockLanguageTag}`)
|
.put(`/custom-phrases/${mockLanguageTag}`)
|
||||||
.send(translation);
|
.send(translation);
|
||||||
expect(response.status).toEqual(400);
|
expect(response.status).toEqual(422);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call upsertCustomPhrase with specified language tag', async () => {
|
it('should call upsertCustomPhrase with specified language tag', async () => {
|
||||||
|
@ -183,9 +183,9 @@ describe('customPhraseRoutes', () => {
|
||||||
expect(response.status).toEqual(404);
|
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}`);
|
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 () => {
|
it('should return 400 status code when the language tag is invalid', async () => {
|
||||||
|
|
|
@ -48,7 +48,7 @@ export default function customPhraseRoutes<T extends AuthedRouter>(
|
||||||
koaGuard({
|
koaGuard({
|
||||||
params: object({ languageTag: languageTagGuard }),
|
params: object({ languageTag: languageTagGuard }),
|
||||||
response: CustomPhrases.guard,
|
response: CustomPhrases.guard,
|
||||||
status: [200],
|
status: [200, 404],
|
||||||
}),
|
}),
|
||||||
async (ctx, next) => {
|
async (ctx, next) => {
|
||||||
const {
|
const {
|
||||||
|
@ -67,7 +67,7 @@ export default function customPhraseRoutes<T extends AuthedRouter>(
|
||||||
params: object({ languageTag: languageTagGuard }),
|
params: object({ languageTag: languageTagGuard }),
|
||||||
body: translationGuard,
|
body: translationGuard,
|
||||||
response: CustomPhrases.guard,
|
response: CustomPhrases.guard,
|
||||||
status: [200],
|
status: [200, 422],
|
||||||
}),
|
}),
|
||||||
async (ctx, next) => {
|
async (ctx, next) => {
|
||||||
const {
|
const {
|
||||||
|
@ -79,7 +79,7 @@ export default function customPhraseRoutes<T extends AuthedRouter>(
|
||||||
|
|
||||||
assertThat(
|
assertThat(
|
||||||
isStrictlyPartial(resource.en.translation, translation),
|
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);
|
ctx.body = await upsertCustomPhrase(languageTag, translation);
|
||||||
|
@ -92,7 +92,7 @@ export default function customPhraseRoutes<T extends AuthedRouter>(
|
||||||
'/custom-phrases/:languageTag',
|
'/custom-phrases/:languageTag',
|
||||||
koaGuard({
|
koaGuard({
|
||||||
params: object({ languageTag: languageTagGuard }),
|
params: object({ languageTag: languageTagGuard }),
|
||||||
status: [204],
|
status: [204, 404, 409],
|
||||||
}),
|
}),
|
||||||
async (ctx, next) => {
|
async (ctx, next) => {
|
||||||
const {
|
const {
|
||||||
|
@ -106,6 +106,7 @@ export default function customPhraseRoutes<T extends AuthedRouter>(
|
||||||
if (fallbackLanguage === languageTag) {
|
if (fallbackLanguage === languageTag) {
|
||||||
throw new RequestError({
|
throw new RequestError({
|
||||||
code: 'localization.cannot_delete_default_language',
|
code: 'localization.cannot_delete_default_language',
|
||||||
|
status: 409,
|
||||||
languageTag,
|
languageTag,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ export default function logtoConfigRoutes<T extends AuthedRouter>(
|
||||||
|
|
||||||
router.get(
|
router.get(
|
||||||
'/configs/admin-console',
|
'/configs/admin-console',
|
||||||
koaGuard({ response: adminConsoleDataGuard, status: 200 }),
|
koaGuard({ response: adminConsoleDataGuard, status: [200, 404] }),
|
||||||
async (ctx, next) => {
|
async (ctx, next) => {
|
||||||
const { value } = await getAdminConsoleConfig();
|
const { value } = await getAdminConsoleConfig();
|
||||||
ctx.body = value;
|
ctx.body = value;
|
||||||
|
@ -25,7 +25,7 @@ export default function logtoConfigRoutes<T extends AuthedRouter>(
|
||||||
koaGuard({
|
koaGuard({
|
||||||
body: adminConsoleDataGuard.partial(),
|
body: adminConsoleDataGuard.partial(),
|
||||||
response: adminConsoleDataGuard,
|
response: adminConsoleDataGuard,
|
||||||
status: 200,
|
status: [200, 404],
|
||||||
}),
|
}),
|
||||||
async (ctx, next) => {
|
async (ctx, next) => {
|
||||||
const { value } = await updateAdminConsoleConfig(ctx.guard.body);
|
const { value } = await updateAdminConsoleConfig(ctx.guard.body);
|
||||||
|
|
|
@ -25,7 +25,7 @@ export default function signInExperiencesRoutes<T extends AuthedRouter>(
|
||||||
'/sign-in-exp',
|
'/sign-in-exp',
|
||||||
koaGuard({
|
koaGuard({
|
||||||
response: SignInExperiences.guard,
|
response: SignInExperiences.guard,
|
||||||
status: [200],
|
status: [200, 404],
|
||||||
}),
|
}),
|
||||||
async (ctx, next) => {
|
async (ctx, next) => {
|
||||||
ctx.body = await findDefaultSignInExperience();
|
ctx.body = await findDefaultSignInExperience();
|
||||||
|
@ -48,7 +48,7 @@ export default function signInExperiencesRoutes<T extends AuthedRouter>(
|
||||||
)
|
)
|
||||||
.partial(),
|
.partial(),
|
||||||
response: SignInExperiences.guard,
|
response: SignInExperiences.guard,
|
||||||
status: [200],
|
status: [200, 400, 404, 422],
|
||||||
}),
|
}),
|
||||||
async (ctx, next) => {
|
async (ctx, next) => {
|
||||||
const {
|
const {
|
||||||
|
|
|
@ -60,6 +60,12 @@ describe('custom-phrase flow', () => {
|
||||||
expect(zhTranslationNew).toEqual(mockZhTranslationUpdated);
|
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 () => {
|
it('failed to get a custom phrase with invalid language tag (zh-ZH)', async () => {
|
||||||
await expect(getCustomPhrase('zh-ZH')).rejects.toThrow(HTTPError);
|
await expect(getCustomPhrase('zh-ZH')).rejects.toThrow(HTTPError);
|
||||||
});
|
});
|
||||||
|
@ -86,6 +92,10 @@ describe('custom-phrase flow', () => {
|
||||||
await expect(deleteCustomPhrase('zh-TW')).rejects.toThrow(HTTPError);
|
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 () => {
|
it('delete all custom phrases', async () => {
|
||||||
await deleteCustomPhrase('zh');
|
await deleteCustomPhrase('zh');
|
||||||
await deleteCustomPhrase('en-US');
|
await deleteCustomPhrase('en-US');
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
|
import { SignInIdentifier } from '@logto/schemas';
|
||||||
|
|
||||||
import { getSignInExperience, updateSignInExperience } from '#src/api/index.js';
|
import { getSignInExperience, updateSignInExperience } from '#src/api/index.js';
|
||||||
|
import { createResponseWithCode } from '#src/helpers/admin-tenant.js';
|
||||||
|
|
||||||
describe('admin console sign-in experience', () => {
|
describe('admin console sign-in experience', () => {
|
||||||
it('should get sign-in experience successfully', async () => {
|
it('should get sign-in experience successfully', async () => {
|
||||||
|
@ -25,4 +28,18 @@ describe('admin console sign-in experience', () => {
|
||||||
const updatedSignInExperience = await updateSignInExperience(newSignInExperience);
|
const updatedSignInExperience = await updateSignInExperience(newSignInExperience);
|
||||||
expect(updatedSignInExperience).toMatchObject(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)
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue