ld-scheduler
Version:
Schedule launch darkly flags on or off
206 lines (187 loc) • 6.72 kB
JavaScript
jest.mock('moment', () => global.td.function('moment'));
jest.mock('./constants', () => ({
taskTypes: {
killSwitch: 'killSwitch',
fallThroughRollout: 'fallThroughRollout'
},
launchDarklyFlagsEndpoint: 'mockBaseUrl/flags'
}));
jest.mock('./getRequestHeaders', () => global.td.function('getRequestHeaders'));
jest.mock('./getScheduledFlags', () => global.td.function('getScheduledFlags'));
jest.mock('./completeFlagDeployment', () => global.td.function('completeFlagDeployment'));
jest.mock('./slack', () => global.td.function('messageSlack'));
import moment from 'moment';
import getRequestHeaders from './getRequestHeaders';
import getScheduledFlags from './getScheduledFlags';
import completeFlagDeployment from './completeFlagDeployment';
import messageSlack from './slack';
const mockMomentFormat = td.function('mockMomentFormat');
const mockMomentIsAfter = td.function('mockMomentIsAfter');
describe('Scheduler', () => {
const scheduler = require('./scheduler').default;
beforeEach(async() => {
const momentObject = {
format: mockMomentFormat,
isAfter: mockMomentIsAfter
};
td.when(moment()).thenReturn(momentObject);
td.when(moment(td.matchers.anything(), 'YYYY-MM-DD HH:mm Z')).thenReturn(momentObject);
td.when(mockMomentFormat(td.matchers.anything())).thenReturn('TestDate');
td.when(getRequestHeaders(td.matchers.anything())).thenReturn('headers');
});
afterEach(() => {
jest.resetAllMocks();
td.reset();
});
it('does not do anything if there is no outstanding task', async() => {
fetch.mockSuccess();
td.when(mockMomentIsAfter(td.matchers.anything())).thenReturn(false);
td.when(getScheduledFlags(td.matchers.anything(), td.matchers.anything())).thenReturn([]);
await scheduler({environment: 'test', apiKey: 'someKey', slack: '/url/to/slack/webhook'});
expect(fetch).not.toHaveBeenCalledWith('/url/to/slack/webhook', {
method: 'POST',
body: JSON.stringify({text: '[Test] Successfully switched on test-flag.'})
});
});
it('patches when there is a scheduled killSwitch flag', async() => {
// arrange
fetch.mockSuccess();
const scheduledFlag = {
key: 'flag1',
tags: ['scheduled', 'some other tag'],
description: `{
"taskType": "killSwitch",
"value": true,
"targetDeploymentDateTime": "2017-02-27 22:00",
"description": "Flag1 description"
}`
};
const outstandingTask = {
key: scheduledFlag.key,
tags: scheduledFlag.tags,
...JSON.parse(scheduledFlag.description)
};
td.when(getScheduledFlags(td.matchers.anything(), td.matchers.anything())).thenReturn([scheduledFlag]);
td.when(mockMomentIsAfter(td.matchers.anything())).thenReturn(true);
// act
await scheduler({environment: 'test', apiKey: 'someKey', slack: '/url/to/slack/webhook'});
// assert
expect(fetch).toHaveBeenCalledWith('mockBaseUrl/flags/flag1', {
method: 'PATCH',
headers: 'headers',
body: JSON.stringify([{
op: 'replace',
path: '/environments/test/on',
value: true,
}])
});
td.verify(completeFlagDeployment(outstandingTask, 'test', 'someKey'));
td.verify(messageSlack({isUpdateSuccessful: true, task: outstandingTask}, 'test', '/url/to/slack/webhook'));
});
it('patches when there is a scheduled fallThroughRollout flag', async() => {
// arrange
fetch.mockSuccess();
const scheduledFlag = {
key: 'flag1',
tags: ['scheduled', 'some other tag'],
description: `{
"taskType": "fallThroughRollout",
"targetDeploymentDateTime": "2017-03-30 02:33",
"description": "Flag1 description",
"value": [
{
"variation": 0,
"weight": 100000
},
{
"variation": 1,
"weight": 0
}
]
}`
};
const outstandingTask = {
key: scheduledFlag.key,
tags: scheduledFlag.tags,
...JSON.parse(scheduledFlag.description)
};
td.when(getScheduledFlags(td.matchers.anything(), td.matchers.anything())).thenReturn([scheduledFlag]);
td.when(mockMomentIsAfter(td.matchers.anything())).thenReturn(true);
// act
await scheduler({environment: 'test', apiKey: 'someKey', slack: '/url/to/slack/webhook'});
// assert
expect(fetch).toHaveBeenCalledWith('mockBaseUrl/flags/flag1', {
method: 'PATCH',
headers: 'headers',
body: JSON.stringify([{
op: 'replace',
path: '/environments/test/fallthrough/rollout/variations',
value: [
{
variation: 0,
weight: 100000
},
{
variation: 1,
weight: 0
}
],
}])
});
td.verify(completeFlagDeployment(outstandingTask, 'test', 'someKey'));
td.verify(messageSlack({isUpdateSuccessful: true, task: outstandingTask}, 'test', '/url/to/slack/webhook'));
});
it('updates slack with correct message if path fails', async() => {
// arrange
fetch.mockSuccess({}, {status: 401, statusText: 'Unauthorized'});
const scheduledFlag = {
key: 'flag1',
tags: ['scheduled', 'some other tag'],
description: `{
"taskType": "fallThroughRollout",
"targetDeploymentDateTime": "2017-03-30 02:33",
"description": "Flag1 description",
"value": [
{
"variation": 0,
"weight": 100000
},
{
"variation": 1,
"weight": 0
}
]
}`
};
const outstandingTask = {
key: scheduledFlag.key,
tags: scheduledFlag.tags,
...JSON.parse(scheduledFlag.description)
};
td.when(getScheduledFlags(td.matchers.anything(), td.matchers.anything())).thenReturn([scheduledFlag]);
td.when(mockMomentIsAfter(td.matchers.anything())).thenReturn(true);
// act
await scheduler({environment: 'test', apiKey: 'someKey', slack: '/url/to/slack/webhook'});
// assert
expect(fetch).toHaveBeenCalledWith('mockBaseUrl/flags/flag1', {
method: 'PATCH',
headers: 'headers',
body: JSON.stringify([{
op: 'replace',
path: '/environments/test/fallthrough/rollout/variations',
value: [
{
variation: 0,
weight: 100000
},
{
variation: 1,
weight: 0
}
],
}])
});
td.verify(completeFlagDeployment(outstandingTask, 'someKey'), {times: 0});
td.verify(messageSlack({isUpdateSuccessful: false, task: outstandingTask}, 'test', '/url/to/slack/webhook'));
});
});