diff --git a/package.json b/package.json index 599c396..1b22c25 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "dependencies": { "@faker-js/faker": "^8.4.1", "@graphql-codegen/plugin-helpers": "^5.0.4", + "@graphql-tools/utils": "^10.7.2", "casual": "^1.6.2", "change-case-all": "^1.0.15", "indefinite": "^2.4.1", @@ -40,6 +41,7 @@ "@graphql-codegen/testing": "^3.0.3", "@graphql-codegen/typescript": "^4.0.7", "@types/jest": "^27.0.2", + "@types/indefinite": "^2.3.4", "@typescript-eslint/eslint-plugin": "^5.1.0", "@typescript-eslint/parser": "^5.1.0", "auto": "^11.1.6", @@ -57,7 +59,7 @@ "prettier": "^2.4.1", "prettier-config-landr": "^0.2.0", "ts-jest": "^27.0.7", - "typescript": "^4.4.4" + "typescript": "^5.7.3" }, "sideEffects": false, "scripts": { diff --git a/src/index.ts b/src/index.ts index 53f88fb..1d3a4b4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,17 +1,10 @@ -import { - parse, - printSchema, - TypeNode, - ASTKindToNode, - ListTypeNode, - NamedTypeNode, - ObjectTypeDefinitionNode, -} from 'graphql'; +import { parse, TypeNode, ASTKindToNode, ListTypeNode, NamedTypeNode, ObjectTypeDefinitionNode } from 'graphql'; import * as allFakerLocales from '@faker-js/faker'; import casual from 'casual'; import { oldVisit, PluginFunction, resolveExternalModuleAndFn } from '@graphql-codegen/plugin-helpers'; import { sentenceCase } from 'sentence-case'; import a from 'indefinite'; +import { printSchemaWithDirectives } from '@graphql-tools/utils'; import { setupFunctionTokens, setupMockValueGenerator } from './mockValueGenerator'; type NamingConvention = 'change-case-all#pascalCase' | 'keep' | string; @@ -460,6 +453,7 @@ const getMockString = ( typesPrefix = '', transformUnderscore: boolean, typeNamesMapping?: Record, + hasOneOfDirective = false, ) => { const typeNameConverter = createNameConverter(typeNamesConvention, transformUnderscore); const NewTypeName = typeNamesMapping[typeName] || typeName; @@ -468,6 +462,10 @@ const getMockString = ( const typename = addTypename ? `\n __typename: '${typeName}',` : ''; const typenameReturnType = addTypename ? `{ __typename: '${typeName}' } & ` : ''; + const overridesArgumentString = !hasOneOfDirective + ? `overrides?: Partial<${casedNameWithPrefix}>` + : `override?: ${casedNameWithPrefix}`; + if (terminateCircularRelationships) { const relationshipsToOmitInit = terminateCircularRelationships === 'immediate' ? '_relationshipsToOmit' : 'new Set(_relationshipsToOmit)'; @@ -476,7 +474,7 @@ export const ${toMockName( typeName, casedName, prefix, - )} = (overrides?: Partial<${casedNameWithPrefix}>, _relationshipsToOmit: Set = new Set()): ${typenameReturnType}${casedNameWithPrefix} => { + )} = (${overridesArgumentString}, _relationshipsToOmit: Set = new Set()): ${typenameReturnType}${casedNameWithPrefix} => { const relationshipsToOmit: Set = ${relationshipsToOmitInit}; relationshipsToOmit.add('${casedName}'); return {${typename} @@ -489,7 +487,7 @@ export const ${toMockName( typeName, casedName, prefix, - )} = (overrides?: Partial<${casedNameWithPrefix}>): ${typenameReturnType}${casedNameWithPrefix} => { + )} = (${overridesArgumentString}): ${typenameReturnType}${casedNameWithPrefix} => { return {${typename} ${fields} }; @@ -622,7 +620,8 @@ type VisitorType = { [K in keyof ASTKindToNode]?: VisitFn = (schema, documents, config) => { - const printedSchema = printSchema(schema); // Returns a string representation of the schema + const printedSchema = printSchemaWithDirectives(schema); // Returns a string representation of the schema + const astNode = parse(printedSchema); // Transforms the string into ASTNode if ('typenames' in config) { @@ -690,6 +689,30 @@ export const plugin: PluginFunction = (schema, docu } }, }; + + const sharedGenerateMockOpts = { + customScalars: config.scalars, + defaultNullableToNull, + dynamicValues, + enumsAsTypes, + enumsPrefix: config.enumsPrefix, + enumValuesConvention, + fieldGeneration: config.fieldGeneration, + generateLibrary, + generatorLocale, + listElementCount, + nonNull: false, + prefix: config.prefix, + terminateCircularRelationships: getTerminateCircularRelationshipsConfig(config), + transformUnderscore, + typeNamesConvention, + typeNamesMapping, + types, + typesPrefix: config.typesPrefix, + useImplementingTypes, + useTypeImports, + }; + const visitor: VisitorType = { FieldDefinition: (node) => { const fieldName = node.name.value; @@ -700,27 +723,8 @@ export const plugin: PluginFunction = (schema, docu const value = generateMockValue({ typeName, fieldName, - types, - typeNamesConvention, - enumValuesConvention, - terminateCircularRelationships: getTerminateCircularRelationshipsConfig(config), - prefix: config.prefix, - typesPrefix: config.typesPrefix, - enumsPrefix: config.enumsPrefix, currentType: node.type, - customScalars: config.scalars, - transformUnderscore, - listElementCount, - dynamicValues, - generateLibrary, - generatorLocale, - fieldGeneration: config.fieldGeneration, - enumsAsTypes, - useTypeImports, - useImplementingTypes, - defaultNullableToNull, - nonNull: false, - typeNamesMapping: config.typeNamesMapping, + ...sharedGenerateMockOpts, }); return ` ${fieldName}: overrides && overrides.hasOwnProperty('${fieldName}') ? overrides.${fieldName}! : ${value},`; @@ -733,43 +737,41 @@ export const plugin: PluginFunction = (schema, docu return { typeName: fieldName, mockFn: () => { - const mockFields = node.fields - ? node.fields - .map((field) => { - const value = generateMockValue({ - typeName: fieldName, - fieldName: field.name.value, - types, - typeNamesConvention, - enumValuesConvention, - terminateCircularRelationships: getTerminateCircularRelationshipsConfig(config), - prefix: config.prefix, - typesPrefix: config.typesPrefix, - enumsPrefix: config.enumsPrefix, - currentType: field.type, - customScalars: config.scalars, - transformUnderscore, - listElementCount, - dynamicValues, - generateLibrary, - generatorLocale, - fieldGeneration: config.fieldGeneration, - enumsAsTypes, - useTypeImports, - useImplementingTypes, - defaultNullableToNull, - nonNull: false, - typeNamesMapping: config.typeNamesMapping, - }); - - return ` ${field.name.value}: overrides && overrides.hasOwnProperty('${field.name.value}') ? overrides.${field.name.value}! : ${value},`; - }) - .join('\n') - : ''; + let mockFieldsString = ''; + + const { directives } = node; + const hasOneOfDirective = directives.some((directive) => directive.name.value === 'oneOf'); + + if (node.fields && node.fields.length > 0 && hasOneOfDirective) { + const field = node.fields[0]; + const value = generateMockValue({ + typeName: fieldName, + fieldName: field.name.value, + currentType: field.type, + ...sharedGenerateMockOpts, + }); + + mockFieldsString = ` ...(override ? override : {${field.name.value} : ${value}}),`; + } else if (node.fields) { + mockFieldsString = node.fields + .map((field) => { + const value = generateMockValue({ + typeName: fieldName, + fieldName: field.name.value, + currentType: field.type, + ...sharedGenerateMockOpts, + }); + + const valueWithOverride = `overrides && overrides.hasOwnProperty('${field.name.value}') ? overrides.${field.name.value}! : ${value}`; + + return ` ${field.name.value}: ${valueWithOverride},`; + }) + .join('\n'); + } return getMockString( fieldName, - mockFields, + mockFieldsString, typeNamesConvention, getTerminateCircularRelationshipsConfig(config), false, @@ -777,6 +779,7 @@ export const plugin: PluginFunction = (schema, docu config.typesPrefix, transformUnderscore, typeNamesMapping, + hasOneOfDirective, ); }, }; diff --git a/tests/__snapshots__/typescript-mock-data.spec.ts.snap b/tests/__snapshots__/typescript-mock-data.spec.ts.snap index 8628fac..62093bd 100644 --- a/tests/__snapshots__/typescript-mock-data.spec.ts.snap +++ b/tests/__snapshots__/typescript-mock-data.spec.ts.snap @@ -64,6 +64,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : null}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : null, @@ -143,6 +149,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : null}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : null, @@ -222,6 +234,12 @@ export const mockUpdateUserInput = (overrides?: Partial): Updat }; }; +export const mockOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const mockMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : mockUser(), @@ -301,6 +319,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -317,7 +341,7 @@ export const aQuery = (overrides?: Partial): Query => { `; exports[`should add enumsPrefix to imports 1`] = ` -"import { Avatar, User, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, Mutation, Query, Api } from './types/graphql'; +"import { Avatar, User, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, OneOfInput, Mutation, Query, Api } from './types/graphql'; export const anAvatar = (overrides?: Partial): Avatar => { return { @@ -381,6 +405,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -461,6 +491,12 @@ export const anUpdateUserInput = (overrides?: Partial): Api }; }; +export const aOneOfInput = (override?: Api.OneOfInput): Api.OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Api.Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -540,6 +576,12 @@ export const anUpdateUserInput = (overrides?: Partial): Api }; }; +export const aOneOfInput = (override?: Api.OneOfInput): Api.OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Api.Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -620,6 +662,12 @@ export const anUpdateUserInput = (overrides?: Partial): Api }; }; +export const aOneOfInput = (override?: Api.OneOfInput): Api.OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Api.Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -699,6 +747,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -778,6 +832,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -857,6 +917,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -936,6 +1002,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -1015,6 +1087,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -1097,6 +1175,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : faker.lorem.word()}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -1181,6 +1265,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : casual.word}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -1262,6 +1352,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -1341,6 +1437,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'aut'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -1357,7 +1459,7 @@ export const aQuery = (overrides?: Partial): Query => { `; exports[`should generate mock data functions with external types file import 1`] = ` -"import { Avatar, User, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, Mutation, Query, AbcStatus, Status, PrefixedEnum } from './types/graphql'; +"import { Avatar, User, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, OneOfInput, Mutation, Query, AbcStatus, Status, PrefixedEnum } from './types/graphql'; export const anAvatar = (overrides?: Partial): Avatar => { return { @@ -1421,6 +1523,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -1500,6 +1608,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -1579,6 +1693,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -1658,6 +1778,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -1737,6 +1863,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -1816,6 +1948,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -1832,7 +1970,7 @@ export const aQuery = (overrides?: Partial): Query => { `; exports[`should generate mock data with PascalCase types and enums by default 1`] = ` -"import { Avatar, User, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, Mutation, Query, AbcStatus, Status, PrefixedEnum } from './types/graphql'; +"import { Avatar, User, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, OneOfInput, Mutation, Query, AbcStatus, Status, PrefixedEnum } from './types/graphql'; export const anAvatar = (overrides?: Partial): Avatar => { return { @@ -1896,6 +2034,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -1975,6 +2119,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -2054,6 +2204,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -2133,6 +2289,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -2212,6 +2374,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -2291,6 +2459,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -2377,6 +2551,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): { __typename: 'Mutation' } & Mutation => { return { __typename: 'Mutation', @@ -2458,6 +2638,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -2537,6 +2723,12 @@ export const anUPDATEUSERINPUT = (overrides?: Partial): UPDATEU }; }; +export const aONEOFINPUT = (override?: ONEOFINPUT): ONEOFINPUT => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMUTATION = (overrides?: Partial): MUTATION => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUSER(), @@ -2553,7 +2745,7 @@ export const aQUERY = (overrides?: Partial): QUERY => { `; exports[`should generate mock data with upperCase types and imports if typeNames is "upper-case#upperCase" 1`] = ` -"import { AVATAR, USER, WITHAVATAR, CAMELCASETHING, PREFIXED_RESPONSE, ABCTYPE, LISTTYPE, UPDATEUSERINPUT, MUTATION, QUERY, ABCSTATUS, STATUS, PREFIXED_ENUM } from './types/graphql'; +"import { AVATAR, USER, WITHAVATAR, CAMELCASETHING, PREFIXED_RESPONSE, ABCTYPE, LISTTYPE, UPDATEUSERINPUT, ONEOFINPUT, MUTATION, QUERY, ABCSTATUS, STATUS, PREFIXED_ENUM } from './types/graphql'; export const anAVATAR = (overrides?: Partial): AVATAR => { return { @@ -2617,6 +2809,12 @@ export const anUPDATEUSERINPUT = (overrides?: Partial): UPDATEU }; }; +export const aONEOFINPUT = (override?: ONEOFINPUT): ONEOFINPUT => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMUTATION = (overrides?: Partial): MUTATION => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUSER(), @@ -2633,7 +2831,7 @@ export const aQUERY = (overrides?: Partial): QUERY => { `; exports[`should generate multiple list elements 1`] = ` -"import { Avatar, User, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, Mutation, Query, AbcStatus, Status, PrefixedEnum } from './types/graphql'; +"import { Avatar, User, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, OneOfInput, Mutation, Query, AbcStatus, Status, PrefixedEnum } from './types/graphql'; export const anAvatar = (overrides?: Partial): Avatar => { return { @@ -2697,6 +2895,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -2713,7 +2917,7 @@ export const aQuery = (overrides?: Partial): Query => { `; exports[`should generate no list elements when listElementCount is 0 1`] = ` -"import { Avatar, User, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, Mutation, Query, AbcStatus, Status, PrefixedEnum } from './types/graphql'; +"import { Avatar, User, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, OneOfInput, Mutation, Query, AbcStatus, Status, PrefixedEnum } from './types/graphql'; export const anAvatar = (overrides?: Partial): Avatar => { return { @@ -2777,6 +2981,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -2793,7 +3003,7 @@ export const aQuery = (overrides?: Partial): Query => { `; exports[`should generate single list element 1`] = ` -"import { Avatar, User, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, Mutation, Query, AbcStatus, Status, PrefixedEnum } from './types/graphql'; +"import { Avatar, User, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, OneOfInput, Mutation, Query, AbcStatus, Status, PrefixedEnum } from './types/graphql'; export const anAvatar = (overrides?: Partial): Avatar => { return { @@ -2857,6 +3067,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -2873,7 +3089,7 @@ export const aQuery = (overrides?: Partial): Query => { `; exports[`should not merge imports into one if enumsPrefix does not contain dots 1`] = ` -"import { Avatar, User, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, Mutation, Query, ApiAbcStatus, ApiStatus, ApiPrefixedEnum } from './types/graphql'; +"import { Avatar, User, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, OneOfInput, Mutation, Query, ApiAbcStatus, ApiStatus, ApiPrefixedEnum } from './types/graphql'; export const anAvatar = (overrides?: Partial): Avatar => { return { @@ -2937,6 +3153,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -2953,7 +3175,7 @@ export const aQuery = (overrides?: Partial): Query => { `; exports[`should not merge imports into one if typesPrefix does not contain dots 1`] = ` -"import { ApiAvatar, ApiUser, ApiWithAvatar, ApiCamelCaseThing, ApiPrefixedResponse, ApiAbcType, ApiListType, ApiUpdateUserInput, ApiMutation, ApiQuery, AbcStatus, Status, PrefixedEnum } from './types/graphql'; +"import { ApiAvatar, ApiUser, ApiWithAvatar, ApiCamelCaseThing, ApiPrefixedResponse, ApiAbcType, ApiListType, ApiUpdateUserInput, ApiOneOfInput, ApiMutation, ApiQuery, AbcStatus, Status, PrefixedEnum } from './types/graphql'; export const anAvatar = (overrides?: Partial): ApiAvatar => { return { @@ -3017,6 +3239,12 @@ export const anUpdateUserInput = (overrides?: Partial): ApiU }; }; +export const aOneOfInput = (override?: ApiOneOfInput): ApiOneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): ApiMutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -3033,7 +3261,7 @@ export const aQuery = (overrides?: Partial): ApiQuery => { `; exports[`should preserve underscores if transformUnderscore is false 1`] = ` -"import { Avatar, User, WithAvatar, CamelCaseThing, Prefixed_Response, AbcType, ListType, UpdateUserInput, Mutation, Query, AbcStatus, Status, Prefixed_Enum } from './types/graphql'; +"import { Avatar, User, WithAvatar, CamelCaseThing, Prefixed_Response, AbcType, ListType, UpdateUserInput, OneOfInput, Mutation, Query, AbcStatus, Status, Prefixed_Enum } from './types/graphql'; export const anAvatar = (overrides?: Partial): Avatar => { return { @@ -3097,6 +3325,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -3113,7 +3347,7 @@ export const aQuery = (overrides?: Partial): Query => { `; exports[`should preserve underscores if transformUnderscore is false and enumsAsTypes is true 1`] = ` -"import { Avatar, User, WithAvatar, CamelCaseThing, Prefixed_Response, AbcType, ListType, UpdateUserInput, Mutation, Query } from './types/graphql'; +"import { Avatar, User, WithAvatar, CamelCaseThing, Prefixed_Response, AbcType, ListType, UpdateUserInput, OneOfInput, Mutation, Query } from './types/graphql'; export const anAvatar = (overrides?: Partial): Avatar => { return { @@ -3177,6 +3411,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -3193,7 +3433,7 @@ export const aQuery = (overrides?: Partial): Query => { `; exports[`should preserve underscores if transformUnderscore is false and enumsAsTypes is true as cast the enum type if useTypeImports is true 1`] = ` -"import type { Avatar, User, WithAvatar, CamelCaseThing, Prefixed_Response, AbcType, ListType, UpdateUserInput, Mutation, Query, AbcStatus, Status, Prefixed_Enum } from './types/graphql'; +"import type { Avatar, User, WithAvatar, CamelCaseThing, Prefixed_Response, AbcType, ListType, UpdateUserInput, OneOfInput, Mutation, Query, AbcStatus, Status, Prefixed_Enum } from './types/graphql'; export const anAvatar = (overrides?: Partial): Avatar => { return { @@ -3257,6 +3497,12 @@ export const anUpdateUserInput = (overrides?: Partial): UpdateU }; }; +export const aOneOfInput = (override?: OneOfInput): OneOfInput => { + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial): Mutation => { return { updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), @@ -3352,6 +3598,14 @@ export const anUpdateUserInput = (overrides?: Partial, _relatio }; }; +export const aOneOfInput = (override?: OneOfInput, _relationshipsToOmit: Set = new Set()): OneOfInput => { + const relationshipsToOmit: Set = new Set(_relationshipsToOmit); + relationshipsToOmit.add('OneOfInput'); + return { + ...(override ? override : {oneOfFieldA : 'tibi'}), + }; +}; + export const aMutation = (overrides?: Partial, _relationshipsToOmit: Set = new Set()): Mutation => { const relationshipsToOmit: Set = new Set(_relationshipsToOmit); relationshipsToOmit.add('Mutation'); diff --git a/tests/typescript-mock-data.spec.ts b/tests/typescript-mock-data.spec.ts index bdd692e..53a169a 100644 --- a/tests/typescript-mock-data.spec.ts +++ b/tests/typescript-mock-data.spec.ts @@ -7,6 +7,8 @@ const testSchema = buildSchema(/* GraphQL */ ` scalar Date scalar AnyObject + directive @oneOf on INPUT_OBJECT + type Avatar { id: ID! url: String! @@ -53,6 +55,11 @@ const testSchema = buildSchema(/* GraphQL */ ` avatar: Avatar } + input OneOfInput @oneOf { + oneOfFieldA: String + oneOfFieldB: String + } + enum ABCStatus { hasXYZStatus } @@ -116,12 +123,20 @@ it('should generate mock data functions with scalars', async () => { expect(result).toMatchSnapshot(); }); +it('should generate mock data for an input type with a oneOf directive', async () => { + const result = await plugin(testSchema, [], {}); + + expect(result).toBeDefined(); + expect(result).toContain(`const aOneOfInput = (override?: OneOfInput): OneOfInput`); + expect(result).toContain(`...(override ? override : {oneOfFieldA : 'tibi'}),`); +}); + it('should generate mock data functions with external types file import', async () => { const result = await plugin(testSchema, [], { typesFile: './types/graphql.ts' }); expect(result).toBeDefined(); expect(result).toContain( - "import { Avatar, User, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, Mutation, Query, AbcStatus, Status, PrefixedEnum } from './types/graphql';", + "import { Avatar, User, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, OneOfInput, Mutation, Query, AbcStatus, Status, PrefixedEnum } from './types/graphql';", ); expect(result).toMatchSnapshot(); }); @@ -379,7 +394,7 @@ it('should add enumsPrefix to imports', async () => { expect(result).toBeDefined(); expect(result).toContain( - "import { Avatar, User, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, Mutation, Query, Api } from './types/graphql';", + "import { Avatar, User, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, OneOfInput, Mutation, Query, Api } from './types/graphql';", ); expect(result).toMatchSnapshot(); }); @@ -404,7 +419,7 @@ it('should not merge imports into one if typesPrefix does not contain dots', asy expect(result).toBeDefined(); expect(result).toContain( - "import { ApiAvatar, ApiUser, ApiWithAvatar, ApiCamelCaseThing, ApiPrefixedResponse, ApiAbcType, ApiListType, ApiUpdateUserInput, ApiMutation, ApiQuery, AbcStatus, Status, PrefixedEnum } from './types/graphql';", + "import { ApiAvatar, ApiUser, ApiWithAvatar, ApiCamelCaseThing, ApiPrefixedResponse, ApiAbcType, ApiListType, ApiUpdateUserInput, ApiOneOfInput, ApiMutation, ApiQuery, AbcStatus, Status, PrefixedEnum } from './types/graphql';", ); expect(result).toMatchSnapshot(); }); @@ -417,7 +432,7 @@ it('should not merge imports into one if enumsPrefix does not contain dots', asy expect(result).toBeDefined(); expect(result).toContain( - "import { Avatar, User, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, Mutation, Query, ApiAbcStatus, ApiStatus, ApiPrefixedEnum } from './types/graphql';", + "import { Avatar, User, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, OneOfInput, Mutation, Query, ApiAbcStatus, ApiStatus, ApiPrefixedEnum } from './types/graphql';", ); expect(result).toMatchSnapshot(); }); @@ -441,7 +456,7 @@ it('should preserve underscores if transformUnderscore is false', async () => { expect(result).toBeDefined(); expect(result).toContain( - "import { Avatar, User, WithAvatar, CamelCaseThing, Prefixed_Response, AbcType, ListType, UpdateUserInput, Mutation, Query, AbcStatus, Status, Prefixed_Enum } from './types/graphql';", + "import { Avatar, User, WithAvatar, CamelCaseThing, Prefixed_Response, AbcType, ListType, UpdateUserInput, OneOfInput, Mutation, Query, AbcStatus, Status, Prefixed_Enum } from './types/graphql';", ); expect(result).toContain( 'export const aPrefixed_Response = (overrides?: Partial): Prefixed_Response => {', @@ -461,7 +476,7 @@ it('should preserve underscores if transformUnderscore is false and enumsAsTypes expect(result).toBeDefined(); expect(result).toContain( - "import { Avatar, User, WithAvatar, CamelCaseThing, Prefixed_Response, AbcType, ListType, UpdateUserInput, Mutation, Query } from './types/graphql';", + "import { Avatar, User, WithAvatar, CamelCaseThing, Prefixed_Response, AbcType, ListType, UpdateUserInput, OneOfInput, Mutation, Query } from './types/graphql';", ); expect(result).toContain( 'export const aPrefixed_Response = (overrides?: Partial): Prefixed_Response => {', @@ -482,7 +497,7 @@ it('should preserve underscores if transformUnderscore is false and enumsAsTypes expect(result).toBeDefined(); expect(result).toContain( - "import type { Avatar, User, WithAvatar, CamelCaseThing, Prefixed_Response, AbcType, ListType, UpdateUserInput, Mutation, Query, AbcStatus, Status, Prefixed_Enum } from './types/graphql';", + "import type { Avatar, User, WithAvatar, CamelCaseThing, Prefixed_Response, AbcType, ListType, UpdateUserInput, OneOfInput, Mutation, Query, AbcStatus, Status, Prefixed_Enum } from './types/graphql';", ); expect(result).toContain( 'export const aPrefixed_Response = (overrides?: Partial): Prefixed_Response => {', diff --git a/tsconfig.json b/tsconfig.json index 4099ea8..2d1a817 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,6 @@ "module": "esnext", "target": "es2018", "lib": ["es6", "esnext", "es2015", "dom"], - "suppressImplicitAnyIndexErrors": true, "moduleResolution": "node", "emitDecoratorMetadata": true, "sourceMap": true, diff --git a/yarn.lock b/yarn.lock index a70dac4..00d33c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1032,6 +1032,16 @@ dset "^3.1.2" tslib "^2.4.0" +"@graphql-tools/utils@^10.7.2": + version "10.7.2" + resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-10.7.2.tgz#feafb7be9211570037288f5a3cadab76de41a097" + integrity sha512-Wn85S+hfkzfVFpXVrQ0hjnePa3p28aB6IdAGCiD1SqBCSMDRzL+OFEtyAyb30nV9Mqflqs9lCqjqlR2puG857Q== + dependencies: + "@graphql-typed-document-node/core" "^3.1.1" + cross-inspect "1.0.1" + dset "^3.1.4" + tslib "^2.4.0" + "@graphql-typed-document-node/core@^3.1.1": version "3.2.0" resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" @@ -1552,6 +1562,11 @@ dependencies: "@types/node" "*" +"@types/indefinite@^2.3.4": + version "2.3.4" + resolved "https://registry.yarnpkg.com/@types/indefinite/-/indefinite-2.3.4.tgz#6525c3cf0615c022ffc087e7e1261c3d3d7c5743" + integrity sha512-X9sp9nbqkZT7hFNUKxicGr6gZLahs95lryW2Vvx5+krDxhWWle4K1OfJ4b8Sjd+FLul3tGhfYehtfeoFF1Ot4g== + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" @@ -2587,6 +2602,13 @@ cross-inspect@1.0.0: dependencies: tslib "^2.4.0" +cross-inspect@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cross-inspect/-/cross-inspect-1.0.1.tgz#15f6f65e4ca963cf4cc1a2b5fef18f6ca328712b" + integrity sha512-Pcw1JTvZLSJH83iiGWt6fRcT+BjZlCDRVwYLbUcHzv/CRpB7r0MlSrGbIyQvVSNyGnbt7G4AXuyCiDR3POvZ1A== + dependencies: + tslib "^2.4.0" + cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -2776,7 +2798,7 @@ dotenv@^8.0.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g== -dset@^3.1.2: +dset@^3.1.2, dset@^3.1.4: version "3.1.4" resolved "https://registry.yarnpkg.com/dset/-/dset-3.1.4.tgz#f8eaf5f023f068a036d08cd07dc9ffb7d0065248" integrity sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA== @@ -3481,9 +3503,9 @@ graphql-tag@^2.11.0: tslib "^2.1.0" graphql@^16.3.0: - version "16.8.1" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07" - integrity sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw== + version "16.10.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.10.0.tgz#24c01ae0af6b11ea87bf55694429198aaa8e220c" + integrity sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ== handlebars@^4.7.7: version "4.7.7" @@ -6236,10 +6258,10 @@ typescript-memoize@^1.0.0-alpha.3: resolved "https://registry.yarnpkg.com/typescript-memoize/-/typescript-memoize-1.1.0.tgz#4a8f512d06fc995167c703a3592219901db8bc79" integrity sha512-LQPKVXK8QrBBkL/zclE6YgSWn0I8ew5m0Lf+XL00IwMhlotqRLlzHV+BRrljVQIc+NohUAuQP7mg4HQwrx5Xbg== -typescript@^4.4.4: - version "4.6.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4" - integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg== +typescript@^5.7.3: + version "5.7.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.3.tgz#919b44a7dbb8583a9b856d162be24a54bf80073e" + integrity sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw== typical@^4.0.0: version "4.0.0"