Skip to content
This repository has been archived by the owner on Jun 25, 2024. It is now read-only.

Commit

Permalink
feat: add referee utils tests (#106)
Browse files Browse the repository at this point in the history
  • Loading branch information
melanahammel authored Jan 15, 2021
1 parent 23d5dfe commit a8ddc72
Show file tree
Hide file tree
Showing 9 changed files with 322 additions and 11 deletions.
2 changes: 1 addition & 1 deletion packages/client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "client",
"version": "1.1.0",
"version": "1.2.0",
"description": "The client lib for the Referee UX",
"author": "Justin Field <[email protected]>",
"homepage": "https://example.com/dashboard/",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,15 @@ describe('LoadCanaryConfigService', () => {
});

it('should fetch template content', async () => {
const fileName = "hello-world-config";
const fileName = 'hello-world-config';
const expectedData = { response: true };
httpMock.onGet(`${process.env.PUBLIC_URL}/templates/${fileName}`).reply(200, expectedData);
const actualData = await loadCanaryConfigService.fetchTemplateContent(fileName);
expect(actualData).toEqual(expectedData);
});

it('should not fetch template content because template is not found', async () => {
const fileName = "fileName";
const fileName = 'fileName';
const expectedData = { response: true };
httpMock.onGet(`${process.env.PUBLIC_URL}/templates/${fileName}`).reply(404, expectedData);
await expect(loadCanaryConfigService.fetchTemplateContent(fileName)).rejects.toThrowError(
Expand Down
6 changes: 1 addition & 5 deletions packages/client/src/stores/CanaryExecutorStore.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { observable, action, computed, toJS } from 'mobx';
import {
CanaryExecutionRequest,
CanaryScope,
KayentaCredential
} from '../domain/Kayenta';
import { CanaryExecutionRequest, CanaryScope, KayentaCredential } from '../domain/Kayenta';
import CanaryExecutionFactory from '../util/CanaryExecutionFactory';
import {
validateAdditionalParameters,
Expand Down
4 changes: 2 additions & 2 deletions packages/client/src/util/MetricUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import axios from 'axios';
import log from './LoggerFactory';
import { ofNullable } from './OptionalUtils';

export const trackEvent = (event: EVENT, dimensions?: KvMap<string>): void => {
export const trackEvent = async (event: EVENT, dimensions?: KvMap<string>): Promise<void> => {
dimensions = ofNullable(dimensions).orElse({});
try {
axios.post(`/metrics`, {
await axios.post(`/metrics`, {
name: event,
dimensions: dimensions
});
Expand Down
21 changes: 21 additions & 0 deletions packages/client/src/util/__tests__/LoggerFactory.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { LoggerFactory } from '../LoggerFactory';

describe('LoggerFactory', () => {
it('should get root logger', () => {
const expectedLoggerName = 'root';
const logger = LoggerFactory.getRootLogger();
expect(logger['name']).toBe(expectedLoggerName);
});

it('should get logger with empty name', () => {
const expectedLoggerName = 'root';
const logger = LoggerFactory.getLogger('');
expect(logger['name']).toBe(expectedLoggerName);
});

it('should get logger with name', () => {
const expectedLoggerName = 'test';
const logger = LoggerFactory.getLogger(expectedLoggerName);
expect(logger['name']).toBe(expectedLoggerName);
});
});
47 changes: 47 additions & 0 deletions packages/client/src/util/__tests__/MetricUtils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import MockAdapter from 'axios-mock-adapter';
import axios from 'axios';
import { EVENT, trackEvent } from '../MetricUtils';

jest.mock('../../util/LoggerFactory', () => {
return {
error: () => {}
};
});

describe('MetricUtils', () => {
let httpMock;

beforeEach(() => {
httpMock = new MockAdapter(axios);
});

afterEach(() => {
httpMock.restore();
});

it('should track load config event with empty dimensions', async () => {
httpMock.onPost(`/metrics`).reply(200);
await expect(trackEvent(EVENT.LOAD_CONFIG)).resolves;
});

it('should track new config event with empty dimensions', async () => {
httpMock.onPost(`/metrics`).reply(200);
await expect(trackEvent(EVENT.NEW_CONFIG)).resolves;
});

it('should track new config event with dimensions', async () => {
const dimensions = { key: 'value' };
httpMock.onPost(`/metrics`).reply(200);
await expect(trackEvent(EVENT.NEW_CONFIG, dimensions)).resolves;
});

it('should track page view event with empty dimensions', async () => {
httpMock.onPost(`/metrics`).reply(200);
await expect(trackEvent(EVENT.PAGE_VIEW)).resolves;
});

it('should fail on track event', async () => {
httpMock.onGet(`/metrics`).reply(404);
await expect(trackEvent(EVENT.LOAD_CONFIG)).rejects;
});
});
102 changes: 102 additions & 0 deletions packages/client/src/util/__tests__/OptionalUtils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { safeGet, safeGetAsync, trimToEmpty } from '../OptionalUtils';

describe('OptionalUtils safeGet', () => {
it('should safely get value', () => {
const inputObject = 'foo';
const expectedValue = 'foo';
const actualValue = safeGet(() => inputObject);
expect(actualValue.get()).toEqual(expectedValue);
});

it('should safely get value of null and return empty', () => {
const inputObject = null;
const actualValue = safeGet(() => inputObject);
expect(actualValue.isPresent()).toEqual(false);
});

it('should safely get value of undefined and return empty', () => {
const inputObject = undefined;
const actualValue = safeGet(() => inputObject);
expect(actualValue.isPresent()).toEqual(false);
});

it('should safely get value of nested object', () => {
const inputObject = {
foo: {
bar: 'baz'
}
};
const expectedValue = 'baz';
const actualValue = safeGet(() => inputObject.foo.bar);
expect(actualValue.get()).toEqual(expectedValue);
});

it('should safely get value of null in nested object and return empty', () => {
const inputObject = {
foo: {
bar: null
}
};
const actualValue = safeGet(() => inputObject.foo.bar);
expect(actualValue.isPresent()).toEqual(false);
});

it('should safely get value of undefined in nested object and return empty', () => {
const inputObject = {
foo: {
bar: undefined
}
};
const actualValue = safeGet(() => inputObject.foo.bar);
expect(actualValue.isPresent()).toEqual(false);
});
});

describe('OptionalUtils safeGetAsync', () => {
it('should safely get value', async () => {
const inputObject = Promise.resolve('foo');
const expectedValue = 'foo';
const actualValue = await safeGetAsync(() => inputObject);
expect(actualValue.get()).toEqual(expectedValue);
});

it('should safely get value of null and return empty', async () => {
const inputObject = Promise.resolve(null);
const actualValue = await safeGetAsync(() => inputObject);
expect(actualValue.isPresent()).toEqual(false);
});

it('should safely get value of undefined and return empty', async () => {
const inputObject = Promise.resolve(undefined);
const actualValue = await safeGetAsync(() => inputObject);
expect(actualValue.isPresent()).toEqual(false);
});
});

describe('OptionalUtils trimToEmpty', () => {
it('should trim string and return string', () => {
const inputString = ' test ';
const expectedString = 'test';
const actualString = trimToEmpty(inputString);
expect(actualString.get()).toEqual(expectedString);
});

it('should trim already trimmed string and return string', () => {
const inputString = 'test';
const expectedString = 'test';
const actualString = trimToEmpty(inputString);
expect(actualString.get()).toEqual(expectedString);
});

it('should trim empty string and return empty', () => {
const inputString = '';
const actualString = trimToEmpty(inputString);
expect(actualString.isPresent()).toEqual(false);
});

it('should trim undefined string and return empty', () => {
const inputString = undefined;
const actualString = trimToEmpty(inputString);
expect(actualString.isPresent()).toEqual(false);
});
});
145 changes: 145 additions & 0 deletions packages/client/src/util/__tests__/ScoreClassUtils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { getClassFromScore, getGroupClassFromScore } from '../ScoreClassUtils';

describe('ScoreClassUtils getClassFromScore', () => {
it('should get class from score and not be the last execution and return pass', () => {
const score = 100;
const canaryScores = [100, 100, 100];
const scoreThresholds = { marginal: 70, pass: 90 };
const canaryRunIndex = 1;
const expectedClass = 'pass';
const actualClass = getClassFromScore(score, canaryScores, scoreThresholds, canaryRunIndex);
expect(actualClass).toEqual(expectedClass);
});

it('should get class from score and not be the last execution and return marginal', () => {
const score = 80;
const canaryScores = [100, 80, 100];
const scoreThresholds = { marginal: 70, pass: 90 };
const canaryRunIndex = 1;
const expectedClass = 'marginal';
const actualClass = getClassFromScore(score, canaryScores, scoreThresholds, canaryRunIndex);
expect(actualClass).toEqual(expectedClass);
});

it('should get class from score and not be the last execution and return fail', () => {
const score = 60;
const canaryScores = [60, 60, 60];
const scoreThresholds = { marginal: 70, pass: 90 };
const canaryRunIndex = 1;
const expectedClass = 'fail';
const actualClass = getClassFromScore(score, canaryScores, scoreThresholds, canaryRunIndex);
expect(actualClass).toEqual(expectedClass);
});

it('should get class from score and be the last execution and return pass', () => {
const score = 95;
const canaryScores = [75, 75, 95];
const scoreThresholds = { marginal: 70, pass: 90 };
const canaryRunIndex = 2;
const expectedClass = 'pass';
const actualClass = getClassFromScore(score, canaryScores, scoreThresholds, canaryRunIndex);
expect(actualClass).toEqual(expectedClass);
});

it('should get class from score and be the last execution and return fail', () => {
const score = 60;
const canaryScores = [60, 60, 60];
const scoreThresholds = { marginal: 70, pass: 90 };
const canaryRunIndex = 2;
const expectedClass = 'fail';
const actualClass = getClassFromScore(score, canaryScores, scoreThresholds, canaryRunIndex);
expect(actualClass).toEqual(expectedClass);
});

it('should get class from score and be the only execution and return pass', () => {
const score = 100;
const canaryScores = [100];
const scoreThresholds = { marginal: 70, pass: 90 };
const canaryRunIndex = 0;
const expectedClass = 'pass';
const actualClass = getClassFromScore(score, canaryScores, scoreThresholds, canaryRunIndex);
expect(actualClass).toEqual(expectedClass);
});

it('should get class from score and be the only execution and return fail', () => {
const score = 0;
const canaryScores = [0];
const scoreThresholds = { marginal: 70, pass: 90 };
const canaryRunIndex = 2;
const expectedClass = 'fail';
const actualClass = getClassFromScore(score, canaryScores, scoreThresholds, canaryRunIndex);
expect(actualClass).toEqual(expectedClass);
});

it('should get class from score with empty arrays and pass', () => {
const score = 100;
const canaryScores = [];
const scoreThresholds = { marginal: 75, pass: 95 };
const canaryRunIndex = 2;
const expectedClass = 'pass';
const actualClass = getClassFromScore(score, canaryScores, scoreThresholds, canaryRunIndex);
expect(actualClass).toEqual(expectedClass);
});

it('should get class from score with empty arrays and be marginal', () => {
const score = 80;
const canaryScores = [];
const scoreThresholds = { marginal: 75, pass: 95 };
const canaryRunIndex = 0;
const expectedClass = 'marginal';
const actualClass = getClassFromScore(score, canaryScores, scoreThresholds, canaryRunIndex);
expect(actualClass).toEqual(expectedClass);
});

it('should get class from score with empty arrays and fail', () => {
const score = 0;
const canaryScores = [];
const scoreThresholds = { marginal: 0, pass: 0 };
const canaryRunIndex = 0;
const expectedClass = 'pass';
const actualClass = getClassFromScore(score, canaryScores, scoreThresholds, canaryRunIndex);
expect(actualClass).toEqual(expectedClass);
});
});

describe('ScoreClassUtils getGroupClassFromScore', () => {
it('should get group class from score and pass', () => {
const score = 100;
const scoreThresholds = { marginal: 70, pass: 90 };
const expectedClass = 'pass';
const actualClass = getGroupClassFromScore(score, scoreThresholds);
expect(actualClass).toEqual(expectedClass);
});

it('should get group class from score and fail', () => {
const score = 0;
const scoreThresholds = { marginal: 70, pass: 90 };
const expectedClass = 'fail';
const actualClass = getGroupClassFromScore(score, scoreThresholds);
expect(actualClass).toEqual(expectedClass);
});

it('should get group class from score and fail for being marginal', () => {
const score = 80;
const scoreThresholds = { marginal: 70, pass: 90 };
const expectedClass = 'fail';
const actualClass = getGroupClassFromScore(score, scoreThresholds);
expect(actualClass).toEqual(expectedClass);
});

it('should get group class from score for lower bound edge case and pass', () => {
const score = 0;
const scoreThresholds = { marginal: 0, pass: 0 };
const expectedClass = 'pass';
const actualClass = getGroupClassFromScore(score, scoreThresholds);
expect(actualClass).toEqual(expectedClass);
});

it('should get group class from score for upper bound edge case and pass', () => {
const score = 100;
const scoreThresholds = { marginal: 100, pass: 100 };
const expectedClass = 'pass';
const actualClass = getGroupClassFromScore(score, scoreThresholds);
expect(actualClass).toEqual(expectedClass);
});
});
2 changes: 1 addition & 1 deletion packages/server/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "server",
"version": "1.1.0",
"version": "1.2.0",
"description": "The backend for the Referee UI",
"author": "Justin Field <[email protected]>",
"homepage": "",
Expand Down

0 comments on commit a8ddc72

Please sign in to comment.