From f568bb8f57fb9df8441d57436a7e625e5aff27e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt?= Date: Mon, 26 Oct 2020 17:31:59 +0100 Subject: [PATCH] fix(amplify-appsync-simulator): appsync scalars --- .../amplify-appsync-simulator/package.json | 2 +- .../src/__tests__/scalars/AWSJSON.test.ts | 62 +++++++++++++++++++ .../__snapshots__/AWSJSON.test.ts.snap | 9 +++ .../src/schema/appsync-scalars/index.ts | 35 ++++++++++- .../src/schema/index.ts | 5 +- 5 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 packages/amplify-appsync-simulator/src/__tests__/scalars/AWSJSON.test.ts create mode 100644 packages/amplify-appsync-simulator/src/__tests__/scalars/__snapshots__/AWSJSON.test.ts.snap diff --git a/packages/amplify-appsync-simulator/package.json b/packages/amplify-appsync-simulator/package.json index 7e0768bf35e..abf91f06e37 100644 --- a/packages/amplify-appsync-simulator/package.json +++ b/packages/amplify-appsync-simulator/package.json @@ -76,7 +76,7 @@ "!**/*.d.ts" ], "testURL": "http://localhost/", - "testRegex": "(src/__tests__/.*.test.*)$", + "testRegex": "(src/__tests__/.*.test.ts)$", "moduleFileExtensions": [ "ts", "tsx", diff --git a/packages/amplify-appsync-simulator/src/__tests__/scalars/AWSJSON.test.ts b/packages/amplify-appsync-simulator/src/__tests__/scalars/AWSJSON.test.ts new file mode 100644 index 00000000000..7ad9a404d40 --- /dev/null +++ b/packages/amplify-appsync-simulator/src/__tests__/scalars/AWSJSON.test.ts @@ -0,0 +1,62 @@ +import { scalars } from '../../schema/appsync-scalars'; + +describe('AWSJSON parse', () => { + it('Should reject an invalid json encoded object', () => { + function parse() { + scalars.AWSJSON.parseValue('{Foo: "Not Valid"}'); + } + expect(parse).toThrowErrorMatchingSnapshot(); + }); + it('Should reject a non json string', () => { + function parse() { + scalars.AWSJSON.parseValue('hello world'); + } + expect(parse).toThrowErrorMatchingSnapshot(); + }); + + it('Should reject a non json boolean', () => { + function parse() { + scalars.AWSJSON.parseValue(true); + } + expect(parse).toThrowErrorMatchingSnapshot(); + }); + + it('Should reject a non json int', () => { + function parse() { + scalars.AWSJSON.parseValue(1); + } + expect(parse).toThrowErrorMatchingSnapshot(); + }); + + it('Should accept a json encoded object', () => { + expect(scalars.AWSJSON.parseValue('{"Foo": "Bar"}')).toMatchObject({ + Foo: 'Bar', + }); + }); + + it('Should accept a json string', () => { + expect(scalars.AWSJSON.parseValue('"Hello world"')).toEqual('Hello world'); + }); + + it('Should accept a json boolean', () => { + expect(scalars.AWSJSON.parseValue('true')).toEqual(true); + }); + + it('Should accept a json int', () => { + expect(scalars.AWSJSON.parseValue('1')).toEqual(1); + }); +}); + +describe('AWSJSON serialize', () => { + it('Should serialize an obkect', () => { + expect(scalars.AWSJSON.serialize({ foo: 'Bar' })).toEqual('{"foo":"Bar"}'); + }); + + it('Should serialize a boolean', () => { + expect(scalars.AWSJSON.serialize(true)).toEqual('true'); + }); + + it('Should serialize an integer', () => { + expect(scalars.AWSJSON.serialize(1)).toEqual('1'); + }); +}); diff --git a/packages/amplify-appsync-simulator/src/__tests__/scalars/__snapshots__/AWSJSON.test.ts.snap b/packages/amplify-appsync-simulator/src/__tests__/scalars/__snapshots__/AWSJSON.test.ts.snap new file mode 100644 index 00000000000..e356e47b29c --- /dev/null +++ b/packages/amplify-appsync-simulator/src/__tests__/scalars/__snapshots__/AWSJSON.test.ts.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`AWSJSON parse Should reject a non json boolean 1`] = `"Unable to parse true as valid JSON."`; + +exports[`AWSJSON parse Should reject a non json int 1`] = `"Unable to parse 1 as valid JSON."`; + +exports[`AWSJSON parse Should reject a non json string 1`] = `"Unable to parse hello world as valid JSON."`; + +exports[`AWSJSON parse Should reject an invalid json encoded object 1`] = `"Unable to parse {Foo: \\"Not Valid\\"} as valid JSON."`; diff --git a/packages/amplify-appsync-simulator/src/schema/appsync-scalars/index.ts b/packages/amplify-appsync-simulator/src/schema/appsync-scalars/index.ts index 4612fe87935..00e86d7dc76 100644 --- a/packages/amplify-appsync-simulator/src/schema/appsync-scalars/index.ts +++ b/packages/amplify-appsync-simulator/src/schema/appsync-scalars/index.ts @@ -1,5 +1,4 @@ import { GraphQLInt, GraphQLScalarType, GraphQLError, Kind, StringValueNode } from 'graphql'; -import GraphQLJSON from 'graphql-type-json'; import { isValidNumber } from 'libphonenumber-js'; import { GraphQLDate, GraphQLTime, GraphQLDateTime } from 'graphql-iso-date'; @@ -139,12 +138,42 @@ const AWSIPAddress = new GraphQLScalarType({ }, }); +const parseJson = (value: string) => { + if (typeof value !== "string") { + throw new GraphQLError(`Unable to parse ${value} as valid JSON.`); + } + + try { + return JSON.parse(value); + } catch (error) { + throw new TypeError(`Unable to parse ${value} as valid JSON.`); + } +} + +const AWSJSON = new GraphQLScalarType({ + name: 'AWSJSON', + description: 'The AWSJSON scalar type represents a valid json object serialized as a string.', + serialize(value) { + return JSON.stringify(value); + }, + parseValue(value) { + return parseJson(value); + }, + parseLiteral(ast) { + if (ast.kind !== Kind.STRING) { + throw new GraphQLError(`Unable to parse ${ast.kind} as valid JSON.`); + } + + return parseJson(ast.value); + }, +}); + export const scalars = { - AWSJSON: GraphQLJSON, + AWSJSON, AWSDate, AWSTime, AWSDateTime, - AWSPhone, + AWSPhone: new AWSPhone({ name: 'AWSPhone', description: 'AWSPhone' }), AWSEmail: EmailAddressResolver, AWSURL: URLResolver, AWSTimestamp, diff --git a/packages/amplify-appsync-simulator/src/schema/index.ts b/packages/amplify-appsync-simulator/src/schema/index.ts index 4b0e1c3e58d..4ca31d09b7a 100644 --- a/packages/amplify-appsync-simulator/src/schema/index.ts +++ b/packages/amplify-appsync-simulator/src/schema/index.ts @@ -98,7 +98,10 @@ export function generateResolvers( return makeExecutableSchema({ typeDefs: doc, - resolvers: resolverMapWithAuth, + resolvers: { + ...resolverMapWithAuth, + ...scalars, + }, schemaDirectives, }); }