Commit 6b5da5f7 authored by David O'Regan's avatar David O'Regan

Merge branch 'vs/remove-jest-test-callback-part-three' into 'master'

Remove jest test callbacks from specs (2/3)

See merge request gitlab-org/gitlab!84480
parents 59217ae2 5e9fc348
......@@ -42,9 +42,9 @@ describe('AddContextCommitsModalStoreActions', () => {
});
describe('setBaseConfig', () => {
it('commits SET_BASE_CONFIG', (done) => {
it('commits SET_BASE_CONFIG', () => {
const options = { contextCommitsPath, mergeRequestIid, projectId };
testAction(
return testAction(
setBaseConfig,
options,
{
......@@ -59,62 +59,54 @@ describe('AddContextCommitsModalStoreActions', () => {
},
],
[],
done,
);
});
});
describe('setTabIndex', () => {
it('commits SET_TABINDEX', (done) => {
testAction(
it('commits SET_TABINDEX', () => {
return testAction(
setTabIndex,
{ tabIndex: 1 },
{ tabIndex: 0 },
[{ type: types.SET_TABINDEX, payload: { tabIndex: 1 } }],
[],
done,
);
});
});
describe('setCommits', () => {
it('commits SET_COMMITS', (done) => {
testAction(
it('commits SET_COMMITS', () => {
return testAction(
setCommits,
{ commits: [], silentAddition: false },
{ isLoadingCommits: false, commits: [] },
[{ type: types.SET_COMMITS, payload: [] }],
[],
done,
);
});
it('commits SET_COMMITS_SILENT', (done) => {
testAction(
it('commits SET_COMMITS_SILENT', () => {
return testAction(
setCommits,
{ commits: [], silentAddition: true },
{ isLoadingCommits: true, commits: [] },
[{ type: types.SET_COMMITS_SILENT, payload: [] }],
[],
done,
);
});
});
describe('createContextCommits', () => {
it('calls API to create context commits', (done) => {
it('calls API to create context commits', async () => {
mock.onPost(contextCommitEndpoint).reply(200, {});
testAction(createContextCommits, { commits: [] }, {}, [], [], done);
await testAction(createContextCommits, { commits: [] }, {}, [], []);
createContextCommits(
await createContextCommits(
{ state: { projectId, mergeRequestIid }, commit: () => null },
{ commits: [] },
)
.then(() => {
done();
})
.catch(done.fail);
);
});
});
......@@ -126,9 +118,9 @@ describe('AddContextCommitsModalStoreActions', () => {
)
.reply(200, [dummyCommit]);
});
it('commits FETCH_CONTEXT_COMMITS', (done) => {
it('commits FETCH_CONTEXT_COMMITS', () => {
const contextCommit = { ...dummyCommit, isSelected: true };
testAction(
return testAction(
fetchContextCommits,
null,
{
......@@ -144,20 +136,18 @@ describe('AddContextCommitsModalStoreActions', () => {
{ type: 'setCommits', payload: { commits: [contextCommit], silentAddition: true } },
{ type: 'setSelectedCommits', payload: [contextCommit] },
],
done,
);
});
});
describe('setContextCommits', () => {
it('commits SET_CONTEXT_COMMITS', (done) => {
testAction(
it('commits SET_CONTEXT_COMMITS', () => {
return testAction(
setContextCommits,
{ data: [] },
{ contextCommits: [], isLoadingContextCommits: false },
[{ type: types.SET_CONTEXT_COMMITS, payload: { data: [] } }],
[],
done,
);
});
});
......@@ -168,71 +158,66 @@ describe('AddContextCommitsModalStoreActions', () => {
.onDelete('/api/v4/projects/gitlab-org%2Fgitlab/merge_requests/1/context_commits')
.reply(204);
});
it('calls API to remove context commits', (done) => {
testAction(
it('calls API to remove context commits', () => {
return testAction(
removeContextCommits,
{ forceReload: false },
{ mergeRequestIid, projectId, toRemoveCommits: [] },
[],
[],
done,
);
});
});
describe('setSelectedCommits', () => {
it('commits SET_SELECTED_COMMITS', (done) => {
testAction(
it('commits SET_SELECTED_COMMITS', () => {
return testAction(
setSelectedCommits,
[dummyCommit],
{ selectedCommits: [] },
[{ type: types.SET_SELECTED_COMMITS, payload: [dummyCommit] }],
[],
done,
);
});
});
describe('setSearchText', () => {
it('commits SET_SEARCH_TEXT', (done) => {
it('commits SET_SEARCH_TEXT', () => {
const searchText = 'Dummy Text';
testAction(
return testAction(
setSearchText,
searchText,
{ searchText: '' },
[{ type: types.SET_SEARCH_TEXT, payload: searchText }],
[],
done,
);
});
});
describe('setToRemoveCommits', () => {
it('commits SET_TO_REMOVE_COMMITS', (done) => {
it('commits SET_TO_REMOVE_COMMITS', () => {
const commitId = 'abcde';
testAction(
return testAction(
setToRemoveCommits,
[commitId],
{ toRemoveCommits: [] },
[{ type: types.SET_TO_REMOVE_COMMITS, payload: [commitId] }],
[],
done,
);
});
});
describe('resetModalState', () => {
it('commits RESET_MODAL_STATE', (done) => {
it('commits RESET_MODAL_STATE', () => {
const commitId = 'abcde';
testAction(
return testAction(
resetModalState,
null,
{ toRemoveCommits: [commitId] },
[{ type: types.RESET_MODAL_STATE }],
[],
done,
);
});
});
......
......@@ -22,8 +22,8 @@ describe('Admin statistics panel actions', () => {
mock.onGet(/api\/(.*)\/application\/statistics/).replyOnce(200, mockStatistics);
});
it('dispatches success with received data', (done) =>
testAction(
it('dispatches success with received data', () => {
return testAction(
actions.fetchStatistics,
null,
state,
......@@ -37,8 +37,8 @@ describe('Admin statistics panel actions', () => {
),
},
],
done,
));
);
});
});
describe('error', () => {
......@@ -46,8 +46,8 @@ describe('Admin statistics panel actions', () => {
mock.onGet(/api\/(.*)\/application\/statistics/).replyOnce(500);
});
it('dispatches error', (done) =>
testAction(
it('dispatches error', () => {
return testAction(
actions.fetchStatistics,
null,
state,
......@@ -61,26 +61,26 @@ describe('Admin statistics panel actions', () => {
payload: new Error('Request failed with status code 500'),
},
],
done,
));
);
});
});
});
describe('requestStatistic', () => {
it('should commit the request mutation', (done) =>
testAction(
it('should commit the request mutation', () => {
return testAction(
actions.requestStatistics,
null,
state,
[{ type: types.REQUEST_STATISTICS }],
[],
done,
));
);
});
});
describe('receiveStatisticsSuccess', () => {
it('should commit received data', (done) =>
testAction(
it('should commit received data', () => {
return testAction(
actions.receiveStatisticsSuccess,
mockStatistics,
state,
......@@ -91,13 +91,13 @@ describe('Admin statistics panel actions', () => {
},
],
[],
done,
));
);
});
});
describe('receiveStatisticsError', () => {
it('should commit error', (done) => {
testAction(
it('should commit error', () => {
return testAction(
actions.receiveStatisticsError,
500,
state,
......@@ -108,7 +108,6 @@ describe('Admin statistics panel actions', () => {
},
],
[],
done,
);
});
});
......
......@@ -36,24 +36,19 @@ describe('U2FAuthenticate', () => {
window.u2f = oldu2f;
});
it('falls back to normal 2fa', (done) => {
component
.start()
.then(() => {
expect(component.switchToFallbackUI).toHaveBeenCalled();
done();
})
.catch(done.fail);
it('falls back to normal 2fa', async () => {
await component.start();
expect(component.switchToFallbackUI).toHaveBeenCalled();
});
});
describe('with u2f available', () => {
beforeEach((done) => {
beforeEach(() => {
// bypass automatic form submission within renderAuthenticated
jest.spyOn(component, 'renderAuthenticated').mockReturnValue(true);
u2fDevice = new MockU2FDevice();
component.start().then(done).catch(done.fail);
return component.start();
});
it('allows authenticating via a U2F device', () => {
......
......@@ -8,12 +8,12 @@ describe('U2FRegister', () => {
let container;
let component;
beforeEach((done) => {
beforeEach(() => {
loadFixtures('u2f/register.html');
u2fDevice = new MockU2FDevice();
container = $('#js-register-token-2fa');
component = new U2FRegister(container, {});
component.start().then(done).catch(done.fail);
return component.start();
});
it('allows registering a U2F device', () => {
......
......@@ -38,35 +38,25 @@ describe('AjaxFilter', () => {
dummyList.list.appendChild(dynamicList);
});
it('calls onLoadingFinished after loading data', (done) => {
it('calls onLoadingFinished after loading data', async () => {
ajaxSpy = (url) => {
expect(url).toBe('dummy endpoint?dummy search key=');
return Promise.resolve(dummyData);
};
AjaxFilter.trigger()
.then(() => {
expect(dummyConfig.onLoadingFinished.mock.calls.length).toBe(1);
})
.then(done)
.catch(done.fail);
await AjaxFilter.trigger();
expect(dummyConfig.onLoadingFinished.mock.calls.length).toBe(1);
});
it('does not call onLoadingFinished if Ajax call fails', (done) => {
it('does not call onLoadingFinished if Ajax call fails', async () => {
const dummyError = new Error('My dummy is sick! :-(');
ajaxSpy = (url) => {
expect(url).toBe('dummy endpoint?dummy search key=');
return Promise.reject(dummyError);
};
AjaxFilter.trigger()
.then(done.fail)
.catch((error) => {
expect(error).toBe(dummyError);
expect(dummyConfig.onLoadingFinished.mock.calls.length).toBe(0);
})
.then(done)
.catch(done.fail);
await expect(AjaxFilter.trigger()).rejects.toEqual(dummyError);
expect(dummyConfig.onLoadingFinished.mock.calls.length).toBe(0);
});
});
});
......@@ -190,43 +190,40 @@ describe('Filtered Search Manager', () => {
const defaultParams = '?scope=all';
const defaultState = '&state=opened';
it('should search with a single word', (done) => {
it('should search with a single word', () => {
initializeManager();
input.value = 'searchTerm';
visitUrl.mockImplementation((url) => {
expect(url).toEqual(`${defaultParams}&search=searchTerm`);
done();
});
manager.search();
});
it('sets default state', (done) => {
it('sets default state', () => {
initializeManager({ useDefaultState: true });
input.value = 'searchTerm';
visitUrl.mockImplementation((url) => {
expect(url).toEqual(`${defaultParams}${defaultState}&search=searchTerm`);
done();
});
manager.search();
});
it('should search with multiple words', (done) => {
it('should search with multiple words', () => {
initializeManager();
input.value = 'awesome search terms';
visitUrl.mockImplementation((url) => {
expect(url).toEqual(`${defaultParams}&search=awesome+search+terms`);
done();
});
manager.search();
});
it('should search with special characters', (done) => {
it('should search with special characters', () => {
initializeManager();
input.value = '~!@#$%^&*()_+{}:<>,.?/';
......@@ -234,13 +231,12 @@ describe('Filtered Search Manager', () => {
expect(url).toEqual(
`${defaultParams}&search=~!%40%23%24%25%5E%26*()_%2B%7B%7D%3A%3C%3E%2C.%3F%2F`,
);
done();
});
manager.search();
});
it('should use replacement URL for condition', (done) => {
it('should use replacement URL for condition', () => {
initializeManager();
tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(
FilteredSearchSpecHelper.createFilterVisualTokenHTML('milestone', '=', '13', true),
......@@ -248,7 +244,6 @@ describe('Filtered Search Manager', () => {
visitUrl.mockImplementation((url) => {
expect(url).toEqual(`${defaultParams}&milestone_title=replaced`);
done();
});
manager.filteredSearchTokenKeys.conditions.push({
......@@ -261,7 +256,7 @@ describe('Filtered Search Manager', () => {
manager.search();
});
it('removes duplicated tokens', (done) => {
it('removes duplicated tokens', () => {
initializeManager();
tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug')}
......@@ -270,7 +265,6 @@ describe('Filtered Search Manager', () => {
visitUrl.mockImplementation((url) => {
expect(url).toEqual(`${defaultParams}&label_name[]=bug`);
done();
});
manager.search();
......
......@@ -18,53 +18,47 @@ describe('RecentSearchesService', () => {
jest.spyOn(RecentSearchesService, 'isAvailable').mockReturnValue(true);
});
it('should default to empty array', (done) => {
it('should default to empty array', () => {
const fetchItemsPromise = service.fetch();
fetchItemsPromise
.then((items) => {
expect(items).toEqual([]);
})
.then(done)
.catch(done.fail);
return fetchItemsPromise.then((items) => {
expect(items).toEqual([]);
});
});
it('should reject when unable to parse', (done) => {
it('should reject when unable to parse', () => {
jest.spyOn(localStorage, 'getItem').mockReturnValue('fail');
const fetchItemsPromise = service.fetch();
fetchItemsPromise
.then(done.fail)
return fetchItemsPromise
.then(() => {
throw new Error();
})
.catch((error) => {
expect(error).toEqual(expect.any(SyntaxError));
})
.then(done)
.catch(done.fail);
});
});
it('should reject when service is unavailable', (done) => {
it('should reject when service is unavailable', () => {
RecentSearchesService.isAvailable.mockReturnValue(false);
service
return service
.fetch()
.then(done.fail)
.then(() => {
throw new Error();
})
.catch((error) => {
expect(error).toEqual(expect.any(Error));
})
.then(done)
.catch(done.fail);
});
});
it('should return items from localStorage', (done) => {
it('should return items from localStorage', () => {
jest.spyOn(localStorage, 'getItem').mockReturnValue('["foo", "bar"]');
const fetchItemsPromise = service.fetch();
fetchItemsPromise
.then((items) => {
expect(items).toEqual(['foo', 'bar']);
})
.then(done)
.catch(done.fail);
return fetchItemsPromise.then((items) => {
expect(items).toEqual(['foo', 'bar']);
});
});
describe('if .isAvailable returns `false`', () => {
......@@ -74,16 +68,16 @@ describe('RecentSearchesService', () => {
jest.spyOn(Storage.prototype, 'getItem').mockImplementation(() => {});
});
it('should not call .getItem', (done) => {
RecentSearchesService.prototype
it('should not call .getItem', () => {
return RecentSearchesService.prototype
.fetch()
.then(done.fail)
.then(() => {
throw new Error();
})
.catch((err) => {
expect(err).toEqual(new RecentSearchesServiceError());
expect(localStorage.getItem).not.toHaveBeenCalled();
})
.then(done)
.catch(done.fail);
});
});
});
});
......
......@@ -46,7 +46,7 @@ describe('Filtered Search Visual Tokens', () => {
jest.spyOn(UsersCache, 'retrieve').mockImplementation((username) => usersCacheSpy(username));
});
it('ignores error if UsersCache throws', (done) => {
it('ignores error if UsersCache throws', async () => {
const dummyError = new Error('Earth rotated backwards');
const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
const tokenValue = tokenValueElement.innerText;
......@@ -55,16 +55,11 @@ describe('Filtered Search Visual Tokens', () => {
return Promise.reject(dummyError);
};
subject
.updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
.then(() => {
expect(createFlash.mock.calls.length).toBe(0);
})
.then(done)
.catch(done.fail);
await subject.updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue);
expect(createFlash.mock.calls.length).toBe(0);
});
it('does nothing if user cannot be found', (done) => {
it('does nothing if user cannot be found', async () => {
const { subject, tokenValueContainer, tokenValueElement } = findElements(authorToken);
const tokenValue = tokenValueElement.innerText;
usersCacheSpy = (username) => {
......@@ -72,16 +67,11 @@ describe('Filtered Search Visual Tokens', () => {
return Promise.resolve(undefined);
};
subject
.updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
.then(() => {
expect(tokenValueElement.innerText).toBe(tokenValue);
})
.then(done)
.catch(done.fail);
await subject.updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue);
expect(tokenValueElement.innerText).toBe(tokenValue);
});
it('replaces author token with avatar and display name', (done) => {
it('replaces author token with avatar and display name', async () => {
const dummyUser = {
name: 'Important Person',
avatar_url: 'https://host.invalid/mypics/avatar.png',
......@@ -93,21 +83,16 @@ describe('Filtered Search Visual Tokens', () => {
return Promise.resolve(dummyUser);
};
subject
.updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
.then(() => {
expect(tokenValueContainer.dataset.originalValue).toBe(tokenValue);
expect(tokenValueElement.innerText.trim()).toBe(dummyUser.name);
const avatar = tokenValueElement.querySelector('img.avatar');
expect(avatar.getAttribute('src')).toBe(dummyUser.avatar_url);
expect(avatar.getAttribute('alt')).toBe('');
})
.then(done)
.catch(done.fail);
await subject.updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue);
expect(tokenValueContainer.dataset.originalValue).toBe(tokenValue);
expect(tokenValueElement.innerText.trim()).toBe(dummyUser.name);
const avatar = tokenValueElement.querySelector('img.avatar');
expect(avatar.getAttribute('src')).toBe(dummyUser.avatar_url);
expect(avatar.getAttribute('alt')).toBe('');
});
it('escapes user name when creating token', (done) => {
it('escapes user name when creating token', async () => {
const dummyUser = {
name: '<script>',
avatar_url: `${TEST_HOST}/mypics/avatar.png`,
......@@ -119,16 +104,11 @@ describe('Filtered Search Visual Tokens', () => {
return Promise.resolve(dummyUser);
};
subject
.updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
.then(() => {
expect(tokenValueElement.innerText.trim()).toBe(dummyUser.name);
tokenValueElement.querySelector('.avatar').remove();
await subject.updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue);
expect(tokenValueElement.innerText.trim()).toBe(dummyUser.name);
tokenValueElement.querySelector('.avatar').remove();
expect(tokenValueElement.innerHTML.trim()).toBe(escape(dummyUser.name));
})
.then(done)
.catch(done.fail);
expect(tokenValueElement.innerHTML.trim()).toBe(escape(dummyUser.name));
});
});
......@@ -177,48 +157,33 @@ describe('Filtered Search Visual Tokens', () => {
const findLabel = (tokenValue) =>
labelData.find((label) => tokenValue === `~${DropdownUtils.getEscapedText(label.title)}`);
it('updates the color of a label token', (done) => {
it('updates the color of a label token', async () => {
const { subject, tokenValueContainer, tokenValueElement } = findElements(bugLabelToken);
const tokenValue = tokenValueElement.innerText;
const matchingLabel = findLabel(tokenValue);
subject
.updateLabelTokenColor(tokenValueContainer, tokenValue)
.then(() => {
expectValueContainerStyle(tokenValueContainer, matchingLabel);
})
.then(done)
.catch(done.fail);
await subject.updateLabelTokenColor(tokenValueContainer, tokenValue);
expectValueContainerStyle(tokenValueContainer, matchingLabel);
});
it('updates the color of a label token with spaces', (done) => {
it('updates the color of a label token with spaces', async () => {
const { subject, tokenValueContainer, tokenValueElement } = findElements(spaceLabelToken);
const tokenValue = tokenValueElement.innerText;
const matchingLabel = findLabel(tokenValue);
subject
.updateLabelTokenColor(tokenValueContainer, tokenValue)
.then(() => {
expectValueContainerStyle(tokenValueContainer, matchingLabel);
})
.then(done)
.catch(done.fail);
await subject.updateLabelTokenColor(tokenValueContainer, tokenValue);
expectValueContainerStyle(tokenValueContainer, matchingLabel);
});
it('does not change color of a missing label', (done) => {
it('does not change color of a missing label', async () => {
const { subject, tokenValueContainer, tokenValueElement } = findElements(missingLabelToken);
const tokenValue = tokenValueElement.innerText;
const matchingLabel = findLabel(tokenValue);
expect(matchingLabel).toBe(undefined);
subject
.updateLabelTokenColor(tokenValueContainer, tokenValue)
.then(() => {
expect(tokenValueContainer.getAttribute('style')).toBe(null);
})
.then(done)
.catch(done.fail);
await subject.updateLabelTokenColor(tokenValueContainer, tokenValue);
expect(tokenValueContainer.getAttribute('style')).toBe(null);
});
});
......
......@@ -29,136 +29,126 @@ describe('Frequent Items Dropdown Store Actions', () => {
});
describe('setNamespace', () => {
it('should set namespace', (done) => {
testAction(
it('should set namespace', () => {
return testAction(
actions.setNamespace,
mockNamespace,
mockedState,
[{ type: types.SET_NAMESPACE, payload: mockNamespace }],
[],
done,
);
});
});
describe('setStorageKey', () => {
it('should set storage key', (done) => {
testAction(
it('should set storage key', () => {
return testAction(
actions.setStorageKey,
mockStorageKey,
mockedState,
[{ type: types.SET_STORAGE_KEY, payload: mockStorageKey }],
[],
done,
);
});
});
describe('requestFrequentItems', () => {
it('should request frequent items', (done) => {
testAction(
it('should request frequent items', () => {
return testAction(
actions.requestFrequentItems,
null,
mockedState,
[{ type: types.REQUEST_FREQUENT_ITEMS }],
[],
done,
);
});
});
describe('receiveFrequentItemsSuccess', () => {
it('should set frequent items', (done) => {
testAction(
it('should set frequent items', () => {
return testAction(
actions.receiveFrequentItemsSuccess,
mockFrequentProjects,
mockedState,
[{ type: types.RECEIVE_FREQUENT_ITEMS_SUCCESS, payload: mockFrequentProjects }],
[],
done,
);
});
});
describe('receiveFrequentItemsError', () => {
it('should set frequent items error state', (done) => {
testAction(
it('should set frequent items error state', () => {
return testAction(
actions.receiveFrequentItemsError,
null,
mockedState,
[{ type: types.RECEIVE_FREQUENT_ITEMS_ERROR }],
[],
done,
);
});
});
describe('fetchFrequentItems', () => {
it('should dispatch `receiveFrequentItemsSuccess`', (done) => {
it('should dispatch `receiveFrequentItemsSuccess`', () => {
mockedState.namespace = mockNamespace;
mockedState.storageKey = mockStorageKey;
testAction(
return testAction(
actions.fetchFrequentItems,
null,
mockedState,
[],
[{ type: 'requestFrequentItems' }, { type: 'receiveFrequentItemsSuccess', payload: [] }],
done,
);
});
it('should dispatch `receiveFrequentItemsError`', (done) => {
it('should dispatch `receiveFrequentItemsError`', () => {
jest.spyOn(AccessorUtilities, 'canUseLocalStorage').mockReturnValue(false);
mockedState.namespace = mockNamespace;
mockedState.storageKey = mockStorageKey;
testAction(
return testAction(
actions.fetchFrequentItems,
null,
mockedState,
[],
[{ type: 'requestFrequentItems' }, { type: 'receiveFrequentItemsError' }],
done,
);
});
});
describe('requestSearchedItems', () => {
it('should request searched items', (done) => {
testAction(
it('should request searched items', () => {
return testAction(
actions.requestSearchedItems,
null,
mockedState,
[{ type: types.REQUEST_SEARCHED_ITEMS }],
[],
done,
);
});
});
describe('receiveSearchedItemsSuccess', () => {
it('should set searched items', (done) => {
testAction(
it('should set searched items', () => {
return testAction(
actions.receiveSearchedItemsSuccess,
mockSearchedProjects,
mockedState,
[{ type: types.RECEIVE_SEARCHED_ITEMS_SUCCESS, payload: mockSearchedProjects }],
[],
done,
);
});
});
describe('receiveSearchedItemsError', () => {
it('should set searched items error state', (done) => {
testAction(
it('should set searched items error state', () => {
return testAction(
actions.receiveSearchedItemsError,
null,
mockedState,
[{ type: types.RECEIVE_SEARCHED_ITEMS_ERROR }],
[],
done,
);
});
});
......@@ -168,10 +158,10 @@ describe('Frequent Items Dropdown Store Actions', () => {
gon.api_version = 'v4';
});
it('should dispatch `receiveSearchedItemsSuccess`', (done) => {
it('should dispatch `receiveSearchedItemsSuccess`', () => {
mock.onGet(/\/api\/v4\/projects.json(.*)$/).replyOnce(200, mockSearchedProjects, {});
testAction(
return testAction(
actions.fetchSearchedItems,
null,
mockedState,
......@@ -183,45 +173,41 @@ describe('Frequent Items Dropdown Store Actions', () => {
payload: { data: mockSearchedProjects, headers: {} },
},
],
done,
);
});
it('should dispatch `receiveSearchedItemsError`', (done) => {
it('should dispatch `receiveSearchedItemsError`', () => {
gon.api_version = 'v4';
mock.onGet(/\/api\/v4\/projects.json(.*)$/).replyOnce(500);
testAction(
return testAction(
actions.fetchSearchedItems,
null,
mockedState,
[],
[{ type: 'requestSearchedItems' }, { type: 'receiveSearchedItemsError' }],
done,
);
});
});
describe('setSearchQuery', () => {
it('should commit query and dispatch `fetchSearchedItems` when query is present', (done) => {
testAction(
it('should commit query and dispatch `fetchSearchedItems` when query is present', () => {
return testAction(
actions.setSearchQuery,
{ query: 'test' },
mockedState,
[{ type: types.SET_SEARCH_QUERY, payload: { query: 'test' } }],
[{ type: 'fetchSearchedItems', payload: { query: 'test' } }],
done,
);
});
it('should commit query and dispatch `fetchFrequentItems` when query is empty', (done) => {
testAction(
it('should commit query and dispatch `fetchFrequentItems` when query is empty', () => {
return testAction(
actions.setSearchQuery,
null,
mockedState,
[{ type: types.SET_SEARCH_QUERY, payload: null }],
[{ type: 'fetchFrequentItems' }],
done,
);
});
});
......
......@@ -11,23 +11,21 @@ describe('initDiscussionTab', () => {
`);
});
it('should pass canCreateNote as false to initImageDiff', (done) => {
it('should pass canCreateNote as false to initImageDiff', () => {
jest
.spyOn(initImageDiffHelper, 'initImageDiff')
.mockImplementation((diffFileEl, canCreateNote) => {
expect(canCreateNote).toEqual(false);
done();
});
initDiscussionTab();
});
it('should pass renderCommentBadge as true to initImageDiff', (done) => {
it('should pass renderCommentBadge as true to initImageDiff', () => {
jest
.spyOn(initImageDiffHelper, 'initImageDiff')
.mockImplementation((diffFileEl, canCreateNote, renderCommentBadge) => {
expect(renderCommentBadge).toEqual(true);
done();
});
initDiscussionTab();
......
......@@ -176,34 +176,36 @@ describe('ReplacedImageDiff', () => {
expect(ImageDiff.prototype.bindEvents).toHaveBeenCalled();
});
it('should register click eventlistener to 2-up view mode', (done) => {
jest.spyOn(ReplacedImageDiff.prototype, 'changeView').mockImplementation((viewMode) => {
expect(viewMode).toEqual(viewTypes.TWO_UP);
done();
});
it('should register click eventlistener to 2-up view mode', () => {
const changeViewSpy = jest
.spyOn(ReplacedImageDiff.prototype, 'changeView')
.mockImplementation(() => {});
replacedImageDiff.bindEvents();
replacedImageDiff.viewModesEls[viewTypes.TWO_UP].click();
expect(changeViewSpy).toHaveBeenCalledWith(viewTypes.TWO_UP, expect.any(Object));
});
it('should register click eventlistener to swipe view mode', (done) => {
jest.spyOn(ReplacedImageDiff.prototype, 'changeView').mockImplementation((viewMode) => {
expect(viewMode).toEqual(viewTypes.SWIPE);
done();
});
it('should register click eventlistener to swipe view mode', () => {
const changeViewSpy = jest
.spyOn(ReplacedImageDiff.prototype, 'changeView')
.mockImplementation(() => {});
replacedImageDiff.bindEvents();
replacedImageDiff.viewModesEls[viewTypes.SWIPE].click();
expect(changeViewSpy).toHaveBeenCalledWith(viewTypes.SWIPE, expect.any(Object));
});
it('should register click eventlistener to onion skin view mode', (done) => {
jest.spyOn(ReplacedImageDiff.prototype, 'changeView').mockImplementation((viewMode) => {
expect(viewMode).toEqual(viewTypes.SWIPE);
done();
});
it('should register click eventlistener to onion skin view mode', () => {
const changeViewSpy = jest
.spyOn(ReplacedImageDiff.prototype, 'changeView')
.mockImplementation(() => {});
replacedImageDiff.bindEvents();
replacedImageDiff.viewModesEls[viewTypes.SWIPE].click();
expect(changeViewSpy).toHaveBeenCalledWith(viewTypes.SWIPE, expect.any(Object));
});
});
......@@ -325,32 +327,34 @@ describe('ReplacedImageDiff', () => {
setupImageFrameEls();
});
it('should pass showCommentIndicator normalized indicator values', (done) => {
it('should pass showCommentIndicator normalized indicator values', () => {
jest.spyOn(imageDiffHelper, 'showCommentIndicator').mockImplementation(() => {});
jest
const resizeCoordinatesToImageElementSpy = jest
.spyOn(imageDiffHelper, 'resizeCoordinatesToImageElement')
.mockImplementation((imageEl, meta) => {
expect(meta.x).toEqual(indicator.x);
expect(meta.y).toEqual(indicator.y);
expect(meta.width).toEqual(indicator.image.width);
expect(meta.height).toEqual(indicator.image.height);
done();
});
.mockImplementation(() => {});
replacedImageDiff.renderNewView(indicator);
expect(resizeCoordinatesToImageElementSpy).toHaveBeenCalledWith(undefined, {
x: indicator.x,
y: indicator.y,
width: indicator.image.width,
height: indicator.image.height,
});
});
it('should call showCommentIndicator', (done) => {
it('should call showCommentIndicator', () => {
const normalized = {
normalized: true,
};
jest.spyOn(imageDiffHelper, 'resizeCoordinatesToImageElement').mockReturnValue(normalized);
jest
const showCommentIndicatorSpy = jest
.spyOn(imageDiffHelper, 'showCommentIndicator')
.mockImplementation((imageFrameEl, normalizedIndicator) => {
expect(normalizedIndicator).toEqual(normalized);
done();
});
.mockImplementation(() => {});
replacedImageDiff.renderNewView(indicator);
expect(showCommentIndicatorSpy).toHaveBeenCalledWith(undefined, normalized);
});
});
});
......
......@@ -38,21 +38,16 @@ describe('CreateMergeRequestDropdown', () => {
});
describe('getRef', () => {
it('escapes branch names correctly', (done) => {
it('escapes branch names correctly', async () => {
const endpoint = `${dropdown.refsPath}contains%23hash`;
jest.spyOn(axios, 'get');
axiosMock.onGet(endpoint).replyOnce({});
dropdown
.getRef('contains#hash')
.then(() => {
expect(axios.get).toHaveBeenCalledWith(
endpoint,
expect.objectContaining({ cancelToken: expect.anything() }),
);
})
.then(done)
.catch(done.fail);
await dropdown.getRef('contains#hash');
expect(axios.get).toHaveBeenCalledWith(
endpoint,
expect.objectContaining({ cancelToken: expect.anything() }),
);
});
});
......
......@@ -23,90 +23,82 @@ describe('RelatedMergeRequest store actions', () => {
});
describe('setInitialState', () => {
it('commits types.SET_INITIAL_STATE with given props', (done) => {
it('commits types.SET_INITIAL_STATE with given props', () => {
const props = { a: 1, b: 2 };
testAction(
return testAction(
actions.setInitialState,
props,
{},
[{ type: types.SET_INITIAL_STATE, payload: props }],
[],
done,
);
});
});
describe('requestData', () => {
it('commits types.REQUEST_DATA', (done) => {
testAction(actions.requestData, null, {}, [{ type: types.REQUEST_DATA }], [], done);
it('commits types.REQUEST_DATA', () => {
return testAction(actions.requestData, null, {}, [{ type: types.REQUEST_DATA }], []);
});
});
describe('receiveDataSuccess', () => {
it('commits types.RECEIVE_DATA_SUCCESS with data', (done) => {
it('commits types.RECEIVE_DATA_SUCCESS with data', () => {
const data = { a: 1, b: 2 };
testAction(
return testAction(
actions.receiveDataSuccess,
data,
{},
[{ type: types.RECEIVE_DATA_SUCCESS, payload: data }],
[],
done,
);
});
});
describe('receiveDataError', () => {
it('commits types.RECEIVE_DATA_ERROR', (done) => {
testAction(
it('commits types.RECEIVE_DATA_ERROR', () => {
return testAction(
actions.receiveDataError,
null,
{},
[{ type: types.RECEIVE_DATA_ERROR }],
[],
done,
);
});
});
describe('fetchMergeRequests', () => {
describe('for a successful request', () => {
it('should dispatch success action', (done) => {
it('should dispatch success action', () => {
const data = { a: 1 };
mock.onGet(`${state.apiEndpoint}?per_page=100`).replyOnce(200, data, { 'x-total': 2 });
testAction(
return testAction(
actions.fetchMergeRequests,
null,
state,
[],
[{ type: 'requestData' }, { type: 'receiveDataSuccess', payload: { data, total: 2 } }],
done,
);
});
});
describe('for a failing request', () => {
it('should dispatch error action', (done) => {
it('should dispatch error action', async () => {
mock.onGet(`${state.apiEndpoint}?per_page=100`).replyOnce(400);
testAction(
await testAction(
actions.fetchMergeRequests,
null,
state,
[],
[{ type: 'requestData' }, { type: 'receiveDataError' }],
() => {
expect(createFlash).toHaveBeenCalledTimes(1);
expect(createFlash).toHaveBeenCalledWith({
message: expect.stringMatching('Something went wrong'),
});
done();
},
);
expect(createFlash).toHaveBeenCalledTimes(1);
expect(createFlash).toHaveBeenCalledWith({
message: expect.stringMatching('Something went wrong'),
});
});
});
});
......
......@@ -375,8 +375,8 @@ describe('Job App', () => {
});
describe('sidebar', () => {
it('has no blank blocks', (done) => {
setupAndMount({
it('has no blank blocks', async () => {
await setupAndMount({
jobData: {
duration: null,
finished_at: null,
......@@ -387,17 +387,14 @@ describe('Job App', () => {
tags: [],
cancel_path: null,
},
})
.then(() => {
const blocks = wrapper.findAll('.blocks-container > *').wrappers;
expect(blocks.length).toBeGreaterThan(0);
blocks.forEach((block) => {
expect(block.text().trim()).not.toBe('');
});
})
.then(done)
.catch(done.fail);
});
const blocks = wrapper.findAll('.blocks-container > *').wrappers;
expect(blocks.length).toBeGreaterThan(0);
blocks.forEach((block) => {
expect(block.text().trim()).not.toBe('');
});
});
});
});
......
......@@ -39,62 +39,60 @@ describe('Job State actions', () => {
});
describe('setJobEndpoint', () => {
it('should commit SET_JOB_ENDPOINT mutation', (done) => {
testAction(
it('should commit SET_JOB_ENDPOINT mutation', () => {
return testAction(
setJobEndpoint,
'job/872324.json',
mockedState,
[{ type: types.SET_JOB_ENDPOINT, payload: 'job/872324.json' }],
[],
done,
);
});
});
describe('setJobLogOptions', () => {
it('should commit SET_JOB_LOG_OPTIONS mutation', (done) => {
testAction(
it('should commit SET_JOB_LOG_OPTIONS mutation', () => {
return testAction(
setJobLogOptions,
{ pagePath: 'job/872324/trace.json' },
mockedState,
[{ type: types.SET_JOB_LOG_OPTIONS, payload: { pagePath: 'job/872324/trace.json' } }],
[],
done,
);
});
});
describe('hideSidebar', () => {
it('should commit HIDE_SIDEBAR mutation', (done) => {
testAction(hideSidebar, null, mockedState, [{ type: types.HIDE_SIDEBAR }], [], done);
it('should commit HIDE_SIDEBAR mutation', () => {
return testAction(hideSidebar, null, mockedState, [{ type: types.HIDE_SIDEBAR }], []);
});
});
describe('showSidebar', () => {
it('should commit HIDE_SIDEBAR mutation', (done) => {
testAction(showSidebar, null, mockedState, [{ type: types.SHOW_SIDEBAR }], [], done);
it('should commit SHOW_SIDEBAR mutation', () => {
return testAction(showSidebar, null, mockedState, [{ type: types.SHOW_SIDEBAR }], []);
});
});
describe('toggleSidebar', () => {
describe('when isSidebarOpen is true', () => {
it('should dispatch hideSidebar', (done) => {
testAction(toggleSidebar, null, mockedState, [], [{ type: 'hideSidebar' }], done);
it('should dispatch hideSidebar', () => {
return testAction(toggleSidebar, null, mockedState, [], [{ type: 'hideSidebar' }]);
});
});
describe('when isSidebarOpen is false', () => {
it('should dispatch showSidebar', (done) => {
it('should dispatch showSidebar', () => {
mockedState.isSidebarOpen = false;
testAction(toggleSidebar, null, mockedState, [], [{ type: 'showSidebar' }], done);
return testAction(toggleSidebar, null, mockedState, [], [{ type: 'showSidebar' }]);
});
});
});
describe('requestJob', () => {
it('should commit REQUEST_JOB mutation', (done) => {
testAction(requestJob, null, mockedState, [{ type: types.REQUEST_JOB }], [], done);
it('should commit REQUEST_JOB mutation', () => {
return testAction(requestJob, null, mockedState, [{ type: types.REQUEST_JOB }], []);
});
});
......@@ -113,10 +111,10 @@ describe('Job State actions', () => {
});
describe('success', () => {
it('dispatches requestJob and receiveJobSuccess ', (done) => {
it('dispatches requestJob and receiveJobSuccess ', () => {
mock.onGet(`${TEST_HOST}/endpoint.json`).replyOnce(200, { id: 121212, name: 'karma' });
testAction(
return testAction(
fetchJob,
null,
mockedState,
......@@ -130,7 +128,6 @@ describe('Job State actions', () => {
type: 'receiveJobSuccess',
},
],
done,
);
});
});
......@@ -140,8 +137,8 @@ describe('Job State actions', () => {
mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500);
});
it('dispatches requestJob and receiveJobError ', (done) => {
testAction(
it('dispatches requestJob and receiveJobError ', () => {
return testAction(
fetchJob,
null,
mockedState,
......@@ -154,46 +151,50 @@ describe('Job State actions', () => {
type: 'receiveJobError',
},
],
done,
);
});
});
});
describe('receiveJobSuccess', () => {
it('should commit RECEIVE_JOB_SUCCESS mutation', (done) => {
testAction(
it('should commit RECEIVE_JOB_SUCCESS mutation', () => {
return testAction(
receiveJobSuccess,
{ id: 121232132 },
mockedState,
[{ type: types.RECEIVE_JOB_SUCCESS, payload: { id: 121232132 } }],
[],
done,
);
});
});
describe('receiveJobError', () => {
it('should commit RECEIVE_JOB_ERROR mutation', (done) => {
testAction(receiveJobError, null, mockedState, [{ type: types.RECEIVE_JOB_ERROR }], [], done);
it('should commit RECEIVE_JOB_ERROR mutation', () => {
return testAction(
receiveJobError,
null,
mockedState,
[{ type: types.RECEIVE_JOB_ERROR }],
[],
);
});
});
describe('scrollTop', () => {
it('should dispatch toggleScrollButtons action', (done) => {
testAction(scrollTop, null, mockedState, [], [{ type: 'toggleScrollButtons' }], done);
it('should dispatch toggleScrollButtons action', () => {
return testAction(scrollTop, null, mockedState, [], [{ type: 'toggleScrollButtons' }]);
});
});
describe('scrollBottom', () => {
it('should dispatch toggleScrollButtons action', (done) => {
testAction(scrollBottom, null, mockedState, [], [{ type: 'toggleScrollButtons' }], done);
it('should dispatch toggleScrollButtons action', () => {
return testAction(scrollBottom, null, mockedState, [], [{ type: 'toggleScrollButtons' }]);
});
});
describe('requestJobLog', () => {
it('should commit REQUEST_JOB_LOG mutation', (done) => {
testAction(requestJobLog, null, mockedState, [{ type: types.REQUEST_JOB_LOG }], [], done);
it('should commit REQUEST_JOB_LOG mutation', () => {
return testAction(requestJobLog, null, mockedState, [{ type: types.REQUEST_JOB_LOG }], []);
});
});
......@@ -212,13 +213,13 @@ describe('Job State actions', () => {
});
describe('success', () => {
it('dispatches requestJobLog, receiveJobLogSuccess and stopPollingJobLog when job is complete', (done) => {
it('dispatches requestJobLog, receiveJobLogSuccess and stopPollingJobLog when job is complete', () => {
mock.onGet(`${TEST_HOST}/endpoint/trace.json`).replyOnce(200, {
html: 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- :',
complete: true,
});
testAction(
return testAction(
fetchJobLog,
null,
mockedState,
......@@ -239,7 +240,6 @@ describe('Job State actions', () => {
type: 'stopPollingJobLog',
},
],
done,
);
});
......@@ -255,8 +255,8 @@ describe('Job State actions', () => {
mock.onGet(`${TEST_HOST}/endpoint/trace.json`).replyOnce(200, jobLogPayload);
});
it('dispatches startPollingJobLog', (done) => {
testAction(
it('dispatches startPollingJobLog', () => {
return testAction(
fetchJobLog,
null,
mockedState,
......@@ -266,14 +266,13 @@ describe('Job State actions', () => {
{ type: 'receiveJobLogSuccess', payload: jobLogPayload },
{ type: 'startPollingJobLog' },
],
done,
);
});
it('does not dispatch startPollingJobLog when timeout is non-empty', (done) => {
it('does not dispatch startPollingJobLog when timeout is non-empty', () => {
mockedState.jobLogTimeout = 1;
testAction(
return testAction(
fetchJobLog,
null,
mockedState,
......@@ -282,7 +281,6 @@ describe('Job State actions', () => {
{ type: 'toggleScrollisInBottom', payload: true },
{ type: 'receiveJobLogSuccess', payload: jobLogPayload },
],
done,
);
});
});
......@@ -293,8 +291,8 @@ describe('Job State actions', () => {
mock.onGet(`${TEST_HOST}/endpoint/trace.json`).reply(500);
});
it('dispatches requestJobLog and receiveJobLogError ', (done) => {
testAction(
it('dispatches requestJobLog and receiveJobLogError ', () => {
return testAction(
fetchJobLog,
null,
mockedState,
......@@ -304,7 +302,6 @@ describe('Job State actions', () => {
type: 'receiveJobLogError',
},
],
done,
);
});
});
......@@ -358,65 +355,58 @@ describe('Job State actions', () => {
window.clearTimeout = origTimeout;
});
it('should commit STOP_POLLING_JOB_LOG mutation ', (done) => {
it('should commit STOP_POLLING_JOB_LOG mutation ', async () => {
const jobLogTimeout = 7;
testAction(
await testAction(
stopPollingJobLog,
null,
{ ...mockedState, jobLogTimeout },
[{ type: types.SET_JOB_LOG_TIMEOUT, payload: 0 }, { type: types.STOP_POLLING_JOB_LOG }],
[],
)
.then(() => {
expect(window.clearTimeout).toHaveBeenCalledWith(jobLogTimeout);
})
.then(done)
.catch(done.fail);
);
expect(window.clearTimeout).toHaveBeenCalledWith(jobLogTimeout);
});
});
describe('receiveJobLogSuccess', () => {
it('should commit RECEIVE_JOB_LOG_SUCCESS mutation ', (done) => {
testAction(
it('should commit RECEIVE_JOB_LOG_SUCCESS mutation ', () => {
return testAction(
receiveJobLogSuccess,
'hello world',
mockedState,
[{ type: types.RECEIVE_JOB_LOG_SUCCESS, payload: 'hello world' }],
[],
done,
);
});
});
describe('receiveJobLogError', () => {
it('should commit stop polling job log', (done) => {
testAction(receiveJobLogError, null, mockedState, [], [{ type: 'stopPollingJobLog' }], done);
it('should commit stop polling job log', () => {
return testAction(receiveJobLogError, null, mockedState, [], [{ type: 'stopPollingJobLog' }]);
});
});
describe('toggleCollapsibleLine', () => {
it('should commit TOGGLE_COLLAPSIBLE_LINE mutation ', (done) => {
testAction(
it('should commit TOGGLE_COLLAPSIBLE_LINE mutation ', () => {
return testAction(
toggleCollapsibleLine,
{ isClosed: true },
mockedState,
[{ type: types.TOGGLE_COLLAPSIBLE_LINE, payload: { isClosed: true } }],
[],
done,
);
});
});
describe('requestJobsForStage', () => {
it('should commit REQUEST_JOBS_FOR_STAGE mutation ', (done) => {
testAction(
it('should commit REQUEST_JOBS_FOR_STAGE mutation ', () => {
return testAction(
requestJobsForStage,
{ name: 'deploy' },
mockedState,
[{ type: types.REQUEST_JOBS_FOR_STAGE, payload: { name: 'deploy' } }],
[],
done,
);
});
});
......@@ -433,12 +423,12 @@ describe('Job State actions', () => {
});
describe('success', () => {
it('dispatches requestJobsForStage and receiveJobsForStageSuccess ', (done) => {
it('dispatches requestJobsForStage and receiveJobsForStageSuccess ', () => {
mock
.onGet(`${TEST_HOST}/jobs.json`)
.replyOnce(200, { latest_statuses: [{ id: 121212, name: 'build' }], retried: [] });
testAction(
return testAction(
fetchJobsForStage,
{ dropdown_path: `${TEST_HOST}/jobs.json` },
mockedState,
......@@ -453,7 +443,6 @@ describe('Job State actions', () => {
type: 'receiveJobsForStageSuccess',
},
],
done,
);
});
});
......@@ -463,8 +452,8 @@ describe('Job State actions', () => {
mock.onGet(`${TEST_HOST}/jobs.json`).reply(500);
});
it('dispatches requestJobsForStage and receiveJobsForStageError', (done) => {
testAction(
it('dispatches requestJobsForStage and receiveJobsForStageError', () => {
return testAction(
fetchJobsForStage,
{ dropdown_path: `${TEST_HOST}/jobs.json` },
mockedState,
......@@ -478,34 +467,31 @@ describe('Job State actions', () => {
type: 'receiveJobsForStageError',
},
],
done,
);
});
});
});
describe('receiveJobsForStageSuccess', () => {
it('should commit RECEIVE_JOBS_FOR_STAGE_SUCCESS mutation ', (done) => {
testAction(
it('should commit RECEIVE_JOBS_FOR_STAGE_SUCCESS mutation ', () => {
return testAction(
receiveJobsForStageSuccess,
[{ id: 121212, name: 'karma' }],
mockedState,
[{ type: types.RECEIVE_JOBS_FOR_STAGE_SUCCESS, payload: [{ id: 121212, name: 'karma' }] }],
[],
done,
);
});
});
describe('receiveJobsForStageError', () => {
it('should commit RECEIVE_JOBS_FOR_STAGE_ERROR mutation ', (done) => {
testAction(
it('should commit RECEIVE_JOBS_FOR_STAGE_ERROR mutation ', () => {
return testAction(
receiveJobsForStageError,
null,
mockedState,
[{ type: types.RECEIVE_JOBS_FOR_STAGE_ERROR }],
[],
done,
);
});
});
......
......@@ -50,7 +50,7 @@ describe('Promote label modal', () => {
vm.$destroy();
});
it('redirects when a label is promoted', (done) => {
it('redirects when a label is promoted', () => {
const responseURL = `${TEST_HOST}/dummy/endpoint`;
jest.spyOn(axios, 'post').mockImplementation((url) => {
expect(url).toBe(labelMockData.url);
......@@ -65,39 +65,35 @@ describe('Promote label modal', () => {
});
});
vm.onSubmit()
.then(() => {
expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestFinished', {
labelUrl: labelMockData.url,
successful: true,
});
})
.then(done)
.catch(done.fail);
return vm.onSubmit().then(() => {
expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestFinished', {
labelUrl: labelMockData.url,
successful: true,
});
});
});
it('displays an error if promoting a label failed', (done) => {
it('displays an error if promoting a label failed', () => {
const dummyError = new Error('promoting label failed');
dummyError.response = { status: 500 };
jest.spyOn(axios, 'post').mockImplementation((url) => {
expect(url).toBe(labelMockData.url);
expect(eventHub.$emit).toHaveBeenCalledWith(
'promoteLabelModal.requestStarted',
labelMockData.url,
);
return Promise.reject(dummyError);
});
vm.onSubmit()
.catch((error) => {
expect(error).toBe(dummyError);
expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestFinished', {
labelUrl: labelMockData.url,
successful: false,
});
})
.then(done)
.catch(done.fail);
return vm.onSubmit().catch((error) => {
expect(error).toBe(dummyError);
expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestFinished', {
labelUrl: labelMockData.url,
successful: false,
});
});
});
});
});
......@@ -82,34 +82,39 @@ describe('getSuppressNetworkErrorsDuringNavigationLink', () => {
isNavigatingAway.mockReturnValue(false);
});
it('forwards successful requests', (done) => {
it('forwards successful requests', () => {
createSubscription(makeMockSuccessLink(), {
next({ data }) {
expect(data).toEqual({ foo: { id: 1 } });
},
error: () => done.fail('Should not happen'),
complete: () => done(),
error: () => {
throw new Error('Should not happen');
},
});
});
it('forwards GraphQL errors', (done) => {
it('forwards GraphQL errors', () => {
createSubscription(makeMockGraphQLErrorLink(), {
next({ errors }) {
expect(errors).toEqual([{ message: 'foo' }]);
},
error: () => done.fail('Should not happen'),
complete: () => done(),
error: () => {
throw new Error('Should not happen');
},
});
});
it('forwards network errors', (done) => {
it('forwards network errors', () => {
createSubscription(makeMockNetworkErrorLink(), {
next: () => done.fail('Should not happen'),
next: () => {
throw new Error('Should not happen');
},
error: (error) => {
expect(error.message).toBe('NetworkError');
done();
},
complete: () => done.fail('Should not happen'),
complete: () => {
throw new Error('Should not happen');
},
});
});
});
......@@ -119,23 +124,25 @@ describe('getSuppressNetworkErrorsDuringNavigationLink', () => {
isNavigatingAway.mockReturnValue(true);
});
it('forwards successful requests', (done) => {
it('forwards successful requests', () => {
createSubscription(makeMockSuccessLink(), {
next({ data }) {
expect(data).toEqual({ foo: { id: 1 } });
},
error: () => done.fail('Should not happen'),
complete: () => done(),
error: () => {
throw new Error('Should not happen');
},
});
});
it('forwards GraphQL errors', (done) => {
it('forwards GraphQL errors', () => {
createSubscription(makeMockGraphQLErrorLink(), {
next({ errors }) {
expect(errors).toEqual([{ message: 'foo' }]);
},
error: () => done.fail('Should not happen'),
complete: () => done(),
error: () => {
throw new Error('Should not happen');
},
});
});
});
......
......@@ -58,17 +58,16 @@ describe('StartupJSLink', () => {
link = ApolloLink.from([startupLink, new ApolloLink(() => Observable.of(FORWARDED_RESPONSE))]);
};
it('forwards requests if no calls are set up', (done) => {
it('forwards requests if no calls are set up', () => {
setupLink();
link.request(mockOperation()).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls).toBe(null);
expect(startupLink.request).toEqual(StartupJSLink.noopRequest);
done();
});
});
it('forwards requests if the operation is not pre-loaded', (done) => {
it('forwards requests if the operation is not pre-loaded', () => {
window.gl = {
startup_graphql_calls: [
{
......@@ -82,12 +81,11 @@ describe('StartupJSLink', () => {
link.request(mockOperation({ operationName: 'notLoaded' })).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls.size).toBe(1);
done();
});
});
describe('variable match errors: ', () => {
it('forwards requests if the variables are not matching', (done) => {
it('forwards requests if the variables are not matching', () => {
window.gl = {
startup_graphql_calls: [
{
......@@ -101,11 +99,10 @@ describe('StartupJSLink', () => {
link.request(mockOperation()).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
it('forwards requests if more variables are set in the operation', (done) => {
it('forwards requests if more variables are set in the operation', () => {
window.gl = {
startup_graphql_calls: [
{
......@@ -118,11 +115,10 @@ describe('StartupJSLink', () => {
link.request(mockOperation()).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
it('forwards requests if less variables are set in the operation', (done) => {
it('forwards requests if less variables are set in the operation', () => {
window.gl = {
startup_graphql_calls: [
{
......@@ -136,11 +132,10 @@ describe('StartupJSLink', () => {
link.request(mockOperation({ variables: { id: 3 } })).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
it('forwards requests if different variables are set', (done) => {
it('forwards requests if different variables are set', () => {
window.gl = {
startup_graphql_calls: [
{
......@@ -154,11 +149,10 @@ describe('StartupJSLink', () => {
link.request(mockOperation({ variables: { id: 3 } })).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
it('forwards requests if array variables have a different order', (done) => {
it('forwards requests if array variables have a different order', () => {
window.gl = {
startup_graphql_calls: [
{
......@@ -172,13 +166,12 @@ describe('StartupJSLink', () => {
link.request(mockOperation({ variables: { id: [4, 3] } })).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
});
describe('error handling', () => {
it('forwards the call if the fetchCall is failing with a HTTP Error', (done) => {
it('forwards the call if the fetchCall is failing with a HTTP Error', () => {
window.gl = {
startup_graphql_calls: [
{
......@@ -192,11 +185,10 @@ describe('StartupJSLink', () => {
link.request(mockOperation()).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
it('forwards the call if it errors (e.g. failing JSON)', (done) => {
it('forwards the call if it errors (e.g. failing JSON)', () => {
window.gl = {
startup_graphql_calls: [
{
......@@ -210,11 +202,10 @@ describe('StartupJSLink', () => {
link.request(mockOperation()).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
it('forwards the call if the response contains an error', (done) => {
it('forwards the call if the response contains an error', () => {
window.gl = {
startup_graphql_calls: [
{
......@@ -228,11 +219,10 @@ describe('StartupJSLink', () => {
link.request(mockOperation()).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
it("forwards the call if the response doesn't contain a data object", (done) => {
it("forwards the call if the response doesn't contain a data object", () => {
window.gl = {
startup_graphql_calls: [
{
......@@ -246,12 +236,11 @@ describe('StartupJSLink', () => {
link.request(mockOperation()).subscribe((result) => {
expect(result).toEqual(FORWARDED_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
});
it('resolves the request if the operation is matching', (done) => {
it('resolves the request if the operation is matching', () => {
window.gl = {
startup_graphql_calls: [
{
......@@ -265,11 +254,10 @@ describe('StartupJSLink', () => {
link.request(mockOperation()).subscribe((result) => {
expect(result).toEqual(STARTUP_JS_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
it('resolves the request exactly once', (done) => {
it('resolves the request exactly once', () => {
window.gl = {
startup_graphql_calls: [
{
......@@ -285,12 +273,11 @@ describe('StartupJSLink', () => {
expect(startupLink.startupCalls.size).toBe(0);
link.request(mockOperation()).subscribe((result2) => {
expect(result2).toEqual(FORWARDED_RESPONSE);
done();
});
});
});
it('resolves the request if the variables have a different order', (done) => {
it('resolves the request if the variables have a different order', () => {
window.gl = {
startup_graphql_calls: [
{
......@@ -304,11 +291,10 @@ describe('StartupJSLink', () => {
link.request(mockOperation({ variables: { name: 'foo', id: 3 } })).subscribe((result) => {
expect(result).toEqual(STARTUP_JS_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
it('resolves the request if the variables have undefined values', (done) => {
it('resolves the request if the variables have undefined values', () => {
window.gl = {
startup_graphql_calls: [
{
......@@ -324,11 +310,10 @@ describe('StartupJSLink', () => {
.subscribe((result) => {
expect(result).toEqual(STARTUP_JS_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
it('resolves the request if the variables are of an array format', (done) => {
it('resolves the request if the variables are of an array format', () => {
window.gl = {
startup_graphql_calls: [
{
......@@ -342,11 +327,10 @@ describe('StartupJSLink', () => {
link.request(mockOperation({ variables: { id: [3, 4] } })).subscribe((result) => {
expect(result).toEqual(STARTUP_JS_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
it('resolves multiple requests correctly', (done) => {
it('resolves multiple requests correctly', () => {
window.gl = {
startup_graphql_calls: [
{
......@@ -368,7 +352,6 @@ describe('StartupJSLink', () => {
link.request(mockOperation({ operationName: OPERATION_NAME })).subscribe((result2) => {
expect(result2).toEqual(STARTUP_JS_RESPONSE);
expect(startupLink.startupCalls.size).toBe(0);
done();
});
});
});
......
......@@ -266,15 +266,18 @@ describe('common_utils', () => {
});
describe('debounceByAnimationFrame', () => {
it('debounces a function to allow a maximum of one call per animation frame', (done) => {
it('debounces a function to allow a maximum of one call per animation frame', () => {
const spy = jest.fn();
const debouncedSpy = commonUtils.debounceByAnimationFrame(spy);
window.requestAnimationFrame(() => {
debouncedSpy();
debouncedSpy();
return new Promise((resolve) => {
window.requestAnimationFrame(() => {
expect(spy).toHaveBeenCalledTimes(1);
done();
debouncedSpy();
debouncedSpy();
window.requestAnimationFrame(() => {
expect(spy).toHaveBeenCalledTimes(1);
resolve();
});
});
});
});
......@@ -372,28 +375,24 @@ describe('common_utils', () => {
jest.spyOn(window, 'setTimeout');
});
it('solves the promise from the callback', (done) => {
it('solves the promise from the callback', () => {
const expectedResponseValue = 'Success!';
commonUtils
return commonUtils
.backOff((next, stop) =>
new Promise((resolve) => {
resolve(expectedResponseValue);
})
.then((resp) => {
stop(resp);
})
.catch(done.fail),
}).then((resp) => {
stop(resp);
}),
)
.then((respBackoff) => {
expect(respBackoff).toBe(expectedResponseValue);
done();
})
.catch(done.fail);
});
});
it('catches the rejected promise from the callback ', (done) => {
it('catches the rejected promise from the callback ', () => {
const errorMessage = 'Mistakes were made!';
commonUtils
return commonUtils
.backOff((next, stop) => {
new Promise((resolve, reject) => {
reject(new Error(errorMessage));
......@@ -406,39 +405,34 @@ describe('common_utils', () => {
.catch((errBackoffResp) => {
expect(errBackoffResp instanceof Error).toBe(true);
expect(errBackoffResp.message).toBe(errorMessage);
done();
});
});
it('solves the promise correctly after retrying a third time', (done) => {
it('solves the promise correctly after retrying a third time', () => {
let numberOfCalls = 1;
const expectedResponseValue = 'Success!';
commonUtils
return commonUtils
.backOff((next, stop) =>
Promise.resolve(expectedResponseValue)
.then((resp) => {
if (numberOfCalls < 3) {
numberOfCalls += 1;
next();
jest.runOnlyPendingTimers();
} else {
stop(resp);
}
})
.catch(done.fail),
Promise.resolve(expectedResponseValue).then((resp) => {
if (numberOfCalls < 3) {
numberOfCalls += 1;
next();
jest.runOnlyPendingTimers();
} else {
stop(resp);
}
}),
)
.then((respBackoff) => {
const timeouts = window.setTimeout.mock.calls.map(([, timeout]) => timeout);
expect(timeouts).toEqual([2000, 4000]);
expect(respBackoff).toBe(expectedResponseValue);
done();
})
.catch(done.fail);
});
});
it('rejects the backOff promise after timing out', (done) => {
commonUtils
it('rejects the backOff promise after timing out', () => {
return commonUtils
.backOff((next) => {
next();
jest.runOnlyPendingTimers();
......@@ -449,7 +443,6 @@ describe('common_utils', () => {
expect(timeouts).toEqual([2000, 4000, 8000, 16000, 32000, 32000]);
expect(errBackoffResp instanceof Error).toBe(true);
expect(errBackoffResp.message).toBe('BACKOFF_TIMEOUT');
done();
});
});
});
......
......@@ -50,58 +50,48 @@ describe('Poll', () => {
};
});
it('calls the success callback when no header for interval is provided', (done) => {
it('calls the success callback when no header for interval is provided', () => {
mockServiceCall({ status: 200 });
setup();
waitForAllCallsToFinish(1, () => {
return waitForAllCallsToFinish(1, () => {
expect(callbacks.success).toHaveBeenCalled();
expect(callbacks.error).not.toHaveBeenCalled();
done();
});
});
it('calls the error callback when the http request returns an error', (done) => {
it('calls the error callback when the http request returns an error', () => {
mockServiceCall({ status: 500 }, true);
setup();
waitForAllCallsToFinish(1, () => {
return waitForAllCallsToFinish(1, () => {
expect(callbacks.success).not.toHaveBeenCalled();
expect(callbacks.error).toHaveBeenCalled();
done();
});
});
it('skips the error callback when request is aborted', (done) => {
it('skips the error callback when request is aborted', () => {
mockServiceCall({ status: 0 }, true);
setup();
waitForAllCallsToFinish(1, () => {
return waitForAllCallsToFinish(1, () => {
expect(callbacks.success).not.toHaveBeenCalled();
expect(callbacks.error).not.toHaveBeenCalled();
expect(callbacks.notification).toHaveBeenCalled();
done();
});
});
it('should call the success callback when the interval header is -1', (done) => {
it('should call the success callback when the interval header is -1', () => {
mockServiceCall({ status: 200, headers: { 'poll-interval': -1 } });
setup()
.then(() => {
expect(callbacks.success).toHaveBeenCalled();
expect(callbacks.error).not.toHaveBeenCalled();
done();
})
.catch(done.fail);
return setup().then(() => {
expect(callbacks.success).toHaveBeenCalled();
expect(callbacks.error).not.toHaveBeenCalled();
});
});
describe('for 2xx status code', () => {
successCodes.forEach((httpCode) => {
it(`starts polling when http status is ${httpCode} and interval header is provided`, (done) => {
it(`starts polling when http status is ${httpCode} and interval header is provided`, () => {
mockServiceCall({ status: httpCode, headers: { 'poll-interval': 1 } });
const Polling = new Poll({
......@@ -114,22 +104,20 @@ describe('Poll', () => {
Polling.makeRequest();
waitForAllCallsToFinish(2, () => {
return waitForAllCallsToFinish(2, () => {
Polling.stop();
expect(service.fetch.mock.calls).toHaveLength(2);
expect(service.fetch).toHaveBeenCalledWith({ page: 1 });
expect(callbacks.success).toHaveBeenCalled();
expect(callbacks.error).not.toHaveBeenCalled();
done();
});
});
});
});
describe('with delayed initial request', () => {
it('delays the first request', async (done) => {
it('delays the first request', async () => {
mockServiceCall({ status: 200, headers: { 'poll-interval': 1 } });
const Polling = new Poll({
......@@ -144,21 +132,19 @@ describe('Poll', () => {
expect(Polling.timeoutID).toBeTruthy();
waitForAllCallsToFinish(2, () => {
return waitForAllCallsToFinish(2, () => {
Polling.stop();
expect(service.fetch.mock.calls).toHaveLength(2);
expect(service.fetch).toHaveBeenCalledWith({ page: 1 });
expect(callbacks.success).toHaveBeenCalled();
expect(callbacks.error).not.toHaveBeenCalled();
done();
});
});
});
describe('stop', () => {
it('stops polling when method is called', (done) => {
it('stops polling when method is called', () => {
mockServiceCall({ status: 200, headers: { 'poll-interval': 1 } });
const Polling = new Poll({
......@@ -175,18 +161,16 @@ describe('Poll', () => {
Polling.makeRequest();
waitForAllCallsToFinish(1, () => {
return waitForAllCallsToFinish(1, () => {
expect(service.fetch.mock.calls).toHaveLength(1);
expect(service.fetch).toHaveBeenCalledWith({ page: 1 });
expect(Polling.stop).toHaveBeenCalled();
done();
});
});
});
describe('enable', () => {
it('should enable polling upon a response', (done) => {
it('should enable polling upon a response', () => {
mockServiceCall({ status: 200 });
const Polling = new Poll({
resource: service,
......@@ -200,19 +184,18 @@ describe('Poll', () => {
response: { status: 200, headers: { 'poll-interval': 1 } },
});
waitForAllCallsToFinish(1, () => {
return waitForAllCallsToFinish(1, () => {
Polling.stop();
expect(service.fetch.mock.calls).toHaveLength(1);
expect(service.fetch).toHaveBeenCalledWith({ page: 4 });
expect(Polling.options.data).toEqual({ page: 4 });
done();
});
});
});
describe('restart', () => {
it('should restart polling when its called', (done) => {
it('should restart polling when its called', () => {
mockServiceCall({ status: 200, headers: { 'poll-interval': 1 } });
const Polling = new Poll({
......@@ -238,7 +221,7 @@ describe('Poll', () => {
Polling.makeRequest();
waitForAllCallsToFinish(2, () => {
return waitForAllCallsToFinish(2, () => {
Polling.stop();
expect(service.fetch.mock.calls).toHaveLength(2);
......@@ -247,7 +230,6 @@ describe('Poll', () => {
expect(Polling.enable).toHaveBeenCalled();
expect(Polling.restart).toHaveBeenCalled();
expect(Polling.options.data).toEqual({ page: 4 });
done();
});
});
});
......
......@@ -93,7 +93,7 @@ describe('UsersCache', () => {
.mockImplementation((query, options) => apiSpy(query, options));
});
it('stores and returns data from API call if cache is empty', (done) => {
it('stores and returns data from API call if cache is empty', async () => {
apiSpy = (query, options) => {
expect(query).toBe('');
expect(options).toEqual({
......@@ -105,16 +105,12 @@ describe('UsersCache', () => {
});
};
UsersCache.retrieve(dummyUsername)
.then((user) => {
expect(user).toBe(dummyUser);
expect(UsersCache.internalStorage[dummyUsername]).toBe(dummyUser);
})
.then(done)
.catch(done.fail);
const user = await UsersCache.retrieve(dummyUsername);
expect(user).toBe(dummyUser);
expect(UsersCache.internalStorage[dummyUsername]).toBe(dummyUser);
});
it('returns undefined if Ajax call fails and cache is empty', (done) => {
it('returns undefined if Ajax call fails and cache is empty', async () => {
const dummyError = new Error('server exploded');
apiSpy = (query, options) => {
......@@ -126,26 +122,18 @@ describe('UsersCache', () => {
return Promise.reject(dummyError);
};
UsersCache.retrieve(dummyUsername)
.then((user) => done.fail(`Received unexpected user: ${JSON.stringify(user)}`))
.catch((error) => {
expect(error).toBe(dummyError);
})
.then(done)
.catch(done.fail);
await expect(UsersCache.retrieve(dummyUsername)).rejects.toEqual(dummyError);
});
it('makes no Ajax call if matching data exists', (done) => {
it('makes no Ajax call if matching data exists', async () => {
UsersCache.internalStorage[dummyUsername] = dummyUser;
apiSpy = () => done.fail(new Error('expected no Ajax call!'));
apiSpy = () => {
throw new Error('expected no Ajax call!');
};
UsersCache.retrieve(dummyUsername)
.then((user) => {
expect(user).toBe(dummyUser);
})
.then(done)
.catch(done.fail);
const user = await UsersCache.retrieve(dummyUsername);
expect(user).toBe(dummyUser);
});
});
......@@ -156,7 +144,7 @@ describe('UsersCache', () => {
jest.spyOn(UserApi, 'getUser').mockImplementation((id) => apiSpy(id));
});
it('stores and returns data from API call if cache is empty', (done) => {
it('stores and returns data from API call if cache is empty', async () => {
apiSpy = (id) => {
expect(id).toBe(dummyUserId);
......@@ -165,16 +153,12 @@ describe('UsersCache', () => {
});
};
UsersCache.retrieveById(dummyUserId)
.then((user) => {
expect(user).toBe(dummyUser);
expect(UsersCache.internalStorage[dummyUserId]).toBe(dummyUser);
})
.then(done)
.catch(done.fail);
const user = await UsersCache.retrieveById(dummyUserId);
expect(user).toBe(dummyUser);
expect(UsersCache.internalStorage[dummyUserId]).toBe(dummyUser);
});
it('returns undefined if Ajax call fails and cache is empty', (done) => {
it('returns undefined if Ajax call fails and cache is empty', async () => {
const dummyError = new Error('server exploded');
apiSpy = (id) => {
......@@ -183,26 +167,18 @@ describe('UsersCache', () => {
return Promise.reject(dummyError);
};
UsersCache.retrieveById(dummyUserId)
.then((user) => done.fail(`Received unexpected user: ${JSON.stringify(user)}`))
.catch((error) => {
expect(error).toBe(dummyError);
})
.then(done)
.catch(done.fail);
await expect(UsersCache.retrieveById(dummyUserId)).rejects.toEqual(dummyError);
});
it('makes no Ajax call if matching data exists', (done) => {
it('makes no Ajax call if matching data exists', async () => {
UsersCache.internalStorage[dummyUserId] = dummyUser;
apiSpy = () => done.fail(new Error('expected no Ajax call!'));
apiSpy = () => {
throw new Error('expected no Ajax call!');
};
UsersCache.retrieveById(dummyUserId)
.then((user) => {
expect(user).toBe(dummyUser);
})
.then(done)
.catch(done.fail);
const user = await UsersCache.retrieveById(dummyUserId);
expect(user).toBe(dummyUser);
});
});
......@@ -213,7 +189,7 @@ describe('UsersCache', () => {
jest.spyOn(UserApi, 'getUserStatus').mockImplementation((id) => apiSpy(id));
});
it('stores and returns data from API call if cache is empty', (done) => {
it('stores and returns data from API call if cache is empty', async () => {
apiSpy = (id) => {
expect(id).toBe(dummyUserId);
......@@ -222,16 +198,12 @@ describe('UsersCache', () => {
});
};
UsersCache.retrieveStatusById(dummyUserId)
.then((userStatus) => {
expect(userStatus).toBe(dummyUserStatus);
expect(UsersCache.internalStorage[dummyUserId].status).toBe(dummyUserStatus);
})
.then(done)
.catch(done.fail);
const userStatus = await UsersCache.retrieveStatusById(dummyUserId);
expect(userStatus).toBe(dummyUserStatus);
expect(UsersCache.internalStorage[dummyUserId].status).toBe(dummyUserStatus);
});
it('returns undefined if Ajax call fails and cache is empty', (done) => {
it('returns undefined if Ajax call fails and cache is empty', async () => {
const dummyError = new Error('server exploded');
apiSpy = (id) => {
......@@ -240,28 +212,20 @@ describe('UsersCache', () => {
return Promise.reject(dummyError);
};
UsersCache.retrieveStatusById(dummyUserId)
.then((userStatus) => done.fail(`Received unexpected user: ${JSON.stringify(userStatus)}`))
.catch((error) => {
expect(error).toBe(dummyError);
})
.then(done)
.catch(done.fail);
await expect(UsersCache.retrieveStatusById(dummyUserId)).rejects.toEqual(dummyError);
});
it('makes no Ajax call if matching data exists', (done) => {
it('makes no Ajax call if matching data exists', async () => {
UsersCache.internalStorage[dummyUserId] = {
status: dummyUserStatus,
};
apiSpy = () => done.fail(new Error('expected no Ajax call!'));
apiSpy = () => {
throw new Error('expected no Ajax call!');
};
UsersCache.retrieveStatusById(dummyUserId)
.then((userStatus) => {
expect(userStatus).toBe(dummyUserStatus);
})
.then(done)
.catch(done.fail);
const userStatus = await UsersCache.retrieveStatusById(dummyUserId);
expect(userStatus).toBe(dummyUserStatus);
});
});
});
......@@ -34,9 +34,9 @@ describe('merge conflicts actions', () => {
describe('fetchConflictsData', () => {
const conflictsPath = 'conflicts/path/mock';
it('on success dispatches setConflictsData', (done) => {
it('on success dispatches setConflictsData', () => {
mock.onGet(conflictsPath).reply(200, {});
testAction(
return testAction(
actions.fetchConflictsData,
conflictsPath,
{},
......@@ -45,13 +45,12 @@ describe('merge conflicts actions', () => {
{ type: types.SET_LOADING_STATE, payload: false },
],
[{ type: 'setConflictsData', payload: {} }],
done,
);
});
it('when data has type equal to error ', (done) => {
it('when data has type equal to error ', () => {
mock.onGet(conflictsPath).reply(200, { type: 'error', message: 'error message' });
testAction(
return testAction(
actions.fetchConflictsData,
conflictsPath,
{},
......@@ -61,13 +60,12 @@ describe('merge conflicts actions', () => {
{ type: types.SET_LOADING_STATE, payload: false },
],
[],
done,
);
});
it('when request fails ', (done) => {
it('when request fails ', () => {
mock.onGet(conflictsPath).reply(400);
testAction(
return testAction(
actions.fetchConflictsData,
conflictsPath,
{},
......@@ -77,15 +75,14 @@ describe('merge conflicts actions', () => {
{ type: types.SET_LOADING_STATE, payload: false },
],
[],
done,
);
});
});
describe('setConflictsData', () => {
it('INTERACTIVE_RESOLVE_MODE updates the correct file ', (done) => {
it('INTERACTIVE_RESOLVE_MODE updates the correct file ', () => {
decorateFiles.mockReturnValue([{ bar: 'baz' }]);
testAction(
return testAction(
actions.setConflictsData,
{ files, foo: 'bar' },
{},
......@@ -96,7 +93,6 @@ describe('merge conflicts actions', () => {
},
],
[],
done,
);
});
});
......@@ -105,24 +101,21 @@ describe('merge conflicts actions', () => {
useMockLocationHelper();
const resolveConflictsPath = 'resolve/conflicts/path/mock';
it('on success reloads the page', (done) => {
it('on success reloads the page', async () => {
mock.onPost(resolveConflictsPath).reply(200, { redirect_to: 'hrefPath' });
testAction(
await testAction(
actions.submitResolvedConflicts,
resolveConflictsPath,
{},
[{ type: types.SET_SUBMIT_STATE, payload: true }],
[],
() => {
expect(window.location.assign).toHaveBeenCalledWith('hrefPath');
done();
},
);
expect(window.location.assign).toHaveBeenCalledWith('hrefPath');
});
it('on errors shows flash', (done) => {
it('on errors shows flash', async () => {
mock.onPost(resolveConflictsPath).reply(400);
testAction(
await testAction(
actions.submitResolvedConflicts,
resolveConflictsPath,
{},
......@@ -131,13 +124,10 @@ describe('merge conflicts actions', () => {
{ type: types.SET_SUBMIT_STATE, payload: false },
],
[],
() => {
expect(createFlash).toHaveBeenCalledWith({
message: 'Failed to save merge conflicts resolutions. Please try again!',
});
done();
},
);
expect(createFlash).toHaveBeenCalledWith({
message: 'Failed to save merge conflicts resolutions. Please try again!',
});
});
});
......@@ -193,9 +183,9 @@ describe('merge conflicts actions', () => {
});
describe('setViewType', () => {
it('commits the right mutation', (done) => {
it('commits the right mutation', async () => {
const payload = 'viewType';
testAction(
await testAction(
actions.setViewType,
payload,
{},
......@@ -206,14 +196,11 @@ describe('merge conflicts actions', () => {
},
],
[],
() => {
expect(Cookies.set).toHaveBeenCalledWith('diff_view', payload, {
expires: 365,
secure: false,
});
done();
},
);
expect(Cookies.set).toHaveBeenCalledWith('diff_view', payload, {
expires: 365,
secure: false,
});
});
});
......@@ -252,8 +239,8 @@ describe('merge conflicts actions', () => {
});
describe('setFileResolveMode', () => {
it('INTERACTIVE_RESOLVE_MODE updates the correct file ', (done) => {
testAction(
it('INTERACTIVE_RESOLVE_MODE updates the correct file ', () => {
return testAction(
actions.setFileResolveMode,
{ file: files[0], mode: INTERACTIVE_RESOLVE_MODE },
{ conflictsData: { files }, getFileIndex: () => 0 },
......@@ -267,11 +254,10 @@ describe('merge conflicts actions', () => {
},
],
[],
done,
);
});
it('EDIT_RESOLVE_MODE updates the correct file ', (done) => {
it('EDIT_RESOLVE_MODE updates the correct file ', async () => {
restoreFileLinesState.mockReturnValue([]);
const file = {
...files[0],
......@@ -280,7 +266,7 @@ describe('merge conflicts actions', () => {
resolutionData: {},
resolveMode: EDIT_RESOLVE_MODE,
};
testAction(
await testAction(
actions.setFileResolveMode,
{ file: files[0], mode: EDIT_RESOLVE_MODE },
{ conflictsData: { files }, getFileIndex: () => 0 },
......@@ -294,17 +280,14 @@ describe('merge conflicts actions', () => {
},
],
[],
() => {
expect(restoreFileLinesState).toHaveBeenCalledWith(file);
done();
},
);
expect(restoreFileLinesState).toHaveBeenCalledWith(file);
});
});
describe('setPromptConfirmationState', () => {
it('updates the correct file ', (done) => {
testAction(
it('updates the correct file ', () => {
return testAction(
actions.setPromptConfirmationState,
{ file: files[0], promptDiscardConfirmation: true },
{ conflictsData: { files }, getFileIndex: () => 0 },
......@@ -318,7 +301,6 @@ describe('merge conflicts actions', () => {
},
],
[],
done,
);
});
});
......@@ -333,11 +315,11 @@ describe('merge conflicts actions', () => {
],
};
it('updates the correct file ', (done) => {
it('updates the correct file ', async () => {
const marLikeMockReturn = { foo: 'bar' };
markLine.mockReturnValue(marLikeMockReturn);
testAction(
await testAction(
actions.handleSelected,
{ file, line: { id: 1, section: 'baz' } },
{ conflictsData: { files }, getFileIndex: () => 0 },
......@@ -359,11 +341,8 @@ describe('merge conflicts actions', () => {
},
],
[],
() => {
expect(markLine).toHaveBeenCalledTimes(3);
done();
},
);
expect(markLine).toHaveBeenCalledTimes(3);
});
});
});
......@@ -32,7 +32,7 @@ describe('delete_milestone_modal.vue', () => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
});
it('deletes milestone and redirects to overview page', (done) => {
it('deletes milestone and redirects to overview page', async () => {
const responseURL = `${TEST_HOST}/delete_milestone_modal.vue/milestoneOverview`;
jest.spyOn(axios, 'delete').mockImplementation((url) => {
expect(url).toBe(props.milestoneUrl);
......@@ -48,19 +48,15 @@ describe('delete_milestone_modal.vue', () => {
});
});
vm.onSubmit()
.then(() => {
expect(redirectTo).toHaveBeenCalledWith(responseURL);
expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', {
milestoneUrl: props.milestoneUrl,
successful: true,
});
})
.then(done)
.catch(done.fail);
await vm.onSubmit();
expect(redirectTo).toHaveBeenCalledWith(responseURL);
expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', {
milestoneUrl: props.milestoneUrl,
successful: true,
});
});
it('displays error if deleting milestone failed', (done) => {
it('displays error if deleting milestone failed', async () => {
const dummyError = new Error('deleting milestone failed');
dummyError.response = { status: 418 };
jest.spyOn(axios, 'delete').mockImplementation((url) => {
......@@ -73,17 +69,12 @@ describe('delete_milestone_modal.vue', () => {
return Promise.reject(dummyError);
});
vm.onSubmit()
.catch((error) => {
expect(error).toBe(dummyError);
expect(redirectTo).not.toHaveBeenCalled();
expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', {
milestoneUrl: props.milestoneUrl,
successful: false,
});
})
.then(done)
.catch(done.fail);
await expect(vm.onSubmit()).rejects.toEqual(dummyError);
expect(redirectTo).not.toHaveBeenCalled();
expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', {
milestoneUrl: props.milestoneUrl,
successful: false,
});
});
});
......
......@@ -109,7 +109,7 @@ describe('Actions menu', () => {
describe('adding new metric from modal', () => {
let origPage;
beforeEach((done) => {
beforeEach(() => {
jest.spyOn(Tracking, 'event').mockReturnValue();
createShallowWrapper();
......@@ -118,7 +118,7 @@ describe('Actions menu', () => {
origPage = document.body.dataset.page;
document.body.dataset.page = 'projects:environments:metrics';
nextTick(done);
return nextTick();
});
afterEach(() => {
......
......@@ -88,8 +88,8 @@ describe('Monitoring store actions', () => {
// Setup
describe('setGettingStartedEmptyState', () => {
it('should commit SET_GETTING_STARTED_EMPTY_STATE mutation', (done) => {
testAction(
it('should commit SET_GETTING_STARTED_EMPTY_STATE mutation', () => {
return testAction(
setGettingStartedEmptyState,
null,
state,
......@@ -99,14 +99,13 @@ describe('Monitoring store actions', () => {
},
],
[],
done,
);
});
});
describe('setInitialState', () => {
it('should commit SET_INITIAL_STATE mutation', (done) => {
testAction(
it('should commit SET_INITIAL_STATE mutation', () => {
return testAction(
setInitialState,
{
currentDashboard: '.gitlab/dashboards/dashboard.yml',
......@@ -123,7 +122,6 @@ describe('Monitoring store actions', () => {
},
],
[],
done,
);
});
});
......@@ -233,51 +231,39 @@ describe('Monitoring store actions', () => {
};
});
it('dispatches a failure', (done) => {
result()
.then(() => {
expect(commit).toHaveBeenCalledWith(
types.SET_ALL_DASHBOARDS,
mockDashboardsErrorResponse.all_dashboards,
);
expect(dispatch).toHaveBeenCalledWith(
'receiveMetricsDashboardFailure',
new Error('Request failed with status code 500'),
);
expect(createFlash).toHaveBeenCalled();
done();
})
.catch(done.fail);
it('dispatches a failure', async () => {
await result();
expect(commit).toHaveBeenCalledWith(
types.SET_ALL_DASHBOARDS,
mockDashboardsErrorResponse.all_dashboards,
);
expect(dispatch).toHaveBeenCalledWith(
'receiveMetricsDashboardFailure',
new Error('Request failed with status code 500'),
);
expect(createFlash).toHaveBeenCalled();
});
it('dispatches a failure action when a message is returned', (done) => {
result()
.then(() => {
expect(dispatch).toHaveBeenCalledWith(
'receiveMetricsDashboardFailure',
new Error('Request failed with status code 500'),
);
expect(createFlash).toHaveBeenCalledWith({
message: expect.stringContaining(mockDashboardsErrorResponse.message),
});
done();
})
.catch(done.fail);
it('dispatches a failure action when a message is returned', async () => {
await result();
expect(dispatch).toHaveBeenCalledWith(
'receiveMetricsDashboardFailure',
new Error('Request failed with status code 500'),
);
expect(createFlash).toHaveBeenCalledWith({
message: expect.stringContaining(mockDashboardsErrorResponse.message),
});
});
it('does not show a flash error when showErrorBanner is disabled', (done) => {
it('does not show a flash error when showErrorBanner is disabled', async () => {
state.showErrorBanner = false;
result()
.then(() => {
expect(dispatch).toHaveBeenCalledWith(
'receiveMetricsDashboardFailure',
new Error('Request failed with status code 500'),
);
expect(createFlash).not.toHaveBeenCalled();
done();
})
.catch(done.fail);
await result();
expect(dispatch).toHaveBeenCalledWith(
'receiveMetricsDashboardFailure',
new Error('Request failed with status code 500'),
);
expect(createFlash).not.toHaveBeenCalled();
});
});
});
......@@ -322,38 +308,30 @@ describe('Monitoring store actions', () => {
state.timeRange = defaultTimeRange;
});
it('commits empty state when state.groups is empty', (done) => {
it('commits empty state when state.groups is empty', async () => {
const localGetters = {
metricsWithData: () => [],
};
fetchDashboardData({ state, commit, dispatch, getters: localGetters })
.then(() => {
expect(Tracking.event).toHaveBeenCalledWith(
document.body.dataset.page,
'dashboard_fetch',
{
label: 'custom_metrics_dashboard',
property: 'count',
value: 0,
},
);
expect(dispatch).toHaveBeenCalledTimes(2);
expect(dispatch).toHaveBeenCalledWith('fetchDeploymentsData');
expect(dispatch).toHaveBeenCalledWith('fetchVariableMetricLabelValues', {
defaultQueryParams: {
start_time: expect.any(String),
end_time: expect.any(String),
step: expect.any(Number),
},
});
await fetchDashboardData({ state, commit, dispatch, getters: localGetters });
expect(Tracking.event).toHaveBeenCalledWith(document.body.dataset.page, 'dashboard_fetch', {
label: 'custom_metrics_dashboard',
property: 'count',
value: 0,
});
expect(dispatch).toHaveBeenCalledTimes(2);
expect(dispatch).toHaveBeenCalledWith('fetchDeploymentsData');
expect(dispatch).toHaveBeenCalledWith('fetchVariableMetricLabelValues', {
defaultQueryParams: {
start_time: expect.any(String),
end_time: expect.any(String),
step: expect.any(Number),
},
});
expect(createFlash).not.toHaveBeenCalled();
done();
})
.catch(done.fail);
expect(createFlash).not.toHaveBeenCalled();
});
it('dispatches fetchPrometheusMetric for each panel query', (done) => {
it('dispatches fetchPrometheusMetric for each panel query', async () => {
state.dashboard.panelGroups = convertObjectPropsToCamelCase(
metricsDashboardResponse.dashboard.panel_groups,
);
......@@ -363,34 +341,24 @@ describe('Monitoring store actions', () => {
metricsWithData: () => [metric.id],
};
fetchDashboardData({ state, commit, dispatch, getters: localGetters })
.then(() => {
expect(dispatch).toHaveBeenCalledWith('fetchPrometheusMetric', {
metric,
defaultQueryParams: {
start_time: expect.any(String),
end_time: expect.any(String),
step: expect.any(Number),
},
});
expect(Tracking.event).toHaveBeenCalledWith(
document.body.dataset.page,
'dashboard_fetch',
{
label: 'custom_metrics_dashboard',
property: 'count',
value: 1,
},
);
await fetchDashboardData({ state, commit, dispatch, getters: localGetters });
expect(dispatch).toHaveBeenCalledWith('fetchPrometheusMetric', {
metric,
defaultQueryParams: {
start_time: expect.any(String),
end_time: expect.any(String),
step: expect.any(Number),
},
});
done();
})
.catch(done.fail);
done();
expect(Tracking.event).toHaveBeenCalledWith(document.body.dataset.page, 'dashboard_fetch', {
label: 'custom_metrics_dashboard',
property: 'count',
value: 1,
});
});
it('dispatches fetchPrometheusMetric for each panel query, handles an error', (done) => {
it('dispatches fetchPrometheusMetric for each panel query, handles an error', async () => {
state.dashboard.panelGroups = metricsDashboardViewModel.panelGroups;
const metric = state.dashboard.panelGroups[0].panels[0].metrics[0];
......@@ -400,30 +368,24 @@ describe('Monitoring store actions', () => {
dispatch.mockRejectedValueOnce(new Error('Error fetching this metric'));
dispatch.mockResolvedValue();
fetchDashboardData({ state, commit, dispatch })
.then(() => {
const defaultQueryParams = {
start_time: expect.any(String),
end_time: expect.any(String),
step: expect.any(Number),
};
expect(dispatch).toHaveBeenCalledTimes(metricsDashboardPanelCount + 2); // plus 1 for deployments
expect(dispatch).toHaveBeenCalledWith('fetchDeploymentsData');
expect(dispatch).toHaveBeenCalledWith('fetchVariableMetricLabelValues', {
defaultQueryParams,
});
expect(dispatch).toHaveBeenCalledWith('fetchPrometheusMetric', {
metric,
defaultQueryParams,
});
await fetchDashboardData({ state, commit, dispatch });
const defaultQueryParams = {
start_time: expect.any(String),
end_time: expect.any(String),
step: expect.any(Number),
};
expect(createFlash).toHaveBeenCalledTimes(1);
expect(dispatch).toHaveBeenCalledTimes(metricsDashboardPanelCount + 2); // plus 1 for deployments
expect(dispatch).toHaveBeenCalledWith('fetchDeploymentsData');
expect(dispatch).toHaveBeenCalledWith('fetchVariableMetricLabelValues', {
defaultQueryParams,
});
expect(dispatch).toHaveBeenCalledWith('fetchPrometheusMetric', {
metric,
defaultQueryParams,
});
done();
})
.catch(done.fail);
done();
expect(createFlash).toHaveBeenCalledTimes(1);
});
});
......@@ -449,10 +411,10 @@ describe('Monitoring store actions', () => {
};
});
it('commits result', (done) => {
it('commits result', () => {
mock.onGet(prometheusEndpointPath).reply(200, { data }); // One attempt
testAction(
return testAction(
fetchPrometheusMetric,
{ metric, defaultQueryParams },
state,
......@@ -472,10 +434,7 @@ describe('Monitoring store actions', () => {
},
],
[],
() => {
done();
},
).catch(done.fail);
);
});
describe('without metric defined step', () => {
......@@ -485,10 +444,10 @@ describe('Monitoring store actions', () => {
step: 60,
};
it('uses calculated step', (done) => {
it('uses calculated step', async () => {
mock.onGet(prometheusEndpointPath).reply(200, { data }); // One attempt
testAction(
await testAction(
fetchPrometheusMetric,
{ metric, defaultQueryParams },
state,
......@@ -508,11 +467,8 @@ describe('Monitoring store actions', () => {
},
],
[],
() => {
expect(mock.history.get[0].params).toEqual(expectedParams);
done();
},
).catch(done.fail);
);
expect(mock.history.get[0].params).toEqual(expectedParams);
});
});
......@@ -527,10 +483,10 @@ describe('Monitoring store actions', () => {
step: 7,
};
it('uses metric step', (done) => {
it('uses metric step', async () => {
mock.onGet(prometheusEndpointPath).reply(200, { data }); // One attempt
testAction(
await testAction(
fetchPrometheusMetric,
{ metric, defaultQueryParams },
state,
......@@ -550,43 +506,39 @@ describe('Monitoring store actions', () => {
},
],
[],
() => {
expect(mock.history.get[0].params).toEqual(expectedParams);
done();
},
).catch(done.fail);
);
expect(mock.history.get[0].params).toEqual(expectedParams);
});
});
it('commits failure, when waiting for results and getting a server error', (done) => {
it('commits failure, when waiting for results and getting a server error', async () => {
mock.onGet(prometheusEndpointPath).reply(500);
const error = new Error('Request failed with status code 500');
testAction(
fetchPrometheusMetric,
{ metric, defaultQueryParams },
state,
[
{
type: types.REQUEST_METRIC_RESULT,
payload: {
metricId: metric.metricId,
await expect(
testAction(
fetchPrometheusMetric,
{ metric, defaultQueryParams },
state,
[
{
type: types.REQUEST_METRIC_RESULT,
payload: {
metricId: metric.metricId,
},
},
},
{
type: types.RECEIVE_METRIC_RESULT_FAILURE,
payload: {
metricId: metric.metricId,
error,
{
type: types.RECEIVE_METRIC_RESULT_FAILURE,
payload: {
metricId: metric.metricId,
error,
},
},
},
],
[],
).catch((e) => {
expect(e).toEqual(error);
done();
});
],
[],
),
).rejects.toEqual(error);
});
});
......@@ -991,20 +943,16 @@ describe('Monitoring store actions', () => {
state.dashboardsEndpoint = '/dashboards.json';
});
it('Succesful POST request resolves', (done) => {
it('Succesful POST request resolves', async () => {
mock.onPost(state.dashboardsEndpoint).reply(statusCodes.CREATED, {
dashboard: dashboardGitResponse[1],
});
testAction(duplicateSystemDashboard, {}, state, [], [])
.then(() => {
expect(mock.history.post).toHaveLength(1);
done();
})
.catch(done.fail);
await testAction(duplicateSystemDashboard, {}, state, [], []);
expect(mock.history.post).toHaveLength(1);
});
it('Succesful POST request resolves to a dashboard', (done) => {
it('Succesful POST request resolves to a dashboard', async () => {
const mockCreatedDashboard = dashboardGitResponse[1];
const params = {
......@@ -1025,50 +973,40 @@ describe('Monitoring store actions', () => {
dashboard: mockCreatedDashboard,
});
testAction(duplicateSystemDashboard, params, state, [], [])
.then((result) => {
expect(mock.history.post).toHaveLength(1);
expect(mock.history.post[0].data).toEqual(expectedPayload);
expect(result).toEqual(mockCreatedDashboard);
done();
})
.catch(done.fail);
const result = await testAction(duplicateSystemDashboard, params, state, [], []);
expect(mock.history.post).toHaveLength(1);
expect(mock.history.post[0].data).toEqual(expectedPayload);
expect(result).toEqual(mockCreatedDashboard);
});
it('Failed POST request throws an error', (done) => {
it('Failed POST request throws an error', async () => {
mock.onPost(state.dashboardsEndpoint).reply(statusCodes.BAD_REQUEST);
testAction(duplicateSystemDashboard, {}, state, [], []).catch((err) => {
expect(mock.history.post).toHaveLength(1);
expect(err).toEqual(expect.any(String));
done();
});
await expect(testAction(duplicateSystemDashboard, {}, state, [], [])).rejects.toEqual(
'There was an error creating the dashboard.',
);
expect(mock.history.post).toHaveLength(1);
});
it('Failed POST request throws an error with a description', (done) => {
it('Failed POST request throws an error with a description', async () => {
const backendErrorMsg = 'This file already exists!';
mock.onPost(state.dashboardsEndpoint).reply(statusCodes.BAD_REQUEST, {
error: backendErrorMsg,
});
testAction(duplicateSystemDashboard, {}, state, [], []).catch((err) => {
expect(mock.history.post).toHaveLength(1);
expect(err).toEqual(expect.any(String));
expect(err).toEqual(expect.stringContaining(backendErrorMsg));
done();
});
await expect(testAction(duplicateSystemDashboard, {}, state, [], [])).rejects.toEqual(
`There was an error creating the dashboard. ${backendErrorMsg}`,
);
expect(mock.history.post).toHaveLength(1);
});
});
// Variables manipulation
describe('updateVariablesAndFetchData', () => {
it('should commit UPDATE_VARIABLE_VALUE mutation and fetch data', (done) => {
testAction(
it('should commit UPDATE_VARIABLE_VALUE mutation and fetch data', () => {
return testAction(
updateVariablesAndFetchData,
{ pod: 'POD' },
state,
......@@ -1083,7 +1021,6 @@ describe('Monitoring store actions', () => {
type: 'fetchDashboardData',
},
],
done,
);
});
});
......
......@@ -263,7 +263,7 @@ describe('NoteHeader component', () => {
});
describe('when author username link is hovered', () => {
it('toggles hover specific CSS classes on author name link', (done) => {
it('toggles hover specific CSS classes on author name link', async () => {
createComponent({ author });
const authorUsernameLink = wrapper.find({ ref: 'authorUsernameLink' });
......@@ -271,19 +271,15 @@ describe('NoteHeader component', () => {
authorUsernameLink.trigger('mouseenter');
nextTick(() => {
expect(authorNameLink.classes()).toContain('hover');
expect(authorNameLink.classes()).toContain('text-underline');
await nextTick();
expect(authorNameLink.classes()).toContain('hover');
expect(authorNameLink.classes()).toContain('text-underline');
authorUsernameLink.trigger('mouseleave');
authorUsernameLink.trigger('mouseleave');
nextTick(() => {
expect(authorNameLink.classes()).not.toContain('hover');
expect(authorNameLink.classes()).not.toContain('text-underline');
done();
});
});
await nextTick();
expect(authorNameLink.classes()).not.toContain('hover');
expect(authorNameLink.classes()).not.toContain('text-underline');
});
});
......
......@@ -561,7 +561,7 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => {
});
describe('postComment', () => {
it('disables the submit button', (done) => {
it('disables the submit button', async () => {
const $submitButton = $form.find('.js-comment-submit-button');
expect($submitButton).not.toBeDisabled();
......@@ -574,13 +574,8 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => {
return [200, note];
});
notes
.postComment(dummyEvent)
.then(() => {
expect($submitButton).not.toBeDisabled();
})
.then(done)
.catch(done.fail);
await notes.postComment(dummyEvent);
expect($submitButton).not.toBeDisabled();
});
});
......
......@@ -62,118 +62,109 @@ describe('Actions Notes Store', () => {
});
describe('setNotesData', () => {
it('should set received notes data', (done) => {
testAction(
it('should set received notes data', () => {
return testAction(
actions.setNotesData,
notesDataMock,
{ notesData: {} },
[{ type: 'SET_NOTES_DATA', payload: notesDataMock }],
[],
done,
);
});
});
describe('setNoteableData', () => {
it('should set received issue data', (done) => {
testAction(
it('should set received issue data', () => {
return testAction(
actions.setNoteableData,
noteableDataMock,
{ noteableData: {} },
[{ type: 'SET_NOTEABLE_DATA', payload: noteableDataMock }],
[],
done,
);
});
});
describe('setUserData', () => {
it('should set received user data', (done) => {
testAction(
it('should set received user data', () => {
return testAction(
actions.setUserData,
userDataMock,
{ userData: {} },
[{ type: 'SET_USER_DATA', payload: userDataMock }],
[],
done,
);
});
});
describe('setLastFetchedAt', () => {
it('should set received timestamp', (done) => {
testAction(
it('should set received timestamp', () => {
return testAction(
actions.setLastFetchedAt,
'timestamp',
{ lastFetchedAt: {} },
[{ type: 'SET_LAST_FETCHED_AT', payload: 'timestamp' }],
[],
done,
);
});
});
describe('setInitialNotes', () => {
it('should set initial notes', (done) => {
testAction(
it('should set initial notes', () => {
return testAction(
actions.setInitialNotes,
[individualNote],
{ notes: [] },
[{ type: 'ADD_OR_UPDATE_DISCUSSIONS', payload: [individualNote] }],
[],
done,
);
});
});
describe('setTargetNoteHash', () => {
it('should set target note hash', (done) => {
testAction(
it('should set target note hash', () => {
return testAction(
actions.setTargetNoteHash,
'hash',
{ notes: [] },
[{ type: 'SET_TARGET_NOTE_HASH', payload: 'hash' }],
[],
done,
);
});
});
describe('toggleDiscussion', () => {
it('should toggle discussion', (done) => {
testAction(
it('should toggle discussion', () => {
return testAction(
actions.toggleDiscussion,
{ discussionId: discussionMock.id },
{ notes: [discussionMock] },
[{ type: 'TOGGLE_DISCUSSION', payload: { discussionId: discussionMock.id } }],
[],
done,
);
});
});
describe('expandDiscussion', () => {
it('should expand discussion', (done) => {
testAction(
it('should expand discussion', () => {
return testAction(
actions.expandDiscussion,
{ discussionId: discussionMock.id },
{ notes: [discussionMock] },
[{ type: 'EXPAND_DISCUSSION', payload: { discussionId: discussionMock.id } }],
[{ type: 'diffs/renderFileForDiscussionId', payload: discussionMock.id }],
done,
);
});
});
describe('collapseDiscussion', () => {
it('should commit collapse discussion', (done) => {
testAction(
it('should commit collapse discussion', () => {
return testAction(
actions.collapseDiscussion,
{ discussionId: discussionMock.id },
{ notes: [discussionMock] },
[{ type: 'COLLAPSE_DISCUSSION', payload: { discussionId: discussionMock.id } }],
[],
done,
);
});
});
......@@ -184,28 +175,18 @@ describe('Actions Notes Store', () => {
});
describe('closeMergeRequest', () => {
it('sets state as closed', (done) => {
store
.dispatch('closeIssuable', { notesData: { closeIssuePath: '' } })
.then(() => {
expect(store.state.noteableData.state).toEqual('closed');
expect(store.state.isToggleStateButtonLoading).toEqual(false);
done();
})
.catch(done.fail);
it('sets state as closed', async () => {
await store.dispatch('closeIssuable', { notesData: { closeIssuePath: '' } });
expect(store.state.noteableData.state).toEqual('closed');
expect(store.state.isToggleStateButtonLoading).toEqual(false);
});
});
describe('reopenMergeRequest', () => {
it('sets state as reopened', (done) => {
store
.dispatch('reopenIssuable', { notesData: { reopenIssuePath: '' } })
.then(() => {
expect(store.state.noteableData.state).toEqual('reopened');
expect(store.state.isToggleStateButtonLoading).toEqual(false);
done();
})
.catch(done.fail);
it('sets state as reopened', async () => {
await store.dispatch('reopenIssuable', { notesData: { reopenIssuePath: '' } });
expect(store.state.noteableData.state).toEqual('reopened');
expect(store.state.isToggleStateButtonLoading).toEqual(false);
});
});
});
......@@ -222,42 +203,39 @@ describe('Actions Notes Store', () => {
});
describe('toggleStateButtonLoading', () => {
it('should set loading as true', (done) => {
testAction(
it('should set loading as true', () => {
return testAction(
actions.toggleStateButtonLoading,
true,
{},
[{ type: 'TOGGLE_STATE_BUTTON_LOADING', payload: true }],
[],
done,
);
});
it('should set loading as false', (done) => {
testAction(
it('should set loading as false', () => {
return testAction(
actions.toggleStateButtonLoading,
false,
{},
[{ type: 'TOGGLE_STATE_BUTTON_LOADING', payload: false }],
[],
done,
);
});
});
describe('toggleIssueLocalState', () => {
it('sets issue state as closed', (done) => {
testAction(actions.toggleIssueLocalState, 'closed', {}, [{ type: 'CLOSE_ISSUE' }], [], done);
it('sets issue state as closed', () => {
return testAction(actions.toggleIssueLocalState, 'closed', {}, [{ type: 'CLOSE_ISSUE' }], []);
});
it('sets issue state as reopened', (done) => {
testAction(
it('sets issue state as reopened', () => {
return testAction(
actions.toggleIssueLocalState,
'reopened',
{},
[{ type: 'REOPEN_ISSUE' }],
[],
done,
);
});
});
......@@ -291,8 +269,8 @@ describe('Actions Notes Store', () => {
return store.dispatch('stopPolling');
};
beforeEach((done) => {
store.dispatch('setNotesData', notesDataMock).then(done).catch(done.fail);
beforeEach(() => {
return store.dispatch('setNotesData', notesDataMock);
});
afterEach(() => {
......@@ -405,14 +383,13 @@ describe('Actions Notes Store', () => {
});
describe('setNotesFetchedState', () => {
it('should set notes fetched state', (done) => {
testAction(
it('should set notes fetched state', () => {
return testAction(
actions.setNotesFetchedState,
true,
{},
[{ type: 'SET_NOTES_FETCHED_STATE', payload: true }],
[],
done,
);
});
});
......@@ -432,10 +409,10 @@ describe('Actions Notes Store', () => {
document.body.setAttribute('data-page', '');
});
it('commits DELETE_NOTE and dispatches updateMergeRequestWidget', (done) => {
it('commits DELETE_NOTE and dispatches updateMergeRequestWidget', () => {
const note = { path: endpoint, id: 1 };
testAction(
return testAction(
actions.removeNote,
note,
store.state,
......@@ -453,16 +430,15 @@ describe('Actions Notes Store', () => {
type: 'updateResolvableDiscussionsCounts',
},
],
done,
);
});
it('dispatches removeDiscussionsFromDiff on merge request page', (done) => {
it('dispatches removeDiscussionsFromDiff on merge request page', () => {
const note = { path: endpoint, id: 1 };
document.body.setAttribute('data-page', 'projects:merge_requests:show');
testAction(
return testAction(
actions.removeNote,
note,
store.state,
......@@ -483,7 +459,6 @@ describe('Actions Notes Store', () => {
type: 'diffs/removeDiscussionsFromDiff',
},
],
done,
);
});
});
......@@ -503,10 +478,10 @@ describe('Actions Notes Store', () => {
document.body.setAttribute('data-page', '');
});
it('dispatches removeNote', (done) => {
it('dispatches removeNote', () => {
const note = { path: endpoint, id: 1 };
testAction(
return testAction(
actions.deleteNote,
note,
{},
......@@ -520,7 +495,6 @@ describe('Actions Notes Store', () => {
},
},
],
done,
);
});
});
......@@ -536,8 +510,8 @@ describe('Actions Notes Store', () => {
axiosMock.onAny().reply(200, res);
});
it('commits ADD_NEW_NOTE and dispatches updateMergeRequestWidget', (done) => {
testAction(
it('commits ADD_NEW_NOTE and dispatches updateMergeRequestWidget', () => {
return testAction(
actions.createNewNote,
{ endpoint: `${TEST_HOST}`, data: {} },
store.state,
......@@ -558,7 +532,6 @@ describe('Actions Notes Store', () => {
type: 'updateResolvableDiscussionsCounts',
},
],
done,
);
});
});
......@@ -572,14 +545,13 @@ describe('Actions Notes Store', () => {
axiosMock.onAny().replyOnce(200, res);
});
it('does not commit ADD_NEW_NOTE or dispatch updateMergeRequestWidget', (done) => {
testAction(
it('does not commit ADD_NEW_NOTE or dispatch updateMergeRequestWidget', () => {
return testAction(
actions.createNewNote,
{ endpoint: `${TEST_HOST}`, data: {} },
store.state,
[],
[],
done,
);
});
});
......@@ -595,8 +567,8 @@ describe('Actions Notes Store', () => {
});
describe('as note', () => {
it('commits UPDATE_NOTE and dispatches updateMergeRequestWidget', (done) => {
testAction(
it('commits UPDATE_NOTE and dispatches updateMergeRequestWidget', () => {
return testAction(
actions.toggleResolveNote,
{ endpoint: `${TEST_HOST}`, isResolved: true, discussion: false },
store.state,
......@@ -614,14 +586,13 @@ describe('Actions Notes Store', () => {
type: 'updateMergeRequestWidget',
},
],
done,
);
});
});
describe('as discussion', () => {
it('commits UPDATE_DISCUSSION and dispatches updateMergeRequestWidget', (done) => {
testAction(
it('commits UPDATE_DISCUSSION and dispatches updateMergeRequestWidget', () => {
return testAction(
actions.toggleResolveNote,
{ endpoint: `${TEST_HOST}`, isResolved: true, discussion: true },
store.state,
......@@ -639,7 +610,6 @@ describe('Actions Notes Store', () => {
type: 'updateMergeRequestWidget',
},
],
done,
);
});
});
......@@ -656,41 +626,38 @@ describe('Actions Notes Store', () => {
});
describe('setCommentsDisabled', () => {
it('should set comments disabled state', (done) => {
testAction(
it('should set comments disabled state', () => {
return testAction(
actions.setCommentsDisabled,
true,
null,
[{ type: 'DISABLE_COMMENTS', payload: true }],
[],
done,
);
});
});
describe('updateResolvableDiscussionsCounts', () => {
it('commits UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS', (done) => {
testAction(
it('commits UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS', () => {
return testAction(
actions.updateResolvableDiscussionsCounts,
null,
{},
[{ type: 'UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS' }],
[],
done,
);
});
});
describe('convertToDiscussion', () => {
it('commits CONVERT_TO_DISCUSSION with noteId', (done) => {
it('commits CONVERT_TO_DISCUSSION with noteId', () => {
const noteId = 'dummy-note-id';
testAction(
return testAction(
actions.convertToDiscussion,
noteId,
{},
[{ type: 'CONVERT_TO_DISCUSSION', payload: noteId }],
[],
done,
);
});
});
......@@ -786,11 +753,11 @@ describe('Actions Notes Store', () => {
describe('replyToDiscussion', () => {
const payload = { endpoint: TEST_HOST, data: {} };
it('updates discussion if response contains disussion', (done) => {
it('updates discussion if response contains disussion', () => {
const discussion = { notes: [] };
axiosMock.onAny().reply(200, { discussion });
testAction(
return testAction(
actions.replyToDiscussion,
payload,
{
......@@ -802,15 +769,14 @@ describe('Actions Notes Store', () => {
{ type: 'startTaskList' },
{ type: 'updateResolvableDiscussionsCounts' },
],
done,
);
});
it('adds a reply to a discussion', (done) => {
it('adds a reply to a discussion', () => {
const res = {};
axiosMock.onAny().reply(200, res);
testAction(
return testAction(
actions.replyToDiscussion,
payload,
{
......@@ -818,21 +784,19 @@ describe('Actions Notes Store', () => {
},
[{ type: mutationTypes.ADD_NEW_REPLY_TO_DISCUSSION, payload: res }],
[],
done,
);
});
});
describe('removeConvertedDiscussion', () => {
it('commits CONVERT_TO_DISCUSSION with noteId', (done) => {
it('commits CONVERT_TO_DISCUSSION with noteId', () => {
const noteId = 'dummy-id';
testAction(
return testAction(
actions.removeConvertedDiscussion,
noteId,
{},
[{ type: 'REMOVE_CONVERTED_DISCUSSION', payload: noteId }],
[],
done,
);
});
});
......@@ -849,8 +813,8 @@ describe('Actions Notes Store', () => {
};
});
it('when unresolved, dispatches action', (done) => {
testAction(
it('when unresolved, dispatches action', () => {
return testAction(
actions.resolveDiscussion,
{ discussionId },
{ ...state, ...getters },
......@@ -865,20 +829,18 @@ describe('Actions Notes Store', () => {
},
},
],
done,
);
});
it('when resolved, does nothing', (done) => {
it('when resolved, does nothing', () => {
getters.isDiscussionResolved = (id) => id === discussionId;
testAction(
return testAction(
actions.resolveDiscussion,
{ discussionId },
{ ...state, ...getters },
[],
[],
done,
);
});
});
......@@ -891,22 +853,17 @@ describe('Actions Notes Store', () => {
const res = { errors: { something: ['went wrong'] } };
const error = { message: 'Unprocessable entity', response: { data: res } };
it('throws an error', (done) => {
actions
.saveNote(
it('throws an error', async () => {
await expect(
actions.saveNote(
{
commit() {},
dispatch: () => Promise.reject(error),
},
payload,
)
.then(() => done.fail('Expected error to be thrown!'))
.catch((err) => {
expect(err).toBe(error);
expect(createFlash).not.toHaveBeenCalled();
})
.then(done)
.catch(done.fail);
),
).rejects.toEqual(error);
expect(createFlash).not.toHaveBeenCalled();
});
});
......@@ -914,46 +871,35 @@ describe('Actions Notes Store', () => {
const res = { errors: { base: ['something went wrong'] } };
const error = { message: 'Unprocessable entity', response: { data: res } };
it('sets flash alert using errors.base message', (done) => {
actions
.saveNote(
{
commit() {},
dispatch: () => Promise.reject(error),
},
{ ...payload, flashContainer },
)
.then((resp) => {
expect(resp.hasFlash).toBe(true);
expect(createFlash).toHaveBeenCalledWith({
message: 'Your comment could not be submitted because something went wrong',
parent: flashContainer,
});
})
.catch(() => done.fail('Expected success response!'))
.then(done)
.catch(done.fail);
it('sets flash alert using errors.base message', async () => {
const resp = await actions.saveNote(
{
commit() {},
dispatch: () => Promise.reject(error),
},
{ ...payload, flashContainer },
);
expect(resp.hasFlash).toBe(true);
expect(createFlash).toHaveBeenCalledWith({
message: 'Your comment could not be submitted because something went wrong',
parent: flashContainer,
});
});
});
describe('if response contains no errors', () => {
const res = { valid: true };
it('returns the response', (done) => {
actions
.saveNote(
{
commit() {},
dispatch: () => Promise.resolve(res),
},
payload,
)
.then((data) => {
expect(data).toBe(res);
expect(createFlash).not.toHaveBeenCalled();
})
.then(done)
.catch(done.fail);
it('returns the response', async () => {
const data = await actions.saveNote(
{
commit() {},
dispatch: () => Promise.resolve(res),
},
payload,
);
expect(data).toBe(res);
expect(createFlash).not.toHaveBeenCalled();
});
});
});
......@@ -970,19 +916,17 @@ describe('Actions Notes Store', () => {
flashContainer = {};
});
const testSubmitSuggestion = (done, expectFn) => {
actions
.submitSuggestion(
{ commit, dispatch },
{ discussionId, noteId, suggestionId, flashContainer },
)
.then(expectFn)
.then(done)
.catch(done.fail);
const testSubmitSuggestion = async (expectFn) => {
await actions.submitSuggestion(
{ commit, dispatch },
{ discussionId, noteId, suggestionId, flashContainer },
);
expectFn();
};
it('when service success, commits and resolves discussion', (done) => {
testSubmitSuggestion(done, () => {
it('when service success, commits and resolves discussion', () => {
testSubmitSuggestion(() => {
expect(commit.mock.calls).toEqual([
[mutationTypes.SET_RESOLVING_DISCUSSION, true],
[mutationTypes.SET_RESOLVING_DISCUSSION, false],
......@@ -997,12 +941,12 @@ describe('Actions Notes Store', () => {
});
});
it('when service fails, flashes error message', (done) => {
it('when service fails, flashes error message', () => {
const response = { response: { data: { message: TEST_ERROR_MESSAGE } } };
Api.applySuggestion.mockReturnValue(Promise.reject(response));
testSubmitSuggestion(done, () => {
return testSubmitSuggestion(() => {
expect(commit.mock.calls).toEqual([
[mutationTypes.SET_RESOLVING_DISCUSSION, true],
[mutationTypes.SET_RESOLVING_DISCUSSION, false],
......@@ -1015,12 +959,12 @@ describe('Actions Notes Store', () => {
});
});
it('when service fails, and no error message available, uses default message', (done) => {
it('when service fails, and no error message available, uses default message', () => {
const response = { response: 'foo' };
Api.applySuggestion.mockReturnValue(Promise.reject(response));
testSubmitSuggestion(done, () => {
return testSubmitSuggestion(() => {
expect(commit.mock.calls).toEqual([
[mutationTypes.SET_RESOLVING_DISCUSSION, true],
[mutationTypes.SET_RESOLVING_DISCUSSION, false],
......@@ -1033,10 +977,10 @@ describe('Actions Notes Store', () => {
});
});
it('when resolve discussion fails, fail gracefully', (done) => {
it('when resolve discussion fails, fail gracefully', () => {
dispatch.mockReturnValue(Promise.reject());
testSubmitSuggestion(done, () => {
return testSubmitSuggestion(() => {
expect(createFlash).not.toHaveBeenCalled();
});
});
......@@ -1056,16 +1000,14 @@ describe('Actions Notes Store', () => {
flashContainer = {};
});
const testSubmitSuggestionBatch = (done, expectFn) => {
actions
.submitSuggestionBatch({ commit, dispatch, state }, { flashContainer })
.then(expectFn)
.then(done)
.catch(done.fail);
const testSubmitSuggestionBatch = async (expectFn) => {
await actions.submitSuggestionBatch({ commit, dispatch, state }, { flashContainer });
expectFn();
};
it('when service succeeds, commits, resolves discussions, resets batch and applying batch state', (done) => {
testSubmitSuggestionBatch(done, () => {
it('when service succeeds, commits, resolves discussions, resets batch and applying batch state', () => {
testSubmitSuggestionBatch(() => {
expect(commit.mock.calls).toEqual([
[mutationTypes.SET_APPLYING_BATCH_STATE, true],
[mutationTypes.SET_RESOLVING_DISCUSSION, true],
......@@ -1085,12 +1027,12 @@ describe('Actions Notes Store', () => {
});
});
it('when service fails, flashes error message, resets applying batch state', (done) => {
it('when service fails, flashes error message, resets applying batch state', () => {
const response = { response: { data: { message: TEST_ERROR_MESSAGE } } };
Api.applySuggestionBatch.mockReturnValue(Promise.reject(response));
testSubmitSuggestionBatch(done, () => {
testSubmitSuggestionBatch(() => {
expect(commit.mock.calls).toEqual([
[mutationTypes.SET_APPLYING_BATCH_STATE, true],
[mutationTypes.SET_RESOLVING_DISCUSSION, true],
......@@ -1106,12 +1048,12 @@ describe('Actions Notes Store', () => {
});
});
it('when service fails, and no error message available, uses default message', (done) => {
it('when service fails, and no error message available, uses default message', () => {
const response = { response: 'foo' };
Api.applySuggestionBatch.mockReturnValue(Promise.reject(response));
testSubmitSuggestionBatch(done, () => {
testSubmitSuggestionBatch(() => {
expect(commit.mock.calls).toEqual([
[mutationTypes.SET_APPLYING_BATCH_STATE, true],
[mutationTypes.SET_RESOLVING_DISCUSSION, true],
......@@ -1128,10 +1070,10 @@ describe('Actions Notes Store', () => {
});
});
it('when resolve discussions fails, fails gracefully, resets batch and applying batch state', (done) => {
it('when resolve discussions fails, fails gracefully, resets batch and applying batch state', () => {
dispatch.mockReturnValue(Promise.reject());
testSubmitSuggestionBatch(done, () => {
testSubmitSuggestionBatch(() => {
expect(commit.mock.calls).toEqual([
[mutationTypes.SET_APPLYING_BATCH_STATE, true],
[mutationTypes.SET_RESOLVING_DISCUSSION, true],
......@@ -1148,14 +1090,13 @@ describe('Actions Notes Store', () => {
describe('addSuggestionInfoToBatch', () => {
const suggestionInfo = batchSuggestionsInfoMock[0];
it("adds a suggestion's info to the current batch", (done) => {
testAction(
it("adds a suggestion's info to the current batch", () => {
return testAction(
actions.addSuggestionInfoToBatch,
suggestionInfo,
{ batchSuggestionsInfo: [] },
[{ type: 'ADD_SUGGESTION_TO_BATCH', payload: suggestionInfo }],
[],
done,
);
});
});
......@@ -1163,14 +1104,13 @@ describe('Actions Notes Store', () => {
describe('removeSuggestionInfoFromBatch', () => {
const suggestionInfo = batchSuggestionsInfoMock[0];
it("removes a suggestion's info the current batch", (done) => {
testAction(
it("removes a suggestion's info the current batch", () => {
return testAction(
actions.removeSuggestionInfoFromBatch,
suggestionInfo.suggestionId,
{ batchSuggestionsInfo: [suggestionInfo] },
[{ type: 'REMOVE_SUGGESTION_FROM_BATCH', payload: suggestionInfo.suggestionId }],
[],
done,
);
});
});
......@@ -1209,8 +1149,8 @@ describe('Actions Notes Store', () => {
});
describe('setDiscussionSortDirection', () => {
it('calls the correct mutation with the correct args', (done) => {
testAction(
it('calls the correct mutation with the correct args', () => {
return testAction(
actions.setDiscussionSortDirection,
{ direction: notesConstants.DESC, persist: false },
{},
......@@ -1221,20 +1161,18 @@ describe('Actions Notes Store', () => {
},
],
[],
done,
);
});
});
describe('setSelectedCommentPosition', () => {
it('calls the correct mutation with the correct args', (done) => {
testAction(
it('calls the correct mutation with the correct args', () => {
return testAction(
actions.setSelectedCommentPosition,
{},
{},
[{ type: mutationTypes.SET_SELECTED_COMMENT_POSITION, payload: {} }],
[],
done,
);
});
});
......@@ -1248,9 +1186,9 @@ describe('Actions Notes Store', () => {
};
describe('if response contains no errors', () => {
it('dispatches requestDeleteDescriptionVersion', (done) => {
it('dispatches requestDeleteDescriptionVersion', () => {
axiosMock.onDelete(endpoint).replyOnce(200);
testAction(
return testAction(
actions.softDeleteDescriptionVersion,
payload,
{},
......@@ -1264,35 +1202,33 @@ describe('Actions Notes Store', () => {
payload: payload.versionId,
},
],
done,
);
});
});
describe('if response contains errors', () => {
const errorMessage = 'Request failed with status code 503';
it('dispatches receiveDeleteDescriptionVersionError and throws an error', (done) => {
it('dispatches receiveDeleteDescriptionVersionError and throws an error', async () => {
axiosMock.onDelete(endpoint).replyOnce(503);
testAction(
actions.softDeleteDescriptionVersion,
payload,
{},
[],
[
{
type: 'requestDeleteDescriptionVersion',
},
{
type: 'receiveDeleteDescriptionVersionError',
payload: new Error(errorMessage),
},
],
)
.then(() => done.fail('Expected error to be thrown'))
.catch(() => {
expect(createFlash).toHaveBeenCalled();
done();
});
await expect(
testAction(
actions.softDeleteDescriptionVersion,
payload,
{},
[],
[
{
type: 'requestDeleteDescriptionVersion',
},
{
type: 'receiveDeleteDescriptionVersionError',
payload: new Error(errorMessage),
},
],
),
).rejects.toEqual(new Error());
expect(createFlash).toHaveBeenCalled();
});
});
});
......@@ -1306,14 +1242,13 @@ describe('Actions Notes Store', () => {
});
describe('updateAssignees', () => {
it('update the assignees state', (done) => {
testAction(
it('update the assignees state', () => {
return testAction(
actions.updateAssignees,
[userDataMock.id],
{ state: noteableDataMock },
[{ type: mutationTypes.UPDATE_ASSIGNEES, payload: [userDataMock.id] }],
[],
done,
);
});
});
......@@ -1376,28 +1311,26 @@ describe('Actions Notes Store', () => {
});
describe('updateDiscussionPosition', () => {
it('update the assignees state', (done) => {
it('update the assignees state', () => {
const updatedPosition = { discussionId: 1, position: { test: true } };
testAction(
return testAction(
actions.updateDiscussionPosition,
updatedPosition,
{ state: { discussions: [] } },
[{ type: mutationTypes.UPDATE_DISCUSSION_POSITION, payload: updatedPosition }],
[],
done,
);
});
});
describe('setFetchingState', () => {
it('commits SET_NOTES_FETCHING_STATE', (done) => {
testAction(
it('commits SET_NOTES_FETCHING_STATE', () => {
return testAction(
actions.setFetchingState,
true,
null,
[{ type: mutationTypes.SET_NOTES_FETCHING_STATE, payload: true }],
[],
done,
);
});
});
......@@ -1409,9 +1342,9 @@ describe('Actions Notes Store', () => {
window.gon = {};
});
it('updates the discussions and dispatches `updateResolvableDiscussionsCounts`', (done) => {
it('updates the discussions and dispatches `updateResolvableDiscussionsCounts`', () => {
axiosMock.onAny().reply(200, { discussion });
testAction(
return testAction(
actions.fetchDiscussions,
{},
null,
......@@ -1420,14 +1353,13 @@ describe('Actions Notes Store', () => {
{ type: mutationTypes.SET_FETCHING_DISCUSSIONS, payload: false },
],
[{ type: 'updateResolvableDiscussionsCounts' }],
done,
);
});
it('dispatches `fetchDiscussionsBatch` action if `paginatedIssueDiscussions` feature flag is enabled', (done) => {
it('dispatches `fetchDiscussionsBatch` action if `paginatedIssueDiscussions` feature flag is enabled', () => {
window.gon = { features: { paginatedIssueDiscussions: true } };
testAction(
return testAction(
actions.fetchDiscussions,
{ path: 'test-path', filter: 'test-filter', persistFilter: 'test-persist-filter' },
null,
......@@ -1444,7 +1376,6 @@ describe('Actions Notes Store', () => {
},
},
],
done,
);
});
});
......@@ -1458,9 +1389,9 @@ describe('Actions Notes Store', () => {
const actionPayload = { config, path: 'test-path', perPage: 20 };
it('updates the discussions and dispatches `updateResolvableDiscussionsCounts if there are no headers', (done) => {
it('updates the discussions and dispatches `updateResolvableDiscussionsCounts if there are no headers', () => {
axiosMock.onAny().reply(200, { discussion }, {});
testAction(
return testAction(
actions.fetchDiscussionsBatch,
actionPayload,
null,
......@@ -1469,13 +1400,12 @@ describe('Actions Notes Store', () => {
{ type: mutationTypes.SET_FETCHING_DISCUSSIONS, payload: false },
],
[{ type: 'updateResolvableDiscussionsCounts' }],
done,
);
});
it('dispatches itself if there is `x-next-page-cursor` header', (done) => {
it('dispatches itself if there is `x-next-page-cursor` header', () => {
axiosMock.onAny().reply(200, { discussion }, { 'x-next-page-cursor': 1 });
testAction(
return testAction(
actions.fetchDiscussionsBatch,
actionPayload,
null,
......@@ -1486,7 +1416,6 @@ describe('Actions Notes Store', () => {
payload: { ...actionPayload, perPage: 30, cursor: 1 },
},
],
done,
);
});
});
......
......@@ -20,10 +20,10 @@ jest.mock('~/api.js');
describe('Actions Package details store', () => {
describe('fetchPackageVersions', () => {
it('should fetch the package versions', (done) => {
it('should fetch the package versions', async () => {
Api.projectPackage = jest.fn().mockResolvedValue({ data: packageEntity });
testAction(
await testAction(
fetchPackageVersions,
undefined,
{ packageEntity },
......@@ -33,20 +33,14 @@ describe('Actions Package details store', () => {
{ type: types.SET_LOADING, payload: false },
],
[],
() => {
expect(Api.projectPackage).toHaveBeenCalledWith(
packageEntity.project_id,
packageEntity.id,
);
done();
},
);
expect(Api.projectPackage).toHaveBeenCalledWith(packageEntity.project_id, packageEntity.id);
});
it("does not set the versions if they don't exist", (done) => {
it("does not set the versions if they don't exist", async () => {
Api.projectPackage = jest.fn().mockResolvedValue({ data: { packageEntity, versions: null } });
testAction(
await testAction(
fetchPackageVersions,
undefined,
{ packageEntity },
......@@ -55,20 +49,14 @@ describe('Actions Package details store', () => {
{ type: types.SET_LOADING, payload: false },
],
[],
() => {
expect(Api.projectPackage).toHaveBeenCalledWith(
packageEntity.project_id,
packageEntity.id,
);
done();
},
);
expect(Api.projectPackage).toHaveBeenCalledWith(packageEntity.project_id, packageEntity.id);
});
it('should create flash on API error', (done) => {
it('should create flash on API error', async () => {
Api.projectPackage = jest.fn().mockRejectedValue();
testAction(
await testAction(
fetchPackageVersions,
undefined,
{ packageEntity },
......@@ -77,41 +65,31 @@ describe('Actions Package details store', () => {
{ type: types.SET_LOADING, payload: false },
],
[],
() => {
expect(Api.projectPackage).toHaveBeenCalledWith(
packageEntity.project_id,
packageEntity.id,
);
expect(createFlash).toHaveBeenCalledWith({
message: FETCH_PACKAGE_VERSIONS_ERROR,
type: 'warning',
});
done();
},
);
expect(Api.projectPackage).toHaveBeenCalledWith(packageEntity.project_id, packageEntity.id);
expect(createFlash).toHaveBeenCalledWith({
message: FETCH_PACKAGE_VERSIONS_ERROR,
type: 'warning',
});
});
});
describe('deletePackage', () => {
it('should call Api.deleteProjectPackage', (done) => {
it('should call Api.deleteProjectPackage', async () => {
Api.deleteProjectPackage = jest.fn().mockResolvedValue();
testAction(deletePackage, undefined, { packageEntity }, [], [], () => {
expect(Api.deleteProjectPackage).toHaveBeenCalledWith(
packageEntity.project_id,
packageEntity.id,
);
done();
});
await testAction(deletePackage, undefined, { packageEntity }, [], []);
expect(Api.deleteProjectPackage).toHaveBeenCalledWith(
packageEntity.project_id,
packageEntity.id,
);
});
it('should create flash on API error', (done) => {
it('should create flash on API error', async () => {
Api.deleteProjectPackage = jest.fn().mockRejectedValue();
testAction(deletePackage, undefined, { packageEntity }, [], [], () => {
expect(createFlash).toHaveBeenCalledWith({
message: DELETE_PACKAGE_ERROR_MESSAGE,
type: 'warning',
});
done();
await testAction(deletePackage, undefined, { packageEntity }, [], []);
expect(createFlash).toHaveBeenCalledWith({
message: DELETE_PACKAGE_ERROR_MESSAGE,
type: 'warning',
});
});
});
......@@ -119,37 +97,33 @@ describe('Actions Package details store', () => {
describe('deletePackageFile', () => {
const fileId = 'a_file_id';
it('should call Api.deleteProjectPackageFile and commit the right data', (done) => {
it('should call Api.deleteProjectPackageFile and commit the right data', async () => {
const packageFiles = [{ id: 'foo' }, { id: fileId }];
Api.deleteProjectPackageFile = jest.fn().mockResolvedValue();
testAction(
await testAction(
deletePackageFile,
fileId,
{ packageEntity, packageFiles },
[{ type: types.UPDATE_PACKAGE_FILES, payload: [{ id: 'foo' }] }],
[],
() => {
expect(Api.deleteProjectPackageFile).toHaveBeenCalledWith(
packageEntity.project_id,
packageEntity.id,
fileId,
);
expect(createFlash).toHaveBeenCalledWith({
message: DELETE_PACKAGE_FILE_SUCCESS_MESSAGE,
type: 'success',
});
done();
},
);
expect(Api.deleteProjectPackageFile).toHaveBeenCalledWith(
packageEntity.project_id,
packageEntity.id,
fileId,
);
expect(createFlash).toHaveBeenCalledWith({
message: DELETE_PACKAGE_FILE_SUCCESS_MESSAGE,
type: 'success',
});
});
it('should create flash on API error', (done) => {
it('should create flash on API error', async () => {
Api.deleteProjectPackageFile = jest.fn().mockRejectedValue();
testAction(deletePackageFile, fileId, { packageEntity }, [], [], () => {
expect(createFlash).toHaveBeenCalledWith({
message: DELETE_PACKAGE_FILE_ERROR_MESSAGE,
type: 'warning',
});
done();
await testAction(deletePackageFile, fileId, { packageEntity }, [], []);
expect(createFlash).toHaveBeenCalledWith({
message: DELETE_PACKAGE_FILE_ERROR_MESSAGE,
type: 'warning',
});
});
});
......
......@@ -32,8 +32,8 @@ describe('Actions Package list store', () => {
};
const filter = [];
it('should fetch the project packages list when isGroupPage is false', (done) => {
testAction(
it('should fetch the project packages list when isGroupPage is false', async () => {
await testAction(
actions.requestPackagesList,
undefined,
{ config: { isGroupPage: false, resourceId: 1 }, sorting, filter },
......@@ -43,17 +43,14 @@ describe('Actions Package list store', () => {
{ type: 'receivePackagesListSuccess', payload: { data: 'foo', headers } },
{ type: 'setLoading', payload: false },
],
() => {
expect(Api.projectPackages).toHaveBeenCalledWith(1, {
params: { page: 1, per_page: 20, sort: sorting.sort, order_by: sorting.orderBy },
});
done();
},
);
expect(Api.projectPackages).toHaveBeenCalledWith(1, {
params: { page: 1, per_page: 20, sort: sorting.sort, order_by: sorting.orderBy },
});
});
it('should fetch the group packages list when isGroupPage is true', (done) => {
testAction(
it('should fetch the group packages list when isGroupPage is true', async () => {
await testAction(
actions.requestPackagesList,
undefined,
{ config: { isGroupPage: true, resourceId: 2 }, sorting, filter },
......@@ -63,19 +60,16 @@ describe('Actions Package list store', () => {
{ type: 'receivePackagesListSuccess', payload: { data: 'baz', headers } },
{ type: 'setLoading', payload: false },
],
() => {
expect(Api.groupPackages).toHaveBeenCalledWith(2, {
params: { page: 1, per_page: 20, sort: sorting.sort, order_by: sorting.orderBy },
});
done();
},
);
expect(Api.groupPackages).toHaveBeenCalledWith(2, {
params: { page: 1, per_page: 20, sort: sorting.sort, order_by: sorting.orderBy },
});
});
it('should fetch packages of a certain type when a filter with a type is present', (done) => {
it('should fetch packages of a certain type when a filter with a type is present', async () => {
const packageType = 'maven';
testAction(
await testAction(
actions.requestPackagesList,
undefined,
{
......@@ -89,24 +83,21 @@ describe('Actions Package list store', () => {
{ type: 'receivePackagesListSuccess', payload: { data: 'foo', headers } },
{ type: 'setLoading', payload: false },
],
() => {
expect(Api.projectPackages).toHaveBeenCalledWith(1, {
params: {
page: 1,
per_page: 20,
sort: sorting.sort,
order_by: sorting.orderBy,
package_type: packageType,
},
});
done();
},
);
expect(Api.projectPackages).toHaveBeenCalledWith(1, {
params: {
page: 1,
per_page: 20,
sort: sorting.sort,
order_by: sorting.orderBy,
package_type: packageType,
},
});
});
it('should create flash on API error', (done) => {
it('should create flash on API error', async () => {
Api.projectPackages = jest.fn().mockRejectedValue();
testAction(
await testAction(
actions.requestPackagesList,
undefined,
{ config: { isGroupPage: false, resourceId: 2 }, sorting, filter },
......@@ -115,15 +106,12 @@ describe('Actions Package list store', () => {
{ type: 'setLoading', payload: true },
{ type: 'setLoading', payload: false },
],
() => {
expect(createFlash).toHaveBeenCalled();
done();
},
);
expect(createFlash).toHaveBeenCalled();
});
it('should force the terraform_module type when forceTerraform is true', (done) => {
testAction(
it('should force the terraform_module type when forceTerraform is true', async () => {
await testAction(
actions.requestPackagesList,
undefined,
{ config: { isGroupPage: false, resourceId: 1, forceTerraform: true }, sorting, filter },
......@@ -133,27 +121,24 @@ describe('Actions Package list store', () => {
{ type: 'receivePackagesListSuccess', payload: { data: 'foo', headers } },
{ type: 'setLoading', payload: false },
],
() => {
expect(Api.projectPackages).toHaveBeenCalledWith(1, {
params: {
page: 1,
per_page: 20,
sort: sorting.sort,
order_by: sorting.orderBy,
package_type: 'terraform_module',
},
});
done();
},
);
expect(Api.projectPackages).toHaveBeenCalledWith(1, {
params: {
page: 1,
per_page: 20,
sort: sorting.sort,
order_by: sorting.orderBy,
package_type: 'terraform_module',
},
});
});
});
describe('receivePackagesListSuccess', () => {
it('should set received packages', (done) => {
it('should set received packages', () => {
const data = 'foo';
testAction(
return testAction(
actions.receivePackagesListSuccess,
{ data, headers },
null,
......@@ -162,33 +147,30 @@ describe('Actions Package list store', () => {
{ type: types.SET_PAGINATION, payload: headers },
],
[],
done,
);
});
});
describe('setInitialState', () => {
it('should commit setInitialState', (done) => {
testAction(
it('should commit setInitialState', () => {
return testAction(
actions.setInitialState,
'1',
null,
[{ type: types.SET_INITIAL_STATE, payload: '1' }],
[],
done,
);
});
});
describe('setLoading', () => {
it('should commit set main loading', (done) => {
testAction(
it('should commit set main loading', () => {
return testAction(
actions.setLoading,
true,
null,
[{ type: types.SET_MAIN_LOADING, payload: true }],
[],
done,
);
});
});
......@@ -199,11 +181,11 @@ describe('Actions Package list store', () => {
delete_api_path: 'foo',
},
};
it('should perform a delete operation on _links.delete_api_path', (done) => {
it('should perform a delete operation on _links.delete_api_path', () => {
mock.onDelete(payload._links.delete_api_path).replyOnce(200);
Api.projectPackages = jest.fn().mockResolvedValue({ data: 'foo' });
testAction(
return testAction(
actions.requestDeletePackage,
payload,
{ pagination: { page: 1 } },
......@@ -212,13 +194,12 @@ describe('Actions Package list store', () => {
{ type: 'setLoading', payload: true },
{ type: 'requestPackagesList', payload: { page: 1 } },
],
done,
);
});
it('should stop the loading and call create flash on api error', (done) => {
it('should stop the loading and call create flash on api error', async () => {
mock.onDelete(payload._links.delete_api_path).replyOnce(400);
testAction(
await testAction(
actions.requestDeletePackage,
payload,
null,
......@@ -227,50 +208,44 @@ describe('Actions Package list store', () => {
{ type: 'setLoading', payload: true },
{ type: 'setLoading', payload: false },
],
() => {
expect(createFlash).toHaveBeenCalled();
done();
},
);
expect(createFlash).toHaveBeenCalled();
});
it.each`
property | actionPayload
${'_links'} | ${{}}
${'delete_api_path'} | ${{ _links: {} }}
`('should reject and createFlash when $property is missing', ({ actionPayload }, done) => {
testAction(actions.requestDeletePackage, actionPayload, null, [], []).catch((e) => {
`('should reject and createFlash when $property is missing', ({ actionPayload }) => {
return testAction(actions.requestDeletePackage, actionPayload, null, [], []).catch((e) => {
expect(e).toEqual(new Error(MISSING_DELETE_PATH_ERROR));
expect(createFlash).toHaveBeenCalledWith({
message: DELETE_PACKAGE_ERROR_MESSAGE,
});
done();
});
});
});
describe('setSorting', () => {
it('should commit SET_SORTING', (done) => {
testAction(
it('should commit SET_SORTING', () => {
return testAction(
actions.setSorting,
'foo',
null,
[{ type: types.SET_SORTING, payload: 'foo' }],
[],
done,
);
});
});
describe('setFilter', () => {
it('should commit SET_FILTER', (done) => {
testAction(
it('should commit SET_FILTER', () => {
return testAction(
actions.setFilter,
'foo',
null,
[{ type: types.SET_FILTER, payload: 'foo' }],
[],
done,
);
});
});
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment