960 api rest batch create not working (#12028)
- fix batch endpoint - migrate batch endpoint to the rest api v2 - add new integration test for batch endpoints
This commit is contained in:
@ -1,21 +0,0 @@
|
|||||||
import { Controller, Post, Req, Res, UseGuards } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { Request, Response } from 'express';
|
|
||||||
|
|
||||||
import { RestApiCoreService } from 'src/engine/api/rest/core/rest-api-core.service';
|
|
||||||
import { cleanGraphQLResponse } from 'src/engine/api/rest/utils/clean-graphql-response.utils';
|
|
||||||
import { JwtAuthGuard } from 'src/engine/guards/jwt-auth.guard';
|
|
||||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
|
||||||
|
|
||||||
@Controller('rest/batch/*')
|
|
||||||
@UseGuards(JwtAuthGuard, WorkspaceAuthGuard)
|
|
||||||
export class RestApiCoreBatchController {
|
|
||||||
constructor(private readonly restApiCoreService: RestApiCoreService) {}
|
|
||||||
|
|
||||||
@Post()
|
|
||||||
async handleApiPost(@Req() request: Request, @Res() res: Response) {
|
|
||||||
const result = await this.restApiCoreService.createMany(request);
|
|
||||||
|
|
||||||
res.status(201).send(cleanGraphQLResponse(result.data));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -20,7 +20,7 @@ import { cleanGraphQLResponse } from 'src/engine/api/rest/utils/clean-graphql-re
|
|||||||
import { JwtAuthGuard } from 'src/engine/guards/jwt-auth.guard';
|
import { JwtAuthGuard } from 'src/engine/guards/jwt-auth.guard';
|
||||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||||
|
|
||||||
@Controller('rest/*')
|
@Controller('rest')
|
||||||
@UseGuards(JwtAuthGuard, WorkspaceAuthGuard)
|
@UseGuards(JwtAuthGuard, WorkspaceAuthGuard)
|
||||||
@UseFilters(RestApiExceptionFilter)
|
@UseFilters(RestApiExceptionFilter)
|
||||||
export class RestApiCoreController {
|
export class RestApiCoreController {
|
||||||
@ -29,37 +29,42 @@ export class RestApiCoreController {
|
|||||||
private readonly restApiCoreServiceV2: RestApiCoreServiceV2,
|
private readonly restApiCoreServiceV2: RestApiCoreServiceV2,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
@Post('batch/*')
|
||||||
|
async handleApiPostBatch(@Req() request: Request, @Res() res: Response) {
|
||||||
|
const result = await this.restApiCoreServiceV2.createMany(request);
|
||||||
|
|
||||||
|
res.status(201).send(result);
|
||||||
|
}
|
||||||
|
|
||||||
@Post('duplicates')
|
@Post('duplicates')
|
||||||
@UseFilters(RestApiExceptionFilter)
|
|
||||||
async handleApiFindDuplicates(@Req() request: Request, @Res() res: Response) {
|
async handleApiFindDuplicates(@Req() request: Request, @Res() res: Response) {
|
||||||
const result = await this.restApiCoreService.findDuplicates(request);
|
const result = await this.restApiCoreService.findDuplicates(request);
|
||||||
|
|
||||||
res.status(200).send(cleanGraphQLResponse(result.data.data));
|
res.status(200).send(cleanGraphQLResponse(result.data.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Post('*')
|
||||||
async handleApiGet(@Req() request: Request, @Res() res: Response) {
|
|
||||||
const result = await this.restApiCoreServiceV2.get(request);
|
|
||||||
|
|
||||||
res.status(200).send(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Delete()
|
|
||||||
async handleApiDelete(@Req() request: Request, @Res() res: Response) {
|
|
||||||
const result = await this.restApiCoreServiceV2.delete(request);
|
|
||||||
|
|
||||||
res.status(200).send(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Post()
|
|
||||||
async handleApiPost(@Req() request: Request, @Res() res: Response) {
|
async handleApiPost(@Req() request: Request, @Res() res: Response) {
|
||||||
const result = await this.restApiCoreServiceV2.createOne(request);
|
const result = await this.restApiCoreServiceV2.createOne(request);
|
||||||
|
|
||||||
res.status(201).send(result);
|
res.status(201).send(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch()
|
@Get('*')
|
||||||
@UseFilters(RestApiExceptionFilter)
|
async handleApiGet(@Req() request: Request, @Res() res: Response) {
|
||||||
|
const result = await this.restApiCoreServiceV2.get(request);
|
||||||
|
|
||||||
|
res.status(200).send(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete('*')
|
||||||
|
async handleApiDelete(@Req() request: Request, @Res() res: Response) {
|
||||||
|
const result = await this.restApiCoreServiceV2.delete(request);
|
||||||
|
|
||||||
|
res.status(200).send(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Patch('*')
|
||||||
async handleApiPatch(@Req() request: Request, @Res() res: Response) {
|
async handleApiPatch(@Req() request: Request, @Res() res: Response) {
|
||||||
const result = await this.restApiCoreServiceV2.update(request);
|
const result = await this.restApiCoreServiceV2.update(request);
|
||||||
|
|
||||||
@ -67,9 +72,9 @@ export class RestApiCoreController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This endpoint is not documented in the OpenAPI schema.
|
// This endpoint is not documented in the OpenAPI schema.
|
||||||
// We keep it to avoid a breaking change since it initially used PUT instead of PATCH,
|
// We keep it to avoid a breaking change since it initially used PUT instead
|
||||||
// and because the PUT verb is often used as a PATCH.
|
// of PATCH, and because the PUT verb is often used as a PATCH.
|
||||||
@Put()
|
@Put('*')
|
||||||
async handleApiPut(@Req() request: Request, @Res() res: Response) {
|
async handleApiPut(@Req() request: Request, @Res() res: Response) {
|
||||||
const result = await this.restApiCoreServiceV2.update(request);
|
const result = await this.restApiCoreServiceV2.update(request);
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,74 @@
|
|||||||
|
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { Request } from 'express';
|
||||||
|
import { isDefined } from 'twenty-shared/utils';
|
||||||
|
|
||||||
|
import { RestApiBaseHandler } from 'src/engine/api/rest/core/interfaces/rest-api-base.handler';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class RestApiCreateManyHandler extends RestApiBaseHandler {
|
||||||
|
async handle(request: Request) {
|
||||||
|
const { objectMetadataNamePlural, objectMetadata, repository } =
|
||||||
|
await this.getRepositoryAndMetadataOrFail(request);
|
||||||
|
|
||||||
|
const body = request.body;
|
||||||
|
|
||||||
|
if (!Array.isArray(body)) {
|
||||||
|
throw new BadRequestException('Body must be an array');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (body.length === 0) {
|
||||||
|
throw new BadRequestException('Input must not be empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
const overriddenRecordsToCreate: Record<string, any>[] = [];
|
||||||
|
|
||||||
|
for (const recordToCreate of body) {
|
||||||
|
const overriddenBody = await this.recordInputTransformerService.process({
|
||||||
|
recordInput: recordToCreate,
|
||||||
|
objectMetadataMapItem: objectMetadata.objectMetadataMapItem,
|
||||||
|
});
|
||||||
|
|
||||||
|
const recordExists =
|
||||||
|
isDefined(overriddenBody.id) &&
|
||||||
|
(await repository.exists({
|
||||||
|
where: {
|
||||||
|
id: overriddenBody.id,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (recordExists) {
|
||||||
|
throw new BadRequestException('Record already exists');
|
||||||
|
}
|
||||||
|
|
||||||
|
overriddenRecordsToCreate.push(overriddenBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
const createdRecords = await repository.save(overriddenRecordsToCreate);
|
||||||
|
|
||||||
|
this.apiEventEmitterService.emitCreateEvents(
|
||||||
|
createdRecords,
|
||||||
|
this.getAuthContextFromRequest(request),
|
||||||
|
objectMetadata.objectMetadataMapItem,
|
||||||
|
);
|
||||||
|
|
||||||
|
const records = await this.getRecord({
|
||||||
|
recordIds: createdRecords.map((record) => record.id),
|
||||||
|
repository,
|
||||||
|
objectMetadata,
|
||||||
|
depth: this.depthInputFactory.create(request),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (records.length !== body.length) {
|
||||||
|
throw new Error(
|
||||||
|
`Error when creating records. ${body.length - records.length} records are missing after creation.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.formatResult({
|
||||||
|
operation: 'create',
|
||||||
|
objectNamePlural: objectMetadataNamePlural,
|
||||||
|
data: records,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -228,12 +228,19 @@ export abstract class RestApiBaseHandler {
|
|||||||
}: FormatResultParams<T>) {
|
}: FormatResultParams<T>) {
|
||||||
let prefix: string;
|
let prefix: string;
|
||||||
|
|
||||||
|
if (isDefined(objectNameSingular) && isDefined(objectNamePlural)) {
|
||||||
|
throw new Error(
|
||||||
|
'Cannot define both objectNameSingular and objectNamePlural',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (operation === 'findOne') {
|
if (operation === 'findOne') {
|
||||||
prefix = objectNameSingular || '';
|
prefix = objectNameSingular || '';
|
||||||
} else if (operation === 'findMany') {
|
} else if (operation === 'findMany') {
|
||||||
prefix = objectNamePlural || '';
|
prefix = objectNamePlural || '';
|
||||||
} else {
|
} else {
|
||||||
prefix = operation + capitalize(objectNameSingular || '');
|
prefix =
|
||||||
|
operation + capitalize(objectNameSingular || objectNamePlural || '');
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -23,7 +23,24 @@ describe('parseCorePath', () => {
|
|||||||
const request: any = { path: '/rest/companies/uuid/toto' };
|
const request: any = { path: '/rest/companies/uuid/toto' };
|
||||||
|
|
||||||
expect(() => parseCorePath(request)).toThrow(
|
expect(() => parseCorePath(request)).toThrow(
|
||||||
"Query path '/rest/companies/uuid/toto' invalid. Valid examples: /rest/companies/id or /rest/companies",
|
"Query path '/rest/companies/uuid/toto' invalid. Valid examples: /rest/companies/id or /rest/companies or /rest/batch/companies",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should parse object from batch request', () => {
|
||||||
|
const request: any = { path: '/rest/batch/companies' };
|
||||||
|
|
||||||
|
expect(parseCorePath(request)).toEqual({
|
||||||
|
object: 'companies',
|
||||||
|
id: undefined,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw for wrong batch request', () => {
|
||||||
|
const request: any = { path: '/rest/batch/companies/uuid' };
|
||||||
|
|
||||||
|
expect(() => parseCorePath(request)).toThrow(
|
||||||
|
"Query path '/rest/batch/companies/uuid' invalid. Valid examples: /rest/companies/id or /rest/companies or /rest/batch/companies",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -9,10 +9,14 @@ export const parseCorePath = (
|
|||||||
|
|
||||||
if (queryAction.length > 2) {
|
if (queryAction.length > 2) {
|
||||||
throw new BadRequestException(
|
throw new BadRequestException(
|
||||||
`Query path '${request.path}' invalid. Valid examples: /rest/companies/id or /rest/companies`,
|
`Query path '${request.path}' invalid. Valid examples: /rest/companies/id or /rest/companies or /rest/batch/companies`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (queryAction.length === 2 && queryAction[0] === 'batch') {
|
||||||
|
return { object: queryAction[1] };
|
||||||
|
}
|
||||||
|
|
||||||
if (queryAction.length === 1) {
|
if (queryAction.length === 1) {
|
||||||
return { object: queryAction[0] };
|
return { object: queryAction[0] };
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,12 +9,14 @@ import { RestApiCreateOneHandler } from 'src/engine/api/rest/core/handlers/rest-
|
|||||||
import { RestApiUpdateOneHandler } from 'src/engine/api/rest/core/handlers/rest-api-update-one.handler';
|
import { RestApiUpdateOneHandler } from 'src/engine/api/rest/core/handlers/rest-api-update-one.handler';
|
||||||
import { RestApiGetOneHandler } from 'src/engine/api/rest/core/handlers/rest-api-get-one.handler';
|
import { RestApiGetOneHandler } from 'src/engine/api/rest/core/handlers/rest-api-get-one.handler';
|
||||||
import { RestApiGetManyHandler } from 'src/engine/api/rest/core/handlers/rest-api-get-many.handler';
|
import { RestApiGetManyHandler } from 'src/engine/api/rest/core/handlers/rest-api-get-many.handler';
|
||||||
|
import { RestApiCreateManyHandler } from 'src/engine/api/rest/core/handlers/rest-api-create-many.handler';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class RestApiCoreServiceV2 {
|
export class RestApiCoreServiceV2 {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly restApiDeleteOneHandler: RestApiDeleteOneHandler,
|
private readonly restApiDeleteOneHandler: RestApiDeleteOneHandler,
|
||||||
private readonly restApiCreateOneHandler: RestApiCreateOneHandler,
|
private readonly restApiCreateOneHandler: RestApiCreateOneHandler,
|
||||||
|
private readonly restApiCreateManyHandler: RestApiCreateManyHandler,
|
||||||
private readonly restApiUpdateOneHandler: RestApiUpdateOneHandler,
|
private readonly restApiUpdateOneHandler: RestApiUpdateOneHandler,
|
||||||
private readonly restApiGetOneHandler: RestApiGetOneHandler,
|
private readonly restApiGetOneHandler: RestApiGetOneHandler,
|
||||||
private readonly restApiGetManyHandler: RestApiGetManyHandler,
|
private readonly restApiGetManyHandler: RestApiGetManyHandler,
|
||||||
@ -28,6 +30,10 @@ export class RestApiCoreServiceV2 {
|
|||||||
return await this.restApiCreateOneHandler.handle(request);
|
return await this.restApiCreateOneHandler.handle(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async createMany(request: Request) {
|
||||||
|
return await this.restApiCreateManyHandler.handle(request);
|
||||||
|
}
|
||||||
|
|
||||||
async update(request: Request) {
|
async update(request: Request) {
|
||||||
return await this.restApiUpdateOneHandler.handle(request);
|
return await this.restApiUpdateOneHandler.handle(request);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,16 +13,17 @@ import { RecordTransformerModule } from 'src/engine/core-modules/record-transfor
|
|||||||
import { WorkspacePermissionsCacheModule } from 'src/engine/metadata-modules/workspace-permissions-cache/workspace-permissions-cache.module';
|
import { WorkspacePermissionsCacheModule } from 'src/engine/metadata-modules/workspace-permissions-cache/workspace-permissions-cache.module';
|
||||||
import { RestApiCoreController } from 'src/engine/api/rest/core/controllers/rest-api-core.controller';
|
import { RestApiCoreController } from 'src/engine/api/rest/core/controllers/rest-api-core.controller';
|
||||||
import { coreQueryBuilderFactories } from 'src/engine/api/rest/core/query-builder/factories/factories';
|
import { coreQueryBuilderFactories } from 'src/engine/api/rest/core/query-builder/factories/factories';
|
||||||
import { RestApiCoreBatchController } from 'src/engine/api/rest/core/controllers/rest-api-core-batch.controller';
|
|
||||||
import { RestApiCoreServiceV2 } from 'src/engine/api/rest/core/rest-api-core-v2.service';
|
import { RestApiCoreServiceV2 } from 'src/engine/api/rest/core/rest-api-core-v2.service';
|
||||||
import { RestApiCoreService } from 'src/engine/api/rest/core/rest-api-core.service';
|
import { RestApiCoreService } from 'src/engine/api/rest/core/rest-api-core.service';
|
||||||
import { RestApiService } from 'src/engine/api/rest/rest-api.service';
|
import { RestApiService } from 'src/engine/api/rest/rest-api.service';
|
||||||
import { ApiEventEmitterService } from 'src/engine/api/graphql/graphql-query-runner/services/api-event-emitter.service';
|
import { ApiEventEmitterService } from 'src/engine/api/graphql/graphql-query-runner/services/api-event-emitter.service';
|
||||||
import { AuthModule } from 'src/engine/core-modules/auth/auth.module';
|
import { AuthModule } from 'src/engine/core-modules/auth/auth.module';
|
||||||
|
import { RestApiCreateManyHandler } from 'src/engine/api/rest/core/handlers/rest-api-create-many.handler';
|
||||||
|
|
||||||
const restApiCoreResolvers = [
|
const restApiCoreResolvers = [
|
||||||
RestApiDeleteOneHandler,
|
RestApiDeleteOneHandler,
|
||||||
RestApiCreateOneHandler,
|
RestApiCreateOneHandler,
|
||||||
|
RestApiCreateManyHandler,
|
||||||
RestApiUpdateOneHandler,
|
RestApiUpdateOneHandler,
|
||||||
RestApiGetOneHandler,
|
RestApiGetOneHandler,
|
||||||
RestApiGetManyHandler,
|
RestApiGetManyHandler,
|
||||||
@ -38,7 +39,7 @@ const restApiCoreResolvers = [
|
|||||||
RecordTransformerModule,
|
RecordTransformerModule,
|
||||||
WorkspacePermissionsCacheModule,
|
WorkspacePermissionsCacheModule,
|
||||||
],
|
],
|
||||||
controllers: [RestApiCoreController, RestApiCoreBatchController],
|
controllers: [RestApiCoreController],
|
||||||
providers: [
|
providers: [
|
||||||
RestApiService,
|
RestApiService,
|
||||||
RestApiCoreService,
|
RestApiCoreService,
|
||||||
|
|||||||
@ -0,0 +1,169 @@
|
|||||||
|
import {
|
||||||
|
TEST_PERSON_1_ID,
|
||||||
|
TEST_PERSON_2_ID,
|
||||||
|
} from 'test/integration/constants/test-person-ids.constants';
|
||||||
|
import { makeRestAPIRequest } from 'test/integration/rest/utils/make-rest-api-request.util';
|
||||||
|
import { deleteAllRecords } from 'test/integration/utils/delete-all-records';
|
||||||
|
import { TEST_COMPANY_1_ID } from 'test/integration/constants/test-company-ids.constants';
|
||||||
|
import { TEST_PRIMARY_LINK_URL } from 'test/integration/constants/test-primary-link-url.constant';
|
||||||
|
|
||||||
|
describe('Core REST API Create Many endpoint', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await deleteAllRecords('person');
|
||||||
|
await makeRestAPIRequest({
|
||||||
|
method: 'post',
|
||||||
|
path: '/companies',
|
||||||
|
body: {
|
||||||
|
id: TEST_COMPANY_1_ID,
|
||||||
|
domainName: {
|
||||||
|
primaryLinkUrl: TEST_PRIMARY_LINK_URL,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create many person', async () => {
|
||||||
|
const requestBody = [
|
||||||
|
{
|
||||||
|
id: TEST_PERSON_1_ID,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: TEST_PERSON_2_ID,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
await makeRestAPIRequest({
|
||||||
|
method: 'post',
|
||||||
|
path: `/batch/people`,
|
||||||
|
body: requestBody,
|
||||||
|
})
|
||||||
|
.expect(201)
|
||||||
|
.expect((res) => {
|
||||||
|
const createdPeople = res.body.data.createPeople;
|
||||||
|
|
||||||
|
expect(createdPeople.length).toBe(2);
|
||||||
|
expect(createdPeople[0].id).toBe(TEST_PERSON_1_ID);
|
||||||
|
expect(createdPeople[1].id).toBe(TEST_PERSON_2_ID);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support depth 0 parameter', async () => {
|
||||||
|
const requestBody = [
|
||||||
|
{
|
||||||
|
id: TEST_PERSON_1_ID,
|
||||||
|
companyId: TEST_COMPANY_1_ID,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: TEST_PERSON_2_ID,
|
||||||
|
companyId: TEST_COMPANY_1_ID,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
await makeRestAPIRequest({
|
||||||
|
method: 'post',
|
||||||
|
path: `/batch/people?depth=0`,
|
||||||
|
body: requestBody,
|
||||||
|
})
|
||||||
|
.expect(201)
|
||||||
|
.expect((res) => {
|
||||||
|
const [createdPerson1, createdPerson2] = res.body.data.createPeople;
|
||||||
|
|
||||||
|
expect(createdPerson1.companyId).toBeDefined();
|
||||||
|
expect(createdPerson1.company).not.toBeDefined();
|
||||||
|
expect(createdPerson2.companyId).toBeDefined();
|
||||||
|
expect(createdPerson2.company).not.toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support depth 1 parameter', async () => {
|
||||||
|
const requestBody = [
|
||||||
|
{
|
||||||
|
id: TEST_PERSON_1_ID,
|
||||||
|
companyId: TEST_COMPANY_1_ID,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: TEST_PERSON_2_ID,
|
||||||
|
companyId: TEST_COMPANY_1_ID,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
await makeRestAPIRequest({
|
||||||
|
method: 'post',
|
||||||
|
path: `/batch/people?depth=1`,
|
||||||
|
body: requestBody,
|
||||||
|
})
|
||||||
|
.expect(201)
|
||||||
|
.expect((res) => {
|
||||||
|
const [createdPerson1, createdPerson2] = res.body.data.createPeople;
|
||||||
|
|
||||||
|
expect(createdPerson1.company).toBeDefined();
|
||||||
|
expect(createdPerson1.company.people).not.toBeDefined();
|
||||||
|
expect(createdPerson2.company).toBeDefined();
|
||||||
|
expect(createdPerson2.company.people).not.toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support depth 2 parameter', async () => {
|
||||||
|
const requestBody = [
|
||||||
|
{
|
||||||
|
id: TEST_PERSON_1_ID,
|
||||||
|
companyId: TEST_COMPANY_1_ID,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: TEST_PERSON_2_ID,
|
||||||
|
companyId: TEST_COMPANY_1_ID,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
await makeRestAPIRequest({
|
||||||
|
method: 'post',
|
||||||
|
path: `/batch/people?depth=2`,
|
||||||
|
body: requestBody,
|
||||||
|
})
|
||||||
|
.expect(201)
|
||||||
|
.expect((res) => {
|
||||||
|
const [createdPerson1, createdPerson2] = res.body.data.createPeople;
|
||||||
|
|
||||||
|
expect(createdPerson1.company.people).toBeDefined();
|
||||||
|
expect(createdPerson2.company.people).toBeDefined();
|
||||||
|
|
||||||
|
const depth2Person1 = createdPerson1.company.people.find(
|
||||||
|
(p) => p.id === createdPerson1.id,
|
||||||
|
);
|
||||||
|
const depth2Person2 = createdPerson2.company.people.find(
|
||||||
|
(p) => p.id === createdPerson2.id,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(depth2Person1).toBeDefined();
|
||||||
|
expect(depth2Person2).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a BadRequestException when trying to create a person with an existing ID', async () => {
|
||||||
|
const requestBody = [
|
||||||
|
{
|
||||||
|
id: TEST_PERSON_1_ID,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: TEST_PERSON_2_ID,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
await makeRestAPIRequest({
|
||||||
|
method: 'post',
|
||||||
|
path: `/batch/people`,
|
||||||
|
body: requestBody,
|
||||||
|
});
|
||||||
|
|
||||||
|
await makeRestAPIRequest({
|
||||||
|
method: 'post',
|
||||||
|
path: `/batch/people`,
|
||||||
|
body: requestBody,
|
||||||
|
})
|
||||||
|
.expect(400)
|
||||||
|
.expect((res) => {
|
||||||
|
expect(res.body.messages[0]).toContain(`Record already exists`);
|
||||||
|
expect(res.body.error).toBe('BadRequestException');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user