ask-cli
Version:
Alexa Skills Kit (ASK) Command Line Interfaces
207 lines (168 loc) • 7.58 kB
JavaScript
const chai = require('chai');
const chaiUuid = require('chai-uuid');
const chaiJsonSchema = require('chai-json-schema');
const sinon = require('sinon');
const { MetricClient, MetricActionResult } = require('@src/clients/metric-client');
const jsonSchema = require('@test/fixture/ask-devtools-metrics.schema.json');
const { expect } = chai;
chai.use(chaiUuid);
chai.use(chaiJsonSchema);
describe('Clients test - cli metric client', () => {
const clientOptions = {
version: '1.0.1',
machineId: '8b2723f2-a25e-4d2c-89df-f9f590b8bb6e',
newUser: true,
clientId: 'ASK CLI',
serverUrl: 'https://somehost.com/dev/telemetry',
};
const { version, machineId, newUser, clientId, serverUrl } = clientOptions;
describe('# constructor validation', () => {
it('| creates instance of MetricClient, expect initial data to be set', () => {
// set up
const client = new MetricClient(clientOptions);
// call
const data = client.getData();
// verify
expect(data).include({ version, machineId, newUser, clientId, timeUploaded: null });
expect(data.actions).eql([]);
expect(data.timeStarted).instanceof(Date);
});
});
describe('# start action validation', () => {
let client;
beforeEach(() => {
client = new MetricClient(clientOptions);
});
it('| adds action, expect action to be set', () => {
const name = 'ask.clone';
const type = 'userCommand';
// call
client.startAction(name, type);
const { actions } = client.getData();
const [action] = actions;
// verify
expect(actions).instanceof(Array).have.lengthOf(1);
expect(action).include({ endTime: null, failureMessage: '', name, result: null, type });
expect(action.startTime).instanceof(Date);
expect(action.id).to.be.a.uuid();
});
it('| adds multiple action, expect actions to be set', () => {
const startActionsParams = [
{ name: 'ask.clone', type: 'userCommand' },
{ name: 'ask.init', type: 'internalCommand' },
{ name: 'ask.foo', type: 'userCommand' }
];
// call
startActionsParams.forEach((params) => {
client.startAction(params.name, params.type);
});
const { actions } = client.getData();
// verify
expect(actions).instanceof(Array).have.lengthOf(startActionsParams.length);
actions.forEach((action, index) => {
const { name, type } = startActionsParams[index];
expect(action).include({ endTime: null, failureMessage: '', name, result: null, type });
expect(action.startTime).instanceof(Date);
expect(action.id).to.be.a.uuid();
});
});
});
describe('# end action validation', () => {
let client;
let action;
const name = 'ask.clone';
const type = 'userCommand';
beforeEach(() => {
client = new MetricClient(clientOptions);
action = client.startAction(name, type);
});
it('| ends action with success, expect end event to be set with success status', () => {
// call
action.end();
// verify
expect(action).include({ failureMessage: '', name, result: MetricActionResult.SUCCESS, type });
expect(action.startTime).instanceof(Date);
expect(action.endTime).instanceof(Date);
expect(action.id).to.be.a.uuid();
});
it('| ends action that was already ended, expect endTime of originally ended action to not change', () => {
// call
// close first time
action.end();
const originalEndTime = action.endTime;
// close second time
action.end();
const endTimeAfterSecondEndRequest = action.endTime;
// verify
expect(action).include({ failureMessage: '', name, result: MetricActionResult.SUCCESS, type });
expect(originalEndTime).eql(endTimeAfterSecondEndRequest);
expect(action.startTime).instanceof(Date);
expect(action.endTime).instanceof(Date);
expect(action.id).to.be.a.uuid();
});
it('| ends action with error message, expect end event to be set with failure status', () => {
const failureMessage = 'Boom!';
// call
action.end(failureMessage);
// verify
expect(action).include({ failureMessage, name, result: MetricActionResult.FAILURE, type });
expect(action.startTime).instanceof(Date);
expect(action.endTime).instanceof(Date);
expect(action.id).to.be.a.uuid();
});
it('| ends action with error object, expect end event to be set with failure status', () => {
const failureMessage = 'Boom!';
// call
action.end(new Error(failureMessage));
// verify
expect(action).include({ failureMessage, name, result: MetricActionResult.FAILURE, type });
expect(action.startTime).instanceof(Date);
expect(action.endTime).instanceof(Date);
expect(action.id).to.be.a.uuid();
});
});
describe('# sends metrics validation', () => {
let client;
let httpClientPostStub;
const name = 'ask.clone';
const type = 'userCommand';
beforeEach(() => {
client = new MetricClient(clientOptions);
client.startAction(name, type);
});
afterEach(() => {
sinon.restore();
});
it('| sends metrics, expect metrics to be send to metric server', async () => {
httpClientPostStub = sinon.stub(client.httpClient, 'post').resolves({});
// call
const { success } = await client.sendData();
// verify
const [calledUrl, calledPayload] = httpClientPostStub.args[0];
expect(success).eql(true);
expect(httpClientPostStub.calledOnce).eql(true);
expect(calledUrl).eql(serverUrl);
expect(JSON.parse(calledPayload)).to.be.jsonSchema(jsonSchema);
});
it('| sends metrics, expect metrics not to be send to metric server when enabled is false', async () => {
httpClientPostStub = sinon.stub(client.httpClient, 'post');
const disabledClient = new MetricClient({ enabled: false, ...clientOptions });
// call
const { success } = await disabledClient.sendData();
// verify
expect(success).eql(true);
expect(httpClientPostStub.called).eql(false);
});
it('| sends metrics, expect to retry on transmission error', async () => {
httpClientPostStub = sinon.stub(client.httpClient, 'post').rejects();
// call
const { success } = await client.sendData();
// verify
const [calledUrl, calledPayload] = httpClientPostStub.args[0];
expect(success).eql(false);
expect(httpClientPostStub.calledThrice).eql(true);
expect(calledUrl).eql(serverUrl);
expect(JSON.parse(calledPayload)).to.be.jsonSchema(jsonSchema);
});
});
});