Skip to content

Commit

Permalink
feat(FieldsConverter): DocumentArray return defined early TypeCompose…
Browse files Browse the repository at this point in the history
…r if it exists, instead of generating new one

See src/__mocks__/languageSchema.js where type name `Language` is pre-defined via `convertSchemaToGraphQL(LanguageSchema, 'Language');`.
Otherwise genereted type may has different names for different models where it is used. By default, name for DocumentArray is `${ParentSchemaName}${ParentSchemaFieldName}`.
  • Loading branch information
nodkz committed Nov 23, 2016
1 parent c5aad84 commit 34e1744
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Schema } from './mongooseCommon';
import { convertSchemaToGraphQL } from '../fieldsConverter';

// name: 'EnumLanguageName',
// description: 'Language names (https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)',
Expand All @@ -14,7 +15,7 @@ const enumLanguageSkill = {
native: { description: 'since birth' },
};

const LanguagesSchema = new Schema(
const LanguageSchema = new Schema(
{
ln: {
type: String,
Expand All @@ -29,4 +30,8 @@ const LanguagesSchema = new Schema(
}
);

export default LanguagesSchema;
export default LanguageSchema;

// Such way we can set Type name for Schema which is used in another schema.
// Otherwise by default it will have name `${ParentSchemaName}${ParentSchemaFieldName}`
convertSchemaToGraphQL(LanguageSchema, 'Language');
4 changes: 2 additions & 2 deletions src/__mocks__/userModel.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { mongoose, Schema } from './mongooseCommon';
import ContactsSchema from './contactsSchema';
import enumEmployment from './enumEmployment';
import LanguagesSchema from './languagesSchema';
import LanguageSchema from './languageSchema';

const UserSchema = new Schema(
{
Expand Down Expand Up @@ -65,7 +65,7 @@ const UserSchema = new Schema(
},

languages: {
type: [LanguagesSchema],
type: [LanguageSchema],
default: [],
description: 'Knowledge of languages',
},
Expand Down
31 changes: 13 additions & 18 deletions src/__tests__/fieldConverter-test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-unused-expressions */
/* eslint-disable no-unused-expressions, no-template-curly-in-string */

import { expect } from 'chai';
import {
Expand Down Expand Up @@ -130,55 +130,49 @@ describe('fieldConverter', () => {
});

describe('arrayToGraphQL()', () => {
const skillsType = arrayToGraphQL(fields.skills);

it('should produce GraphQLList', () => {
const skillsType = arrayToGraphQL(fields.skills);
expect(skillsType).to.be.instanceof(GraphQLList);
});

it('should has string in ofType', () => {
const skillsType = arrayToGraphQL(fields.skills);
expect(skillsType.ofType.name).to.equal('String');
});
});

describe('enumToGraphQL()', () => {
const genderEnum = enumToGraphQL(fields.gender);

it('should be instance of GraphQLEnumType', () => {
const genderEnum = enumToGraphQL(fields.gender);
expect(genderEnum).be.instanceof(GraphQLEnumType);
});

it('should have type name `Enum${FieldName}`', () => {
const genderEnum = enumToGraphQL(fields.gender);
expect(genderEnum.name).to.equal('EnumGender');
});

it('should pass all enum values to GQ type', () => {
const genderEnum = enumToGraphQL(fields.gender);
expect(genderEnum._values.length).to.equal(fields.gender.enumValues.length);
expect(genderEnum._values[0].value).to.equal(fields.gender.enumValues[0]);
});
});

describe('embeddedToGraphQL()', () => {
const embeddedType = embeddedToGraphQL(fields.contacts);
const embeddedFields = embeddedType._typeConfig.fields();

it('should set name to graphql type', () => {
expect(embeddedType.name).to.equal('Contacts');
const embeddedType = embeddedToGraphQL(fields.contacts);
expect(embeddedType.name).to.equal('UserContacts');
});

it('should have embedded fields', () => {
const embeddedType = embeddedToGraphQL(fields.contacts);
const embeddedFields = embeddedType._typeConfig.fields();
expect(embeddedFields.email).to.be.ok;
});

it('should have embedded fields with MongoID type, except pseudoID', () => {
expect(embeddedFields.locationId).to.be.ok;
expect(embeddedFields._id).to.be.undefined;
});

it('should skip pseudo mongoose _id field', () => {
expect(embeddedFields._id).to.be.undefined;
});

it('should return null if subdocument is empty', async () => {
const UserTC = composeWithMongoose(UserModel);
const schema = new GraphQLSchema({
Expand Down Expand Up @@ -263,8 +257,9 @@ describe('fieldConverter', () => {
expect(languagesType).to.be.instanceof(GraphQLList);
});

it('should has Languages type in ofType', () => {
expect(languagesType.ofType.name).to.equal('Languages');
it('should has Language type in ofType', () => {
// see src/__mocks__/languageSchema.js where type name `Language` is defined
expect(languagesType.ofType.name).to.equal('Language');
});

it('should skip pseudo mongoose _id field in document', () => {
Expand Down
5 changes: 5 additions & 0 deletions src/fieldsConverter.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ export function convertModelToGraphQL(
model: MongooseModelT | MongoosePseudoModelT,
typeName: string
): TypeComposer {
// if model already has generated TypeComposer early, then return it
if (model.schema && model.schema._gqcTypeComposer instanceof TypeComposer) {
return model.schema._gqcTypeComposer;
}

if (!typeName) {
throw new Error('You provide empty name for type. '
+ '`name` argument should be non-empty string.');
Expand Down

0 comments on commit 34e1744

Please sign in to comment.