0.0.43 • Published 4 years ago

@spokedev/zola v0.0.43

Weekly downloads
-
License
-
Repository
-
Last release
4 years ago

Zola

The 'Zola' project is designed to:

  • Provide a single stub (head) for all required services
  • Support component testing of 'tech error scenarios'
  • Reduce the amount of effort required to mock and stub during component and unit testing
  • Increase the amount of testing through cucumber and 'remote stubs'

Getting Started

Zola provides a single stubbed server for multiple apis at once. It is brought to life by swagger/openApi docs of the APIs or services you want to stub. These swaggers can be sourced remotely or locally. In order to specify which swaggers you want and where zola can find them you need to create a manifest.json in the root of your directory.

manifest.json:

[
  {
    "name":"foo",
    "type":"gitlab",
    "path": "./definitions/foo.yaml",
    "id":"2145",
    "branch":"master"
  },
  {
    "name":"bar",
    "type":"local",
    "path": "./definitions/stubdefinitions/bar.json"
  },
  {
    "name":"foobar",
    "type":"gitlab",
    "path": "./definitions/foobar.yaml",
    "id":"2145",
    "tag":"v0.0.3"
  }
]

Manifest Keys:

keydescription
nameThe name of the api you wish to stub. This will be used to write the new JSON swagger (if converted from yaml)
typeSwagger location type. Enum: gitlab, local, s3
pathSwagger location path so zola can find it
idSpecific to gitlab and not required for local, s3
tagSpecific to gitlab and not required for local, s3. Takes priority over branch if both are specified
branchSpecific to gitlab and not required for local, s3. Tag takes priority if both are specified

Environment Variables:

Access tokens are required for remote repositories. These need to be provided as environment variables

gitlab: ACCESS_TOKEN=your_gitlab_access_token

You can change the port that zola runs on, default = 4000, by setting the following:

port : ZOLA_PORT=4000

Installing Zola:

npm i @spokedev/zola

If you do not have access to @spokedev npm registry ask administrator for access.

Dependencies:

Currently zola is dependent on the swagger validator from core_utils. This can be added as a submodule with the following command:

git submodule add git@gitlab.spokedev.xyz:core/core_utils.git

Then add the below to your dependencies in your root package.json

"core_utils": "file:core_utils"

Scripts:

There are three scripts that can be added to your root package.json to utilise zola's core functionality. These are:

  "scripts": {
    "discovery": "DEBUG=zola ./node_modules/.bin/discovery",
    "generate": "DEBUG=zola ./node_modules/.bin/generate",
    "stubs": "DEBUG=zola ./node_modules/.bin/zola"
  }

discovery: Once you've added the above scripts npm run discovery will tell zola to go and discover the specified swaggers from the manifest.json. Once discovered they are written to your local project as JSON in the following dirctory ./definitions/stubdefinitions.

generate: Once discovery has been run the generate script can be follow. This will generate the default responses and create the required server and routers needed to properly stub any API. It will also flatten and combine all the different swaggers into a single one so it can be used by the schema validator in core_utils.

stubs: Once generate has been run you can then start the server by calling npm run stubs. This will start zola locally.

Requests:

Once zola is running you can fire https requests to all the exposed routes. When the server is started zola will log all the available paths so you can clearly see.

Validation:

All requests are validated against the generated combined swaggers. When a request is received the schema validator middleware will check all the fields received match the format of those specified in the swaggers. I will also check against required and no additional properties. The schema validator does a lot and will reject any request that doesn't match the swagger.

Important

The more detailed your swaggers have the stronger zola is. By providing required, additionalProperties: false, examples, formats etc the better the responses will be and the stronger the schema validator will be.

Responses:

After running the generate script zola will create a directory at the root of you project called responses/stubresponses. The responses will be stored per specified service with an index file exporting the. Using the above manifest.json as an example the response structure would be.

-project
  -responses
    - stubsresponses
      -foo
        get.foo.{fooId}.json
        post.foo.json
        index.js
      -bar
        delete.bar.{barId}.json
        patch.bar.{barId}.json
        index.js
      -foobar
        get.foobar.{foobarId}.json
        patch.bar.{foobarId}.json
        index.js

