diff --git a/src/__mocks__/languagesSchema.js b/src/__mocks__/languageSchema.js similarity index 68% rename from src/__mocks__/languagesSchema.js rename to src/__mocks__/languageSchema.js index 4f07e50e..94ffbfe8 100644 --- a/src/__mocks__/languagesSchema.js +++ b/src/__mocks__/languageSchema.js @@ -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)', @@ -14,7 +15,7 @@ const enumLanguageSkill = { native: { description: 'since birth' }, }; -const LanguagesSchema = new Schema( +const LanguageSchema = new Schema( { ln: { type: String, @@ -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'); diff --git a/src/__mocks__/userModel.js b/src/__mocks__/userModel.js index 76d9b56a..bc599fe4 100644 --- a/src/__mocks__/userModel.js +++ b/src/__mocks__/userModel.js @@ -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( { @@ -65,7 +65,7 @@ const UserSchema = new Schema( }, languages: { - type: [LanguagesSchema], + type: [LanguageSchema], default: [], description: 'Knowledge of languages', }, diff --git a/src/__tests__/fieldConverter-test.js b/src/__tests__/fieldConverter-test.js index be5d6c20..ee8f838b 100644 --- a/src/__tests__/fieldConverter-test.js +++ b/src/__tests__/fieldConverter-test.js @@ -1,4 +1,4 @@ -/* eslint-disable no-unused-expressions */ +/* eslint-disable no-unused-expressions, no-template-curly-in-string */ import { expect } from 'chai'; import { @@ -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({ @@ -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', () => { diff --git a/src/fieldsConverter.js b/src/fieldsConverter.js index 1c9e014e..834c1e5e 100644 --- a/src/fieldsConverter.js +++ b/src/fieldsConverter.js @@ -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.');