Skip to content

Commit 8a52b23

Browse files
committed
Add removeMany resolver
1 parent 083dff6 commit 8a52b23

File tree

2 files changed

+195
-0
lines changed

2 files changed

+195
-0
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/* @flow */
2+
3+
import { expect } from 'chai';
4+
import { UserModel } from '../../__mocks__/userModel.js';
5+
import removeMany from '../removeMany';
6+
import Resolver from '../../../../graphql-compose/src/resolver/resolver';
7+
import TypeComposer from '../../../../graphql-compose/src/typeComposer';
8+
import { convertModelToGraphQL } from '../../fieldsConverter';
9+
import { GraphQLInt, GraphQLNonNull } from 'graphql';
10+
11+
const UserType = convertModelToGraphQL(UserModel, 'User');
12+
13+
describe('removeMany() ->', () => {
14+
let user1;
15+
let user2;
16+
let user3;
17+
18+
beforeEach('clear UserModel collection', (done) => {
19+
UserModel.collection.drop(() => {
20+
done();
21+
});
22+
});
23+
24+
beforeEach('add test user document to mongoDB', () => {
25+
user1 = new UserModel({
26+
name: 'userName1',
27+
gender: 'male',
28+
relocation: true,
29+
age: 28,
30+
});
31+
32+
user2 = new UserModel({
33+
name: 'userName2',
34+
gender: 'female',
35+
relocation: true,
36+
age: 29,
37+
});
38+
39+
user3 = new UserModel({
40+
name: 'userName3',
41+
gender: 'female',
42+
relocation: true,
43+
age: 30,
44+
});
45+
46+
return Promise.all([
47+
user1.save(),
48+
user2.save(),
49+
user3.save(),
50+
]);
51+
});
52+
53+
it('should return Resolver object', () => {
54+
const resolver = removeMany(UserModel, UserType);
55+
expect(resolver).to.be.instanceof(Resolver);
56+
});
57+
58+
describe('Resolver.args', () => {
59+
it('should have required `filter` arg', () => {
60+
const resolver = removeMany(UserModel, UserType);
61+
const filterField = resolver.getArg('filter');
62+
expect(filterField).to.be.ok;
63+
expect(filterField).property('type').instanceof(GraphQLNonNull);
64+
});
65+
});
66+
67+
describe('Resolver.resolve():Promise', () => {
68+
it('should be promise', () => {
69+
const result = removeMany(UserModel, UserType).resolve({});
70+
expect(result).instanceof(Promise);
71+
result.catch(() => 'catch error if appear, hide it from mocha');
72+
});
73+
74+
it('should rejected with Error if args.filter is empty', async () => {
75+
const result = removeMany(UserModel, UserType).resolve({ args: {} });
76+
await expect(result).be.rejectedWith(Error, 'at least one value in args.filter');
77+
});
78+
79+
it('should remove data in database', (done) => {
80+
removeMany(UserModel, UserType).resolve({
81+
args: {
82+
filter: { _id: user1.id },
83+
},
84+
}).then(() => {
85+
UserModel.collection.findOne({ _id: user1._id }, (err, doc) => {
86+
expect(err).to.be.null;
87+
expect(doc).to.be.null;
88+
done();
89+
});
90+
});
91+
});
92+
93+
it('should not remove unsuitable data to filter in database', (done) => {
94+
removeMany(UserModel, UserType).resolve({
95+
args: {
96+
filter: { _id: user1.id },
97+
},
98+
}).then(() => {
99+
UserModel.collection.findOne({ _id: user2._id }, (err, doc) => {
100+
expect(err).to.be.null;
101+
expect(doc).to.be.ok;
102+
done();
103+
});
104+
});
105+
});
106+
107+
it('should return payload.numAffected', async () => {
108+
const result = await removeMany(UserModel, UserType).resolve({
109+
args: {
110+
filter: { gender: 'female' },
111+
},
112+
});
113+
expect(result).have.property('numAffected', 2);
114+
});
115+
});
116+
117+
describe('Resolver.getOutputType()', () => {
118+
it('should have correct output type name', () => {
119+
const outputType = removeMany(UserModel, UserType).getOutputType();
120+
expect(outputType).property('name').to.equal(`RemoveMany${UserType.name}Payload`);
121+
});
122+
123+
it('should have numAffected field', () => {
124+
const outputType = removeMany(UserModel, UserType).getOutputType();
125+
const numAffectedField = new TypeComposer(outputType).getField('numAffected');
126+
expect(numAffectedField).property('type').to.equal(GraphQLInt);
127+
});
128+
});
129+
});

src/resolvers/removeMany.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 { filterHelperArgsGen, filterHelper } from './helpers/filter';
4+
import { GraphQLObjectType, GraphQLInt } from 'graphql';
5+
6+
import type {
7+
MongooseModelT,
8+
ExtendedResolveParams,
9+
} from '../definition';
10+
import Resolver from '../../../graphql-compose/src/resolver/resolver';
11+
12+
export default function removeMany(
13+
model: MongooseModelT,
14+
gqType: GraphQLObjectType,
15+
): Resolver {
16+
const resolver = new Resolver({
17+
name: 'removeMany',
18+
kind: 'mutation',
19+
description: 'Remove many documents without returning them: '
20+
+ 'Use Query.remove mongoose method. '
21+
+ 'Do not apply mongoose defaults, setters, hooks and validation. ',
22+
outputType: new GraphQLObjectType({
23+
name: `RemoveMany${gqType.name}Payload`,
24+
fields: {
25+
numAffected: {
26+
type: GraphQLInt,
27+
description: 'Affected documents number',
28+
},
29+
},
30+
}),
31+
args: {
32+
...filterHelperArgsGen(model, {
33+
filterTypeName: `Filter${gqType.name}Input`,
34+
isRequired: true,
35+
}),
36+
},
37+
resolve: (resolveParams: ExtendedResolveParams) => {
38+
const filterData = resolveParams.args && resolveParams.args.filter || {};
39+
40+
if (!(typeof filterData === 'object')
41+
|| Object.keys(filterData).length === 0
42+
) {
43+
return Promise.reject(
44+
new Error(`${gqType.name}.removeMany resolver requires at least one value in args.filter`)
45+
);
46+
}
47+
48+
resolveParams.query = model.find();
49+
filterHelper(resolveParams);
50+
resolveParams.query = resolveParams.query.remove();
51+
52+
return resolveParams.query
53+
.exec()
54+
.then(res => {
55+
if (res.result && res.result.ok) {
56+
return {
57+
numAffected: res.result.n,
58+
};
59+
}
60+
61+
return Promise.reject(res);
62+
});
63+
},
64+
});
65+
66+
return resolver;
67+
}

0 commit comments

Comments
 (0)