Response filenames are based upon the request method and path:

  POST /foo                                                  ===> post.cards.js

Path params extracted and kept for filtering:

  GET /foo/75b71e22-fa3a-11e8-8eb2-f2801f1b9fd1              ===> get.foo.{fooId}.json
  DELETE /bar/75b71e22-fa3a-11e8-8eb2-f2801f1b9fd1           ===> delete.bar.{barId}.json
  PATCH /foobar/75b71e22-fa3a-11e8-8eb2-f2801f1b9fd1         ===> patch.foobar.{foobarId}.json

To override the default responses zola checks the root of the responses directory first. If it can find the file by path and method that it needs it will use that. If not it will move down to responses/stubresponses

If you want an override response for get.foo.{fooId}.json the you folder structure would look like:

-project
  -responses
    -foo
      get.foo.{fooId}.json //THIS WILL OVERRIDE THE GENERATED RESPONSES BELOW
      index.js
    - stubsresponses
      -foo
        get.foo.{fooId}.json //THIS WILL BE OVERRIDDEN BY THE MANUALLY CREATED DIRECTORY/FILE ABOVE (PROVIDED TEMPLATE MATCHES)
        post.foo.json
        index.js
      -bar
        delete.bar.{barId}.json
        patch.bar.{barId}.json
        index.js
      -foobar
        get.foobar.{foobarId}.json
        patch.bar.{foobarId}.json
        index.js

Overrides:

Zola supports single time overrides two ways:

  1. /stubs/override: When zola is running it exposes a POST route will accept a body as defined below

Override body

{
  "path": "/path/of/route/to/stub",
  "method": "POST",
  "statusCode": 400,
  "body": {
    "stub": "body is optional, it provides a body zola will use to respond."
  }
}

The above body will cause the next request to POST /path/of/route/to/stub to return a 400 error with a specifc body. If no body is required the default response will be loaded from the responses directory.

  1. await zola.override(statusCode, path, method, body): Require the zola package into your test steps and call the override(statusCode, path, method, body) function giving the required arguments while zola is running. The statusCode (arg) is the status code you want returned from the given method (arg) and path (arg). The body isn't required but will override any other responses.
const zola = require('@spokedev/zola');

async function test() {
  await zola.override(400, '/foo/id', 'POST', {foo: 'bar'});
}

Assert:

Zola can assert against a body it receives if asked to. The assert functionality is similar to the overrides there are two ways to ask zola to assert against a give body:

  1. /stubs/assert: When zola is running it exposes a POST route will accept a body as defined below

Assert body

{
  "path": "/path/of/route/to/assert",
  "method": "POST",
  "body": {
    "assset": "body is required, it will use this body to assert against the request body"
  }
}

The above body will cause the next request to POST /path/of/route/to/assert to have its request body compared to the received body above. If they match the stub will continue as usual if not an error will be returned.

  1. await zola.assert(path, method, body): Require the zola package into your test steps and call the assert(path, method, body) function giving the required arguments while zola is running. This function (like the override above) simply wraps a http call to the exposed zola route and will achieve the same as step one, it is just an easier way to accesses it.
const zola = require('@spokedev/zola');

async function test() {
  await zola.assert('/foo/id', 'POST', {foo: 'bar'});
}

Clear Asserts and Overrides:

There are two ways to clear all assert and override events from zola while it is running.

  1. /stubs/override/clear: When zola is running it exposes a DELETE route, no body required. This will clear all assertions and overrides

  2. await zola.clearEvents(): Require the zola package into your test steps and call the clearEvents() function while zola is running. This function (like the override above) simply wraps a http call to the exposed zola route and will achieve the same as step one, it is just an easier way to accesses it.

Assert_Route:

Zola can assert if a route has been hit during the current run time. The assert functionality is similar to the overrides however the difference is it gives you an immediate answer. There are two ways to ask zola to assert if a route has been hit:

  1. /stubs/assert/route: When zola is running it exposes a POST route will accept a body as defined below

Assert body

{
  "path": "/was/this/route/hit",
  "method": "POST"
}

