1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | var graphql_1 = require("graphql");
|
4 | var graphql_2 = require("graphql");
|
5 | var uuid = require("uuid");
|
6 | var schemaGenerator_1 = require("./schemaGenerator");
|
7 |
|
8 | function mockServer(schema, mocks, preserveResolvers) {
|
9 | if (preserveResolvers === void 0) { preserveResolvers = false; }
|
10 | var mySchema;
|
11 | if (!(schema instanceof graphql_1.GraphQLSchema)) {
|
12 |
|
13 | mySchema = schemaGenerator_1.buildSchemaFromTypeDefinitions(schema);
|
14 | }
|
15 | else {
|
16 | mySchema = schema;
|
17 | }
|
18 | addMockFunctionsToSchema({ schema: mySchema, mocks: mocks, preserveResolvers: preserveResolvers });
|
19 | return { query: function (query, vars) { return graphql_2.graphql(mySchema, query, {}, {}, vars); } };
|
20 | }
|
21 | exports.mockServer = mockServer;
|
22 |
|
23 |
|
24 |
|
25 | function addMockFunctionsToSchema(_a) {
|
26 | var schema = _a.schema, _b = _a.mocks, mocks = _b === void 0 ? {} : _b, _c = _a.preserveResolvers, preserveResolvers = _c === void 0 ? false : _c;
|
27 | function isObject(thing) {
|
28 | return thing === Object(thing) && !Array.isArray(thing);
|
29 | }
|
30 | if (!schema) {
|
31 | throw new Error('Must provide schema to mock');
|
32 | }
|
33 | if (!(schema instanceof graphql_1.GraphQLSchema)) {
|
34 | throw new Error('Value at "schema" must be of type GraphQLSchema');
|
35 | }
|
36 | if (!isObject(mocks)) {
|
37 | throw new Error('mocks must be of type Object');
|
38 | }
|
39 |
|
40 | var mockFunctionMap = new Map();
|
41 | Object.keys(mocks).forEach(function (typeName) {
|
42 | mockFunctionMap.set(typeName, mocks[typeName]);
|
43 | });
|
44 | mockFunctionMap.forEach(function (mockFunction, mockTypeName) {
|
45 | if (typeof mockFunction !== 'function') {
|
46 | throw new Error("mockFunctionMap[" + mockTypeName + "] must be a function");
|
47 | }
|
48 | });
|
49 | var defaultMockMap = new Map();
|
50 | defaultMockMap.set('Int', function () { return Math.round(Math.random() * 200) - 100; });
|
51 | defaultMockMap.set('Float', function () { return Math.random() * 200 - 100; });
|
52 | defaultMockMap.set('String', function () { return 'Hello World'; });
|
53 | defaultMockMap.set('Boolean', function () { return Math.random() > 0.5; });
|
54 | defaultMockMap.set('ID', function () { return uuid.v4(); });
|
55 | function mergeObjects(a, b) {
|
56 | return Object.assign(a, b);
|
57 | }
|
58 | function copyOwnPropsIfNotPresent(target, source) {
|
59 | Object.getOwnPropertyNames(source).forEach(function (prop) {
|
60 | if (!Object.getOwnPropertyDescriptor(target, prop)) {
|
61 | Object.defineProperty(target, prop, Object.getOwnPropertyDescriptor(source, prop));
|
62 | }
|
63 | });
|
64 | }
|
65 | function copyOwnProps(target) {
|
66 | var sources = [];
|
67 | for (var _i = 1; _i < arguments.length; _i++) {
|
68 | sources[_i - 1] = arguments[_i];
|
69 | }
|
70 | sources.forEach(function (source) {
|
71 | var chain = source;
|
72 | while (chain) {
|
73 | copyOwnPropsIfNotPresent(target, chain);
|
74 | chain = Object.getPrototypeOf(chain);
|
75 | }
|
76 | });
|
77 | return target;
|
78 | }
|
79 |
|
80 | function getRandomElement(ary) {
|
81 | var sample = Math.floor(Math.random() * ary.length);
|
82 | return ary[sample];
|
83 | }
|
84 |
|
85 |
|
86 |
|
87 |
|
88 | function mergeMocks(genericMockFunction, customMock) {
|
89 | if (Array.isArray(customMock)) {
|
90 | return customMock.map(function (el) { return mergeMocks(genericMockFunction, el); });
|
91 | }
|
92 | if (isObject(customMock)) {
|
93 | return mergeObjects(genericMockFunction(), customMock);
|
94 | }
|
95 | return customMock;
|
96 | }
|
97 | function getResolveType(namedFieldType) {
|
98 | if (namedFieldType instanceof graphql_1.GraphQLInterfaceType ||
|
99 | namedFieldType instanceof graphql_1.GraphQLUnionType) {
|
100 | return namedFieldType.resolveType;
|
101 | }
|
102 | else {
|
103 | return undefined;
|
104 | }
|
105 | }
|
106 | function assignResolveType(type) {
|
107 | var fieldType = graphql_1.getNullableType(type);
|
108 | var namedFieldType = graphql_1.getNamedType(fieldType);
|
109 | var oldResolveType = getResolveType(namedFieldType);
|
110 | if (preserveResolvers && oldResolveType && oldResolveType.length) {
|
111 | return;
|
112 | }
|
113 | if (namedFieldType instanceof graphql_1.GraphQLUnionType ||
|
114 | namedFieldType instanceof graphql_1.GraphQLInterfaceType) {
|
115 |
|
116 |
|
117 | namedFieldType.resolveType = function (data, context, info) {
|
118 | return info.schema.getType(data.__typename);
|
119 | };
|
120 | }
|
121 | }
|
122 | var mockType = function (type, typeName, fieldName) {
|
123 |
|
124 |
|
125 |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 | return function (root, args, context, info) {
|
131 |
|
132 | var fieldType = graphql_1.getNullableType(type);
|
133 | var namedFieldType = graphql_1.getNamedType(fieldType);
|
134 | if (root && typeof root[fieldName] !== 'undefined') {
|
135 | var result = void 0;
|
136 |
|
137 | if (typeof root[fieldName] === 'function') {
|
138 | result = root[fieldName](root, args, context, info);
|
139 | if (result instanceof MockList) {
|
140 | result = result.mock(root, args, context, info, fieldType, mockType);
|
141 | }
|
142 | }
|
143 | else {
|
144 | result = root[fieldName];
|
145 | }
|
146 |
|
147 |
|
148 | if (mockFunctionMap.has(namedFieldType.name)) {
|
149 | result = mergeMocks(mockFunctionMap
|
150 | .get(namedFieldType.name)
|
151 | .bind(null, root, args, context, info), result);
|
152 | }
|
153 | return result;
|
154 | }
|
155 | if (fieldType instanceof graphql_1.GraphQLList) {
|
156 | return [
|
157 | mockType(fieldType.ofType)(root, args, context, info),
|
158 | mockType(fieldType.ofType)(root, args, context, info),
|
159 | ];
|
160 | }
|
161 | if (mockFunctionMap.has(fieldType.name) &&
|
162 | !(fieldType instanceof graphql_1.GraphQLUnionType ||
|
163 | fieldType instanceof graphql_1.GraphQLInterfaceType)) {
|
164 |
|
165 | return mockFunctionMap.get(fieldType.name)(root, args, context, info);
|
166 | }
|
167 | if (fieldType instanceof graphql_1.GraphQLObjectType) {
|
168 |
|
169 | return {};
|
170 | }
|
171 |
|
172 |
|
173 | if (fieldType instanceof graphql_1.GraphQLUnionType ||
|
174 | fieldType instanceof graphql_1.GraphQLInterfaceType) {
|
175 | var implementationType = void 0;
|
176 | if (mockFunctionMap.has(fieldType.name)) {
|
177 | var interfaceMockObj = mockFunctionMap.get(fieldType.name)(root, args, context, info);
|
178 | if (!interfaceMockObj || !interfaceMockObj.__typename) {
|
179 | return Error("Please return a __typename in \"" + fieldType.name + "\"");
|
180 | }
|
181 | implementationType = schema.getType(interfaceMockObj.__typename);
|
182 | }
|
183 | else {
|
184 | var possibleTypes = schema.getPossibleTypes(fieldType);
|
185 | implementationType = getRandomElement(possibleTypes);
|
186 | }
|
187 | return Object.assign({ __typename: implementationType }, mockType(implementationType)(root, args, context, info));
|
188 | }
|
189 | if (fieldType instanceof graphql_1.GraphQLEnumType) {
|
190 | return getRandomElement(fieldType.getValues()).value;
|
191 | }
|
192 | if (defaultMockMap.has(fieldType.name)) {
|
193 | return defaultMockMap.get(fieldType.name)(root, args, context, info);
|
194 | }
|
195 |
|
196 |
|
197 |
|
198 | return Error("No mock defined for type \"" + fieldType.name + "\"");
|
199 | };
|
200 | };
|
201 | schemaGenerator_1.forEachField(schema, function (field, typeName, fieldName) {
|
202 | assignResolveType(field.type);
|
203 | var mockResolver;
|
204 |
|
205 |
|
206 |
|
207 | var isOnQueryType = schema.getQueryType()
|
208 | ? schema.getQueryType().name === typeName
|
209 | : false;
|
210 | var isOnMutationType = schema.getMutationType()
|
211 | ? schema.getMutationType().name === typeName
|
212 | : false;
|
213 | if (isOnQueryType || isOnMutationType) {
|
214 | if (mockFunctionMap.has(typeName)) {
|
215 | var rootMock_1 = mockFunctionMap.get(typeName);
|
216 |
|
217 | if (rootMock_1(undefined, {}, {}, {})[fieldName]) {
|
218 |
|
219 | mockResolver = function (root, args, context, info) {
|
220 | var updatedRoot = root || {};
|
221 | updatedRoot[fieldName] = rootMock_1(root, args, context, info)[fieldName];
|
222 |
|
223 |
|
224 |
|
225 |
|
226 |
|
227 | return mockType(field.type, typeName, fieldName)(updatedRoot, args, context, info);
|
228 | };
|
229 | }
|
230 | }
|
231 | }
|
232 | if (!mockResolver) {
|
233 | mockResolver = mockType(field.type, typeName, fieldName);
|
234 | }
|
235 | if (!preserveResolvers || !field.resolve) {
|
236 | field.resolve = mockResolver;
|
237 | }
|
238 | else {
|
239 | var oldResolver_1 = field.resolve;
|
240 | field.resolve = function (rootObject, args, context, info) {
|
241 | return Promise.all([
|
242 | mockResolver(rootObject, args, context, info),
|
243 | oldResolver_1(rootObject, args, context, info),
|
244 | ]).then(function (values) {
|
245 | var mockedValue = values[0], resolvedValue = values[1];
|
246 |
|
247 | if (mockedValue instanceof Error) {
|
248 |
|
249 | if (undefined === resolvedValue) {
|
250 | throw mockedValue;
|
251 | }
|
252 | return resolvedValue;
|
253 | }
|
254 | if (resolvedValue instanceof Date && mockedValue instanceof Date) {
|
255 | return undefined !== resolvedValue ? resolvedValue : mockedValue;
|
256 | }
|
257 | if (isObject(mockedValue) && isObject(resolvedValue)) {
|
258 |
|
259 |
|
260 | var emptyObject = Object.create(Object.getPrototypeOf(resolvedValue));
|
261 | return copyOwnProps(emptyObject, resolvedValue, mockedValue);
|
262 | }
|
263 | return undefined !== resolvedValue ? resolvedValue : mockedValue;
|
264 | });
|
265 | };
|
266 | }
|
267 | });
|
268 | }
|
269 | exports.addMockFunctionsToSchema = addMockFunctionsToSchema;
|
270 | var MockList = (function () {
|
271 |
|
272 | function MockList(len, wrappedFunction) {
|
273 | this.len = len;
|
274 | if (typeof wrappedFunction !== 'undefined') {
|
275 | if (typeof wrappedFunction !== 'function') {
|
276 | throw new Error('Second argument to MockList must be a function or undefined');
|
277 | }
|
278 | this.wrappedFunction = wrappedFunction;
|
279 | }
|
280 | }
|
281 | MockList.prototype.mock = function (root, args, context, info, fieldType, mockTypeFunc) {
|
282 | var arr;
|
283 | if (Array.isArray(this.len)) {
|
284 | arr = new Array(this.randint(this.len[0], this.len[1]));
|
285 | }
|
286 | else {
|
287 | arr = new Array(this.len);
|
288 | }
|
289 | for (var i = 0; i < arr.length; i++) {
|
290 | if (typeof this.wrappedFunction === 'function') {
|
291 | var res = this.wrappedFunction(root, args, context, info);
|
292 | if (res instanceof MockList) {
|
293 | var nullableType = graphql_1.getNullableType(fieldType.ofType);
|
294 | arr[i] = res.mock(root, args, context, info, nullableType, mockTypeFunc);
|
295 | }
|
296 | else {
|
297 | arr[i] = res;
|
298 | }
|
299 | }
|
300 | else {
|
301 | arr[i] = mockTypeFunc(fieldType.ofType)(root, args, context, info);
|
302 | }
|
303 | }
|
304 | return arr;
|
305 | };
|
306 | MockList.prototype.randint = function (low, high) {
|
307 | return Math.floor(Math.random() * (high - low + 1) + low);
|
308 | };
|
309 | return MockList;
|
310 | }());
|
311 | exports.MockList = MockList;
|
312 |
|
\ | No newline at end of file |