Skip to content

Commit 73862fb

Browse files
committed
Add range filters
1 parent e84265d commit 73862fb

File tree

4 files changed

+97
-65
lines changed

4 files changed

+97
-65
lines changed

src/introspection/getFilterTypesFromData.js

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,32 @@
1-
import { GraphQLInputObjectType, GraphQLString } from 'graphql';
1+
import {
2+
GraphQLInputObjectType,
3+
GraphQLString,
4+
GraphQLInt,
5+
GraphQLFloat,
6+
} from 'graphql';
27
import getFieldsFromEntities from './getFieldsFromEntities';
8+
import getValuesFromEntities from './getValuesFromEntities';
9+
import getTypeFromValues from './getTypeFromValues';
310
import { getTypeFromKey } from '../nameConverter';
411

12+
const getNumberFiltersFromEntities = entities => {
13+
const fieldValues = getValuesFromEntities(entities);
14+
return Object.keys(fieldValues).reduce((fields, fieldName) => {
15+
const fieldType = getTypeFromValues(
16+
fieldName,
17+
fieldValues[fieldName],
18+
false,
19+
);
20+
if (fieldType == GraphQLInt || fieldType == GraphQLFloat) {
21+
fields[`${fieldName}_lt`] = { type: fieldType };
22+
fields[`${fieldName}_lte`] = { type: fieldType };
23+
fields[`${fieldName}_gt`] = { type: fieldType };
24+
fields[`${fieldName}_gte`] = { type: fieldType };
25+
}
26+
return fields;
27+
}, {});
28+
};
29+
530
/**
631
* Get a list of GraphQLObjectType for filtering data
732
*
@@ -41,6 +66,10 @@ import { getTypeFromKey } from '../nameConverter';
4166
* // id: { type: GraphQLString },
4267
* // title: { type: GraphQLString },
4368
* // views: { type: GraphQLInt },
69+
* // views_lt: { type: GraphQLInt },
70+
* // views_lte: { type: GraphQLInt },
71+
* // views_gt: { type: GraphQLInt },
72+
* // views_gte: { type: GraphQLInt },
4473
* // user_id: { type: GraphQLString },
4574
* // }
4675
* // }),
@@ -63,6 +92,7 @@ export default data =>
6392
fields: {
6493
q: { type: GraphQLString },
6594
...getFieldsFromEntities(data[key], false),
95+
...getNumberFiltersFromEntities(data[key]),
6696
},
6797
}),
6898
}),

src/introspection/getFilterTypesFromData.spec.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,18 @@ test('creates one q field per entity field', () => {
7575
const CommentFilterFields = filterTypes.User.getFields();
7676
expect(CommentFilterFields.q.type.toString()).toEqual('String');
7777
});
78+
79+
test('creates 4 fields for number field for range filters', () => {
80+
const filterTypes = getFilterTypesFromData(data);
81+
const PostFilterFields = filterTypes.Post.getFields();
82+
expect(PostFilterFields.views_lt.type.toString()).toEqual('Int');
83+
expect(PostFilterFields.views_lte.type.toString()).toEqual('Int');
84+
expect(PostFilterFields.views_gt.type.toString()).toEqual('Int');
85+
expect(PostFilterFields.views_gte.type.toString()).toEqual('Int');
86+
});
87+
88+
test('does not create vomparison fiels for non-number fields', () => {
89+
const filterTypes = getFilterTypesFromData(data);
90+
const PostFilterFields = filterTypes.Post.getFields();
91+
expect(PostFilterFields.title_lte).toBeUndefined();
92+
});

src/introspection/getSchemaFromData.spec.js

Lines changed: 20 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -137,38 +137,16 @@ test('creates three query fields per data type', () => {
137137
},
138138
]);
139139
expect(queries['allPosts'].type.toString()).toEqual('[Post]');
140-
expect(queries['allPosts'].args).toEqual([
141-
{
142-
defaultValue: undefined,
143-
description: null,
144-
name: 'page',
145-
type: GraphQLInt,
146-
},
147-
{
148-
defaultValue: undefined,
149-
description: null,
150-
name: 'perPage',
151-
type: GraphQLInt,
152-
},
153-
{
154-
defaultValue: undefined,
155-
description: null,
156-
name: 'sortField',
157-
type: GraphQLString,
158-
},
159-
{
160-
defaultValue: undefined,
161-
description: null,
162-
name: 'sortOrder',
163-
type: GraphQLString,
164-
},
165-
{
166-
defaultValue: undefined,
167-
description: null,
168-
name: 'filter',
169-
type: GraphQLString,
170-
},
171-
]);
140+
expect(queries['allPosts'].args[0].name).toEqual('page');
141+
expect(queries['allPosts'].args[0].type).toEqual(GraphQLInt);
142+
expect(queries['allPosts'].args[1].name).toEqual('perPage');
143+
expect(queries['allPosts'].args[1].type).toEqual(GraphQLInt);
144+
expect(queries['allPosts'].args[2].name).toEqual('sortField');
145+
expect(queries['allPosts'].args[2].type).toEqual(GraphQLString);
146+
expect(queries['allPosts'].args[3].name).toEqual('sortOrder');
147+
expect(queries['allPosts'].args[3].type).toEqual(GraphQLString);
148+
expect(queries['allPosts'].args[4].name).toEqual('filter');
149+
expect(queries['allPosts'].args[4].type.toString()).toEqual('PostFilter');
172150
expect(queries['_allPostsMeta'].type.toString()).toEqual('ListMetadata');
173151

174152
expect(queries['User'].type.name).toEqual(UserType.name);
@@ -181,38 +159,16 @@ test('creates three query fields per data type', () => {
181159
},
182160
]);
183161
expect(queries['allUsers'].type.toString()).toEqual('[User]');
184-
expect(queries['allUsers'].args).toEqual([
185-
{
186-
defaultValue: undefined,
187-
description: null,
188-
name: 'page',
189-
type: GraphQLInt,
190-
},
191-
{
192-
defaultValue: undefined,
193-
description: null,
194-
name: 'perPage',
195-
type: GraphQLInt,
196-
},
197-
{
198-
defaultValue: undefined,
199-
description: null,
200-
name: 'sortField',
201-
type: GraphQLString,
202-
},
203-
{
204-
defaultValue: undefined,
205-
description: null,
206-
name: 'sortOrder',
207-
type: GraphQLString,
208-
},
209-
{
210-
defaultValue: undefined,
211-
description: null,
212-
name: 'filter',
213-
type: GraphQLString,
214-
},
215-
]);
162+
expect(queries['allUsers'].args[0].name).toEqual('page');
163+
expect(queries['allUsers'].args[0].type).toEqual(GraphQLInt);
164+
expect(queries['allUsers'].args[1].name).toEqual('perPage');
165+
expect(queries['allUsers'].args[1].type).toEqual(GraphQLInt);
166+
expect(queries['allUsers'].args[2].name).toEqual('sortField');
167+
expect(queries['allUsers'].args[2].type).toEqual(GraphQLString);
168+
expect(queries['allUsers'].args[3].name).toEqual('sortOrder');
169+
expect(queries['allUsers'].args[3].type).toEqual(GraphQLString);
170+
expect(queries['allUsers'].args[4].name).toEqual('filter');
171+
expect(queries['allUsers'].args[4].type.toString()).toEqual('UserFilter');
216172
expect(queries['_allPostsMeta'].type.toString()).toEqual('ListMetadata');
217173
});
218174

src/jsonGraphqlExpress.spec.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,37 @@ describe('all* route', () => {
183183
},
184184
}),
185185
]));
186+
it('filters by value range on each integer field using the related filters', () =>
187+
Promise.all([
188+
gqlAgent(
189+
'{ allPosts(filter: { views_lt: 76 }) { id } }',
190+
).expect({
191+
data: {
192+
allPosts: [{ id: 2 }],
193+
},
194+
}),
195+
gqlAgent(
196+
'{ allPosts(filter: { views_lte: 76 }) { id } }',
197+
).expect({
198+
data: {
199+
allPosts: [{ id: 2 }, { id: 3 }],
200+
},
201+
}),
202+
gqlAgent(
203+
'{ allPosts(filter: { views_gt: 76 }) { id } }',
204+
).expect({
205+
data: {
206+
allPosts: [{ id: 1 }],
207+
},
208+
}),
209+
gqlAgent(
210+
'{ allPosts(filter: { views_gte: 76 }) { id } }',
211+
).expect({
212+
data: {
213+
allPosts: [{ id: 1 }, { id: 3 }],
214+
},
215+
}),
216+
]));
186217
});
187218
});
188219

0 commit comments

Comments
 (0)