Giter Site home page Giter Site logo

alan-cooney / appsync-template-tester Goto Github PK

View Code? Open in Web Editor NEW
35.0 35.0 11.0 170 KB

Unit test AppSync VTL resolvers, with popular frameworks such as Jest

Home Page: https://www.npmjs.com/package/appsync-template-tester

License: MIT License

TypeScript 100.00%

appsync-template-tester's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

appsync-template-tester's Issues

Example from documentation seems to bring up an error.

I ran into the same problem as in #11 which produces the following error when it is run:

this._input.match is not a function

You can fix the problem by changing the parser creation line to:

const parser = new Parser(template.toString());

The documentation should probably be updated.

Add Support for #return

Hello everyone,

I just tried out your code and it works splendid.

However, I came accross some obstacles. Is it planned to add the #return command as well? See https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference.html

Also I came across another issue. Somehow the set values don't get resolved correctly if they are not defined and resolved with $util functionallity. For example when having the following template

#set($notDefined = $util.escapeJavaScript($notDefined))

#if($util.isNullOrEmpty($notDefined))
{ 
  "this-should-be-outputted": null
}
#else
{
  "this-will-be-outputted": "$notDefined"
}
#end

The upper json should be returned then. However, appsync would resolve to the bottom json.

The response I get in the test is then

{
  "this-will-be-outputted": "undefined"
}

Thank you very much for your time!

Best wishes,
Sebastian

Feature: $ctx.stash checks

Background

$ctx.stash can keep data across mapping templates in Pipline resolver.

What this means is you can use the stash to pass arbitrary data across request and response mapping templates, and across functions in a pipeline resolver.

https://docs.aws.amazon.com/appsync/latest/devguide/pipeline-resolvers.html#ctx-stash

Suggestion

We want to check stash values after resolve.

Like this:

const vtl = '$ctx.stash.put("key", "value")';
const parser = new Parser(vtl);
const res = parser.resolve({});
expect(parser.stash).toStrictEqual({ key: "value" });

Add support for $util.dynamodb.toStringSetJson()

Currently, when introducing this utility function breaks the response from parser.resolve(context)

Sample resolver to put an item into dynamo

	"version" : "2018-05-29",
	"operation" : "PutItem",
	"key": {
		"id" : $util.dynamodb.toDynamoDBJson("id")
	},
	"attributeValues" : {
		"id" : $util.dynamodb.toDynamoDBJson($newId),
		"posts" : $util.dynamodb.toStringSetJson(["1", "2"])
	}
}

Sample test

    const context = {
      ...baseContext,
      arguments: {
        ...baseContext.arguments,
        id: 'id',
      },
    };
   const response = parser.resolve(context);
   console.log(response)

The console log returns a string instead of JS object outputting

   {
        "version" : "2018-05-29",
        "operation" : "PutItem",
        "key": {
                "id" : {"S":"id"},
        },
        "attributeValues" : {
                "id" : {"S":"id"},
                "posts" : $util.dynamodb.toStringSetJson(["1", "2"])
        }
    }

Out put should be

...
posts: { SS: ["1", "2"]}
...

Currently using version 1.1.9

Is contains on array (maybe also on string) not supported?

According to https://stackoverflow.com/questions/57604233/how-to-check-if-value-exists-in-an-array-using-velocity-template-language you can check in VTL if an array contains a certain key. I checked this by using the following VTL in AWS AppSync and it works. But when I try to unittest it with this library, it fails. It seems that 'contains' is not recognized and completely ignored.

I minimized the VTL to the part that doesn't work, so it's not the complete VTL I'm using but I think this should be enough
VTL:

#foreach($item in $abilities)
  #if($item.array.contains($ctx.args.ability))
    ...
  #end
#end

Where $item.array is an actual array like: ['1', '2'] and $ctx.args.ability is a string like '2'.

Could you help me understand the issue here?

Feature - List helpers in $util.list

List helpers in $util.list

$util.list contains methods to help with common List operations, such as removing or retaining items from a list for filtering use cases.

$util.list.copyAndRetainAll(List, List) : List
Makes a shallow copy of the supplied list in the first argument, retaining only the items specified in the second argument, if they are present. All other items will be removed from the copy.

$util.list.copyAndRemoveAll(List, List) : List
Makes a shallow copy of the supplied list in the first argument, removing any items where the item is specified in the second argument, if they are present. All other items will be retained in the copy.

