-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtestHelpers.ts
144 lines (126 loc) · 3.88 KB
/
testHelpers.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import { graphql, GraphQLSchema, ExecutionResult, GraphQLError } from 'graphql';
import {
SchemaComposer,
Resolver,
ObjectTypeComposerFieldConfigAsObjectDefinition,
inspect,
SchemaPrinterOptions,
} from 'graphql-compose';
const FIELD = 'field';
interface RunQueryOpts {
fc: ObjectTypeComposerFieldConfigAsObjectDefinition<any, any, any> | Resolver;
operation: string;
variables?: Record<string, any>;
source?: Record<string, any>;
context?: Record<string, any>;
schemaComposer?: SchemaComposer<any>;
}
export function testBuildSchema(
fc: ObjectTypeComposerFieldConfigAsObjectDefinition<any, any, any> | Resolver,
schemaComposer?: SchemaComposer<any>
): GraphQLSchema {
const sc = schemaComposer || new SchemaComposer();
sc.Query.setField(FIELD, fc);
return sc.buildSchema();
}
function _getArgsForQuery(
fc: ObjectTypeComposerFieldConfigAsObjectDefinition<any, any, any> | Resolver,
variables: Record<string, any> = {},
schemaComposer?: SchemaComposer<any>
): {
queryVars: string;
fieldVars: string;
} {
const sc = schemaComposer || new SchemaComposer();
sc.Query.setField(FIELD, fc);
const varNames = Object.keys(variables);
const argNames = sc.Query.getFieldArgNames(FIELD);
if (argNames.length === 0 && varNames.length > 0) {
throw new Error(
`FieldConfig does not have any arguments. But in test you provided the following variables: ${inspect(
variables
)}`
);
}
varNames.forEach((varName) => {
if (!argNames.includes(varName)) {
throw new Error(
`FieldConfig does not have '${varName}' argument. Available arguments: '${argNames.join(
"', '"
)}'.`
);
}
});
argNames.forEach((argName) => {
if (sc.Query.isFieldArgNonNull(FIELD, argName)) {
const val = variables[argName];
if (val === null || val === undefined) {
throw new Error(
`FieldConfig has required argument '${argName}'. But you did not provide it in your test via variables: '${inspect(
variables
)}'.`
);
}
}
});
const queryVars = varNames
.map((n) => `$${n}: ${String(sc.Query.getFieldArgType(FIELD, n))}`)
.join(' ');
const fieldVars = varNames.map((n) => `${n}: $${n}`).join(' ');
return {
queryVars: queryVars ? `(${queryVars})` : '',
fieldVars: fieldVars ? `(${fieldVars})` : '',
};
}
export async function testOperation(opts: RunQueryOpts): Promise<ExecutionResult> {
const schema = testBuildSchema(opts.fc, opts.schemaComposer);
const res = await graphql({
schema,
source: opts.operation,
rootValue: opts?.source,
contextValue: opts?.context,
variableValues: opts?.variables,
});
return res;
}
export async function testOperationData(
opts: Omit<RunQueryOpts, 'operation'> & { selectionSet: string }
): Promise<Record<string, any> | null> {
const { selectionSet, ...restOpts } = opts;
const ac = _getArgsForQuery(opts.fc, opts.variables, opts.schemaComposer);
const res = await testOperation({
operation: `
query ${ac.queryVars} {
field${ac.fieldVars} ${selectionSet.trim()}
}
`,
...restOpts,
});
if (res.errors) {
throw new Error((res?.errors?.[0] as any) || 'GraphQL Error');
}
return res?.data?.field as any;
}
export async function testOperationErrors(
opts: RunQueryOpts
): Promise<readonly GraphQLError[] | void> {
const res = await testOperation(opts);
return res?.errors;
}
export function testSDL(
opts: {
fc: ObjectTypeComposerFieldConfigAsObjectDefinition<any, any, any> | Resolver;
schemaComposer?: SchemaComposer<any>;
deep?: boolean;
} & SchemaPrinterOptions
): string {
const sc = opts.schemaComposer || new SchemaComposer();
sc.Query.setField(FIELD, opts.fc);
sc.buildSchema();
return sc.Query.toSDL({
...opts,
deep: opts.deep ?? true,
omitDescriptions: true,
omitSpecifiedByUrl: true,
});
}