diff --git a/README.md b/README.md index bac1abc..f0ff221 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,11 @@ When disabled, underscores will be retained for type names when the case is chan When enabled, values will be generated dynamically when the mock function is called rather than statically when the mock function is generated. The values are generated consistently from a [casual seed](https://github.com/boo1ean/casual#seeding) that can be manually configured using the generated `seedMocks(seed: number)` function, as shown in [this test](https://github.com/JimmyPaolini/graphql-codegen-typescript-mock-data/blob/dynamic-mode/tests/dynamicValues/spec.ts#L13). +### generateLibrary (`'casual' | 'faker'`, defaultValue: `'casual'`) + +Select a library to generate mock values. The default is [casual](https://github.com/boo1ean/casual), Other options include [faker](https://github.com/faker-js/faker). +casual dependents on Node API and cannot be executed in a browser. faker is useful when you want to use a mock function with the dynamicValues option enabled in the browser. + ## Examples of usage **codegen.yml** diff --git a/package.json b/package.json index 4c18384..a3a0455 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "fakes" ], "dependencies": { + "@faker-js/faker": "^7.5.0", "@graphql-codegen/plugin-helpers": "^2.4.1", "casual": "^1.6.2", "indefinite": "^2.4.1", @@ -36,7 +37,6 @@ "devDependencies": { "@auto-it/conventional-commits": "^10.33.0", "@graphql-codegen/testing": "^1.17.7", - "@types/faker": "^5.5.9", "@types/jest": "^27.0.2", "@typescript-eslint/eslint-plugin": "^5.1.0", "@typescript-eslint/parser": "^5.1.0", diff --git a/src/index.ts b/src/index.ts index 643c980..377916f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ import { pascalCase } from 'pascal-case'; import { upperCase } from 'upper-case'; import { sentenceCase } from 'sentence-case'; import a from 'indefinite'; +import { setupFunctionTokens, setupMockValueGenerator } from './mockValueGenerator'; type NamingConvention = 'upper-case#upperCase' | 'pascal-case#pascalCase' | 'keep'; @@ -23,6 +24,7 @@ type Options = { transformUnderscore: boolean; listElementCount: number; dynamicValues: boolean; + generateLibrary: 'casual' | 'faker'; }; const convertName = (value: string, fn: (v: string) => string, transformUnderscore: boolean): string => { @@ -104,22 +106,24 @@ const getNamedType = (opts: Options): string | number | boolean = return ''; } - if (!opts.dynamicValues) casual.seed(hashedString(opts.typeName + opts.fieldName)); + const mockValueGenerator = setupMockValueGenerator({ + generateLibrary: opts.generateLibrary, + dynamicValues: opts.dynamicValues, + }); + if (!opts.dynamicValues) mockValueGenerator.seed(hashedString(opts.typeName + opts.fieldName)); const name = opts.currentType.name.value; const casedName = createNameConverter(opts.typenamesConvention, opts.transformUnderscore)(name); switch (name) { case 'String': - return opts.dynamicValues ? `casual.word` : `'${casual.word}'`; + return mockValueGenerator.word(); case 'Float': - return opts.dynamicValues - ? `Math.round(casual.double(0, 10) * 100) / 100` - : Math.round(casual.double(0, 10) * 100) / 100; + return mockValueGenerator.float(); case 'ID': - return opts.dynamicValues ? `casual.uuid` : `'${casual.uuid}'`; + return mockValueGenerator.uuid(); case 'Boolean': - return opts.dynamicValues ? `casual.boolean` : casual.boolean; + return mockValueGenerator.boolean(); case 'Int': - return opts.dynamicValues ? `casual.integer(0, 9999)` : casual.integer(0, 9999); + return mockValueGenerator.integer(); default: { const foundType = opts.types.find((enumType: TypeItem) => enumType.name === name); if (foundType) { @@ -151,11 +155,9 @@ const getNamedType = (opts: Options): string | number | boolean = // mapping for this particular scalar if (!customScalar || !customScalar.generator) { if (foundType.name === 'Date') { - return opts.dynamicValues - ? `new Date(casual.unix_time).toISOString()` - : `'${new Date(casual.unix_time).toISOString()}'`; + return mockValueGenerator.date(); } - return opts.dynamicValues ? `casual.word` : `'${casual.word}'`; + return mockValueGenerator.word(); } // If there is a mapping to a `casual` type, then use it and make sure @@ -332,6 +334,7 @@ export interface TypescriptMocksPluginConfig { transformUnderscore?: boolean; listElementCount?: number; dynamicValues?: boolean; + generateLibrary?: 'casual' | 'faker'; } interface TypeItem { @@ -372,6 +375,7 @@ export const plugin: PluginFunction = (schema, docu const transformUnderscore = config.transformUnderscore ?? true; const listElementCount = config.listElementCount > 0 ? config.listElementCount : 1; const dynamicValues = !!config.dynamicValues; + const generateLibrary = config.generateLibrary || 'casual'; // List of types that are enums const types: TypeItem[] = []; const visitor: VisitorType = { @@ -416,6 +420,7 @@ export const plugin: PluginFunction = (schema, docu transformUnderscore, listElementCount, dynamicValues, + generateLibrary, }); return ` ${fieldName}: overrides && overrides.hasOwnProperty('${fieldName}') ? overrides.${fieldName}! : ${value},`; @@ -446,6 +451,7 @@ export const plugin: PluginFunction = (schema, docu transformUnderscore, listElementCount, dynamicValues, + generateLibrary, }); return ` ${field.name.value}: overrides && overrides.hasOwnProperty('${field.name.value}') ? overrides.${field.name.value}! : ${value},`; @@ -541,13 +547,14 @@ export const plugin: PluginFunction = (schema, docu .filter((mockFn: () => string) => !!mockFn) .map((mockFn: () => string) => mockFn()) .join('\n'); + const functionTokens = setupFunctionTokens(generateLibrary); let mockFile = ''; - if (dynamicValues) mockFile += "import casual from 'casual';\n"; + if (dynamicValues) mockFile += `${functionTokens.import}\n`; mockFile += typesFileImport; - if (dynamicValues) mockFile += '\ncasual.seed(0);\n'; + if (dynamicValues) mockFile += `\n${functionTokens.seed}\n`; mockFile += mockFns; - if (dynamicValues) mockFile += '\n\nexport const seedMocks = (seed: number) => casual.seed(seed);'; + if (dynamicValues) mockFile += `\n\n${functionTokens.seedFunction}`; mockFile += '\n'; return mockFile; }; diff --git a/src/mockValueGenerator.ts b/src/mockValueGenerator.ts new file mode 100644 index 0000000..d56e472 --- /dev/null +++ b/src/mockValueGenerator.ts @@ -0,0 +1,104 @@ +import { faker } from '@faker-js/faker'; +import casual from 'casual'; + +interface MockValueGenerator { + dynamicValues: boolean; + word: () => string; + uuid: () => string; + boolean: () => boolean | string; + integer: () => number | string; + float: () => number | string; + date: () => string; + seed: (seed: number) => void; +} + +type MockValueGeneratorOptions = { + dynamicValues: boolean; +}; + +type FunctionTokens = Record<'import' | 'seed' | 'seedFunction', string>; + +type SetupMockValueGeneratorOptions = { + generateLibrary: 'casual' | 'faker'; + dynamicValues: boolean; +}; + +class CasualMockValueGenerator implements MockValueGenerator { + dynamicValues: boolean; + + constructor(opts: MockValueGeneratorOptions) { + this.dynamicValues = opts.dynamicValues; + } + + word = () => (this.dynamicValues ? `casual.word` : `'${casual.word}'`); + uuid = () => (this.dynamicValues ? `casual.uuid` : `'${casual.uuid}'`); + boolean = () => (this.dynamicValues ? `casual.boolean` : casual.boolean); + integer = () => (this.dynamicValues ? `casual.integer(0, 9999)` : `${casual.integer(0, 9999)}`); + float = () => + this.dynamicValues + ? `Math.round(casual.double(0, 10) * 100) / 100` + : `${Math.round(casual.double(0, 10) * 100) / 100}`; + date = () => + this.dynamicValues + ? `new Date(casual.unix_time).toISOString()` + : `'${new Date(casual.unix_time).toISOString()}'`; + seed = (seed: number) => casual.seed(seed); +} + +const casualFunctionTokens: FunctionTokens = { + import: `import casual from 'casual';`, + seed: 'casual.seed(0);', + seedFunction: 'export const seedMocks = (seed: number) => casual.seed(seed);', +}; + +class FakerMockValueGenerator implements MockValueGenerator { + dynamicValues: boolean; + + constructor(opts: MockValueGeneratorOptions) { + this.dynamicValues = opts.dynamicValues; + } + + word = () => (this.dynamicValues ? `faker.lorem.word()` : `'${faker.lorem.word()}'`); + uuid = () => (this.dynamicValues ? `faker.datatype.uuid()` : `'${faker.datatype.uuid()}'`); + boolean = () => (this.dynamicValues ? `faker.datatype.boolean()` : faker.datatype.boolean()); + integer = () => + this.dynamicValues + ? `faker.datatype.number({ min: 0, max: 9999 })` + : faker.datatype.number({ min: 0, max: 9999 }); + float = () => + this.dynamicValues + ? `faker.datatype.float({ min: 0, max: 10, precision: 0.1 })` + : faker.datatype.float({ min: 0, max: 10, precision: 0.1 }); + date = () => + this.dynamicValues + ? `faker.date.past().toISOString(1, new Date(2022, 0))` + : `'${faker.date.past(1, new Date(2022, 0)).toISOString()}'`; + seed = (seed: number) => faker.seed(seed); +} + +const fakerFunctionTokens: FunctionTokens = { + import: `import { faker } from '@faker-js/faker';`, + seed: 'faker.seed(0);', + seedFunction: 'export const seedMocks = (seed: number) => faker.seed(seed);', +}; + +export const setupMockValueGenerator = ({ + generateLibrary, + dynamicValues, +}: SetupMockValueGeneratorOptions): MockValueGenerator => { + switch (generateLibrary) { + case 'casual': + return new CasualMockValueGenerator({ dynamicValues }); + case 'faker': + return new FakerMockValueGenerator({ dynamicValues }); + } +}; + +export const setupFunctionTokens = (generateLibrary: 'casual' | 'faker'): FunctionTokens => { + switch (generateLibrary) { + case 'casual': + return casualFunctionTokens; + case 'faker': + return fakerFunctionTokens; + } +}; diff --git a/tests/__snapshots__/typescript-mock-data.spec.ts.snap b/tests/__snapshots__/typescript-mock-data.spec.ts.snap index 027bc65..62fa827 100644 --- a/tests/__snapshots__/typescript-mock-data.spec.ts.snap +++ b/tests/__snapshots__/typescript-mock-data.spec.ts.snap @@ -944,6 +944,89 @@ export const seedMocks = (seed: number) => casual.seed(seed); " `; +exports[`should generate dynamic values with faker 1`] = ` +"import { faker } from '@faker-js/faker'; + +faker.seed(0); + +export const anAvatar = (overrides?: Partial): Avatar => { + return { + id: overrides && overrides.hasOwnProperty('id') ? overrides.id! : faker.datatype.uuid(), + url: overrides && overrides.hasOwnProperty('url') ? overrides.url! : faker.lorem.word(), + }; +}; + +export const aUser = (overrides?: Partial): User => { + return { + id: overrides && overrides.hasOwnProperty('id') ? overrides.id! : faker.datatype.uuid(), + creationDate: overrides && overrides.hasOwnProperty('creationDate') ? overrides.creationDate! : faker.date.past().toISOString(1, new Date(2022, 0)), + login: overrides && overrides.hasOwnProperty('login') ? overrides.login! : faker.lorem.word(), + avatar: overrides && overrides.hasOwnProperty('avatar') ? overrides.avatar! : anAvatar(), + status: overrides && overrides.hasOwnProperty('status') ? overrides.status! : Status.Online, + customStatus: overrides && overrides.hasOwnProperty('customStatus') ? overrides.customStatus! : AbcStatus.HasXyzStatus, + scalarValue: overrides && overrides.hasOwnProperty('scalarValue') ? overrides.scalarValue! : faker.lorem.word(), + camelCaseThing: overrides && overrides.hasOwnProperty('camelCaseThing') ? overrides.camelCaseThing! : aCamelCaseThing(), + unionThing: overrides && overrides.hasOwnProperty('unionThing') ? overrides.unionThing! : anAvatar(), + prefixedEnum: overrides && overrides.hasOwnProperty('prefixedEnum') ? overrides.prefixedEnum! : PrefixedEnum.PrefixedValue, + }; +}; + +export const aWithAvatar = (overrides?: Partial): WithAvatar => { + return { + id: overrides && overrides.hasOwnProperty('id') ? overrides.id! : faker.datatype.uuid(), + avatar: overrides && overrides.hasOwnProperty('avatar') ? overrides.avatar! : anAvatar(), + }; +}; + +export const aCamelCaseThing = (overrides?: Partial): CamelCaseThing => { + return { + id: overrides && overrides.hasOwnProperty('id') ? overrides.id! : faker.datatype.uuid(), + }; +}; + +export const aPrefixedResponse = (overrides?: Partial): PrefixedResponse => { + return { + ping: overrides && overrides.hasOwnProperty('ping') ? overrides.ping! : faker.lorem.word(), + }; +}; + +export const anAbcType = (overrides?: Partial): AbcType => { + return { + abc: overrides && overrides.hasOwnProperty('abc') ? overrides.abc! : faker.lorem.word(), + }; +}; + +export const aListType = (overrides?: Partial): ListType => { + return { + stringList: overrides && overrides.hasOwnProperty('stringList') ? overrides.stringList! : [faker.lorem.word()], + }; +}; + +export const anUpdateUserInput = (overrides?: Partial): UpdateUserInput => { + return { + id: overrides && overrides.hasOwnProperty('id') ? overrides.id! : faker.datatype.uuid(), + login: overrides && overrides.hasOwnProperty('login') ? overrides.login! : faker.lorem.word(), + avatar: overrides && overrides.hasOwnProperty('avatar') ? overrides.avatar! : anAvatar(), + }; +}; + +export const aMutation = (overrides?: Partial): Mutation => { + return { + updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), + }; +}; + +export const aQuery = (overrides?: Partial): Query => { + return { + user: overrides && overrides.hasOwnProperty('user') ? overrides.user! : aUser(), + prefixed_query: overrides && overrides.hasOwnProperty('prefixed_query') ? overrides.prefixed_query! : aPrefixedResponse(), + }; +}; + +export const seedMocks = (seed: number) => faker.seed(seed); +" +`; + exports[`should generate mock data functions 1`] = ` " export const anAvatar = (overrides?: Partial): Avatar => { @@ -1022,6 +1105,84 @@ export const aQuery = (overrides?: Partial): Query => { " `; +exports[`should generate mock data functions with casual 1`] = ` +" +export const anAvatar = (overrides?: Partial): Avatar => { + return { + id: overrides && overrides.hasOwnProperty('id') ? overrides.id! : '0550ff93-dd31-49b4-8c38-ff1cb68bdc38', + url: overrides && overrides.hasOwnProperty('url') ? overrides.url! : 'aliquid', + }; +}; + +export const aUser = (overrides?: Partial): User => { + return { + id: overrides && overrides.hasOwnProperty('id') ? overrides.id! : 'a5756f00-41a6-422a-8a7d-d13ee6a63750', + creationDate: overrides && overrides.hasOwnProperty('creationDate') ? overrides.creationDate! : '1970-01-09T16:33:21.532Z', + login: overrides && overrides.hasOwnProperty('login') ? overrides.login! : 'libero', + avatar: overrides && overrides.hasOwnProperty('avatar') ? overrides.avatar! : anAvatar(), + status: overrides && overrides.hasOwnProperty('status') ? overrides.status! : Status.Online, + customStatus: overrides && overrides.hasOwnProperty('customStatus') ? overrides.customStatus! : AbcStatus.HasXyzStatus, + scalarValue: overrides && overrides.hasOwnProperty('scalarValue') ? overrides.scalarValue! : 'neque', + camelCaseThing: overrides && overrides.hasOwnProperty('camelCaseThing') ? overrides.camelCaseThing! : aCamelCaseThing(), + unionThing: overrides && overrides.hasOwnProperty('unionThing') ? overrides.unionThing! : anAvatar(), + prefixedEnum: overrides && overrides.hasOwnProperty('prefixedEnum') ? overrides.prefixedEnum! : PrefixedEnum.PrefixedValue, + }; +}; + +export const aWithAvatar = (overrides?: Partial): WithAvatar => { + return { + id: overrides && overrides.hasOwnProperty('id') ? overrides.id! : '89f515e7-31e0-461d-a230-c4c7f4dafc5c', + avatar: overrides && overrides.hasOwnProperty('avatar') ? overrides.avatar! : anAvatar(), + }; +}; + +export const aCamelCaseThing = (overrides?: Partial): CamelCaseThing => { + return { + id: overrides && overrides.hasOwnProperty('id') ? overrides.id! : '345b9cf9-00fa-4974-800f-aeee5ee7fd42', + }; +}; + +export const aPrefixedResponse = (overrides?: Partial): PrefixedResponse => { + return { + ping: overrides && overrides.hasOwnProperty('ping') ? overrides.ping! : 'sunt', + }; +}; + +export const anAbcType = (overrides?: Partial): AbcType => { + return { + abc: overrides && overrides.hasOwnProperty('abc') ? overrides.abc! : 'sit', + }; +}; + +export const aListType = (overrides?: Partial): ListType => { + return { + stringList: overrides && overrides.hasOwnProperty('stringList') ? overrides.stringList! : ['voluptatem'], + }; +}; + +export const anUpdateUserInput = (overrides?: Partial): UpdateUserInput => { + return { + id: overrides && overrides.hasOwnProperty('id') ? overrides.id! : '1d6a9360-c92b-4660-8e5f-04155047bddc', + login: overrides && overrides.hasOwnProperty('login') ? overrides.login! : 'qui', + avatar: overrides && overrides.hasOwnProperty('avatar') ? overrides.avatar! : anAvatar(), + }; +}; + +export const aMutation = (overrides?: Partial): Mutation => { + return { + updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), + }; +}; + +export const aQuery = (overrides?: Partial): Query => { + return { + user: overrides && overrides.hasOwnProperty('user') ? overrides.user! : aUser(), + prefixed_query: overrides && overrides.hasOwnProperty('prefixed_query') ? overrides.prefixed_query! : aPrefixedResponse(), + }; +}; +" +`; + 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'; @@ -1101,6 +1262,84 @@ export const aQuery = (overrides?: Partial): Query => { " `; +exports[`should generate mock data functions with faker 1`] = ` +" +export const anAvatar = (overrides?: Partial): Avatar => { + return { + id: overrides && overrides.hasOwnProperty('id') ? overrides.id! : '1550ff93-cd31-49b4-bc38-ef1cb68bdc38', + url: overrides && overrides.hasOwnProperty('url') ? overrides.url! : 'aliquid', + }; +}; + +export const aUser = (overrides?: Partial): User => { + return { + id: overrides && overrides.hasOwnProperty('id') ? overrides.id! : 'b5756f00-51a6-422a-9a7d-c13ee6a63750', + creationDate: overrides && overrides.hasOwnProperty('creationDate') ? overrides.creationDate! : '2021-06-27T14:29:24.774Z', + login: overrides && overrides.hasOwnProperty('login') ? overrides.login! : 'libero', + avatar: overrides && overrides.hasOwnProperty('avatar') ? overrides.avatar! : anAvatar(), + status: overrides && overrides.hasOwnProperty('status') ? overrides.status! : Status.Online, + customStatus: overrides && overrides.hasOwnProperty('customStatus') ? overrides.customStatus! : AbcStatus.HasXyzStatus, + scalarValue: overrides && overrides.hasOwnProperty('scalarValue') ? overrides.scalarValue! : 'neque', + camelCaseThing: overrides && overrides.hasOwnProperty('camelCaseThing') ? overrides.camelCaseThing! : aCamelCaseThing(), + unionThing: overrides && overrides.hasOwnProperty('unionThing') ? overrides.unionThing! : anAvatar(), + prefixedEnum: overrides && overrides.hasOwnProperty('prefixedEnum') ? overrides.prefixedEnum! : PrefixedEnum.PrefixedValue, + }; +}; + +export const aWithAvatar = (overrides?: Partial): WithAvatar => { + return { + id: overrides && overrides.hasOwnProperty('id') ? overrides.id! : '99f515e7-21e0-461d-8230-d4c7f4dafc5c', + avatar: overrides && overrides.hasOwnProperty('avatar') ? overrides.avatar! : anAvatar(), + }; +}; + +export const aCamelCaseThing = (overrides?: Partial): CamelCaseThing => { + return { + id: overrides && overrides.hasOwnProperty('id') ? overrides.id! : '245b9cf9-10fa-4974-900f-beee5ee7fd42', + }; +}; + +export const aPrefixedResponse = (overrides?: Partial): PrefixedResponse => { + return { + ping: overrides && overrides.hasOwnProperty('ping') ? overrides.ping! : 'sunt', + }; +}; + +export const anAbcType = (overrides?: Partial): AbcType => { + return { + abc: overrides && overrides.hasOwnProperty('abc') ? overrides.abc! : 'sit', + }; +}; + +export const aListType = (overrides?: Partial): ListType => { + return { + stringList: overrides && overrides.hasOwnProperty('stringList') ? overrides.stringList! : ['voluptatem'], + }; +}; + +export const anUpdateUserInput = (overrides?: Partial): UpdateUserInput => { + return { + id: overrides && overrides.hasOwnProperty('id') ? overrides.id! : '0d6a9360-d92b-4660-9e5f-14155047bddc', + login: overrides && overrides.hasOwnProperty('login') ? overrides.login! : 'eos', + avatar: overrides && overrides.hasOwnProperty('avatar') ? overrides.avatar! : anAvatar(), + }; +}; + +export const aMutation = (overrides?: Partial): Mutation => { + return { + updateUser: overrides && overrides.hasOwnProperty('updateUser') ? overrides.updateUser! : aUser(), + }; +}; + +export const aQuery = (overrides?: Partial): Query => { + return { + user: overrides && overrides.hasOwnProperty('user') ? overrides.user! : aUser(), + prefixed_query: overrides && overrides.hasOwnProperty('prefixed_query') ? overrides.prefixed_query! : aPrefixedResponse(), + }; +}; +" +`; + exports[`should generate mock data functions with scalars 1`] = ` " export const anAvatar = (overrides?: Partial): Avatar => { diff --git a/tests/generateLibrary/faker/__snapshots__/spec.ts.snap b/tests/generateLibrary/faker/__snapshots__/spec.ts.snap new file mode 100644 index 0000000..6ca9ca4 --- /dev/null +++ b/tests/generateLibrary/faker/__snapshots__/spec.ts.snap @@ -0,0 +1,25 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should generate dynamic values when dynamicValues is true 1`] = ` +Object { + "id": "89bd9d8d-69a6-474e-8f46-7cc8796ed151", + "obj": Object { + "bool": true, + "flt": 3.7, + "int": 202, + }, + "str": "est", +} +`; + +exports[`should generate dynamic values when dynamicValues is true 2`] = ` +Object { + "id": "fc2ddf7c-c78c-4a1b-a928-fc816742cb73", + "obj": Object { + "bool": false, + "flt": 0.1, + "int": 1352, + }, + "str": "similique", +} +`; diff --git a/tests/generateLibrary/faker/spec.ts b/tests/generateLibrary/faker/spec.ts new file mode 100644 index 0000000..c166261 --- /dev/null +++ b/tests/generateLibrary/faker/spec.ts @@ -0,0 +1,26 @@ +import { anA, seedMocks } from './mocks'; + +it('should generate dynamic values when dynamicValues is true', () => { + const a1 = anA(); + expect(a1).toMatchSnapshot(); + + const a2 = anA(); + expect(a2).toMatchSnapshot(); + + expect(a1).not.toEqual(a2); +}); + +it('should generate dynamic values from seed when dynamicValues is true', () => { + seedMocks(0); + const a1 = anA(); + + seedMocks(0); + const a1Copy = anA(); + + seedMocks(1); + const a2 = anA(); + + expect(a1).toEqual(a1Copy); + expect(a1).not.toEqual(a2); + expect(a1Copy).not.toEqual(a2); +}); diff --git a/tests/generateLibrary/schema.ts b/tests/generateLibrary/schema.ts new file mode 100644 index 0000000..d8d5bea --- /dev/null +++ b/tests/generateLibrary/schema.ts @@ -0,0 +1,15 @@ +import { buildSchema } from 'graphql'; + +export default buildSchema(/* GraphQL */ ` + type A { + id: ID! + str: String! + obj: B! + } + + type B { + int: Int! + flt: Float! + bool: Boolean! + } +`); diff --git a/tests/generateLibrary/types.ts b/tests/generateLibrary/types.ts new file mode 100644 index 0000000..334aa82 --- /dev/null +++ b/tests/generateLibrary/types.ts @@ -0,0 +1,11 @@ +export type A = { + id: string; + str: string; + obj: B; +}; + +export type B = { + int: number; + flt: number; + bool: boolean; +}; diff --git a/tests/globalSetup.ts b/tests/globalSetup.ts index 47a9586..e449b13 100644 --- a/tests/globalSetup.ts +++ b/tests/globalSetup.ts @@ -2,6 +2,7 @@ import fs from 'fs'; import { plugin } from '../src'; import circularRelationshipsSchema from './terminateCircularRelationships/schema'; import dynamicValuesSchema from './dynamicValues/schema'; +import generateLibrarySchema from './generateLibrary/schema'; export default async () => { const terminateCircularRelationshipsMocks = await plugin(circularRelationshipsSchema, [], { @@ -15,4 +16,11 @@ export default async () => { dynamicValues: true, }); fs.writeFileSync('./tests/dynamicValues/mocks.ts', dynamicValuesMocks.toString()); + + const generateWithFakerMocks = await plugin(generateLibrarySchema, [], { + typesFile: '../types.ts', + dynamicValues: true, + generateLibrary: 'faker', + }); + fs.writeFileSync('./tests/generateLibrary/faker/mocks.ts', generateWithFakerMocks.toString()); }; diff --git a/tests/typescript-mock-data.spec.ts b/tests/typescript-mock-data.spec.ts index 8fc7037..c84edfa 100644 --- a/tests/typescript-mock-data.spec.ts +++ b/tests/typescript-mock-data.spec.ts @@ -88,6 +88,23 @@ it('should generate mock data functions', async () => { expect(result).toMatchSnapshot(); }); +it('should generate mock data functions with faker', async () => { + const result = await plugin(testSchema, [], { generateLibrary: 'faker' }); + + expect(result).toBeDefined(); + expect(result).toMatchSnapshot(); +}); + +it('should generate mock data functions with casual', async () => { + const result = await plugin(testSchema, [], { generateLibrary: 'casual' }); + + expect(result).toBeDefined(); + expect(result).toMatchSnapshot(); + + const defaultResult = await plugin(testSchema, [], {}); + expect(result).toStrictEqual(defaultResult); +}); + it('should generate mock data functions with scalars', async () => { const result = await plugin(testSchema, [], {}); @@ -425,3 +442,10 @@ it('should generate dynamic values in mocks', async () => { expect(result).toBeDefined(); expect(result).toMatchSnapshot(); }); + +it('should generate dynamic values with faker', async () => { + const result = await plugin(testSchema, [], { dynamicValues: true, generateLibrary: 'faker' }); + + expect(result).toBeDefined(); + expect(result).toMatchSnapshot(); +}); diff --git a/yarn.lock b/yarn.lock index ba23eb4..d5c28f5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -430,6 +430,11 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@faker-js/faker@^7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@faker-js/faker/-/faker-7.5.0.tgz#8e8265f65f5b68d2a57886d59b03788eeb676264" + integrity sha512-8wNUCCUHvfvI0gQpDUho/3gPzABffnCn5um65F8dzQ86zz6dlt4+nmAA7PQUc8L+eH+9RgR/qzy5N/8kN0Ozdw== + "@graphql-codegen/plugin-helpers@1.17.7": version "1.17.7" resolved "https://registry.yarnpkg.com/@graphql-codegen/plugin-helpers/-/plugin-helpers-1.17.7.tgz#5903105fda9470aafefe9da29e3a6fb3a52b8376" @@ -916,11 +921,6 @@ resolved "https://registry.yarnpkg.com/@types/command-line-usage/-/command-line-usage-5.0.2.tgz#ba5e3f6ae5a2009d466679cc431b50635bf1a064" integrity sha512-n7RlEEJ+4x4TS7ZQddTmNSxP+zziEG0TNsMfiRIxcIVXt71ENJ9ojeXmGO3wPoTdn7pJcU2xc3CJYMktNT6DPg== -"@types/faker@^5.5.9": - version "5.5.9" - resolved "https://registry.yarnpkg.com/@types/faker/-/faker-5.5.9.tgz#588ede92186dc557bff8341d294335d50d255f0c" - integrity sha512-uCx6mP3UY5SIO14XlspxsGjgaemrxpssJI0Ol+GfhxtcKpv9pgRZYsS4eeKeHVLje6Qtc8lGszuBI461+gVZBA== - "@types/graceful-fs@^4.1.2": version "4.1.5" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15"