Skip to main content

Test use case

Prerequisites

Test the provider map

Out of profile, provider definition, and map, only the map contains logic which should be automatically tested. This document describes the process of testing the map using Jest and Nock libraries. Additionally these tests can be used as continuous integration tests against the provider's sandbox or live servers.

You can use OneSDK in your tests to perform the use cases through the provider's map. You need to explicitly set the provider to make sure that the correct map is being tested.

super.json

To know more about profiles, maps and their configurations in super.json, check out our documentation about /s Comlink

Setting up testing enviroment

Install necessary packages into your project:

npm install --save-dev jest nock

Write a test for the provider map

Use OneSDK like in Run Capability and test out result coming from perform.

profile.provider.test.js
const { SuperfaceClient } = require('@superfaceai/one-sdk');

describe('scope/profile-name/provider', () => {
let sdk, profile, provider;

beforeAll(async () => {
sdk = new SuperfaceClient();
profile = await sdk.getProfile('scope/profile-name');
provider = await sdk.getProvider('provider');
});

it('returns a result when called with ...', async () => {
const input = {
/* Input object as defined in the profile */
};
const result = await profile
.getUseCase('UseCaseName')
.perform(input, { provider });

expect(result.isOk()).toBe(true);
});
});
caution

This test example will hit live APIs.

If your capabilities require authorization, you can load keys from enviroment variables as described in Run Capability

If you want to reduce amount of calls to live APIs, see section about recording traffic.

Asserting results

Usually we want to assert result coming from our map. Result from perform always returns a Result type that is either Ok or Err. This follows the neverthrow approach.

We can use methods isOk() and isErr() to narrow down the result to either result.value or result.error properties which we can then test.

Or we can use method unwrap(), which is less safe because it can throw an error.

profile.provider.test.js
const { SuperfaceClient } = require('@superfaceai/one-sdk');

describe('scope/profile-name/provider', () => {
let sdk, profile, provider;

beforeAll(async () => {
sdk = new SuperfaceClient();
profile = await sdk.getProfile('scope/profile-name');
provider = await sdk.getProvider('provider');
});

it('should return a result when called with ...', async () => {
const input = {
// ...
};
const result = await profile
.getUseCase('UseCaseName')
.perform(input, { provider });

expect(result.isOk()).toBe(true);
expect(result.unwrap()).toEqual({
result: 'test',
});
});
});
caution

If result.isErr() is true and you call result.unwrap(), it will throw an error.

For this situation you can use the toThrow matcher:

expect(result.isErr()).toBe(true);
expect(() => {
result.unwrap();
}).toThrow();

Using Jest snapshots

You can use Jest snapshots to automatically capture the result:

profile.provider.test.js
const { SuperfaceClient } = require('@superfaceai/one-sdk');

describe('scope/profile-name/provider', () => {
let sdk, profile, provider;

beforeAll(async () => {
sdk = new SuperfaceClient();
profile = await sdk.getProfile('scope/profile-name');
provider = await sdk.getProvider('provider');
});

it('should return a result when called with ...', async () => {
const input = {
// ...
};
const result = await profile
.getUseCase('UseCaseName')
.perform(input, { provider });

expect(result.isOk()).toBe(true);
expect(result.unwrap()).toMatchSnapshot();
});
});
caution

If result.isErr() is true, result.unwrap() will throw an error.

To capture snapshot of error, you can use toThrowErrorMatchingSnapshot matcher:

expect(result.isErr()).toBe(true);
expect(() => {
result.unwrap();
}).toThrowErrorMatchingSnapshot();

Recording traffic

If you don't want to hit providers API upon each test run you can set up recording with nock and use prerecorded responses during development.

profile.provider.test.js
const { SuperfaceClient } = require('@superfaceai/one-sdk');
const nockBack = require('nock').back;

describe('scope/profile-name/provider', () => {
let sdk, profile, provider;

beforeAll(async () => {
sdk = new SuperfaceClient();
profile = await sdk.getProfile('scope/profile-name');
provider = await sdk.getProvider('provider');

nockBack.fixtures = '/path/to/fixtures/';
nockBack.setMode('record');
});

it('should return a result when called with ...', async () => {
const input = {
// ...
};

const { nockDone } = await back('your-recording.json');

const result = await profile
.getUseCase('UseCaseName')
.perform(input, { provider });

nockDone();

expect(result.isOk()).toBe(true);
expect(result.unwrap()).toEqual({
result: 'test',
});
});
});

Comlink profile and map files (.supr and .suma) needs to be compiled to their AST form (with .ast.json extension).

Run the following command to perform a one-off compilation:

npx @superfaceai/cli@3 compile

This will generate .ast.json files next to the existing source files linked from super.json file.

caution

The compilation is necessary after every change to local .suma and .supr files.

Running tests

When your tests are ready, run them with Jest CLI:

npx jest

You can use --updateSnapshot flag when modifying tests or when the expected results change. See Jest documentation for further CLI options.

Examples

If you wish to use your new use case in another Node.js application, please refer to the following guide.