mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
chore: add response guard and integration tests for application APIs (#3771)
This commit is contained in:
parent
d2e6e1fd5b
commit
0e46ddacca
4 changed files with 47 additions and 16 deletions
|
@ -169,6 +169,7 @@ describe('application route', () => {
|
|||
'http://127.0.0.1',
|
||||
'http://localhost:3002',
|
||||
],
|
||||
postLogoutRedirectUris: [],
|
||||
},
|
||||
})
|
||||
).resolves.toHaveProperty('status', 200);
|
||||
|
@ -179,6 +180,7 @@ describe('application route', () => {
|
|||
applicationRequest.patch('/applications/foo').send({
|
||||
oidcClientMetadata: {
|
||||
redirectUris: ['www.example.com', 'com.example://callback'],
|
||||
postLogoutRedirectUris: [],
|
||||
},
|
||||
})
|
||||
).resolves.toHaveProperty('status', 400);
|
||||
|
@ -194,6 +196,7 @@ describe('application route', () => {
|
|||
'com.example://callback',
|
||||
'io.logto://Abc123',
|
||||
],
|
||||
postLogoutRedirectUris: [],
|
||||
},
|
||||
})
|
||||
).resolves.toHaveProperty('status', 200);
|
||||
|
@ -205,6 +208,7 @@ describe('application route', () => {
|
|||
type: ApplicationType.Native,
|
||||
oidcClientMetadata: {
|
||||
redirectUris: ['https://www.example.com', 'com.example/callback'],
|
||||
postLogoutRedirectUris: [],
|
||||
},
|
||||
})
|
||||
).resolves.toHaveProperty('status', 400);
|
||||
|
|
|
@ -35,20 +35,25 @@ export default function applicationRoutes<T extends AuthedRouter>(
|
|||
queries.applicationsRoles;
|
||||
const { findRoleByRoleName } = queries.roles;
|
||||
|
||||
router.get('/applications', koaPagination(), async (ctx, next) => {
|
||||
const { limit, offset } = ctx.pagination;
|
||||
router.get(
|
||||
'/applications',
|
||||
koaPagination(),
|
||||
koaGuard({ response: z.array(Applications.guard), status: 200 }),
|
||||
async (ctx, next) => {
|
||||
const { limit, offset } = ctx.pagination;
|
||||
|
||||
const [{ count }, applications] = await Promise.all([
|
||||
findTotalNumberOfApplications(),
|
||||
findAllApplications(limit, offset),
|
||||
]);
|
||||
const [{ count }, applications] = await Promise.all([
|
||||
findTotalNumberOfApplications(),
|
||||
findAllApplications(limit, offset),
|
||||
]);
|
||||
|
||||
// Return totalCount to pagination middleware
|
||||
ctx.pagination.totalCount = count;
|
||||
ctx.body = applications;
|
||||
// Return totalCount to pagination middleware
|
||||
ctx.pagination.totalCount = count;
|
||||
ctx.body = applications;
|
||||
|
||||
return next();
|
||||
});
|
||||
return next();
|
||||
}
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/applications',
|
||||
|
@ -57,6 +62,8 @@ export default function applicationRoutes<T extends AuthedRouter>(
|
|||
.omit({ id: true, createdAt: true })
|
||||
.partial()
|
||||
.merge(Applications.createGuard.pick({ name: true, type: true })),
|
||||
response: Applications.guard,
|
||||
status: [200, 422],
|
||||
}),
|
||||
async (ctx, next) => {
|
||||
const { oidcClientMetadata, ...rest } = ctx.guard.body;
|
||||
|
@ -77,6 +84,7 @@ export default function applicationRoutes<T extends AuthedRouter>(
|
|||
koaGuard({
|
||||
params: object({ id: string().min(1) }),
|
||||
response: Applications.guard.merge(z.object({ isAdmin: z.boolean() })),
|
||||
status: [200, 404],
|
||||
}),
|
||||
async (ctx, next) => {
|
||||
const {
|
||||
|
@ -114,6 +122,8 @@ export default function applicationRoutes<T extends AuthedRouter>(
|
|||
isAdmin: boolean().optional(),
|
||||
})
|
||||
),
|
||||
response: Applications.guard,
|
||||
status: [200, 404, 500],
|
||||
}),
|
||||
async (ctx, next) => {
|
||||
const {
|
||||
|
@ -135,7 +145,11 @@ export default function applicationRoutes<T extends AuthedRouter>(
|
|||
|
||||
assertThat(
|
||||
internalAdminRole,
|
||||
new RequestError('entity.not_exists', { name: InternalRole.Admin })
|
||||
new RequestError({
|
||||
code: 'entity.not_exists',
|
||||
status: 500,
|
||||
data: { name: InternalRole.Admin },
|
||||
})
|
||||
);
|
||||
|
||||
if (isAdmin && !usedToBeAdmin) {
|
||||
|
@ -155,7 +169,11 @@ export default function applicationRoutes<T extends AuthedRouter>(
|
|||
|
||||
router.delete(
|
||||
'/applications/:id',
|
||||
koaGuard({ params: object({ id: string().min(1) }) }),
|
||||
koaGuard({
|
||||
params: object({ id: string().min(1) }),
|
||||
response: z.undefined(),
|
||||
status: [204, 404],
|
||||
}),
|
||||
async (ctx, next) => {
|
||||
const { id } = ctx.guard.params;
|
||||
// Note: will need delete cascade when application is joint with other tables
|
||||
|
|
|
@ -17,6 +17,8 @@ export const createApplication = async (name: string, type: ApplicationType) =>
|
|||
})
|
||||
.json<Application>();
|
||||
|
||||
export const getApplications = async () => authedAdminApi.get('applications').json<Application[]>();
|
||||
|
||||
export const getApplication = async (applicationId: string) =>
|
||||
authedAdminApi.get(`applications/${applicationId}`).json<Application>();
|
||||
|
||||
|
|
|
@ -6,13 +6,13 @@ import {
|
|||
getApplication,
|
||||
updateApplication,
|
||||
deleteApplication,
|
||||
getApplications,
|
||||
} from '#src/api/index.js';
|
||||
|
||||
describe('admin console application', () => {
|
||||
it('should create application successfully', async () => {
|
||||
const applicationName = 'test-create-app';
|
||||
const applicationType = ApplicationType.SPA;
|
||||
|
||||
const application = await createApplication(applicationName, applicationType);
|
||||
|
||||
expect(application.name).toBe(applicationName);
|
||||
|
@ -25,7 +25,7 @@ describe('admin console application', () => {
|
|||
});
|
||||
|
||||
it('should update application details successfully', async () => {
|
||||
const application = await createApplication('test-update-app', ApplicationType.SPA);
|
||||
const application = await createApplication('test-update-app', ApplicationType.Traditional);
|
||||
|
||||
const newApplicationDescription = `new_${application.description ?? ''}`;
|
||||
|
||||
|
@ -46,8 +46,15 @@ describe('admin console application', () => {
|
|||
expect(updatedApplication.oidcClientMetadata.redirectUris).toEqual(newRedirectUris);
|
||||
});
|
||||
|
||||
it('should fetch all applications created above', async () => {
|
||||
const applications = await getApplications();
|
||||
const applicationNames = applications.map(({ name }) => name);
|
||||
expect(applicationNames).toContain('test-create-app');
|
||||
expect(applicationNames).toContain('test-update-app');
|
||||
});
|
||||
|
||||
it('should delete application successfully', async () => {
|
||||
const application = await createApplication('test-delete-app', ApplicationType.SPA);
|
||||
const application = await createApplication('test-delete-app', ApplicationType.Native);
|
||||
|
||||
await deleteApplication(application.id);
|
||||
|
||||
|
|
Loading…
Reference in a new issue