[1/n]: Migrate deleteOne Rest API to use TwentyORM directly (#9784)
# This PR - Addressing #3644 - Migrates the `DELETE /rest/*` endpoint to use TwentyORM - Factorizes common middleware logic into a common module --------- Co-authored-by: martmull <martmull@hotmail.fr>
This commit is contained in:
@ -0,0 +1,4 @@
|
||||
export const PERSON_1_ID = '777a8457-eb2d-40ac-a707-551b615b6987';
|
||||
export const PERSON_2_ID = '777a8457-eb2d-40ac-a707-551b615b6988';
|
||||
export const PERSON_3_ID = '777a8457-eb2d-40ac-a707-551b615b6989';
|
||||
export const FAKE_PERSON_ID = '777a8457-eb2d-40ac-a707-551b615b6990';
|
||||
@ -0,0 +1,14 @@
|
||||
export const PERSON_GQL_FIELDS = `
|
||||
id
|
||||
city
|
||||
jobTitle
|
||||
avatarUrl
|
||||
intro
|
||||
searchVector
|
||||
name {
|
||||
firstName
|
||||
lastName
|
||||
}
|
||||
createdAt
|
||||
deletedAt
|
||||
`;
|
||||
@ -1,3 +1,9 @@
|
||||
import {
|
||||
PERSON_1_ID,
|
||||
PERSON_2_ID,
|
||||
PERSON_3_ID,
|
||||
} from 'test/integration/constants/mock-person-ids.constants';
|
||||
import { PERSON_GQL_FIELDS } from 'test/integration/constants/person-gql-fields.constants';
|
||||
import { createManyOperationFactory } from 'test/integration/graphql/utils/create-many-operation-factory.util';
|
||||
import { createOneOperationFactory } from 'test/integration/graphql/utils/create-one-operation-factory.util';
|
||||
import { deleteManyOperationFactory } from 'test/integration/graphql/utils/delete-many-operation-factory.util';
|
||||
@ -11,25 +17,6 @@ import { updateManyOperationFactory } from 'test/integration/graphql/utils/updat
|
||||
import { updateOneOperationFactory } from 'test/integration/graphql/utils/update-one-operation-factory.util';
|
||||
import { generateRecordName } from 'test/integration/utils/generate-record-name';
|
||||
|
||||
const PERSON_1_ID = '777a8457-eb2d-40ac-a707-551b615b6987';
|
||||
const PERSON_2_ID = '777a8457-eb2d-40ac-a707-551b615b6988';
|
||||
const PERSON_3_ID = '777a8457-eb2d-40ac-a707-551b615b6989';
|
||||
|
||||
const PERSON_GQL_FIELDS = `
|
||||
id
|
||||
city
|
||||
jobTitle
|
||||
avatarUrl
|
||||
intro
|
||||
searchVector
|
||||
name {
|
||||
firstName
|
||||
lastName
|
||||
}
|
||||
createdAt
|
||||
deletedAt
|
||||
`;
|
||||
|
||||
describe('people resolvers (integration)', () => {
|
||||
it('1. should create and return people', async () => {
|
||||
const personCity1 = generateRecordName(PERSON_1_ID);
|
||||
|
||||
@ -0,0 +1,107 @@
|
||||
import {
|
||||
FAKE_PERSON_ID,
|
||||
PERSON_1_ID,
|
||||
} from 'test/integration/constants/mock-person-ids.constants';
|
||||
import { PERSON_GQL_FIELDS } from 'test/integration/constants/person-gql-fields.constants';
|
||||
import { createManyOperationFactory } from 'test/integration/graphql/utils/create-many-operation-factory.util';
|
||||
import { findOneOperationFactory } from 'test/integration/graphql/utils/find-one-operation-factory.util';
|
||||
import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util';
|
||||
import { makeRestAPIRequest } from 'test/integration/rest/utils/make-rest-api-request.util';
|
||||
import { generateRecordName } from 'test/integration/utils/generate-record-name';
|
||||
|
||||
describe('Core REST API Delete One endpoint', () => {
|
||||
let people: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
const personCity1 = generateRecordName(PERSON_1_ID);
|
||||
|
||||
// TODO: move this creation to REST API when the POST method is migrated
|
||||
const graphqlOperation = createManyOperationFactory({
|
||||
objectMetadataSingularName: 'person',
|
||||
objectMetadataPluralName: 'people',
|
||||
gqlFields: PERSON_GQL_FIELDS,
|
||||
data: [
|
||||
{
|
||||
id: PERSON_1_ID,
|
||||
city: personCity1,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const response = await makeGraphqlAPIRequest(graphqlOperation);
|
||||
|
||||
people = response.body.data.createPeople;
|
||||
expect(people.length).toBe(1);
|
||||
expect(people[0].id).toBe(PERSON_1_ID);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// TODO: move this creation to REST API when the GET method is migrated
|
||||
const graphqlOperation = findOneOperationFactory({
|
||||
objectMetadataSingularName: 'person',
|
||||
gqlFields: PERSON_GQL_FIELDS,
|
||||
filter: {
|
||||
id: {
|
||||
eq: PERSON_1_ID,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await makeGraphqlAPIRequest(graphqlOperation)
|
||||
.expect(400)
|
||||
.expect((res) => {
|
||||
expect(res.body.error.message).toContain(`Record not found`);
|
||||
});
|
||||
});
|
||||
|
||||
it('1a. should delete one person', async () => {
|
||||
const response = await makeRestAPIRequest(
|
||||
'delete',
|
||||
`/people/${PERSON_1_ID}`,
|
||||
);
|
||||
|
||||
expect(response.body.data.deletePerson.id).toBe(PERSON_1_ID);
|
||||
});
|
||||
|
||||
it('1.b. should return a BadRequestException when trying to delete a non-existing person', async () => {
|
||||
await makeRestAPIRequest('delete', `/people/${FAKE_PERSON_ID}`)
|
||||
.expect(400)
|
||||
.expect((res) => {
|
||||
expect(res.body.messages[0]).toContain(
|
||||
`Could not find any entity of type "person"`,
|
||||
);
|
||||
expect(res.body.error).toBe('Bad Request');
|
||||
});
|
||||
});
|
||||
|
||||
it('1.c. should return an UnauthorizedException when no token is provided', async () => {
|
||||
await makeRestAPIRequest('delete', `/people/${PERSON_1_ID}`, {
|
||||
authorization: '',
|
||||
})
|
||||
.expect(401)
|
||||
.expect((res) => {
|
||||
expect(res.body.error).toBe('UNAUTHENTICATED');
|
||||
});
|
||||
});
|
||||
|
||||
it('1.d. should return an UnauthorizedException when an invalid token is provided', async () => {
|
||||
await makeRestAPIRequest('delete', `/people/${PERSON_1_ID}`, {
|
||||
authorization: 'Bearer invalid-token',
|
||||
})
|
||||
.expect(401)
|
||||
.expect((res) => {
|
||||
expect(res.body.error).toBe('UNAUTHENTICATED');
|
||||
});
|
||||
});
|
||||
|
||||
it('1.e. should return an UnauthorizedException when an expired token is provided', async () => {
|
||||
await makeRestAPIRequest('delete', `/people/${PERSON_1_ID}`, {
|
||||
authorization: `Bearer ${EXPIRED_ACCESS_TOKEN}`,
|
||||
})
|
||||
.expect(401)
|
||||
.expect((res) => {
|
||||
expect(res.body.error).toBe('UNAUTHENTICATED');
|
||||
expect(res.body.messages[0]).toBe('Token has expired.'); // Adjust this based on your API's error response
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,18 @@
|
||||
import { IncomingHttpHeaders } from 'http';
|
||||
|
||||
import request from 'supertest';
|
||||
|
||||
export type RestAPIRequestMethod = 'get' | 'post' | 'put' | 'patch' | 'delete';
|
||||
|
||||
export const makeRestAPIRequest = (
|
||||
method: RestAPIRequestMethod,
|
||||
path: string,
|
||||
headers: IncomingHttpHeaders = {},
|
||||
) => {
|
||||
const client = request(`http://localhost:${APP_PORT}`);
|
||||
|
||||
return client[method]('/rest' + path)
|
||||
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
|
||||
.set({ ...headers })
|
||||
.send();
|
||||
};
|
||||
Reference in New Issue
Block a user