Skip to content

Commit c4eae4d

Browse files
committed
test(discriminator): add test suits for _disTypes, minor refactor
1 parent e93a6ab commit c4eae4d

File tree

4 files changed

+251
-40
lines changed

4 files changed

+251
-40
lines changed

src/__tests__/_disTypes-test.js

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
import { graphql, schemaComposer } from 'graphql-compose/lib/index';
2+
import { mongoose } from '../__mocks__/mongooseCommon';
3+
import { composeWithMongooseDiscriminators } from '../composeWithMongooseDiscriminators';
4+
5+
beforeAll(() => mongoose.connect());
6+
afterAll(() => mongoose.disconnect());
7+
8+
describe('_disTypes Test With and Without test_disTypes Options set', () => {
9+
const options = { discriminatorKey: 'kind' };
10+
11+
const eventSchema = new mongoose.Schema({ refId: String }, options);
12+
const Event = mongoose.model('Event', eventSchema);
13+
14+
const clickedLinkSchema = new mongoose.Schema({ url: String });
15+
const ClickedLinkEvent = Event.discriminator('ClickedLinkEvent', clickedLinkSchema);
16+
17+
afterEach(() => Event.remove({}));
18+
19+
describe('No test_disTypes, Include types Manually in Query', () => {
20+
let EventTC;
21+
let ClickedLinkEventTC;
22+
23+
beforeAll(() => {
24+
schemaComposer.clear();
25+
Event.schema._gqcTypeComposer = undefined;
26+
ClickedLinkEvent.schema._gqcTypeComposer = undefined;
27+
EventTC = composeWithMongooseDiscriminators(Event);
28+
ClickedLinkEventTC = EventTC.discriminator(ClickedLinkEvent);
29+
});
30+
31+
it('creating Types from models', () => {
32+
expect(EventTC.getFieldNames()).toEqual(['_id', 'kind', 'refId']);
33+
expect(ClickedLinkEventTC.getFieldNames()).toEqual(['_id', 'kind', 'refId', 'url']);
34+
});
35+
36+
it('manually override resolver output type for findMany', async () => {
37+
// let's check graphql response
38+
39+
await Event.create({ refId: 'aaa' });
40+
await Event.create({ refId: 'bbb' });
41+
await ClickedLinkEvent.create({ refId: 'ccc', url: 'url1' });
42+
await ClickedLinkEvent.create({ refId: 'ddd', url: 'url2' });
43+
44+
schemaComposer.rootQuery().addFields({
45+
eventFindMany: EventTC.getResolver('findMany'),
46+
ClickedLinkEvent: ClickedLinkEventTC.getResolver('findMany'),
47+
GenericEvent: EventTC.getResolver('findOne').setType(EventTC),
48+
});
49+
50+
const schema = schemaComposer.buildSchema();
51+
52+
const res = await graphql.graphql(
53+
schema,
54+
`{
55+
eventFindMany {
56+
__typename
57+
... on GenericEvent {
58+
refId
59+
}
60+
... on ClickedLinkEvent {
61+
kind
62+
refId
63+
url
64+
}
65+
}
66+
}`
67+
);
68+
69+
expect(res).toEqual({
70+
data: {
71+
eventFindMany: [
72+
{ __typename: 'GenericEvent', refId: 'aaa' },
73+
{ __typename: 'GenericEvent', refId: 'bbb' },
74+
{ __typename: 'ClickedLinkEvent', kind: 'ClickedLinkEvent', refId: 'ccc', url: 'url1' },
75+
{ __typename: 'ClickedLinkEvent', kind: 'ClickedLinkEvent', refId: 'ddd', url: 'url2' },
76+
],
77+
},
78+
});
79+
});
80+
});
81+
82+
describe('opts test_disTypes TRUE', () => {
83+
let EventTC;
84+
let ClickedLinkEventTC;
85+
86+
beforeAll(() => {
87+
schemaComposer.clear();
88+
Event.schema._gqcTypeComposer = undefined;
89+
ClickedLinkEvent.schema._gqcTypeComposer = undefined;
90+
EventTC = composeWithMongooseDiscriminators(Event, { test_disTypes: true });
91+
ClickedLinkEventTC = EventTC.discriminator(ClickedLinkEvent);
92+
});
93+
94+
it('creating Types from models', () => {
95+
expect(EventTC.getFieldNames()).toEqual(['_id', 'kind', 'refId']);
96+
expect(ClickedLinkEventTC.getFieldNames()).toEqual(['_id', 'kind', 'refId', 'url']);
97+
});
98+
99+
it('manually override resolver output type for findMany', async () => {
100+
// let's check graphql response
101+
102+
await Event.create({ refId: 'aaa' });
103+
await Event.create({ refId: 'bbb' });
104+
await ClickedLinkEvent.create({ refId: 'ccc', url: 'url1' });
105+
await ClickedLinkEvent.create({ refId: 'ddd', url: 'url2' });
106+
107+
schemaComposer.rootQuery().addFields({
108+
eventFindMany: EventTC.getResolver('findMany'),
109+
});
110+
111+
const schema = schemaComposer.buildSchema();
112+
113+
const res = await graphql.graphql(
114+
schema,
115+
`{
116+
eventFindMany {
117+
__typename
118+
... on GenericEvent {
119+
refId
120+
}
121+
... on ClickedLinkEvent {
122+
kind
123+
refId
124+
url
125+
}
126+
}
127+
}`
128+
);
129+
130+
expect(res).toEqual({
131+
data: {
132+
eventFindMany: [
133+
{ __typename: 'GenericEvent', refId: 'aaa' },
134+
{ __typename: 'GenericEvent', refId: 'bbb' },
135+
{ __typename: 'ClickedLinkEvent', kind: 'ClickedLinkEvent', refId: 'ccc', url: 'url1' },
136+
{ __typename: 'ClickedLinkEvent', kind: 'ClickedLinkEvent', refId: 'ddd', url: 'url2' },
137+
],
138+
},
139+
});
140+
});
141+
});
142+
143+
describe('opts test_disTypes FALSE', () => {
144+
let EventTC;
145+
let ClickedLinkEventTC;
146+
147+
beforeAll(() => {
148+
schemaComposer.clear();
149+
Event.schema._gqcTypeComposer = undefined;
150+
ClickedLinkEvent.schema._gqcTypeComposer = undefined;
151+
EventTC = composeWithMongooseDiscriminators(Event, { test_disTypes: false });
152+
ClickedLinkEventTC = EventTC.discriminator(ClickedLinkEvent);
153+
});
154+
155+
it('creating Types from models', () => {
156+
expect(EventTC.getFieldNames()).toEqual(['_id', 'kind', 'refId']);
157+
expect(ClickedLinkEventTC.getFieldNames()).toEqual(['_id', 'kind', 'refId', 'url']);
158+
});
159+
160+
it('manually override resolver output type for findMany', async () => {
161+
// let's check graphql response
162+
163+
await Event.create({ refId: 'aaa' });
164+
await Event.create({ refId: 'bbb' });
165+
await ClickedLinkEvent.create({ refId: 'ccc', url: 'url1' });
166+
await ClickedLinkEvent.create({ refId: 'ddd', url: 'url2' });
167+
168+
schemaComposer.rootQuery().addFields({
169+
eventFindMany: EventTC.getResolver('findMany'),
170+
});
171+
172+
const schema = schemaComposer.buildSchema();
173+
174+
const res = await graphql.graphql(
175+
schema,
176+
`{
177+
eventFindMany {
178+
__typename
179+
... on GenericEvent {
180+
refId
181+
}
182+
... on ClickedLinkEvent {
183+
kind
184+
refId
185+
url
186+
}
187+
}
188+
}`
189+
);
190+
191+
expect(res.errors[0].message).toEqual('Unknown type "GenericEvent".');
192+
expect(res.errors[1].message).toEqual('Unknown type "ClickedLinkEvent".');
193+
});
194+
});
195+
});

