Skip to content

Commit 9aeda48

Browse files
committed
Add createOne resolver
1 parent 3bffc66 commit 9aeda48

File tree

3 files changed

+174
-0
lines changed

3 files changed

+174
-0
lines changed

src/definition.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export type MonooseModelIndex = [
2020

2121
export type MongooseModelT = {
2222
schema: MongooseModelSchemaT,
23+
create(doc: Object | Object[]): Promise,
2324
findOne(conditions: ?Object, projection?: Object): MongooseQuery,
2425
findById(id: mixed, projection?: Object, options?: Object): MongooseQuery,
2526
find(conditions: ?Object, projection?: Object, options?: Object): MongooseQuery,
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/* @flow */
2+
3+
import { expect } from 'chai';
4+
import { UserModel } from '../../__mocks__/userModel.js';
5+
import createOne from '../createOne';
6+
import Resolver from '../../../../graphql-compose/src/resolver/resolver';
7+
import TypeComposer from '../../../../graphql-compose/src/typeComposer';
8+
import { convertModelToGraphQL } from '../../fieldsConverter';
9+
import GraphQLMongoID from '../../types/mongoid';
10+
import { GraphQLNonNull } from 'graphql/type';
11+
12+
const UserType = convertModelToGraphQL(UserModel, 'User');
13+
14+
describe('createOne() ->', () => {
15+
before('clear UserModel collection', (done) => {
16+
UserModel.collection.drop(() => {
17+
done();
18+
});
19+
});
20+
21+
it('should return Resolver object', () => {
22+
const resolver = createOne(UserModel, UserType);
23+
expect(resolver).to.be.instanceof(Resolver);
24+
});
25+
26+
describe('Resolver.args', () => {
27+
it('should have required `input` arg', () => {
28+
const resolver = createOne(UserModel, UserType);
29+
const argConfig = resolver.getArg('input');
30+
expect(argConfig).property('type').instanceof(GraphQLNonNull);
31+
expect(argConfig).deep.property('type.ofType.name', 'CreateOneUserInput');
32+
});
33+
});
34+
35+
describe('Resolver.resolve():Promise', () => {
36+
it('should be promise', () => {
37+
const result = createOne(UserModel, UserType).resolve({});
38+
expect(result).instanceof(Promise);
39+
result.catch(() => 'catch error if appear, hide it from mocha');
40+
});
41+
42+
it('should rejected with Error if args.input is empty', async () => {
43+
const result = createOne(UserModel, UserType).resolve({ args: {} });
44+
await expect(result).be.rejectedWith(Error, 'at least one value in args.input');
45+
});
46+
47+
it('should return payload.recordId', async () => {
48+
const result = await createOne(UserModel, UserType).resolve({
49+
args: {
50+
input: { name: 'newName' },
51+
},
52+
});
53+
expect(result).property('recordId').to.be.ok;
54+
});
55+
56+
it('should create document with args.input', async () => {
57+
const result = await createOne(UserModel, UserType).resolve({
58+
args: {
59+
input: { name: 'newName' },
60+
},
61+
});
62+
expect(result).have.deep.property('record.name', 'newName');
63+
});
64+
65+
it('should save document to database', (done) => {
66+
const checkedName = 'nameForMongoDB';
67+
createOne(UserModel, UserType).resolve({
68+
args: {
69+
input: { name: checkedName },
70+
},
71+
}).then((res) => {
72+
UserModel.collection.findOne({ _id: res.record._id }, (err, doc) => {
73+
expect(doc.name).to.be.equal(checkedName);
74+
done();
75+
});
76+
});
77+
});
78+
79+
it('should return payload.record', async () => {
80+
const result = await createOne(UserModel, UserType).resolve({
81+
args: {
82+
input: { name: 'NewUser' },
83+
},
84+
});
85+
expect(result).have.deep.property('record.id', result.recordId);
86+
});
87+
});
88+
89+
describe('Resolver.getOutputType()', () => {
90+
it('should have correct output type name', () => {
91+
const outputType = createOne(UserModel, UserType).getOutputType();
92+
expect(outputType).property('name').to.equal(`CreateOne${UserType.name}Payload`);
93+
});
94+
95+
it('should have recordId field', () => {
96+
const outputType = createOne(UserModel, UserType).getOutputType();
97+
const recordIdField = new TypeComposer(outputType).getField('recordId');
98+
expect(recordIdField).property('type').to.equal(GraphQLMongoID);
99+
});
100+
101+
it('should have record field', () => {
102+
const outputType = createOne(UserModel, UserType).getOutputType();
103+
const recordField = new TypeComposer(outputType).getField('record');
104+
expect(recordField).property('type').to.equal(UserType);
105+
});
106+
});
107+
});

src/resolvers/createOne.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,67 @@
11
/* @flow */
2+
/* eslint-disable no-param-reassign */
3+
import { inputHelperArgsGen } from './helpers/input';
4+
import { GraphQLObjectType } from 'graphql';
5+
import GraphQLMongoID from '../types/mongoid';
6+
7+
import type {
8+
MongooseModelT,
9+
ExtendedResolveParams,
10+
} from '../definition';
11+
import Resolver from '../../../graphql-compose/src/resolver/resolver';
12+
13+
export default function createOne(
14+
model: MongooseModelT,
15+
gqType: GraphQLObjectType,
16+
): Resolver {
17+
const resolver = new Resolver({
18+
name: 'createOne',
19+
kind: 'mutation',
20+
description: 'Create one document with mongoose defaults, setters, hooks and validation',
21+
outputType: new GraphQLObjectType({
22+
name: `CreateOne${gqType.name}Payload`,
23+
fields: {
24+
recordId: {
25+
type: GraphQLMongoID,
26+
description: 'Created document ID',
27+
},
28+
record: {
29+
type: gqType,
30+
description: 'Created document',
31+
},
32+
},
33+
}),
34+
args: {
35+
...inputHelperArgsGen(gqType, {
36+
inputTypeName: `CreateOne${gqType.name}Input`,
37+
removeFields: ['id', '_id'],
38+
isRequired: true,
39+
}),
40+
},
41+
resolve: (resolveParams: ExtendedResolveParams) => {
42+
const inputData = resolveParams.args && resolveParams.args.input || {};
43+
44+
if (!(typeof inputData === 'object')
45+
|| Object.keys(inputData).length === 0
46+
) {
47+
return Promise.reject(
48+
new Error(`${gqType.name}.createOne resolver requires at least one value in args.input`)
49+
);
50+
}
51+
52+
return model.create(inputData)
53+
.then(record => {
54+
if (record) {
55+
return {
56+
record: record.toObject(),
57+
recordId: record.id,
58+
};
59+
}
60+
61+
return null;
62+
});
63+
},
64+
});
65+
66+
return resolver;
67+
}

0 commit comments

Comments
 (0)