This above will check if a route has been hit in the current run time of zola. If the above route has been it the response below will be returned. Once a route has been asserted against it is forgotten, so if you repeated the above request the response route be false (if the route hadn't been hit since).

Assert Response

{
  "routeWasHit": true
}
  1. await zola.assertRoute(path, method): Require the zola package into your test steps and call the assertRoute(path, method) function giving the required arguments while zola is running. This function (like the override above) simply wraps a http call to the exposed zola route and will achieve the same as step one, it is just an easier way to accesses it.
const zola = require('@spokedev/zola');

async function test() {
  const { routeWasHit } = await zola.assertRoute('/was/this/route/hit', 'POST');

  if( routeWasHit ) {
    return 'success';
  } else {
    throw new Error('fail');
  }
}

Collection

Zola lets you create a postman collection based off existing swaggers and given config. There is a collection command exposed which can be added to package.json scripts:

  "scripts": {
    "collection": "DEBUG=zola ./node_modules/.bin/collection"
  }

As it is currently set up it cannot be run in isolation and requires a few elements before it can be run successfully. The first item is the release repo.

Release

When collection script is run it will look for a release dir in the root of the project, with that dir it looks for a manifest.json. This manifest is similar to the usual manifest mentioned above (it's an array of objects) but it expects less information. So all it expects is for a name and id to exist. It can have further attributes but they'll be ignored. Also if no id exists that service will be completely ignored. Example for the ./release/manifest.json:

[
  {"name":"serviceOne", "id": "2178","version":"latest","replica":1},
  {"name":"serviceTwo", "id": "2200","version":"latest","replica":1},
  {"name":"serviceThree", "version":"latest","replica":1},
]

In the above example serviceThree will be ignored because it has no id attribute.

Config File

Once the ./release/manifest.json is in place zola will require a persona config file. The default name is matilda, so if you don't pass an arguments (name) when you run npm run collection then zola will default to the name matilda and will look for a config file in the root of the project called ./matilda.json. The idea for this logic is to create personas that can be loaded up as postman collections. You could have a number of different ./{names}.json files that allow for the interaction with a number of different persons. Each time you run npm run collection <name> it will discover all the swaggers from the release manifest then get the ./matilda.json config file and use the values in this config to enrich each manifest object and create a postman collection related to matilda. An example of the config file would be:

{
  "personId": "debb3913-b9bb-45b8-ad01-e1b7b50384ce",
  "entityId": "2e3564ea-4261-48f0-b1e4-fa7b2e34fd7e",
  "propositionType": "SME",
  "baseUrl": "https://base.url.of.your.service",
  "authorization": "authToken"
}

With the above config file a postman collection will be created with given header values used (personId, entityId, propositionType, authorization) and with the given base url. Current implementation is tied to these exact header types.

Using the release manifest and the config file zola will be able to generate a postman collection which it will write to ./definitions/collection/postmanCollection.json

0.0.43

4 years ago

0.0.42

5 years ago

0.0.41

5 years ago

0.0.40

5 years ago

0.0.39

5 years ago

0.0.38

5 years ago

0.0.37

5 years ago

0.0.36

5 years ago

0.0.35

5 years ago

0.0.34

5 years ago

0.0.33

5 years ago

0.0.32

5 years ago

0.0.31

5 years ago

0.0.30

5 years ago

0.0.29

5 years ago

0.0.28

5 years ago

0.0.27

5 years ago

0.0.26

5 years ago

0.0.25

5 years ago

0.0.24

5 years ago

0.0.23

5 years ago

0.0.22

5 years ago

0.0.21

5 years ago

0.0.20

5 years ago

0.0.19

5 years ago

0.0.18

5 years ago

0.0.17

5 years ago

0.0.16

5 years ago

0.0.15

5 years ago

0.0.14

5 years ago

0.0.13

5 years ago

0.0.12

5 years ago

0.0.11

5 years ago

0.0.10

5 years ago

0.0.9

5 years ago

0.0.8

5 years ago

0.0.7

5 years ago

0.0.6

5 years ago

0.0.5

5 years ago

0.0.4

5 years ago

0.0.3

5 years ago

0.0.2

5 years ago

0.0.1

5 years ago