Test use case
Prerequisites
- Existing Node.js project set up
- Existing local profile
- Existing provider definition
- Existing local map between profile & the provider
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.
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.
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);
});
});
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.
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',
});
});
});
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:
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();
});
});
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.
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',
});
});
});
Compile Comlink source files to AST
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.
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
- Integration test for expected result data format
- Integration test for expected output for given input
If you wish to use your new use case in another Node.js application, please refer to the following guide.