Skip to content

Commit b27e199

Browse files
author
s.vanriessen
committed
chore: add more tests and docs
1 parent 69fd16c commit b27e199

File tree

5 files changed

+120
-31
lines changed

5 files changed

+120
-31
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,26 @@ export const aUser = (overrides?: Partial<User>): User => {
155155
}
156156
```
157157
158+
### typeNamesMapping (`{ [typeName: string]: string }`, defaultValue: `{}`)
159+
160+
Allows you to define mappings to rename the types. This is useful when you want to override the generated type name. For example, if you have a type called `User` and you want to rename it to `RenamedUser` you can do the following:
161+
162+
```
163+
plugins:
164+
- typescript-mock-data:
165+
typesFile: '../generated-types.ts'
166+
typeNamesMapping:
167+
User: RenamedUser
168+
```
169+
170+
This will generate the following mock function:
171+
172+
```
173+
export const aUser = (overrides?: Partial<RenamedUser>): RenamedUser => {
174+
```
175+
176+
**Note:** It is not possible to rename your enums using this option.
177+
158178
### transformUnderscore (`boolean`, defaultValue: `true`)
159179
160180
When disabled, underscores will be retained for type names when the case is changed. It has no effect if `typeNames` is set to `keep`.

src/index.ts

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ type Options<T = TypeNode> = {
3939
useImplementingTypes: boolean;
4040
defaultNullableToNull: boolean;
4141
nonNull: boolean;
42+
typeNamesMapping?: Record<string, string>;
4243
};
4344

4445
const getTerminateCircularRelationshipsConfig = ({ terminateCircularRelationships }: TypescriptMocksPluginConfig) =>
@@ -64,6 +65,15 @@ const createNameConverter =
6465
return `${prefix}${convertName(value, resolveExternalModuleAndFn(convention), transformUnderscore)}`;
6566
};
6667

68+
const renameImports = (list: string[], typeNamesMapping: Record<string, string>) => {
69+
return list.map((type) => {
70+
if (typeNamesMapping && typeNamesMapping[type]) {
71+
return `${type} as ${typeNamesMapping[type]}`;
72+
}
73+
return type;
74+
});
75+
};
76+
6777
const toMockName = (typedName: string, casedName: string, prefix?: string) => {
6878
if (prefix) {
6979
return `${prefix}${casedName}`;
@@ -380,14 +390,20 @@ const getNamedType = (opts: Options<NamedTypeNode | ObjectTypeDefinitionNode>):
380390
opts.typeNamesConvention,
381391
opts.transformUnderscore,
382392
);
383-
const casedNameWithPrefix = typeNameConverter(name, opts.typesPrefix);
393+
const renamedType = renameImports([name], opts.typeNamesMapping)[0];
394+
const casedNameWithPrefix = typeNameConverter(renamedType, opts.typesPrefix);
384395
return `relationshipsToOmit.has('${casedName}') ? {} as ${casedNameWithPrefix} : ${toMockName(
385396
name,
386397
casedName,
387398
opts.prefix,
388399
)}({}, relationshipsToOmit)`;
389400
} else {
390-
return `relationshipsToOmit.has('${casedName}') ? {} as ${casedName} : ${toMockName(
401+
const renamedType = renameImports([name], opts.typeNamesMapping)[0];
402+
const renamedCasedName = createNameConverter(
403+
opts.typeNamesConvention,
404+
opts.transformUnderscore,
405+
)(renamedType);
406+
return `relationshipsToOmit.has('${casedName}') ? {} as ${renamedCasedName} : ${toMockName(
391407
name,
392408
casedName,
393409
opts.prefix,
@@ -443,10 +459,10 @@ const getMockString = (
443459
prefix,
444460
typesPrefix = '',
445461
transformUnderscore: boolean,
446-
newTypeNames?: Record<string, string>,
462+
typeNamesMapping?: Record<string, string>,
447463
) => {
448464
const typeNameConverter = createNameConverter(typeNamesConvention, transformUnderscore);
449-
const NewTypeName = newTypeNames[typeName] || typeName;
465+
const NewTypeName = typeNamesMapping[typeName] || typeName;
450466
const casedName = typeNameConverter(typeName);
451467
const casedNameWithPrefix = typeNameConverter(NewTypeName, typesPrefix);
452468
const typename = addTypename ? `\n __typename: '${typeName}',` : '';
@@ -491,7 +507,7 @@ const getImportTypes = ({
491507
transformUnderscore,
492508
enumsAsTypes,
493509
useTypeImports,
494-
newTypeNames,
510+
typeNamesMapping,
495511
}: {
496512
typeNamesConvention: NamingConvention;
497513
definitions: any;
@@ -502,24 +518,21 @@ const getImportTypes = ({
502518
transformUnderscore: boolean;
503519
enumsAsTypes: boolean;
504520
useTypeImports: boolean;
505-
newTypeNames?: Record<string, string>;
521+
typeNamesMapping?: Record<string, string>;
506522
}) => {
507523
const typenameConverter = createNameConverter(typeNamesConvention, transformUnderscore);
508524
const typeImports = typesPrefix?.endsWith('.')
509525
? [typesPrefix.slice(0, -1)]
510526
: definitions
511527
.filter(({ typeName }: { typeName: string }) => !!typeName)
512528
.map(({ typeName }: { typeName: string }) => typenameConverter(typeName, typesPrefix));
513-
const renamedTypeImports = typeImports.map((type) => {
514-
if (newTypeNames[type]) {
515-
return `${type} as ${newTypeNames[type]}`;
516-
}
517-
return type;
518-
});
529+
519530
const enumTypes = enumsPrefix?.endsWith('.')
520531
? [enumsPrefix.slice(0, -1)]
521532
: types.filter(({ type }) => type === 'enum').map(({ name }) => typenameConverter(name, enumsPrefix));
522533

534+
const renamedTypeImports = renameImports(typeImports, typeNamesMapping);
535+
523536
if (!enumsAsTypes || useTypeImports) {
524537
renamedTypeImports.push(...enumTypes);
525538
}
@@ -576,7 +589,7 @@ export interface TypescriptMocksPluginConfig {
576589
useImplementingTypes?: boolean;
577590
defaultNullableToNull?: boolean;
578591
useTypeImports?: boolean;
579-
newTypeNames?: Record<string, string>;
592+
typeNamesMapping?: Record<string, string>;
580593
}
581594

582595
interface TypeItem {
@@ -627,7 +640,7 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
627640
const useImplementingTypes = config.useImplementingTypes ?? false;
628641
const defaultNullableToNull = config.defaultNullableToNull ?? false;
629642
const generatorLocale = config.locale || 'en';
630-
const newTypeNames = config.newTypeNames || {};
643+
const typeNamesMapping = config.typeNamesMapping || {};
631644

632645
// List of types that are enums
633646
const types: TypeItem[] = [];
@@ -707,6 +720,7 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
707720
useImplementingTypes,
708721
defaultNullableToNull,
709722
nonNull: false,
723+
typeNamesMapping: config.typeNamesMapping,
710724
});
711725

712726
return ` ${fieldName}: overrides && overrides.hasOwnProperty('${fieldName}') ? overrides.${fieldName}! : ${value},`;
@@ -745,6 +759,7 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
745759
useImplementingTypes,
746760
defaultNullableToNull,
747761
nonNull: false,
762+
typeNamesMapping: config.typeNamesMapping,
748763
});
749764

750765
return ` ${field.name.value}: overrides && overrides.hasOwnProperty('${field.name.value}') ? overrides.${field.name.value}! : ${value},`;
@@ -761,7 +776,7 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
761776
config.prefix,
762777
config.typesPrefix,
763778
transformUnderscore,
764-
newTypeNames,
779+
typeNamesMapping,
765780
);
766781
},
767782
};
@@ -785,7 +800,7 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
785800
config.prefix,
786801
config.typesPrefix,
787802
transformUnderscore,
788-
newTypeNames,
803+
typeNamesMapping,
789804
);
790805
},
791806
};
@@ -807,7 +822,7 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
807822
config.prefix,
808823
config.typesPrefix,
809824
transformUnderscore,
810-
newTypeNames,
825+
typeNamesMapping,
811826
);
812827
},
813828
};
@@ -830,7 +845,7 @@ export const plugin: PluginFunction<TypescriptMocksPluginConfig> = (schema, docu
830845
transformUnderscore: transformUnderscore,
831846
useTypeImports: config.useTypeImports,
832847
enumsAsTypes,
833-
newTypeNames,
848+
typeNamesMapping,
834849
});
835850
// Function that will generate the mocks.
836851
// We generate it after having visited because we need to distinct types from enums

tests/typeNamesMapping/schema.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { buildSchema } from 'graphql/index';
2+
3+
export default buildSchema(/* GraphQL */ `
4+
enum EnumExample {
5+
LOREM
6+
IPSUM
7+
}
8+
9+
type A {
10+
id: ID!
11+
str: String!
12+
email: String!
13+
}
14+
15+
type B {
16+
id: ID!
17+
str: String!
18+
email: String!
19+
}
20+
21+
type C {
22+
id: ID!
23+
str: String!
24+
enum: EnumExample!
25+
D: D!
26+
}
27+
28+
type D {
29+
nested: C!
30+
}
31+
`);

tests/typeNamesMapping/spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { plugin } from '../../src';
2+
import testSchema from './schema';
3+
4+
it('should support typeNamesMapping', async () => {
5+
const result = await plugin(testSchema, [], {
6+
typesFile: './types/graphql.ts',
7+
typeNamesMapping: { A: 'RenamedAType' },
8+
});
9+
10+
expect(result).toBeDefined();
11+
expect(result).toContain("import { A as RenamedAType, B, C, D, EnumExample } from './types/graphql';");
12+
});
13+
14+
it('should support typeNamesMapping with circular relationships', async () => {
15+
const result = await plugin(testSchema, [], {
16+
typesFile: './types/graphql.ts',
17+
typeNamesMapping: { D: 'RenamedDType' },
18+
terminateCircularRelationships: 'immediate',
19+
});
20+
21+
expect(result).toBeDefined();
22+
expect(result).toContain("import { A, B, C, D as RenamedDType, EnumExample } from './types/graphql';");
23+
expect(result).toContain(
24+
"D: overrides && overrides.hasOwnProperty('D') ? overrides.D! : relationshipsToOmit.has('D') ? {} as DAsRenamedDType : aD({}, relationshipsToOmit),",
25+
);
26+
});
27+
28+
it('should not support typeNamesMapping when enum type is given', async () => {
29+
const result = await plugin(testSchema, [], {
30+
typesFile: './types/graphql.ts',
31+
typeNamesMapping: { EnumExample: 'RenamedEnum' },
32+
});
33+
34+
expect(result).toBeDefined();
35+
expect(result).toContain("import { A, B, C, D, EnumExample } from './types/graphql';");
36+
});

tests/useTypeImports/spec.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,3 @@ it('should support useTypeImports', async () => {
1010
);
1111
expect(result).toMatchSnapshot();
1212
});
13-
14-
it('should support useTypeImports', async () => {
15-
const result = await plugin(testSchema, [], {
16-
typesFile: './types/graphql.ts',
17-
useTypeImports: true,
18-
newTypeNames: { Partial: 'RenamedPartial' },
19-
});
20-
21-
expect(result).toBeDefined();
22-
expect(result).toContain(
23-
"import type { Avatar, User, Partial as RenamedPartial, WithAvatar, CamelCaseThing, PrefixedResponse, AbcType, ListType, UpdateUserInput, Mutation, Query, AbcStatus, Status, PrefixedEnum } from './types/graphql';",
24-
);
25-
});

0 commit comments

Comments
 (0)