Skip to content

Commit e7c886f

Browse files
authored
fix: custom generator for native scalars (#95)
Only non-native scalars were supported by the `scalars` config. We now check if a custom scalar is defined for each native type fixes #91
1 parent d70ac53 commit e7c886f

File tree

5 files changed

+147
-38
lines changed

5 files changed

+147
-38
lines changed

src/index.ts

Lines changed: 48 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,33 @@ const getScalarDefinition = (value: ScalarDefinition | ScalarGeneratorName): Sca
101101
return value;
102102
};
103103

104+
const getCustomScalarValue = (customScalar: ScalarDefinition, opts: Options<NamedTypeNode>) => {
105+
// If there is a mapping to a `casual` type, then use it and make sure
106+
// to call it if it's a function
107+
const embeddedGenerator = casual[customScalar.generator];
108+
if (!embeddedGenerator && customScalar.generator) {
109+
return customScalar.generator;
110+
}
111+
112+
const generatorArgs: unknown[] = Array.isArray(customScalar.arguments)
113+
? customScalar.arguments
114+
: [customScalar.arguments];
115+
if (opts.dynamicValues) {
116+
return `casual['${customScalar.generator}']${
117+
typeof embeddedGenerator === 'function' ? `(...${JSON.stringify(generatorArgs)})` : ''
118+
}`;
119+
}
120+
const value = typeof embeddedGenerator === 'function' ? embeddedGenerator(...generatorArgs) : embeddedGenerator;
121+
122+
if (typeof value === 'string') {
123+
return `'${value}'`;
124+
}
125+
if (typeof value === 'object') {
126+
return `${JSON.stringify(value)}`;
127+
}
128+
return value;
129+
};
130+
104131
const getNamedType = (opts: Options<NamedTypeNode>): string | number | boolean => {
105132
if (!opts.currentType) {
106133
return '';
@@ -114,16 +141,26 @@ const getNamedType = (opts: Options<NamedTypeNode>): string | number | boolean =
114141
const name = opts.currentType.name.value;
115142
const casedName = createNameConverter(opts.typenamesConvention, opts.transformUnderscore)(name);
116143
switch (name) {
117-
case 'String':
118-
return mockValueGenerator.word();
119-
case 'Float':
120-
return mockValueGenerator.float();
121-
case 'ID':
122-
return mockValueGenerator.uuid();
123-
case 'Boolean':
124-
return mockValueGenerator.boolean();
125-
case 'Int':
126-
return mockValueGenerator.integer();
144+
case 'String': {
145+
const customScalar = opts.customScalars ? getScalarDefinition(opts.customScalars['String']) : null;
146+
return customScalar ? getCustomScalarValue(customScalar, opts) : mockValueGenerator.word();
147+
}
148+
case 'Float': {
149+
const customScalar = opts.customScalars ? getScalarDefinition(opts.customScalars['Float']) : null;
150+
return customScalar ? getCustomScalarValue(customScalar, opts) : mockValueGenerator.float();
151+
}
152+
case 'ID': {
153+
const customScalar = opts.customScalars ? getScalarDefinition(opts.customScalars['ID']) : null;
154+
return customScalar ? getCustomScalarValue(customScalar, opts) : mockValueGenerator.uuid();
155+
}
156+
case 'Boolean': {
157+
const customScalar = opts.customScalars ? getScalarDefinition(opts.customScalars['Boolean']) : null;
158+
return customScalar ? getCustomScalarValue(customScalar, opts) : mockValueGenerator.boolean();
159+
}
160+
case 'Int': {
161+
const customScalar = opts.customScalars ? getScalarDefinition(opts.customScalars['Int']) : null;
162+
return customScalar ? getCustomScalarValue(customScalar, opts) : mockValueGenerator.integer();
163+
}
127164
default: {
128165
const foundType = opts.types.find((enumType: TypeItem) => enumType.name === name);
129166
if (foundType) {
@@ -160,34 +197,7 @@ const getNamedType = (opts: Options<NamedTypeNode>): string | number | boolean =
160197
return mockValueGenerator.word();
161198
}
162199

163-
// If there is a mapping to a `casual` type, then use it and make sure
164-
// to call it if it's a function
165-
const embeddedGenerator = casual[customScalar.generator];
166-
167-
if (!embeddedGenerator && customScalar.generator) {
168-
return customScalar.generator;
169-
}
170-
171-
const generatorArgs: unknown[] = Array.isArray(customScalar.arguments)
172-
? customScalar.arguments
173-
: [customScalar.arguments];
174-
if (opts.dynamicValues) {
175-
return `casual['${customScalar.generator}']${
176-
typeof embeddedGenerator === 'function' ? `(...${JSON.stringify(generatorArgs)})` : ''
177-
}`;
178-
}
179-
const value =
180-
typeof embeddedGenerator === 'function'
181-
? embeddedGenerator(...generatorArgs)
182-
: embeddedGenerator;
183-
184-
if (typeof value === 'string') {
185-
return `'${value}'`;
186-
}
187-
if (typeof value === 'object') {
188-
return `${JSON.stringify(value)}`;
189-
}
190-
return value;
200+
return getCustomScalarValue(customScalar, opts);
191201
}
192202
default:
193203
throw `foundType is unknown: ${foundType.name}: ${foundType.type}`;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`should generate custom scalars for native and custom types 1`] = `
4+
"
5+
export const anA = (overrides?: Partial<A>): A => {
6+
return {
7+
id: overrides && overrides.hasOwnProperty('id') ? overrides.id! : 82,
8+
str: overrides && overrides.hasOwnProperty('str') ? overrides.str! : 'ea corrupti qui incidunt eius consequatur blanditiis',
9+
obj: overrides && overrides.hasOwnProperty('obj') ? overrides.obj! : aB(),
10+
anyObject: overrides && overrides.hasOwnProperty('anyObject') ? overrides.anyObject! : '[email protected]',
11+
};
12+
};
13+
14+
export const aB = (overrides?: Partial<B>): B => {
15+
return {
16+
int: overrides && overrides.hasOwnProperty('int') ? overrides.int! : -93,
17+
flt: overrides && overrides.hasOwnProperty('flt') ? overrides.flt! : -24.509902694262564,
18+
bool: overrides && overrides.hasOwnProperty('bool') ? overrides.bool! : false,
19+
};
20+
};
21+
"
22+
`;

tests/scalars/schema.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { buildSchema } from 'graphql';
2+
3+
export default buildSchema(/* GraphQL */ `
4+
scalar AnyObject
5+
6+
type A {
7+
id: ID!
8+
str: String!
9+
obj: B!
10+
anyObject: AnyObject!
11+
}
12+
13+
type B {
14+
int: Int!
15+
flt: Float!
16+
bool: Boolean!
17+
}
18+
`);

tests/scalars/spec.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { plugin } from '../../src';
2+
import testSchema from './schema';
3+
4+
it('should generate custom scalars for native and custom types', async () => {
5+
const result = await plugin(testSchema, [], {
6+
scalars: {
7+
String: 'string',
8+
Float: {
9+
generator: 'double',
10+
arguments: [-100, 0],
11+
},
12+
ID: {
13+
generator: 'integer',
14+
arguments: [1, 100],
15+
},
16+
Boolean: 'false',
17+
Int: {
18+
generator: 'integer',
19+
arguments: [-100, 0],
20+
},
21+
AnyObject: 'email',
22+
},
23+
});
24+
25+
expect(result).toBeDefined();
26+
27+
// String
28+
expect(result).toContain(
29+
"str: overrides && overrides.hasOwnProperty('str') ? overrides.str! : 'ea corrupti qui incidunt eius consequatur blanditiis',",
30+
);
31+
32+
// Float
33+
expect(result).toContain(
34+
"flt: overrides && overrides.hasOwnProperty('flt') ? overrides.flt! : -24.509902694262564,",
35+
);
36+
37+
// ID
38+
expect(result).toContain("id: overrides && overrides.hasOwnProperty('id') ? overrides.id! : 82,");
39+
40+
// Boolean
41+
expect(result).toContain("bool: overrides && overrides.hasOwnProperty('bool') ? overrides.bool! : false");
42+
43+
// Int
44+
expect(result).toContain("int: overrides && overrides.hasOwnProperty('int') ? overrides.int! : -93,");
45+
46+
expect(result).toMatchSnapshot();
47+
});

tests/scalars/types.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export type A = {
2+
id: string;
3+
str: string;
4+
obj: B;
5+
anyObject: any;
6+
};
7+
8+
export type B = {
9+
int: number;
10+
flt: number;
11+
bool: boolean;
12+
};

0 commit comments

Comments
 (0)