$util.list.sortList(List, Boolean, String) : List
Sorts a list of objects, which is provided in the first argument. If the second argument is true, the list is sorted in a descending manner; if the second argument is false, the list is sorted in an ascending manner. The third argument is the string name of the property used to sort a list of custom objects. If it's a list of just Strings, Integers, Floats, or Doubles, the third argument can be any random string. If all of the objects are not from the same class, the original list is returned. Only lists containing a maximum of 1000 objects are supported.

Feature: $util.map methods

Map helpers in $util.map

$util.map contains methods to help with common Map operations, such as removing or retaining items from a Map for filtering use cases.

$util.map.copyAndRetainAllKeys(Map, List) : Map
Makes a shallow copy of the first map, retaining only the keys specified in the list, if they are present. All other keys will be removed from the copy.

$util.map.copyAndRemoveAllKeys(Map, List) : Map
Makes a shallow copy of the first map, removing any entries where the key is specified in the list, if they are present. All other keys will be retained in the copy.

Uncaught TypeError: Parser is not a constructor

I've followed your usage example, but I am getting this error..

I've enabled type: module in root package.json and Here is script of root package.json:

"scripts": {
    "test": "NODE_OPTIONS=--experimental-vm-modules npx jest"
  }

Here is the test I am using:

import Parser from "appsync-template-tester";
import { readFileSync } from "fs";
import path, { join } from "path";
import { fileURLToPath } from "url";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Load a VTL template file to test
const templateFilePath = join(__dirname, "../../services/appsync/mapping-templates/Query.me.request.vtl");
const template = readFileSync(templateFilePath);

// Create the resolver
const parser = new Parser(template); // Note: this line throws this exception

test("Query.me.request.vtl", () => {
  // The Context (ctx) object for resolver
  const context = {
    result: {
      id: "testId",
    },
  };

  // parser.resolve() automatically typecasts (note JSON becomes a JS object for ease of testing)
  const response = parser.resolve(context);

  // For convenience, the response is returned as a JS object rather than JSON
  expect(response.id).toBe("testId");
});

Support for mocking $extensions

Could support be added to this project for mocking the methods available via $extension? I am wanting to assert that $extensions.evictFromApiCache is invoked in my VTL template with the correct arguments.

I have cloned this repository and implemented what I see as a reasonable solution, but I don't have access to create a pull request. The changes were:

src/index.ts:

Add a new optional additionalExtensions argument to the resolve method, which is spread into the extensions object and passed via params:

public resolve(context: Context, additionalUtil?: object, additionalExtensions?: object): any {
    ...

    const extensions = { ...additionalExtensions }

    const params = {
      context: clonedContext,
      ctx: clonedContext,
      util,
      utils: util,
      extensions
    };

src/tests/index.ts:

A new unit test covering extensions:

test("resolve with additional extensions", () => {
  // Given.
  const mockEvictFromApiCache = jest.fn();
  const parser = new Parser(`$extensions.evictFromApiCache("Query", "users", {
    "context.arguments.id": $context.arguments.id
  })`);

  // When.
  parser.resolve({ arguments: { id: 10 } }, undefined, {
    evictFromApiCache: mockEvictFromApiCache,
  });

  // Then.
  expect(mockEvictFromApiCache).toHaveBeenCalledTimes(1)
  expect(mockEvictFromApiCache).toHaveBeenCalledWith("Query", "users", { "context.arguments.id": 10 })
});

And a small addition to the README:

Extensions

AWS AppSync provides extension methods via $extensions, for example $extensions.evictFromApiCache. It can be useful to assert that your VTL template is invoking these methods, therefore, you can provide custom extensions with your own implementations. Note that default extension methods are not provided. To read more about AWS AppSync extensions see the Extensions
docs
.

  // Given.
  const mockEvictFromApiCache = jest.fn();
  const parser = new Parser(`$extensions.evictFromApiCache("Query", "users", {
    "context.arguments.id": $context.arguments.id
  })`);

  // When.
  parser.resolve({ arguments: { id: 10 } }, undefined, {
    evictFromApiCache: mockEvictFromApiCache,
  });

  // Then.
  expect(mockEvictFromApiCache).toHaveBeenCalledTimes(1)
  expect(mockEvictFromApiCache).toHaveBeenCalledWith("Query", "users", { "context.arguments.id": 10 })

Is there any chance this could be added to the module and released to the public NPM registry as a new version? I am very keen to continue using your published package.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.