src/__tests__/integration-discriminators-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ describe('#78 Mongoose and Discriminators', () => {
1717
const clickedLinkSchema = new mongoose.Schema({ url: String });
1818
const ClickedLinkEvent = Event.discriminator('ClickedLinkEvent', clickedLinkSchema);
1919

20-
const EventTC = composeWithMongooseDiscriminators(Event);
20+
const EventTC = composeWithMongooseDiscriminators(Event, { test_disTypes: true });
2121
const ClickedLinkEventTC = EventTC.discriminator(ClickedLinkEvent);
2222

2323
// Todo: Remove

src/composeWithMongooseDiscriminators.js

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ import { reorderFields } from './discriminators/utils';
2424
const { GraphQLInterfaceType } = graphql;
2525

2626
export type Options = {
27-
reorderFields: string[] | boolean, // true order: _id, DKey, DInterfaceFields, DiscriminatorFields
28-
customizationOptions: TypeConverterOpts,
27+
test_disTypes?: boolean,
28+
reorderFields?: boolean | string[], // true order: _id, DKey, DInterfaceFields, DiscriminatorFields
29+
customizationOptions?: TypeConverterOpts,
2930
};
3031

3132
type Discriminators = {
@@ -119,23 +120,23 @@ export class DiscriminatorTypeComposer extends TypeComposer {
119120

120121
childTCs: TypeComposer[];
121122

122-
constructor(
123-
baseModel: Model,
124-
opts: Options = {
123+
constructor(baseModel: Model, opts?: any) {
124+
if (!baseModel || !(baseModel: any).discriminators) {
125+
throw Error('Discriminator Key not Set, Use composeWithMongoose for Normal Collections');
126+
}
127+
128+
opts = { // eslint-disable-line
125129
reorderFields: true,
126130
customizationOptions: {
127131
schemaComposer,
128132
},
129-
}
130-
) {
131-
if (!baseModel || !(baseModel: any).discriminators) {
132-
throw Error('Discriminator Key not Set, Use composeWithMongoose for Normal Collections');
133-
}
133+
...opts,
134+
};
134135

135136
super(composeWithMongoose(baseModel, opts.customizationOptions).gqType);
136137

137138
// !ORDER MATTERS
138-
this.opts = opts || {};
139+
this.opts = opts;
139140
this.modelName = (baseModel: any).modelName;
140141
this.discriminatorKey = (baseModel: any).schema.get('discriminatorKey') || '__t';
141142

@@ -144,24 +145,35 @@ export class DiscriminatorTypeComposer extends TypeComposer {
144145
this.discriminators = (baseModel: any).discriminators;
145146

146147
this.childTCs = [];
147-
this.GQC = opts.customizationOptions.schemaComposer || schemaComposer;
148+
this.GQC =
149+
opts.customizationOptions && opts.customizationOptions.schemaComposer
150+
? opts.customizationOptions.schemaComposer
151+
: schemaComposer;
148152
this.setTypeName(`Generic${this.modelName}`);
149153
this.DKeyETC = createAndSetDKeyETC(this, this.discriminators);
150154

151-
reorderFields(this, this.opts.reorderFields, this.discriminatorKey);
155+
reorderFields(this, (this.opts: any).reorderFields, this.discriminatorKey);
152156

153157
this.DInterface = createDInterface(this);
154158
this.setInterfaces([this.DInterface]);
155159

156-
// Add a Generic Field, else we have generic Errors when resolving interface
157-
// this is somehow i don't understand, but we don't get any type if we never query it
158-
// I guess under the hud, graphql-compose shakes it off.
159-
this.GQC.Query.addFields({
160-
[`${this.getTypeName()[0].toLowerCase() +
161-
this.getTypeName().substr(1)}One`]: this.getResolver('findOne')
162-
.clone({ name: 'GenericOne' })
163-
.setType(this.getType()),
164-
});
160+
// Hoist on _disTypes
161+
if (opts.test_disTypes) {
162+
if (!this.GQC.rootQuery().hasField('_disTypes')) {
163+
this.GQC.rootQuery().addFields({
164+
_disTypes: TypeComposer.create({
165+
name: '_disTypes',
166+
description: 'Hoisting for Discriminator Types',
167+
}),
168+
});
169+
}
170+
171+
this.GQC.rootQuery()
172+
.getFieldTC('_disTypes')
173+
.addFields({
174+
[this.getTypeName()]: this,
175+
});
176+
}
165177

166178
// prepare Base Resolvers
167179
prepareBaseResolvers(this);
@@ -232,7 +244,10 @@ export class DiscriminatorTypeComposer extends TypeComposer {
232244

233245
/* eslint no-use-before-define: 0 */
234246
discriminator(childModel: Model, opts?: TypeConverterOpts): TypeComposer {
235-
const customizationOpts = mergeCustomizationOptions(this.opts.customizationOptions, opts);
247+
const customizationOpts = mergeCustomizationOptions(
248+
(this.opts: any).customizationOptions,
249+
opts
250+
);
236251

237252
let childTC = composeWithMongoose(childModel, customizationOpts);
238253

@@ -246,10 +261,7 @@ export class DiscriminatorTypeComposer extends TypeComposer {
246261

247262
export function composeWithMongooseDiscriminators(
248263
baseModel: Model,
249-
opts: Options = {
250-
reorderFields: true,
251-
customizationOptions: {},
252-
}
264+
opts?: Options
253265
): DiscriminatorTypeComposer {
254266
return new DiscriminatorTypeComposer(baseModel, opts);
255267
}

src/discriminators/composeChildTC.js

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,21 +35,25 @@ export function composeChildTC(
3535

3636
composedChildTC.setInterfaces([baseDTC.getDInterface()]);
3737

38-
// Add this field, else we have Unknown type Error when we query for this field when we haven't
39-
// added a query that returns this type on rootQuery.
40-
// this is somehow i don't understand, but we don't get any type if we never query it
41-
// I guess under the hud, graphql-compose shakes it off.
42-
baseDTC.getGQC().Query.addFields({
43-
[`${composedChildTC.getTypeName()[0].toLowerCase() +
44-
composedChildTC.getTypeName().substr(1)}One`]: composedChildTC
45-
.getResolver('findOne')
46-
.clone({ name: `${composedChildTC.getTypeName()}One` })
47-
.setType(composedChildTC.getType()),
48-
});
38+
// hoist this type
39+
if (opts.test_disTypes) {
40+
baseDTC
41+
.getGQC()
42+
.rootQuery()
43+
.getFieldTC('_disTypes')
44+
.addFields({
45+
[composedChildTC.getTypeName()]: composedChildTC,
46+
});
47+
}
4948

5049
prepareChildResolvers(baseDTC, composedChildTC, opts);
5150

52-
reorderFields(composedChildTC, opts.reorderFields, baseDTC.getDKey(), baseDTC.getFieldNames());
51+
reorderFields(
52+
composedChildTC,
53+
(opts: any).reorderFields,
54+
baseDTC.getDKey(),
55+
baseDTC.getFieldNames()
56+
);
5357

5458
return composedChildTC;
5559
}

0 commit comments

Comments
 (0)