mirror of
https://github.com/logto-io/logto.git
synced 2024-12-30 20:33:54 -05:00
Merge pull request #4645 from logto-io/gao-refactor-integration-test-apis
refactor(test): add ApiFactory for integration tests
This commit is contained in:
commit
d5a87623de
5 changed files with 92 additions and 118 deletions
29
packages/integration-tests/src/api/factory.ts
Normal file
29
packages/integration-tests/src/api/factory.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import { authedAdminApi } from './api.js';
|
||||||
|
|
||||||
|
export class ApiFactory<
|
||||||
|
Schema extends Record<string, unknown>,
|
||||||
|
PostData extends Record<string, unknown>,
|
||||||
|
PatchData extends Record<string, unknown> = Partial<PostData>,
|
||||||
|
> {
|
||||||
|
constructor(public readonly path: string) {}
|
||||||
|
|
||||||
|
async create(data: PostData): Promise<Schema> {
|
||||||
|
return authedAdminApi.post(this.path, { json: data }).json<Schema>();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getList(params?: URLSearchParams): Promise<Schema[]> {
|
||||||
|
return authedAdminApi.get(this.path + '?' + (params?.toString() ?? '')).json<Schema[]>();
|
||||||
|
}
|
||||||
|
|
||||||
|
async get(id: string): Promise<Schema> {
|
||||||
|
return authedAdminApi.get(this.path + '/' + id).json<Schema>();
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(id: string, data: PatchData): Promise<Schema> {
|
||||||
|
return authedAdminApi.patch(this.path + '/' + id, { json: data }).json<Schema>();
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(id: string): Promise<void> {
|
||||||
|
await authedAdminApi.delete(this.path + '/' + id);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,39 +1,15 @@
|
||||||
import { type OrganizationScope } from '@logto/schemas';
|
import { type OrganizationScope } from '@logto/schemas';
|
||||||
|
|
||||||
import { authedAdminApi } from './api.js';
|
import { ApiFactory } from './factory.js';
|
||||||
|
|
||||||
export const createOrganizationScope = async (name: string, description?: string) => {
|
class OrganizationScopeApi extends ApiFactory<
|
||||||
return authedAdminApi
|
OrganizationScope,
|
||||||
.post('organization-scopes', {
|
{ name: string; description?: string }
|
||||||
json: {
|
> {
|
||||||
name,
|
constructor() {
|
||||||
description,
|
super('organization-scopes');
|
||||||
},
|
}
|
||||||
})
|
}
|
||||||
.json<OrganizationScope>();
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getOrganizationScopes = async (params?: URLSearchParams) => {
|
/** API methods for operating organization template scopes. */
|
||||||
return authedAdminApi
|
export const scopeApi = new OrganizationScopeApi();
|
||||||
.get('organization-scopes?' + (params?.toString() ?? ''))
|
|
||||||
.json<OrganizationScope[]>();
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getOrganizationScope = async (id: string) => {
|
|
||||||
return authedAdminApi.get('organization-scopes/' + id).json<OrganizationScope>();
|
|
||||||
};
|
|
||||||
|
|
||||||
export const updateOrganizationScope = async (id: string, name: string, description?: string) => {
|
|
||||||
return authedAdminApi
|
|
||||||
.patch('organization-scopes/' + id, {
|
|
||||||
json: {
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.json<OrganizationScope>();
|
|
||||||
};
|
|
||||||
|
|
||||||
export const deleteOrganizationScope = async (id: string) => {
|
|
||||||
return authedAdminApi.delete('organization-scopes/' + id);
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,37 +1,12 @@
|
||||||
import { type Organization } from '@logto/schemas';
|
import { type Organization } from '@logto/schemas';
|
||||||
|
|
||||||
import { authedAdminApi } from './api.js';
|
import { ApiFactory } from './factory.js';
|
||||||
|
|
||||||
export const createOrganization = async (name: string, description?: string) => {
|
class OrganizationApi extends ApiFactory<Organization, { name: string; description?: string }> {
|
||||||
return authedAdminApi
|
constructor() {
|
||||||
.post('organizations', {
|
super('organizations');
|
||||||
json: {
|
}
|
||||||
name,
|
}
|
||||||
description,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.json<Organization>();
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getOrganizations = async (params?: URLSearchParams) => {
|
/** API methods for operating organizations. */
|
||||||
return authedAdminApi.get('organizations?' + (params?.toString() ?? '')).json<Organization[]>();
|
export const organizationApi = new OrganizationApi();
|
||||||
};
|
|
||||||
|
|
||||||
export const getOrganization = async (id: string) => {
|
|
||||||
return authedAdminApi.get('organizations/' + id).json<Organization>();
|
|
||||||
};
|
|
||||||
|
|
||||||
export const updateOrganization = async (id: string, name: string, description?: string) => {
|
|
||||||
return authedAdminApi
|
|
||||||
.patch('organizations/' + id, {
|
|
||||||
json: {
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.json<Organization>();
|
|
||||||
};
|
|
||||||
|
|
||||||
export const deleteOrganization = async (id: string) => {
|
|
||||||
return authedAdminApi.delete('organizations/' + id);
|
|
||||||
};
|
|
||||||
|
|
|
@ -4,21 +4,15 @@ import { generateStandardId } from '@logto/shared';
|
||||||
import { isKeyInObject } from '@silverhand/essentials';
|
import { isKeyInObject } from '@silverhand/essentials';
|
||||||
import { HTTPError } from 'got';
|
import { HTTPError } from 'got';
|
||||||
|
|
||||||
import {
|
import { scopeApi } from '#src/api/organization-scope.js';
|
||||||
createOrganizationScope,
|
|
||||||
getOrganizationScopes,
|
|
||||||
getOrganizationScope,
|
|
||||||
updateOrganizationScope,
|
|
||||||
deleteOrganizationScope,
|
|
||||||
} from '#src/api/organization-scope.js';
|
|
||||||
|
|
||||||
const randomId = () => generateStandardId(4);
|
const randomId = () => generateStandardId(4);
|
||||||
|
|
||||||
describe('organization scopes', () => {
|
describe('organization scopes', () => {
|
||||||
it('should fail if the name of the new organization scope already exists', async () => {
|
it('should fail if the name of the new organization scope already exists', async () => {
|
||||||
const name = 'test' + randomId();
|
const name = 'test' + randomId();
|
||||||
await createOrganizationScope(name);
|
await scopeApi.create({ name });
|
||||||
const response = await createOrganizationScope(name).catch((error: unknown) => error);
|
const response = await scopeApi.create({ name }).catch((error: unknown) => error);
|
||||||
|
|
||||||
assert(response instanceof HTTPError);
|
assert(response instanceof HTTPError);
|
||||||
|
|
||||||
|
@ -30,9 +24,9 @@ describe('organization scopes', () => {
|
||||||
|
|
||||||
it('should get organization scopes successfully', async () => {
|
it('should get organization scopes successfully', async () => {
|
||||||
const [name1, name2] = ['test' + randomId(), 'test' + randomId()];
|
const [name1, name2] = ['test' + randomId(), 'test' + randomId()];
|
||||||
await createOrganizationScope(name1, 'A test organization scope.');
|
await scopeApi.create({ name: name1, description: 'A test organization scope.' });
|
||||||
await createOrganizationScope(name2);
|
await scopeApi.create({ name: name2 });
|
||||||
const scopes = await getOrganizationScopes();
|
const scopes = await scopeApi.getList();
|
||||||
|
|
||||||
expect(scopes).toContainEqual(
|
expect(scopes).toContainEqual(
|
||||||
expect.objectContaining({ name: name1, description: 'A test organization scope.' })
|
expect.objectContaining({ name: name1, description: 'A test organization scope.' })
|
||||||
|
@ -43,13 +37,13 @@ describe('organization scopes', () => {
|
||||||
it('should get organization scopes with pagination', async () => {
|
it('should get organization scopes with pagination', async () => {
|
||||||
// Add 20 scopes to exceed the default page size
|
// Add 20 scopes to exceed the default page size
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
Array.from({ length: 30 }).map(async () => createOrganizationScope('test' + randomId()))
|
Array.from({ length: 30 }).map(async () => scopeApi.create({ name: 'test' + randomId() }))
|
||||||
);
|
);
|
||||||
|
|
||||||
const scopes = await getOrganizationScopes();
|
const scopes = await scopeApi.getList();
|
||||||
expect(scopes).toHaveLength(20);
|
expect(scopes).toHaveLength(20);
|
||||||
|
|
||||||
const scopes2 = await getOrganizationScopes(
|
const scopes2 = await scopeApi.getList(
|
||||||
new URLSearchParams({
|
new URLSearchParams({
|
||||||
page: '2',
|
page: '2',
|
||||||
page_size: '10',
|
page_size: '10',
|
||||||
|
@ -61,22 +55,25 @@ describe('organization scopes', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to create and get organization scopes by id', async () => {
|
it('should be able to create and get organization scopes by id', async () => {
|
||||||
const createdScope = await createOrganizationScope('test' + randomId());
|
const createdScope = await scopeApi.create({ name: 'test' + randomId() });
|
||||||
const scope = await getOrganizationScope(createdScope.id);
|
const scope = await scopeApi.get(createdScope.id);
|
||||||
|
|
||||||
expect(scope).toStrictEqual(createdScope);
|
expect(scope).toStrictEqual(createdScope);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fail when try to get an organization scope that does not exist', async () => {
|
it('should fail when try to get an organization scope that does not exist', async () => {
|
||||||
const response = await getOrganizationScope('0').catch((error: unknown) => error);
|
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.statusCode).toBe(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to update organization scope', async () => {
|
it('should be able to update organization scope', async () => {
|
||||||
const createdScope = await createOrganizationScope('test' + randomId());
|
const createdScope = await scopeApi.create({ name: 'test' + randomId() });
|
||||||
const newName = 'test' + randomId();
|
const newName = 'test' + randomId();
|
||||||
const scope = await updateOrganizationScope(createdScope.id, newName, 'test description.');
|
const scope = await scopeApi.update(createdScope.id, {
|
||||||
|
name: newName,
|
||||||
|
description: 'test description.',
|
||||||
|
});
|
||||||
expect(scope).toStrictEqual({
|
expect(scope).toStrictEqual({
|
||||||
...createdScope,
|
...createdScope,
|
||||||
name: newName,
|
name: newName,
|
||||||
|
@ -85,14 +82,14 @@ describe('organization scopes', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to delete organization scope', async () => {
|
it('should be able to delete organization scope', async () => {
|
||||||
const createdScope = await createOrganizationScope('test' + randomId());
|
const createdScope = await scopeApi.create({ name: 'test' + randomId() });
|
||||||
await deleteOrganizationScope(createdScope.id);
|
await scopeApi.delete(createdScope.id);
|
||||||
const response = await getOrganizationScope(createdScope.id).catch((error: unknown) => error);
|
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.statusCode).toBe(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fail when try to delete an organization scope that does not exist', async () => {
|
it('should fail when try to delete an organization scope that does not exist', async () => {
|
||||||
const response = await deleteOrganizationScope('0').catch((error: unknown) => error);
|
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.statusCode).toBe(404);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,18 +1,12 @@
|
||||||
import { HTTPError } from 'got';
|
import { HTTPError } from 'got';
|
||||||
|
|
||||||
import {
|
import { organizationApi } from '#src/api/organization.js';
|
||||||
createOrganization,
|
|
||||||
deleteOrganization,
|
|
||||||
getOrganization,
|
|
||||||
getOrganizations,
|
|
||||||
updateOrganization,
|
|
||||||
} from '#src/api/organization.js';
|
|
||||||
|
|
||||||
describe('organizations', () => {
|
describe('organizations', () => {
|
||||||
it('should get organizations successfully', async () => {
|
it('should get organizations successfully', async () => {
|
||||||
await createOrganization('test', 'A test organization.');
|
await organizationApi.create({ name: 'test', description: 'A test organization.' });
|
||||||
await createOrganization('test2');
|
await organizationApi.create({ name: 'test2' });
|
||||||
const organizations = await getOrganizations();
|
const organizations = await organizationApi.getList();
|
||||||
|
|
||||||
expect(organizations).toContainEqual(
|
expect(organizations).toContainEqual(
|
||||||
expect.objectContaining({ name: 'test', description: 'A test organization.' })
|
expect.objectContaining({ name: 'test', description: 'A test organization.' })
|
||||||
|
@ -24,12 +18,14 @@ describe('organizations', () => {
|
||||||
|
|
||||||
it('should get organizations with pagination', async () => {
|
it('should get organizations with pagination', async () => {
|
||||||
// Add 20 organizations to exceed the default page size
|
// Add 20 organizations to exceed the default page size
|
||||||
await Promise.all(Array.from({ length: 30 }).map(async () => createOrganization('test')));
|
await Promise.all(
|
||||||
|
Array.from({ length: 30 }).map(async () => organizationApi.create({ name: 'test' }))
|
||||||
|
);
|
||||||
|
|
||||||
const organizations = await getOrganizations();
|
const organizations = await organizationApi.getList();
|
||||||
expect(organizations).toHaveLength(20);
|
expect(organizations).toHaveLength(20);
|
||||||
|
|
||||||
const organizations2 = await getOrganizations(
|
const organizations2 = await organizationApi.getList(
|
||||||
new URLSearchParams({
|
new URLSearchParams({
|
||||||
page: '2',
|
page: '2',
|
||||||
page_size: '10',
|
page_size: '10',
|
||||||
|
@ -41,25 +37,24 @@ describe('organizations', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to create and get organizations by id', async () => {
|
it('should be able to create and get organizations by id', async () => {
|
||||||
const createdOrganization = await createOrganization('test');
|
const createdOrganization = await organizationApi.create({ name: 'test' });
|
||||||
const organization = await getOrganization(createdOrganization.id);
|
const organization = await organizationApi.get(createdOrganization.id);
|
||||||
|
|
||||||
expect(organization).toStrictEqual(createdOrganization);
|
expect(organization).toStrictEqual(createdOrganization);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fail when try to get an organization that does not exist', async () => {
|
it('should fail when try to get an organization that does not exist', async () => {
|
||||||
const response = await getOrganization('0').catch((error: unknown) => error);
|
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.statusCode).toBe(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to update organization', async () => {
|
it('should be able to update organization', async () => {
|
||||||
const createdOrganization = await createOrganization('test');
|
const createdOrganization = await organizationApi.create({ name: 'test' });
|
||||||
const organization = await updateOrganization(
|
const organization = await organizationApi.update(createdOrganization.id, {
|
||||||
createdOrganization.id,
|
name: 'test2',
|
||||||
'test2',
|
description: 'test description.',
|
||||||
'test description.'
|
});
|
||||||
);
|
|
||||||
expect(organization).toStrictEqual({
|
expect(organization).toStrictEqual({
|
||||||
...createdOrganization,
|
...createdOrganization,
|
||||||
name: 'test2',
|
name: 'test2',
|
||||||
|
@ -68,14 +63,16 @@ describe('organizations', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to delete organization', async () => {
|
it('should be able to delete organization', async () => {
|
||||||
const createdOrganization = await createOrganization('test');
|
const createdOrganization = await organizationApi.create({ name: 'test' });
|
||||||
await deleteOrganization(createdOrganization.id);
|
await organizationApi.delete(createdOrganization.id);
|
||||||
const response = await getOrganization(createdOrganization.id).catch((error: unknown) => error);
|
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.statusCode).toBe(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fail when try to delete an organization that does not exist', async () => {
|
it('should fail when try to delete an organization that does not exist', async () => {
|
||||||
const response = await deleteOrganization('0').catch((error: unknown) => error);
|
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.statusCode).toBe(404);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue