Skip to content

Commit

Permalink
feat(graphql): Expose setRelations mutation
Browse files Browse the repository at this point in the history
  • Loading branch information
doug-martin committed Apr 13, 2021
1 parent 227d02d commit 676a4d5
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ type Query {

type Mutation {
addTestsToTestResolverDTO(input: RelationsInput!): TestResolverDTO!
setTestsOnTestResolverDTO(input: RelationsInput!): TestResolverDTO!
}

input RelationsInput {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ type Query {

type Mutation {
addRelationsToTestResolverDTO(input: RelationsInput!): TestResolverDTO!
setRelationsOnTestResolverDTO(input: RelationsInput!): TestResolverDTO!
}

input RelationsInput {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,40 +102,99 @@ describe('UpdateRelationsResolver', () => {
many: { relations: { DTO: TestRelationDTO, disableUpdate: true } },
}));

it('should call the service findRelation with the provided dto and correct relation name', async () => {
const { resolver, mockService } = await createResolverFromNest(TestResolver);
const input: RelationsInputType = {
id: 'id-1',
relationIds: ['relation-id-1', 'relation-id-2'],
};
const output: TestResolverDTO = {
id: 'record-id',
stringField: 'foo',
};
when(mockService.addRelations('relations', input.id, deepEqual(input.relationIds), undefined)).thenResolve(
output,
);
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const result = await resolver.addRelationsToTestResolverDTO({ input });
return expect(result).toEqual(output);
describe('add relations', () => {
it('should call the service addRelations with the dto id and relationIds', async () => {
const { resolver, mockService } = await createResolverFromNest(TestResolver);
const input: RelationsInputType = {
id: 'id-1',
relationIds: ['relation-id-1', 'relation-id-2'],
};
const output: TestResolverDTO = {
id: 'record-id',
stringField: 'foo',
};
when(mockService.addRelations('relations', input.id, deepEqual(input.relationIds), undefined)).thenResolve(
output,
);
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const result = await resolver.addRelationsToTestResolverDTO({ input });
return expect(result).toEqual(output);
});

it('should call the service addRelations with the custom dto name dto id and relationIds', async () => {
const { resolver, mockService } = await createResolverFromNest(TestResolver);
const input: RelationsInputType = {
id: 'id-1',
relationIds: ['relation-id-1', 'relation-id-2'],
};
const output: TestResolverDTO = {
id: 'record-id',
stringField: 'foo',
};
when(mockService.addRelations('others', input.id, deepEqual(input.relationIds), undefined)).thenResolve(output);
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const result = await resolver.addCustomsToTestResolverDTO({ input });
return expect(result).toEqual(output);
});
});

it('should call the service findRelation with the provided dto and custom relation name', async () => {
const { resolver, mockService } = await createResolverFromNest(TestResolver);
const input: RelationsInputType = {
id: 'id-1',
relationIds: ['relation-id-1', 'relation-id-2'],
};
const output: TestResolverDTO = {
id: 'record-id',
stringField: 'foo',
};
when(mockService.addRelations('others', input.id, deepEqual(input.relationIds), undefined)).thenResolve(output);
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const result = await resolver.addCustomsToTestResolverDTO({ input });
return expect(result).toEqual(output);
describe('set relations', () => {
it('should call the service setRelations with the dto id and relationIds', async () => {
const { resolver, mockService } = await createResolverFromNest(TestResolver);
const input: RelationsInputType = {
id: 'id-1',
relationIds: ['relation-id-1', 'relation-id-2'],
};
const output: TestResolverDTO = {
id: 'record-id',
stringField: 'foo',
};
when(mockService.setRelations('relations', input.id, deepEqual(input.relationIds), undefined)).thenResolve(
output,
);
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const result = await resolver.setRelationsOnTestResolverDTO({ input });
return expect(result).toEqual(output);
});

it('should call the service setRelations with the dto id and an empty relationIds', async () => {
const { resolver, mockService } = await createResolverFromNest(TestResolver);
const input: RelationsInputType = {
id: 'id-1',
relationIds: [],
};
const output: TestResolverDTO = {
id: 'record-id',
stringField: 'foo',
};
when(mockService.setRelations('relations', input.id, deepEqual(input.relationIds), undefined)).thenResolve(
output,
);
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const result = await resolver.setRelationsOnTestResolverDTO({ input });
return expect(result).toEqual(output);
});

it('should call the service setRelations with the custom dto name dto id and relationIds', async () => {
const { resolver, mockService } = await createResolverFromNest(TestResolver);
const input: RelationsInputType = {
id: 'id-1',
relationIds: ['relation-id-1', 'relation-id-2'],
};
const output: TestResolverDTO = {
id: 'record-id',
stringField: 'foo',
};
when(mockService.setRelations('others', input.id, deepEqual(input.relationIds), undefined)).thenResolve(output);
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const result = await resolver.setCustomsOnTestResolverDTO({ input });
return expect(result).toEqual(output);
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -61,21 +61,11 @@ describe('RelationsInputType', (): void => {
]);
});

it('should validate that relationsIds is not empty', () => {
it('should allow an empty relationIds array', () => {
const input: RelationsInputType = { id: 1, relationIds: [] };
const it = plainToClass(RelationsInput, input);
const errors = validateSync(it);
expect(errors).toEqual([
{
children: [],
constraints: {
arrayNotEmpty: 'relationIds should not be empty',
},
property: 'relationIds',
target: input,
value: input.relationIds,
},
]);
expect(errors).toEqual([]);
});

it('should validate that relationsIds is unique', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,21 @@ const UpdateManyRelationMixin = <DTO, Relation>(DTOClass: Class<DTO>, relation:
const { input } = await transformAndValidate(AddArgs, addArgs);
return this.service.addRelations(relationName, input.id, input.relationIds, modifyRelationsFilter);
}

@ResolverMutation(() => DTOClass, {}, commonResolverOpts, {
interceptors: [AuthorizerInterceptor(DTOClass)],
})
async [`set${pluralBaseName}On${dtoNames.baseName}`](
@Args() addArgs: AddArgs,
@ModifyRelationAuthorizerFilter(pluralBaseNameLower, {
operationGroup: OperationGroup.UPDATE,
many: true,
})
modifyRelationsFilter?: ModifyRelationOptions<DTO, Relation>,
): Promise<DTO> {
const { input } = await transformAndValidate(AddArgs, addArgs);
return this.service.setRelations(relationName, input.id, input.relationIds, modifyRelationsFilter);
}
}
return UpdateManyMixin;
};
Expand Down
3 changes: 1 addition & 2 deletions packages/query-graphql/src/types/relations-input.type.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Class } from '@nestjs-query/core';
import { Field, ID, InputType } from '@nestjs/graphql';
import { IsNotEmpty, ArrayNotEmpty, ArrayUnique } from 'class-validator';
import { IsNotEmpty, ArrayUnique } from 'class-validator';

export interface RelationsInputType {
id: string | number;
Expand All @@ -21,7 +21,6 @@ export function RelationsInputType(): Class<RelationsInputType> {
id!: string | number;

@Field(() => [ID], { description: 'The ids of the relations.' })
@ArrayNotEmpty()
@ArrayUnique()
@IsNotEmpty({ each: true })
relationIds!: (string | number)[];
Expand Down

0 comments on commit 676a4d5

Please sign in to comment.