From 28cd21b953efdbb51769310f3dc588bcf791ac94 Mon Sep 17 00:00:00 2001 From: nohehf Date: Fri, 23 Sep 2022 11:44:36 +0200 Subject: [PATCH 1/3] feat: basic mock --- src/converters.ts | 25 ++--------- src/format.ts | 107 ++++++++++++++++++++++++++------------------ src/mock.ts | 66 +++++++++++++++++++++++++++ src/outrospector.ts | 2 +- 4 files changed, 135 insertions(+), 65 deletions(-) create mode 100644 src/mock.ts diff --git a/src/converters.ts b/src/converters.ts index ab39e0b..16d3d9c 100644 --- a/src/converters.ts +++ b/src/converters.ts @@ -1,4 +1,5 @@ import { parse, print } from "https://esm.sh/v90/graphql@16.5.0"; +import { generateMockData, getDefaultTypeValue, MockResponse } from "./mock.ts"; import { Argument, ObjectField, Outrospection, Query } from "./outrospector.ts"; export interface FormattedArgument { @@ -18,6 +19,7 @@ export interface FormattedQuery { fullQuery: string; variables: string; outrospectQuery: Query; + mockResponse: MockResponse; } export interface QueryCollection { @@ -25,26 +27,6 @@ export interface QueryCollection { mutations: FormattedQuery[]; } -// @TODO: rework this -function getDefaultValue(type: string) { - switch (type) { - case "ID": - return `"0"`; - case "STRING" || "String": - return `""`; - case "INT" || "Int": - return `0`; - case "FLOAT": - return `0.0`; - case "BOOLEAN": - return `false`; - case "INPUT_OBJECT": - return `{}`; - default: - return `null`; - } -} - function nestedArgToString(arg: Argument, argStr?: string): string { if (!argStr) argStr = arg.typeName; if (arg.nesting.length === 0) { @@ -64,7 +46,7 @@ function formatArgument(arg: Argument): FormattedArgument { const formattedType: string = nestedArgToString(arg); const defaultNonNullValue = formattedType - .replace(arg.typeName, getDefaultValue(arg.typeName)) + .replace(arg.typeName, String(getDefaultTypeValue(arg.typeName))) .replaceAll("!", ""); const defaultValue = formattedType.includes("!") ? defaultNonNullValue @@ -152,6 +134,7 @@ function formatQuery( fullQuery: "", variables: "", outrospectQuery: query, + mockResponse: generateMockData(query, outrospection), }; Array.from(query.args).forEach(([_, arg], index) => { diff --git a/src/format.ts b/src/format.ts index e8ad3e5..6685a2d 100644 --- a/src/format.ts +++ b/src/format.ts @@ -1,28 +1,39 @@ import { FormattedQuery, QueryCollection } from "./converters.ts"; +import { MockResponse } from "./mock.ts"; -export interface PostmanItem { - name: string; - request: { - method: string; - header: { - key: string; - value: string; - }[]; - body: { - mode: string; - graphql: { - query: string; - variables: string; - }; - }; - url: { - raw: string; - protocol: string; - host: string[]; - path: string[]; +interface PostmanRequest { + method: string; + header: { + key: string; + value: string; + }[]; + body: { + mode: string; + graphql: { + query: string; + variables: string; }; }; - response: null[]; + url: { + raw: string; + protocol: string; + host: string[]; + path: string[]; + }; +} + +interface PostmanResponse { + name: string; + originalRequest: PostmanRequest; + body: string; + header: null[]; + cookie: null[]; + _postman_previewlanguage: "json"; +} +export interface PostmanItem { + name: string; + request: PostmanRequest; + response: (PostmanResponse | null)[]; } export interface PostmanFolder { @@ -49,30 +60,40 @@ function queryToItem( const host = [...rootUrl.split(".")]; const protocol = url.split("://")[0]; - const postmanItem: PostmanItem = { - name: query.outrospectQuery.name, - request: { - method: "POST", - header: [ - ...(authorization - ? [{ key: "Authorization", value: authorization }] - : []), - ], - body: { - mode: "graphql", - graphql: { - query: query.fullQuery, - variables: query.variables, - }, - }, - url: { - raw: url, - protocol, - host, - path, + const request: PostmanRequest = { + method: "POST", + header: [ + ...(authorization + ? [{ key: "Authorization", value: authorization }] + : []), + ], + body: { + mode: "graphql", + graphql: { + query: query.fullQuery, + variables: query.variables, }, }, - response: [], + url: { + raw: url, + protocol, + host, + path, + }, + }; + + const postmanItem: PostmanItem = { + name: query.outrospectQuery.name, + request: request, + response: [{ + name: query.outrospectQuery.name, + originalRequest: request, + body: JSON.stringify(query.mockResponse, null, 2), + //body: query.mockResponse, + header: [], + cookie: [], + _postman_previewlanguage: "json", + }], }; return postmanItem; diff --git a/src/mock.ts b/src/mock.ts new file mode 100644 index 0000000..05eb2e3 --- /dev/null +++ b/src/mock.ts @@ -0,0 +1,66 @@ +// The goal of this module is to generate fake data for types, for variables and mock responses + +import { Outrospection, Query } from "./outrospector.ts"; + +const defaultValues = { + ID: "1", + String: "", + STRING: "", + Int: 0, + INT: 0, + Float: 0.0, + FLOAT: 0.0, + Boolean: false, + BOOLEAN: false, + INPUT_OBJECT: {}, + OBJECT: {}, +}; + +const defaultScalarValue = "1"; + +export function getDefaultTypeValue(typeName: string) { + return Object(defaultValues)[typeName] ?? null; +} + +export interface MockResponse { + data: { + // deno-lint-ignore no-explicit-any + [key: string]: any; + }; +} + +export function generateMockData( + query: Query, + outrospection: Outrospection, +): MockResponse { + const mockData = new Map(); + + const type = outrospection.types.get(query.typeName); + if (!type) { + throw new Error(`Type ${query.typeName} not found in outrospection`); + } + + if (type.kind === "OBJECT") { + type.fields?.forEach((field) => { + mockData.set(field.name, getDefaultTypeValue(field.typeName)); + }); + } else if (type.kind === "SCALAR") { + mockData.set(type.name, defaultScalarValue); + } else { + //@TODO: handle other types if needed + mockData.set( + "notImplemented", + `Mock data for return type ${type.kind} is not implemented yet`, + ); + } + + const mock = { + data: { + [query.name]: { + "__typename": query.typeName, + ...Object.fromEntries(mockData), + }, + }, + }; + return mock; +} diff --git a/src/outrospector.ts b/src/outrospector.ts index b87799d..dcea150 100644 --- a/src/outrospector.ts +++ b/src/outrospector.ts @@ -8,7 +8,7 @@ import { import { getQueryAndMutationTypes } from "./lib.ts"; // @TODO add real support for "INTERFACE" | "UNION" | "INPUT_OBJECT" -type TypeBaseKind = +export type TypeBaseKind = | "LIST" | "NON_NULL" | "SCALAR" From 1ef2bd6bdd38a5e2c07cde5d20f1348553b6da5d Mon Sep 17 00:00:00 2001 From: nohehf Date: Fri, 23 Sep 2022 11:47:41 +0200 Subject: [PATCH 2/3] fix: lint --- src/format.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/format.ts b/src/format.ts index 6685a2d..d1bb07d 100644 --- a/src/format.ts +++ b/src/format.ts @@ -1,5 +1,4 @@ import { FormattedQuery, QueryCollection } from "./converters.ts"; -import { MockResponse } from "./mock.ts"; interface PostmanRequest { method: string; From a84537ff453463a51c1938ff35ecce14e8ae738a Mon Sep 17 00:00:00 2001 From: nohehf Date: Fri, 23 Sep 2022 12:06:41 +0200 Subject: [PATCH 3/3] feat: add code and status to mocked response --- src/format.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/format.ts b/src/format.ts index d1bb07d..50e0ff9 100644 --- a/src/format.ts +++ b/src/format.ts @@ -28,6 +28,8 @@ interface PostmanResponse { header: null[]; cookie: null[]; _postman_previewlanguage: "json"; + status: "OK"; + code: 200; } export interface PostmanItem { name: string; @@ -92,6 +94,8 @@ function queryToItem( header: [], cookie: [], _postman_previewlanguage: "json", + status: "OK", + code: 200, }], };