@ibm-adw/skill-toolkit
Version:
Developing your own skills with IBM Automation Digital Worker Skill Toolkit
282 lines (256 loc) • 9.1 kB
JavaScript
// skill-api.test.js
/* eslint-env jest */
'use strict';
const skill = require('../skill-api');
const outputSchema = require('../skill-config')['outputSchema'];
const Ajv = require('ajv');
const ajv = new Ajv();
const axios = require('axios');
const context = {
logger: {
trace: jest.fn(),
debug: jest.fn(),
info: jest.fn(),
warn: jest.fn(),
error: jest.fn()
}
};
const assertValidOutput = (result, configuration) => {
// Test result is a valid JSON according to outputSchema(config)
ajv.validate(outputSchema(configuration), result);
expect(ajv.errors).toBe(null);
};
describe('SKILL RUNTIME - Basic Tests', () => {
test('Checking a skill called without input is throwing', async () => {
const config = {};
try {
await skill(config)(undefined, context);
} catch (error) {
expect(error.message).toBe('Skill is called without input.');
}
});
test('Checking a correct input logs in context', async () => {
const config = {
'useCountry': false
};
const input = {
name: 'Jane'
};
const result = await skill(config)(input, context);
expect(context.logger.info).toHaveBeenCalledTimes(2);
assertValidOutput(result, config);
});
test('Checking a correct input with a country ID provided at config time', async () => {
const config = {
'useCountry': true,
'countryRetrievalMethod': 'set',
'countryId': 'US'
};
const input = {
name: 'Jane'
};
const result = await skill(config)(input, context);
expect(result).toHaveProperty('name');
expect(result).toHaveProperty('age');
expect(result).toHaveProperty('count');
expect(result).toHaveProperty('countryId');
expect(result.countryId).toBe(config.countryId);
});
test('Checking a correct input with a country ID provided at runtime', async () => {
const config = {
'useCountry': true,
'countryRetrievalMethod': 'provide'
};
const input = {
name: 'Jane',
countryId: 'US'
};
const result = await skill(config)(input, context);
expect(result).toHaveProperty('name');
expect(result).toHaveProperty('age');
expect(result).toHaveProperty('count');
expect(result).toHaveProperty('countryId');
expect(result.countryId).toBe(input.countryId);
});
test('Checking a correct input with a timeout', async () => {
const config = {
'useCountry': true,
'countryRetrievalMethod': 'set',
'countryId': 'US'
};
const input = {
name: 'Jane',
timeout: 10000
};
const result = await skill(config)(input, context);
expect(result).toHaveProperty('name');
expect(result).toHaveProperty('age');
expect(result).toHaveProperty('count');
expect(result).toHaveProperty('countryId');
expect(result.countryId).toBe(config.countryId);
});
test('Checking a correct input without a country ID', async () => {
const config = {
'useCountry': false
};
const input = {
name: 'Jane'
};
const result = await skill(config)(input, context);
expect(result).toHaveProperty('name');
expect(result).toHaveProperty('age');
expect(result).toHaveProperty('count');
expect(result).not.toHaveProperty('countryId');
});
test('Checking an invalid input (with the country ID already defined in the configuration) is throwing', async () => {
const config = {
'useCountry': true,
'countryRetrievalMethod': 'set',
'countryId': 'US'
};
const input = {
name: 'Jane',
'countryId': 'FR'
};
try {
await skill(config)(input, context);
} catch (error) {
expect(error.message).toBe('The country ID is already defined in the configuration and cannot be overridden at runtime.');
}
});
test('Checking an invalid input (with the country ID missing in the configuration) is throwing', async () => {
const config = {
'useCountry': true,
'countryRetrievalMethod': 'set',
};
const input = {
name: 'Jane',
'countryId': 'FR'
};
try {
await skill(config)(input, context);
} catch (error) {
expect(error.message).toBe('The country ID is missing in the configuration. You must set the country ID in the configuration or specify that you want to provide it at runtime.');
}
});
test('Checking an invalid input (with a country ID that is not provided at runtime) is throwing', async () => {
const config = {
'useCountry': true,
'countryRetrievalMethod': 'provide'
};
const input = {
name: 'Jane'
};
try {
await skill(config)(input, context);
} catch (error) {
expect(error.message).toBe('The country ID is undefined. You must set the country ID in the configuration or provide it in the `countryId` property in the input at runtime.');
}
});
test('Checking an invalid input (without country retrieval method) is throwing', async () => {
const config = {
'useCountry': true
};
const input = {
name: 'Jane',
countryId: 'US'
};
try {
await skill(config)(input, context);
} catch (error) {
expect(error.message).toBe('The country retrieval method is undefined. You must set the country retrieval method in the configuration.');
}
});
test('Checking an invalid input (with an incorrect country ID) is throwing', async () => {
const config = {
'useCountry': true,
'countryRetrievalMethod': 'provide'
};
const input = {
name: 'Jane',
countryId: 'UK'
};
try {
await skill(config)(input, context);
} catch (error) {
expect(error.message).toBe('The UK country ID is not valid. Only ISO 3166-1 alpha-2 codes are supported.');
}
});
test('Checking an invalid input (without a first name) is throwing', async () => {
const config = {
'useCountry': false
};
const input = {};
try {
await skill(config)(input, context);
} catch (error) {
expect(error.message).toBe('Request failed with status code 422: Missing \'name\' parameter');
}
});
test('Checking an invalid input (without the flag indicating whether to use country) is throwing', async () => {
const config = {};
const input = {
name: 'Jane'
};
try {
await skill(config)(input, context);
} catch (error) {
expect(error.message).toBe('The flag indicating whether to use the country is undefined. You must set the flag indicating whether to use the country in the configuration.');
}
});
test('Standard axios error', async () => {
const config = {
'useCountry': false
};
const input = {
name: 'Jane'
};
jest.spyOn(axios, 'get').mockImplementation(() => Promise.reject({
response: {
status: 400,
data: {
error: 'some error'
}
}
}));
try {
await skill(config)(input, context);
} catch (error) {
expect(error.message).toBe('Request failed with status code 400: some error');
}
});
test('Axios error with an unresponsive server', async () => {
const config = {
'useCountry': false
};
const input = {
name: 'Jane'
};
jest.spyOn(axios, 'get').mockImplementation(() => Promise.reject({
config: {
url: 'https://dummy'
},
request: {}
}));
try {
await skill(config)(input, context);
} catch (error) {
expect(error.message).toBe('Request failed due to an unresponsive server at https://dummy');
}
});
test('Axios error while setting up the request', async () => {
const config = {
'useCountry': false
};
const input = {
name: 'Jane'
};
jest.spyOn(axios, 'get').mockImplementation(() => Promise.reject(new Error('some error')));
try {
await skill(config)(input, context);
expect(true).toBe(false);
} catch (error) {
expect(error.message).toBe('some error');
}
});
});