Skip to content

Commit bf26926

Browse files
committed
Add tests for helpers
1 parent 8250fb8 commit bf26926

File tree

10 files changed

+490
-22
lines changed

10 files changed

+490
-22
lines changed
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/* @flow */
2+
3+
import { expect, spy } from 'chai';
4+
import {
5+
filterHelperArgs,
6+
filterHelper,
7+
getIndexedFieldNames,
8+
} from '../filter';
9+
import { UserModel } from '../../../__mocks__/userModel.js';
10+
import { GraphQLInputObjectType, GraphQLNonNull } from 'graphql';
11+
import { convertModelToGraphQL } from '../../../fieldsConverter';
12+
import InputTypeComposer from '../../../../../graphql-compose/src/inputTypeComposer';
13+
14+
const UserType = convertModelToGraphQL(UserModel, 'User');
15+
16+
describe('Resolver helper `filter` ->', () => {
17+
describe('getIndexedFieldNames()', () => {
18+
it('should return array of indexed fieldNames', () => {
19+
const indexedFields = getIndexedFieldNames(UserModel);
20+
expect(indexedFields).have.members(
21+
['_id', 'employment', 'name']
22+
);
23+
expect(indexedFields).not.have.members(
24+
['age', 'gender']
25+
);
26+
});
27+
});
28+
29+
describe('filterHelperArgs()', () => {
30+
it('should throw error if `filterTypeName` not provided in opts', () => {
31+
expect(() => filterHelperArgs(UserType))
32+
.to.throw('provide non-empty `filterTypeName`');
33+
});
34+
35+
it('should return filter field', () => {
36+
const args = filterHelperArgs(UserType, {
37+
filterTypeName: 'FilterUserType',
38+
});
39+
expect(args).has.property('filter');
40+
expect(args).has.deep.property('filter.name', 'filter');
41+
expect(args).has.deep.property('filter.type').instanceof(GraphQLInputObjectType);
42+
});
43+
44+
it('should for opts.isRequired=true return GraphQLNonNull', () => {
45+
const args = filterHelperArgs(UserType, {
46+
filterTypeName: 'FilterUserType',
47+
isRequired: true,
48+
});
49+
expect(args).has.property('filter');
50+
expect(args).has.deep.property('filter.name', 'filter');
51+
expect(args).has.deep.property('filter.type').instanceof(GraphQLNonNull);
52+
});
53+
54+
it('should remove fields via opts.removeFields', () => {
55+
const args = filterHelperArgs(UserType, {
56+
filterTypeName: 'FilterUserType',
57+
removeFields: ['name', 'age'],
58+
});
59+
const inputTypeComposer = new InputTypeComposer(args.filter.type);
60+
expect(inputTypeComposer.hasField('name')).to.be.false;
61+
expect(inputTypeComposer.hasField('age')).to.be.false;
62+
expect(inputTypeComposer.hasField('gender')).to.be.true;
63+
});
64+
65+
it('should set required fields via opts.requiredFields', () => {
66+
const args = filterHelperArgs(UserType, {
67+
filterTypeName: 'FilterUserType',
68+
requiredFields: ['name', 'age'],
69+
});
70+
const inputTypeComposer = new InputTypeComposer(args.filter.type);
71+
expect(inputTypeComposer.getFieldType('name')).instanceof(GraphQLNonNull);
72+
expect(inputTypeComposer.getFieldType('age')).instanceof(GraphQLNonNull);
73+
expect(inputTypeComposer.getFieldType('gender')).not.instanceof(GraphQLNonNull);
74+
});
75+
76+
it('should throw error if opts.onlyIndexed=true and opts.model not provided', () => {
77+
expect(() => {
78+
filterHelperArgs(UserType, {
79+
filterTypeName: 'FilterUserType',
80+
onlyIndexed: true,
81+
});
82+
}).to.throw('You should provide `model`');
83+
});
84+
85+
it('should leave only indexed fields if opts.onlyIndexed=true', () => {
86+
const args = filterHelperArgs(UserType, {
87+
filterTypeName: 'FilterUserType',
88+
onlyIndexed: true,
89+
model: UserModel,
90+
});
91+
const inputTypeComposer = new InputTypeComposer(args.filter.type);
92+
expect(inputTypeComposer.hasField('_id')).to.be.true;
93+
expect(inputTypeComposer.hasField('name')).to.be.true;
94+
expect(inputTypeComposer.hasField('age')).to.be.false;
95+
expect(inputTypeComposer.hasField('gender')).to.be.false;
96+
});
97+
98+
it('should opts.onlyIndexed=true and opts.removeFields works together', () => {
99+
const args = filterHelperArgs(UserType, {
100+
filterTypeName: 'FilterUserType',
101+
onlyIndexed: true,
102+
model: UserModel,
103+
removeFields: ['name'],
104+
});
105+
const inputTypeComposer = new InputTypeComposer(args.filter.type);
106+
expect(inputTypeComposer.hasField('_id')).to.be.true;
107+
expect(inputTypeComposer.hasField('name')).to.be.false;
108+
expect(inputTypeComposer.hasField('age')).to.be.false;
109+
expect(inputTypeComposer.hasField('gender')).to.be.false;
110+
});
111+
});
112+
113+
describe('filterHelper()', () => {
114+
let spyFn;
115+
let resolveParams;
116+
117+
beforeEach(() => {
118+
spyFn = spy();
119+
resolveParams = {
120+
query: {
121+
where: spyFn,
122+
},
123+
};
124+
});
125+
126+
it('should not call query.where if args.filter is empty', () => {
127+
filterHelper(resolveParams);
128+
expect(spyFn).to.have.not.been.called();
129+
});
130+
it('should call query.where if args.filter is provided', () => {
131+
resolveParams.args = {
132+
filter: { name: 'nodkz' },
133+
};
134+
filterHelper(resolveParams);
135+
expect(spyFn).to.have.been.called.with({ name: 'nodkz' });
136+
});
137+
it('should convert deep object in args.filter to dotted object', () => {
138+
resolveParams.args = {
139+
filter: {
140+
name: {
141+
first: 'Pavel',
142+
},
143+
age: 30,
144+
},
145+
};
146+
filterHelper(resolveParams);
147+
expect(spyFn).to.have.been.called.with({
148+
'name.first': 'Pavel',
149+
age: 30,
150+
});
151+
});
152+
});
153+
});
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/* @flow */
2+
3+
import { expect } from 'chai';
4+
import { inputHelperArgs } from '../input';
5+
import { UserModel } from '../../../__mocks__/userModel.js';
6+
import { GraphQLInputObjectType, GraphQLNonNull } from 'graphql';
7+
import { convertModelToGraphQL } from '../../../fieldsConverter';
8+
import InputTypeComposer from '../../../../../graphql-compose/src/inputTypeComposer';
9+
10+
const UserType = convertModelToGraphQL(UserModel, 'User');
11+
12+
describe('Resolver helper `input` ->', () => {
13+
describe('inputHelperArgs()', () => {
14+
it('should throw error if `inputTypeName` not provided in opts', () => {
15+
expect(() => inputHelperArgs(UserType))
16+
.to.throw('provide non-empty `inputTypeName`');
17+
});
18+
19+
it('should return input field', () => {
20+
const args = inputHelperArgs(UserType, {
21+
inputTypeName: 'InputUserType',
22+
});
23+
expect(args).has.property('input');
24+
expect(args).has.deep.property('input.name', 'input');
25+
expect(args).has.deep.property('input.type').instanceof(GraphQLInputObjectType);
26+
});
27+
28+
it('should for opts.isRequired=true return GraphQLNonNull', () => {
29+
const args = inputHelperArgs(UserType, {
30+
inputTypeName: 'InputUserType',
31+
isRequired: true,
32+
});
33+
expect(args).has.property('input');
34+
expect(args).has.deep.property('input.name', 'input');
35+
expect(args).has.deep.property('input.type').instanceof(GraphQLNonNull);
36+
});
37+
38+
it('should remove fields via opts.removeFields', () => {
39+
const args = inputHelperArgs(UserType, {
40+
inputTypeName: 'InputUserType',
41+
removeFields: ['name', 'age'],
42+
});
43+
const inputTypeComposer = new InputTypeComposer(args.input.type);
44+
expect(inputTypeComposer.hasField('name')).to.be.false;
45+
expect(inputTypeComposer.hasField('age')).to.be.false;
46+
expect(inputTypeComposer.hasField('gender')).to.be.true;
47+
});
48+
49+
it('should set required fields via opts.requiredFields', () => {
50+
const args = inputHelperArgs(UserType, {
51+
inputTypeName: 'InputUserType',
52+
requiredFields: ['name', 'age'],
53+
});
54+
const inputTypeComposer = new InputTypeComposer(args.input.type);
55+
expect(inputTypeComposer.getFieldType('name')).instanceof(GraphQLNonNull);
56+
expect(inputTypeComposer.getFieldType('age')).instanceof(GraphQLNonNull);
57+
expect(inputTypeComposer.getFieldType('gender')).not.instanceof(GraphQLNonNull);
58+
});
59+
});
60+
});
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/* @flow */
2+
3+
import { expect, spy } from 'chai';
4+
import { limitHelperArgs, limitHelper } from '../limit';
5+
import {
6+
GraphQLInt,
7+
} from 'graphql';
8+
9+
describe('Resolver helper `limit` ->', () => {
10+
describe('limitHelperArgs()', () => {
11+
it('should return limit field', () => {
12+
const args = limitHelperArgs();
13+
expect(args).has.property('limit');
14+
expect(args).has.deep.property('limit.name', 'limit');
15+
expect(args).has.deep.property('limit.type', GraphQLInt);
16+
});
17+
it('should process `opts.defaultValue` arg', () => {
18+
expect(limitHelperArgs())
19+
.has.deep.property('limit.defaultValue', 1000);
20+
expect(limitHelperArgs({
21+
defaultValue: 333,
22+
})).has.deep.property('limit.defaultValue', 333);
23+
});
24+
});
25+
26+
describe('limitHelper()', () => {
27+
let spyFn;
28+
let resolveParams;
29+
30+
beforeEach(() => {
31+
spyFn = spy();
32+
resolveParams = {
33+
query: {
34+
limit: spyFn,
35+
},
36+
};
37+
});
38+
39+
it('should not call query.limit if args.limit is empty', () => {
40+
limitHelper(resolveParams);
41+
expect(spyFn).to.have.not.been.called();
42+
});
43+
it('should call query.limit if args.limit is provided', () => {
44+
resolveParams.args = { limit: 333 };
45+
limitHelper(resolveParams);
46+
expect(spyFn).to.have.been.called.with(333);
47+
});
48+
it('should convert string to int in args.limit', () => {
49+
resolveParams.args = { limit: '444' };
50+
limitHelper(resolveParams);
51+
expect(spyFn).to.have.been.called.with(444);
52+
});
53+
});
54+
});
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* @flow */
2+
3+
import { expect, spy } from 'chai';
4+
import { projectionHelper } from '../projection';
5+
6+
describe('Resolver helper `projection` ->', () => {
7+
describe('projectionHelper()', () => {
8+
let spyFn;
9+
let resolveParams;
10+
11+
beforeEach(() => {
12+
spyFn = spy();
13+
resolveParams = {
14+
query: {
15+
select: spyFn,
16+
},
17+
};
18+
});
19+
20+
it('should not call query.select if projection is empty', () => {
21+
projectionHelper(resolveParams);
22+
expect(spyFn).to.have.not.been.called();
23+
});
24+
it('should call query.select if projection is provided', () => {
25+
resolveParams.projection = { name: 1, age: 1 };
26+
projectionHelper(resolveParams);
27+
expect(spyFn).to.have.been.called.with(resolveParams.projection);
28+
});
29+
});
30+
});
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/* @flow */
2+
3+
import { expect, spy } from 'chai';
4+
import { skipHelperArgs, skipHelper } from '../skip';
5+
import {
6+
GraphQLInt,
7+
} from 'graphql';
8+
9+
describe('Resolver helper `skip` ->', () => {
10+
describe('limitHelperArgs()', () => {
11+
it('should return skip field', () => {
12+
const args = skipHelperArgs();
13+
expect(args).has.property('skip');
14+
expect(args).has.deep.property('skip.name', 'skip');
15+
expect(args).has.deep.property('skip.type', GraphQLInt);
16+
});
17+
});
18+
19+
describe('skipHelper()', () => {
20+
let spyFn;
21+
let resolveParams;
22+
23+
beforeEach(() => {
24+
spyFn = spy();
25+
resolveParams = {
26+
query: {
27+
skip: spyFn,
28+
},
29+
};
30+
});
31+
32+
it('should not call query.skip if args.skip is empty', () => {
33+
skipHelper(resolveParams);
34+
expect(spyFn).to.have.not.been.called();
35+
});
36+
it('should call query.skip if args.skip is provided', () => {
37+
resolveParams.args = { skip: 333 };
38+
skipHelper(resolveParams);
39+
expect(spyFn).to.have.been.called.with(333);
40+
});
41+
it('should convert skip to int in args.skip', () => {
42+
resolveParams.args = { skip: '444' };
43+
skipHelper(resolveParams);
44+
expect(spyFn).to.have.been.called.with(444);
45+
});
46+
});
47+
});

0 commit comments

Comments
 (0)