Commit 9642a472 authored by Mike Greiling's avatar Mike Greiling

Merge branch '51712-new-line-before-expect' into 'master'

3. enable jasmine/new-line-before-expect

See merge request gitlab-org/gitlab-ce!22234
parents 28d412e5 6f5723a1
......@@ -36,5 +36,4 @@ rules:
- ignore:
- 'fixtures/blob'
# Temporarily disabled to facilitate an upgrade to eslint-plugin-jasmine
jasmine/new-line-before-expect: off
jasmine/prefer-toHaveBeenCalledWith: off
......@@ -42,6 +42,7 @@ describe('Ajax Loading Spinner', () => {
req.complete({});
const icon = ajaxLoadingSpinner.querySelector('i');
expect(icon).toHaveClass('fa-trash-o');
expect(icon).not.toHaveClass('fa-spinner');
expect(icon).not.toHaveClass('fa-spin');
......
......@@ -74,6 +74,7 @@ import '~/lib/utils/common_utils';
return lazyAssert(done, function() {
var $emojiMenu;
$emojiMenu = $('.emoji-menu');
expect($emojiMenu.length).toBe(1);
expect($emojiMenu.hasClass('is-visible')).toBe(true);
expect($emojiMenu.find('.js-emoji-menu-search').length).toBe(1);
......@@ -85,7 +86,8 @@ import '~/lib/utils/common_utils';
$('.js-add-award.note-action-button').click();
return lazyAssert(done, function() {
var $emojiMenu = $('.emoji-menu');
return expect($emojiMenu.length).toBe(1);
expect($emojiMenu.length).toBe(1);
});
});
......@@ -97,6 +99,7 @@ import '~/lib/utils/common_utils';
var $emojiMenu;
$emojiMenu = $('.emoji-menu');
$('body').click();
expect($emojiMenu.length).toBe(1);
expect($emojiMenu.hasClass('is-visible')).toBe(false);
return expect($('.js-awards-block.current').length).toBe(0);
......@@ -111,6 +114,7 @@ import '~/lib/utils/common_utils';
var $emojiMenu;
$emojiMenu = $('.emoji-menu');
$('.emoji-search').click();
expect($emojiMenu.length).toBe(1);
expect($emojiMenu.hasClass('is-visible')).toBe(true);
return expect($('.js-awards-block.current').length).toBe(1);
......@@ -124,6 +128,7 @@ import '~/lib/utils/common_utils';
$votesBlock = $('.js-awards-block').eq(0);
awardsHandler.addAwardToEmojiBar($votesBlock, 'heart', false);
$emojiButton = $votesBlock.find('[data-name=heart]');
expect($emojiButton.length).toBe(1);
expect($emojiButton.next('.js-counter').text()).toBe('1');
return expect($votesBlock.hasClass('hidden')).toBe(false);
......@@ -135,7 +140,8 @@ import '~/lib/utils/common_utils';
awardsHandler.addAwardToEmojiBar($votesBlock, 'heart', false);
awardsHandler.addAwardToEmojiBar($votesBlock, 'heart', false);
$emojiButton = $votesBlock.find('[data-name=heart]');
return expect($emojiButton.length).toBe(0);
expect($emojiButton.length).toBe(0);
});
return it('should decrement the emoji counter', function() {
var $emojiButton, $votesBlock;
......@@ -144,6 +150,7 @@ import '~/lib/utils/common_utils';
$emojiButton = $votesBlock.find('[data-name=heart]');
$emojiButton.next('.js-counter').text(5);
awardsHandler.addAwardToEmojiBar($votesBlock, 'heart', false);
expect($emojiButton.length).toBe(1);
return expect($emojiButton.next('.js-counter').text()).toBe('4');
});
......@@ -156,7 +163,8 @@ import '~/lib/utils/common_utils';
$thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent();
$thumbsUpEmoji.attr('data-title', 'sam');
awardsHandler.userAuthored($thumbsUpEmoji);
return expect($thumbsUpEmoji.data('originalTitle')).toBe(
expect($thumbsUpEmoji.data('originalTitle')).toBe(
'You cannot vote on your own issue, MR and note',
);
});
......@@ -170,13 +178,15 @@ import '~/lib/utils/common_utils';
awardsHandler.userAuthored($thumbsUpEmoji);
jasmine.clock().tick(2801);
jasmine.clock().uninstall();
return expect($thumbsUpEmoji.data('originalTitle')).toBe('sam');
expect($thumbsUpEmoji.data('originalTitle')).toBe('sam');
});
});
describe('::getAwardUrl', function() {
return it('returns the url for request', function() {
return expect(awardsHandler.getAwardUrl()).toBe(
expect(awardsHandler.getAwardUrl()).toBe(
'http://test.host/snippets/1/toggle_award_emoji',
);
});
......@@ -190,11 +200,13 @@ import '~/lib/utils/common_utils';
$thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent();
$thumbsDownEmoji = $votesBlock.find('[data-name=thumbsdown]').parent();
awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false);
expect($thumbsUpEmoji.hasClass('active')).toBe(true);
expect($thumbsDownEmoji.hasClass('active')).toBe(false);
$thumbsUpEmoji.tooltip();
$thumbsDownEmoji.tooltip();
awardsHandler.addAward($votesBlock, awardUrl, 'thumbsdown', true);
expect($thumbsUpEmoji.hasClass('active')).toBe(false);
return expect($thumbsDownEmoji.hasClass('active')).toBe(true);
});
......@@ -206,9 +218,11 @@ import '~/lib/utils/common_utils';
awardUrl = awardsHandler.getAwardUrl();
$votesBlock = $('.js-awards-block').eq(0);
awardsHandler.addAward($votesBlock, awardUrl, 'fire', false);
expect($votesBlock.find('[data-name=fire]').length).toBe(1);
awardsHandler.removeEmoji($votesBlock.find('[data-name=fire]').closest('button'));
return expect($votesBlock.find('[data-name=fire]').length).toBe(0);
expect($votesBlock.find('[data-name=fire]').length).toBe(0);
});
});
......@@ -221,7 +235,8 @@ import '~/lib/utils/common_utils';
$thumbsUpEmoji.attr('data-title', 'sam, jerry, max, and andy');
awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false);
$thumbsUpEmoji.tooltip();
return expect($thumbsUpEmoji.data('originalTitle')).toBe('You, sam, jerry, max, and andy');
expect($thumbsUpEmoji.data('originalTitle')).toBe('You, sam, jerry, max, and andy');
});
return it('handles the special case where "You" is not cleanly comma seperated', function() {
var $thumbsUpEmoji, $votesBlock, awardUrl;
......@@ -231,7 +246,8 @@ import '~/lib/utils/common_utils';
$thumbsUpEmoji.attr('data-title', 'sam');
awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false);
$thumbsUpEmoji.tooltip();
return expect($thumbsUpEmoji.data('originalTitle')).toBe('You and sam');
expect($thumbsUpEmoji.data('originalTitle')).toBe('You and sam');
});
});
......@@ -245,7 +261,8 @@ import '~/lib/utils/common_utils';
$thumbsUpEmoji.addClass('active');
awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false);
$thumbsUpEmoji.tooltip();
return expect($thumbsUpEmoji.data('originalTitle')).toBe('sam, jerry, max, and andy');
expect($thumbsUpEmoji.data('originalTitle')).toBe('sam, jerry, max, and andy');
});
return it('handles the special case where "You" is not cleanly comma seperated', function() {
var $thumbsUpEmoji, $votesBlock, awardUrl;
......@@ -256,7 +273,8 @@ import '~/lib/utils/common_utils';
$thumbsUpEmoji.addClass('active');
awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false);
$thumbsUpEmoji.tooltip();
return expect($thumbsUpEmoji.data('originalTitle')).toBe('sam');
expect($thumbsUpEmoji.data('originalTitle')).toBe('sam');
});
});
......@@ -267,6 +285,7 @@ import '~/lib/utils/common_utils';
expect($('[data-name=angel]').is(':visible')).toBe(true);
expect($('[data-name=anger]').is(':visible')).toBe(true);
awardsHandler.searchEmojis('ali');
expect($('[data-name=angel]').is(':visible')).toBe(false);
expect($('[data-name=anger]').is(':visible')).toBe(false);
expect($('[data-name=alien]').is(':visible')).toBe(true);
......@@ -282,10 +301,12 @@ import '~/lib/utils/common_utils';
return openAndWaitForEmojiMenu()
.then(() => {
awardsHandler.searchEmojis('ali');
expect($('[data-name=angel]').is(':visible')).toBe(false);
expect($('[data-name=anger]').is(':visible')).toBe(false);
expect($('[data-name=alien]').is(':visible')).toBe(true);
awardsHandler.searchEmojis('');
expect($('[data-name=angel]').is(':visible')).toBe(true);
expect($('[data-name=anger]').is(':visible')).toBe(true);
expect($('[data-name=alien]').is(':visible')).toBe(true);
......@@ -309,6 +330,7 @@ import '~/lib/utils/common_utils';
expect($emoji.length).toBe(1);
expect($block.find(emojiSelector).length).toBe(0);
$emoji.click();
expect($menu.hasClass('.is-visible')).toBe(false);
expect($block.find(emojiSelector).length).toBe(1);
});
......@@ -332,6 +354,7 @@ import '~/lib/utils/common_utils';
`.emoji-menu-list:not(.frequent-emojis) ${emojiSelector}`,
);
$emoji.click();
expect($block.find(emojiSelector).length).toBe(0);
})
.then(done)
......
......@@ -66,8 +66,10 @@ describe('BadgeForm component', () => {
};
const expectInvalidInput = inputElementSelector => {
const inputElement = vm.$el.querySelector(inputElementSelector);
expect(inputElement).toBeMatchedBy(':invalid');
const feedbackElement = vm.$el.querySelector(`${inputElementSelector} + .invalid-feedback`);
expect(feedbackElement).toBeVisible();
};
......@@ -90,6 +92,7 @@ describe('BadgeForm component', () => {
submitForm();
expectInvalidInput(imageUrlSelector);
expect(vm[submitAction]).not.toHaveBeenCalled();
});
......@@ -99,6 +102,7 @@ describe('BadgeForm component', () => {
submitForm();
expectInvalidInput(imageUrlSelector);
expect(vm[submitAction]).not.toHaveBeenCalled();
});
......@@ -108,6 +112,7 @@ describe('BadgeForm component', () => {
submitForm();
expectInvalidInput(linkUrlSelector);
expect(vm[submitAction]).not.toHaveBeenCalled();
});
......@@ -117,6 +122,7 @@ describe('BadgeForm component', () => {
submitForm();
expectInvalidInput(linkUrlSelector);
expect(vm[submitAction]).not.toHaveBeenCalled();
});
......@@ -143,8 +149,10 @@ describe('BadgeForm component', () => {
it('renders one button', () => {
expect(vm.$el.querySelector('.row-content-block')).toBeNull();
const buttons = vm.$el.querySelectorAll('.form-group:last-of-type button');
expect(buttons.length).toBe(1);
const buttonAddElement = buttons[0];
expect(buttonAddElement).toBeVisible();
expect(buttonAddElement).toHaveText('Add badge');
});
......@@ -165,11 +173,14 @@ describe('BadgeForm component', () => {
it('renders two buttons', () => {
const buttons = vm.$el.querySelectorAll('.row-content-block button');
expect(buttons.length).toBe(2);
const buttonSaveElement = buttons[0];
expect(buttonSaveElement).toBeVisible();
expect(buttonSaveElement).toHaveText('Save changes');
const buttonCancelElement = buttons[1];
expect(buttonCancelElement).toBeVisible();
expect(buttonCancelElement).toHaveText('Cancel');
});
......
......@@ -34,6 +34,7 @@ describe('BadgeListRow component', () => {
it('renders the badge', () => {
const badgeElement = vm.$el.querySelector('.project-badge');
expect(badgeElement).not.toBeNull();
expect(badgeElement.getAttribute('src')).toBe(badge.renderedImageUrl);
});
......@@ -48,11 +49,14 @@ describe('BadgeListRow component', () => {
it('shows edit and delete buttons', () => {
const buttons = vm.$el.querySelectorAll('.table-button-footer button');
expect(buttons).toHaveLength(2);
const buttonEditElement = buttons[0];
expect(buttonEditElement).toBeVisible();
expect(buttonEditElement).toHaveSpriteIcon('pencil');
const buttonDeleteElement = buttons[1];
expect(buttonDeleteElement).toBeVisible();
expect(buttonDeleteElement).toHaveSpriteIcon('remove');
});
......@@ -91,6 +95,7 @@ describe('BadgeListRow component', () => {
it('hides edit and delete buttons', () => {
const buttons = vm.$el.querySelectorAll('.table-button-footer button');
expect(buttons).toHaveLength(0);
});
});
......
......@@ -34,11 +34,13 @@ describe('BadgeList component', () => {
it('renders a header with the badge count', () => {
const header = vm.$el.querySelector('.card-header');
expect(header).toHaveText(new RegExp(`Your badges\\s+${numberOfDummyBadges}`));
});
it('renders a row for each badge', () => {
const rows = vm.$el.querySelectorAll('.gl-responsive-table-row');
expect(rows).toHaveLength(numberOfDummyBadges);
});
......@@ -59,6 +61,7 @@ describe('BadgeList component', () => {
Vue.nextTick()
.then(() => {
const loadingIcon = vm.$el.querySelector('.fa-spinner');
expect(loadingIcon).toBeVisible();
})
.then(done)
......
......@@ -38,6 +38,7 @@ describe('BadgeSettings component', () => {
$(modal).on('shown.bs.modal', () => {
expect(modal).toContainText('Delete badge?');
const badgeElement = modal.querySelector('img.project-badge');
expect(badgeElement).not.toBe(null);
expect(badgeElement.getAttribute('src')).toBe(badge.renderedImageUrl);
......@@ -53,14 +54,17 @@ describe('BadgeSettings component', () => {
it('displays a form to add a badge', () => {
const form = vm.$el.querySelector('form:nth-of-type(2)');
expect(form).not.toBe(null);
const button = form.querySelector('.btn-success');
expect(button).not.toBe(null);
expect(button).toHaveText(/Add badge/);
});
it('displays badge list', () => {
const badgeListElement = vm.$el.querySelector('.card');
expect(badgeListElement).not.toBe(null);
expect(badgeListElement).toBeVisible();
expect(badgeListElement).toContainText('Your badges');
......@@ -77,17 +81,21 @@ describe('BadgeSettings component', () => {
it('displays a form to edit a badge', () => {
const form = vm.$el.querySelector('form:nth-of-type(1)');
expect(form).not.toBe(null);
const submitButton = form.querySelector('.btn-success');
expect(submitButton).not.toBe(null);
expect(submitButton).toHaveText(/Save changes/);
const cancelButton = form.querySelector('.btn-cancel');
expect(cancelButton).not.toBe(null);
expect(cancelButton).toHaveText(/Cancel/);
});
it('displays no badge list', () => {
const badgeListElement = vm.$el.querySelector('.card');
expect(badgeListElement).toBeHidden();
});
});
......@@ -102,6 +110,7 @@ describe('BadgeSettings component', () => {
deleteButton.click();
const badge = store.state.badgeInModal;
expect(vm.deleteBadge).toHaveBeenCalledWith(badge);
});
});
......
......@@ -107,6 +107,7 @@ describe('Badge component', () => {
expect(vm.isLoading).toBe(false);
expect(vm.hasError).toBe(false);
const { badgeImage, loadingIcon, reloadButton } = findElements();
expect(badgeImage).toBeVisible();
expect(loadingIcon).toBeHidden();
expect(reloadButton).toBeHidden();
......@@ -119,6 +120,7 @@ describe('Badge component', () => {
Vue.nextTick()
.then(() => {
const { badgeImage, loadingIcon, reloadButton } = findElements();
expect(badgeImage).toBeHidden();
expect(loadingIcon).toBeVisible();
expect(reloadButton).toBeHidden();
......@@ -134,6 +136,7 @@ describe('Badge component', () => {
Vue.nextTick()
.then(() => {
const { badgeImage, loadingIcon, reloadButton } = findElements();
expect(badgeImage).toBeHidden();
expect(loadingIcon).toBeHidden();
expect(reloadButton).toBeVisible();
......
......@@ -94,6 +94,7 @@ describe('Badges store actions', () => {
link_url: badgeInAddForm.linkUrl,
}),
);
expect(dispatch.calls.allArgs()).toEqual([['requestNewBadge']]);
dispatch.calls.reset();
return [200, dummyResponse];
......@@ -117,6 +118,7 @@ describe('Badges store actions', () => {
link_url: badgeInAddForm.linkUrl,
}),
);
expect(dispatch.calls.allArgs()).toEqual([['requestNewBadge']]);
dispatch.calls.reset();
return [500, ''];
......@@ -296,6 +298,7 @@ describe('Badges store actions', () => {
.loadBadges({ state, dispatch }, dummyData)
.then(() => {
const badges = dummyReponse.map(transformBackendBadge);
expect(dispatch.calls.allArgs()).toEqual([['receiveLoadBadges', badges]]);
})
.then(done)
......@@ -416,6 +419,7 @@ describe('Badges store actions', () => {
.then(() => {
expect(axios.get.calls.count()).toBe(1);
const url = axios.get.calls.argsFor(0)[0];
expect(url).toMatch(`^${dummyEndpointUrl}/render?`);
expect(url).toMatch('\\?link_url=%3Cscript%3EI%20am%20dangerous!%3C%2Fscript%3E&');
expect(url).toMatch('&image_url=%26make-sandwhich%3Dtrue$');
......@@ -436,6 +440,7 @@ describe('Badges store actions', () => {
.renderBadge({ state, dispatch })
.then(() => {
const renderedBadge = transformBackendBadge(dummyReponse);
expect(dispatch.calls.allArgs()).toEqual([['receiveRenderedBadge', renderedBadge]]);
})
.then(done)
......@@ -525,6 +530,7 @@ describe('Badges store actions', () => {
link_url: badgeInEditForm.linkUrl,
}),
);
expect(dispatch.calls.allArgs()).toEqual([['requestUpdatedBadge']]);
dispatch.calls.reset();
return [200, dummyResponse];
......@@ -548,6 +554,7 @@ describe('Badges store actions', () => {
link_url: badgeInEditForm.linkUrl,
}),
);
expect(dispatch.calls.allArgs()).toEqual([['requestUpdatedBadge']]);
dispatch.calls.reset();
return [500, ''];
......
......@@ -12,6 +12,7 @@ describe('Autosize behavior', () => {
it('does not overwrite the resize property', () => {
load();
expect($('textarea')).toHaveCss({
resize: 'vertical',
});
......
......@@ -29,6 +29,7 @@ describe('CopyAsGFM', () => {
it('wraps pasted code when not already in code tags', () => {
spyOn(window.gl.utils, 'insertText').and.callFake((el, textFunc) => {
const insertedText = textFunc('This is code: ', '');
expect(insertedText).toEqual('`code`');
});
......@@ -38,6 +39,7 @@ describe('CopyAsGFM', () => {
it('does not wrap pasted code when already in code tags', () => {
spyOn(window.gl.utils, 'insertText').and.callFake((el, textFunc) => {
const insertedText = textFunc('This is code: `', '`');
expect(insertedText).toEqual('code');
});
......@@ -86,6 +88,7 @@ describe('CopyAsGFM', () => {
simulateCopy();
const expectedGFM = '- List Item1\n- List Item2';
expect(clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', expectedGFM);
});
......@@ -95,6 +98,7 @@ describe('CopyAsGFM', () => {
simulateCopy();
const expectedGFM = '1. List Item1\n1. List Item2';
expect(clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', expectedGFM);
});
});
......
......@@ -30,6 +30,7 @@ describe('Quick Submit behavior', function () {
keyCode: 32,
}),
);
expect(this.spies.submit).not.toHaveBeenTriggered();
});
......@@ -40,6 +41,7 @@ describe('Quick Submit behavior', function () {
metaKey: false,
}),
);
expect(this.spies.submit).not.toHaveBeenTriggered();
});
......@@ -49,6 +51,7 @@ describe('Quick Submit behavior', function () {
repeat: true,
}),
);
expect(this.spies.submit).not.toHaveBeenTriggered();
});
......@@ -86,7 +89,8 @@ describe('Quick Submit behavior', function () {
describe('In Macintosh', () => {
it('responds to Meta+Enter', () => {
this.textarea.trigger(keydownEvent());
return expect(this.spies.submit).toHaveBeenTriggered();
expect(this.spies.submit).toHaveBeenTriggered();
});
it('excludes other modifier keys', () => {
......@@ -105,13 +109,15 @@ describe('Quick Submit behavior', function () {
shiftKey: true,
}),
);
return expect(this.spies.submit).not.toHaveBeenTriggered();
expect(this.spies.submit).not.toHaveBeenTriggered();
});
});
} else {
it('responds to Ctrl+Enter', () => {
this.textarea.trigger(keydownEvent());
return expect(this.spies.submit).toHaveBeenTriggered();
expect(this.spies.submit).toHaveBeenTriggered();
});
it('excludes other modifier keys', () => {
......@@ -130,7 +136,8 @@ describe('Quick Submit behavior', function () {
shiftKey: true,
}),
);
return expect(this.spies.submit).not.toHaveBeenTriggered();
expect(this.spies.submit).not.toHaveBeenTriggered();
});
}
});
......@@ -12,33 +12,39 @@ describe('requiresInput', () => {
it('disables submit when any field is required', () => {
$('.js-requires-input').requiresInput();
expect(submitButton).toBeDisabled();
});
it('enables submit when no field is required', () => {
$('*[required=required]').prop('required', false);
$('.js-requires-input').requiresInput();
expect(submitButton).not.toBeDisabled();
});
it('enables submit when all required fields are pre-filled', () => {
$('*[required=required]').remove();
$('.js-requires-input').requiresInput();
expect($('.submit')).not.toBeDisabled();
});
it('enables submit when all required fields receive input', () => {
$('.js-requires-input').requiresInput();
$('#required1').val('input1').change();
expect(submitButton).toBeDisabled();
$('#optional1').val('input1').change();
expect(submitButton).toBeDisabled();
$('#required2').val('input2').change();
$('#required3').val('input3').change();
$('#required4').val('input4').change();
$('#required5').val('1').change();
expect($('.submit')).not.toBeDisabled();
});
});
......@@ -130,6 +130,7 @@ describe('setupSecretValues', () => {
values.forEach((value) => {
expect(value.classList.contains('hide')).toEqual(true);
});
expect(placeholders.length).toEqual(3);
placeholders.forEach((placeholder) => {
expect(placeholder.classList.contains('hide')).toEqual(false);
......@@ -148,6 +149,7 @@ describe('setupSecretValues', () => {
values.forEach((value) => {
expect(value.classList.contains('hide')).toEqual(false);
});
expect(placeholders.length).toEqual(3);
placeholders.forEach((placeholder) => {
expect(placeholder.classList.contains('hide')).toEqual(true);
......@@ -159,6 +161,7 @@ describe('setupSecretValues', () => {
values.forEach((value) => {
expect(value.classList.contains('hide')).toEqual(true);
});
expect(placeholders.length).toEqual(3);
placeholders.forEach((placeholder) => {
expect(placeholder.classList.contains('hide')).toEqual(false);
......@@ -184,6 +187,7 @@ describe('setupSecretValues', () => {
values.forEach((value) => {
expect(value.classList.contains('hide')).toEqual(false);
});
expect(placeholders.length).toEqual(4);
placeholders.forEach((placeholder) => {
expect(placeholder.classList.contains('hide')).toEqual(true);
......@@ -195,6 +199,7 @@ describe('setupSecretValues', () => {
values.forEach((value) => {
expect(value.classList.contains('hide')).toEqual(true);
});
expect(placeholders.length).toEqual(4);
placeholders.forEach((placeholder) => {
expect(placeholder.classList.contains('hide')).toEqual(false);
......
......@@ -57,9 +57,11 @@ describe('ShortcutsIssuable', function() {
it('leaves existing input intact', () => {
$(FORM_SELECTOR).val('This text was already here.');
expect($(FORM_SELECTOR).val()).toBe('This text was already here.');
ShortcutsIssuable.replyWithSelectedText(true);
expect($(FORM_SELECTOR).val()).toBe('This text was already here.\n\n> Selected text.\n\n');
});
......@@ -70,6 +72,7 @@ describe('ShortcutsIssuable', function() {
});
ShortcutsIssuable.replyWithSelectedText(true);
expect(triggered).toBe(true);
});
......
......@@ -26,6 +26,7 @@ describe('BlobForkSuggestion', () => {
it('showSuggestionSection', () => {
blobForkSuggestion.showSuggestionSection('/foo', 'foo');
expect(suggestionSection.classList.contains('hidden')).toEqual(false);
expect(forkButton.getAttribute('href')).toEqual('/foo');
expect(actionTextPiece.textContent).toEqual('foo');
......@@ -33,6 +34,7 @@ describe('BlobForkSuggestion', () => {
it('hideSuggestionSection', () => {
blobForkSuggestion.hideSuggestionSection();
expect(suggestionSection.classList.contains('hidden')).toEqual(true);
});
});
......@@ -165,6 +165,7 @@ describe('Blob viewer', () => {
expect(
simpleBtn.classList.contains('active'),
).toBeTruthy();
expect(simpleBtn.blur).toHaveBeenCalled();
});
......
......@@ -86,10 +86,12 @@ describe('Store', () => {
description: 'testing;'
}
});
expect(boardsStore.state.lists.length).toBe(1);
setTimeout(() => {
const list = boardsStore.findList('id', listObj.id);
expect(list).toBeDefined();
expect(list.id).toBe(listObj.id);
expect(list.position).toBe(0);
......@@ -103,6 +105,7 @@ describe('Store', () => {
it('check for blank state not adding', () => {
boardsStore.addList(listObj);
expect(boardsStore.shouldAddBlankState()).toBe(false);
});
......@@ -118,6 +121,7 @@ describe('Store', () => {
boardsStore.addBlankState();
const list = boardsStore.findList('type', 'blank', 'blank');
expect(list).toBeDefined();
});
......
......@@ -47,6 +47,7 @@ describe('Issue model', () => {
color: 'blue',
description: 'bugs!'
});
expect(issue.labels.length).toBe(2);
});
......@@ -63,12 +64,14 @@ describe('Issue model', () => {
it('finds label', () => {
const label = issue.findLabel(issue.labels[0]);
expect(label).toBeDefined();
});
it('removes label', () => {
const label = issue.findLabel(issue.labels[0]);
issue.removeLabel(label);
expect(issue.labels.length).toBe(0);
});
......@@ -79,9 +82,11 @@ describe('Issue model', () => {
color: 'blue',
description: 'bugs!'
});
expect(issue.labels.length).toBe(2);
issue.removeLabels([issue.labels[0], issue.labels[1]]);
expect(issue.labels.length).toBe(0);
});
......@@ -98,17 +103,20 @@ describe('Issue model', () => {
it('finds assignee', () => {
const assignee = issue.findAssignee(issue.assignees[0]);
expect(assignee).toBeDefined();
});
it('removes assignee', () => {
const assignee = issue.findAssignee(issue.assignees[0]);
issue.removeAssignee(assignee);
expect(issue.assignees.length).toBe(0);
});
it('removes all assignees', () => {
issue.removeAllAssignees();
expect(issue.assignees.length).toBe(0);
});
......@@ -131,6 +139,7 @@ describe('Issue model', () => {
it('updates data', () => {
issue.updateData({ subscribed: true });
expect(issue.subscribed).toBe(true);
});
......
......@@ -60,6 +60,7 @@ describe('List model', () => {
it('destroys the list', (done) => {
boardsStore.addList(listObj);
list = boardsStore.findList('id', listObj.id);
expect(boardsStore.state.lists.length).toBe(1);
list.destroy();
......@@ -72,6 +73,7 @@ describe('List model', () => {
it('gets issue from list', (done) => {
setTimeout(() => {
const issue = list.findIssue(1);
expect(issue).toBeDefined();
done();
}, 0);
......@@ -80,8 +82,10 @@ describe('List model', () => {
it('removes issue', (done) => {
setTimeout(() => {
const issue = list.findIssue(1);
expect(list.issues.length).toBe(1);
list.removeIssue(issue);
expect(list.issues.length).toBe(0);
done();
}, 0);
......
......@@ -14,13 +14,15 @@ import '~/commons/bootstrap';
var $input;
$input = $('input').first();
$input.disable();
return expect($input).toHaveAttr('disabled', 'disabled');
expect($input).toHaveAttr('disabled', 'disabled');
});
return it('adds the disabled class', function() {
var $input;
$input = $('input').first();
$input.disable();
return expect($input).toHaveClass('disabled');
expect($input).toHaveClass('disabled');
});
});
return describe('enable', function() {
......@@ -32,13 +34,15 @@ import '~/commons/bootstrap';
var $input;
$input = $('input').first();
$input.enable();
return expect($input).not.toHaveAttr('disabled');
expect($input).not.toHaveAttr('disabled');
});
return it('removes the disabled class', function() {
var $input;
$input = $('input').first();
$input.enable();
return expect($input).not.toHaveClass('disabled');
expect($input).not.toHaveClass('disabled');
});
});
});
......
......@@ -41,6 +41,7 @@ describe('VariableList', () => {
// Check for the correct default in the new row
const $keyInput = $wrapper.find('.js-row:last-child').find('.js-ci-variable-input-key');
expect($keyInput.val()).toBe('');
});
......@@ -54,6 +55,7 @@ describe('VariableList', () => {
// Check for the correct default in the new row
const $valueInput = $wrapper.find('.js-row:last-child').find('.js-ci-variable-input-key');
expect($valueInput.val()).toBe('');
});
......@@ -129,6 +131,7 @@ describe('VariableList', () => {
// Check for the correct default in the new row
const $protectedInput = $wrapper.find('.js-row:last-child').find('.js-ci-variable-input-protected');
expect($protectedInput.val()).toBe('false');
})
.then(done)
......@@ -166,6 +169,7 @@ describe('VariableList', () => {
it('should enable all remove buttons', () => {
variableList.toggleEnableRow(false);
expect($wrapper.find('.js-row-remove-button[disabled]').length).toBe(3);
variableList.toggleEnableRow(true);
......@@ -175,6 +179,7 @@ describe('VariableList', () => {
it('should enable all key inputs', () => {
variableList.toggleEnableRow(false);
expect($wrapper.find('.js-ci-variable-input-key[disabled]').length).toBe(3);
variableList.toggleEnableRow(true);
......
......@@ -19,6 +19,7 @@ describe('NativeFormVariableList', () => {
describe('onFormSubmit', () => {
it('should clear out the `name` attribute on the inputs for the last empty row on form submission (avoid BE validation)', () => {
const $row = $wrapper.find('.js-row');
expect($row.find('.js-ci-variable-input-key').attr('name')).toBe('schedule[variables_attributes][][key]');
expect($row.find('.js-ci-variable-input-value').attr('name')).toBe('schedule[variables_attributes][][secret_value]');
......
......@@ -86,6 +86,7 @@ describe('Clusters', () => {
});
const flashMessage = document.querySelector('.js-cluster-application-notice .flash-text');
expect(flashMessage).toBeNull();
});
......@@ -99,6 +100,7 @@ describe('Clusters', () => {
});
const flashMessage = document.querySelector('.js-cluster-application-notice .flash-text');
expect(flashMessage).not.toBeNull();
expect(flashMessage.textContent.trim()).toEqual('Helm Tiller was successfully installed on your Kubernetes cluster');
});
......@@ -115,6 +117,7 @@ describe('Clusters', () => {
});
const flashMessage = document.querySelector('.js-cluster-application-notice .flash-text');
expect(flashMessage).not.toBeNull();
expect(flashMessage.textContent.trim()).toEqual('Helm Tiller, Ingress was successfully installed on your Kubernetes cluster');
});
......@@ -128,9 +131,11 @@ describe('Clusters', () => {
expect(
cluster.creatingContainer.classList.contains('hidden'),
).toBeFalsy();
expect(
cluster.successContainer.classList.contains('hidden'),
).toBeTruthy();
expect(
cluster.errorContainer.classList.contains('hidden'),
).toBeTruthy();
......@@ -142,9 +147,11 @@ describe('Clusters', () => {
expect(
cluster.creatingContainer.classList.contains('hidden'),
).toBeFalsy();
expect(
cluster.successContainer.classList.contains('hidden'),
).toBeTruthy();
expect(
cluster.errorContainer.classList.contains('hidden'),
).toBeTruthy();
......@@ -158,9 +165,11 @@ describe('Clusters', () => {
expect(
cluster.creatingContainer.classList.contains('hidden'),
).toBeTruthy();
expect(
cluster.successContainer.classList.contains('hidden'),
).toBeFalsy();
expect(
cluster.errorContainer.classList.contains('hidden'),
).toBeTruthy();
......@@ -172,9 +181,11 @@ describe('Clusters', () => {
expect(
cluster.creatingContainer.classList.contains('hidden'),
).toBeTruthy();
expect(
cluster.successContainer.classList.contains('hidden'),
).toBeTruthy();
expect(
cluster.errorContainer.classList.contains('hidden'),
).toBeTruthy();
......@@ -188,9 +199,11 @@ describe('Clusters', () => {
expect(
cluster.creatingContainer.classList.contains('hidden'),
).toBeTruthy();
expect(
cluster.successContainer.classList.contains('hidden'),
).toBeTruthy();
expect(
cluster.errorContainer.classList.contains('hidden'),
).toBeFalsy();
......@@ -206,9 +219,11 @@ describe('Clusters', () => {
expect(
cluster.creatingContainer.classList.contains('hidden'),
).toBeTruthy();
expect(
cluster.successContainer.classList.contains('hidden'),
).toBeTruthy();
expect(
cluster.errorContainer.classList.contains('hidden'),
).toBeFalsy();
......@@ -219,6 +234,7 @@ describe('Clusters', () => {
describe('installApplication', () => {
it('tries to install helm', (done) => {
spyOn(cluster.service, 'installApplication').and.returnValue(Promise.resolve());
expect(cluster.store.state.applications.helm.requestStatus).toEqual(null);
cluster.installApplication({ id: 'helm' });
......@@ -238,6 +254,7 @@ describe('Clusters', () => {
it('tries to install ingress', (done) => {
spyOn(cluster.service, 'installApplication').and.returnValue(Promise.resolve());
expect(cluster.store.state.applications.ingress.requestStatus).toEqual(null);
cluster.installApplication({ id: 'ingress' });
......@@ -257,6 +274,7 @@ describe('Clusters', () => {
it('tries to install runner', (done) => {
spyOn(cluster.service, 'installApplication').and.returnValue(Promise.resolve());
expect(cluster.store.state.applications.runner.requestStatus).toEqual(null);
cluster.installApplication({ id: 'runner' });
......@@ -276,6 +294,7 @@ describe('Clusters', () => {
it('tries to install jupyter', (done) => {
spyOn(cluster.service, 'installApplication').and.returnValue(Promise.resolve());
expect(cluster.store.state.applications.jupyter.requestStatus).toEqual(null);
cluster.installApplication({ id: 'jupyter', params: { hostname: cluster.store.state.applications.jupyter.hostname } });
......@@ -294,6 +313,7 @@ describe('Clusters', () => {
it('sets error request status when the request fails', (done) => {
spyOn(cluster.service, 'installApplication').and.returnValue(Promise.reject(new Error('STUBBED ERROR')));
expect(cluster.store.state.applications.helm.requestStatus).toEqual(null);
cluster.installApplication({ id: 'helm' });
......
......@@ -4,10 +4,12 @@ describe('CommitMergeRequests', () => {
describe('createContent', () => {
it('should return created content', () => {
const content1 = CommitMergeRequests.createContent([{ iid: 1, path: '/path1', title: 'foo' }, { iid: 2, path: '/path2', title: 'baz' }])[0];
expect(content1.tagName).toEqual('SPAN');
expect(content1.childElementCount).toEqual(4);
const content2 = CommitMergeRequests.createContent([])[0];
expect(content2.tagName).toEqual('SPAN');
expect(content2.childElementCount).toEqual(0);
expect(content2.innerText).toEqual('No related merge requests found');
......@@ -26,6 +28,7 @@ describe('CommitMergeRequests', () => {
describe('createHeader', () => {
it('should return created header', () => {
const header = CommitMergeRequests.createHeader(0, 1)[0];
expect(header.tagName).toEqual('SPAN');
expect(header.innerText).toEqual('1 merge request');
});
......@@ -34,6 +37,7 @@ describe('CommitMergeRequests', () => {
describe('createItem', () => {
it('should return created item', () => {
const item = CommitMergeRequests.createItem({ iid: 1, path: '/path', title: 'foo' })[0];
expect(item.tagName).toEqual('SPAN');
expect(item.childElementCount).toEqual(2);
expect(item.children[0].tagName).toEqual('A');
......@@ -44,6 +48,7 @@ describe('CommitMergeRequests', () => {
describe('createLink', () => {
it('should return created link', () => {
const link = CommitMergeRequests.createLink({ iid: 1, path: '/path', title: 'foo' })[0];
expect(link.tagName).toEqual('A');
expect(link.href).toMatch(/\/path$/);
expect(link.innerText).toEqual('!1');
......@@ -53,6 +58,7 @@ describe('CommitMergeRequests', () => {
describe('createTitle', () => {
it('should return created title', () => {
const title = CommitMergeRequests.createTitle({ iid: 1, path: '/path', title: 'foo' })[0];
expect(title.tagName).toEqual('SPAN');
expect(title.innerText).toEqual('foo');
});
......
......@@ -63,6 +63,7 @@ describe('CreateItemDropdown', () => {
$('.js-dropdown-menu-toggle').click();
const $itemEls = $wrapperEl.find('.js-dropdown-content a');
expect($itemEls.length).toEqual(DROPDOWN_ITEM_DATA.length);
});
});
......@@ -106,6 +107,7 @@ describe('CreateItemDropdown', () => {
createItemAndClearInput(NEW_ITEM_TEXT);
const $itemEls = $wrapperEl.find('.js-dropdown-content a');
expect($itemEls.length).toEqual(1 + DROPDOWN_ITEM_DATA.length);
expect($($itemEls.get(DROPDOWN_ITEM_DATA.length)).text()).toEqual(NEW_ITEM_TEXT);
});
......@@ -114,6 +116,7 @@ describe('CreateItemDropdown', () => {
createItemAndClearInput(DROPDOWN_ITEM_DATA[0].text);
const $itemEls = $wrapperEl.find('.js-dropdown-content a');
expect($itemEls.length).toEqual(DROPDOWN_ITEM_DATA.length);
});
});
......@@ -142,11 +145,13 @@ describe('CreateItemDropdown', () => {
.trigger('input');
const $itemElsAfterFilter = $wrapperEl.find('.js-dropdown-content a');
expect($itemElsAfterFilter.length).toEqual(1);
createItemDropdown.clearDropdown();
const $itemElsAfterClear = $wrapperEl.find('.js-dropdown-content a');
expect($itemElsAfterClear.length).toEqual(0);
expect(filterInput.val()).toEqual('');
});
......@@ -176,6 +181,7 @@ describe('CreateItemDropdown', () => {
createItemAndClearInput('new-item');
const $itemEls = $wrapperEl.find('.js-dropdown-content a');
expect($itemEls.length).toEqual(1 + DROPDOWN_ITEM_DATA.length);
expect($($itemEls[3]).text()).toEqual('new-item-text');
expect($wrapperEl.find('.dropdown-toggle-text').text()).toEqual('new-item-title');
......
......@@ -59,6 +59,7 @@ describe('CreateMergeRequestDropdown', () => {
expect(dropdown.createBranchPath).toBe(
`${TEST_HOST}/branches?branch_name=contains%23hash&issue=42`,
);
expect(dropdown.createMrPath).toBe(
`${TEST_HOST}/create_merge_request?branch_name=contains%23hash&ref=master`,
);
......
......@@ -24,9 +24,11 @@ describe('Cycle analytics banner', () => {
expect(
vm.$el.querySelector('p').textContent.trim().replace(/[\r\n]+/g, ' '),
).toContain('Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.');
expect(
vm.$el.querySelector('a').textContent.trim(),
).toEqual('Read more');
expect(
vm.$el.querySelector('a').getAttribute('href'),
).toEqual('path');
......
......@@ -24,36 +24,43 @@ describe('Date time utils', () => {
describe('get day name', () => {
it('should return Sunday', () => {
const day = datetimeUtility.getDayName(new Date('07/17/2016'));
expect(day).toBe('Sunday');
});
it('should return Monday', () => {
const day = datetimeUtility.getDayName(new Date('07/18/2016'));
expect(day).toBe('Monday');
});
it('should return Tuesday', () => {
const day = datetimeUtility.getDayName(new Date('07/19/2016'));
expect(day).toBe('Tuesday');
});
it('should return Wednesday', () => {
const day = datetimeUtility.getDayName(new Date('07/20/2016'));
expect(day).toBe('Wednesday');
});
it('should return Thursday', () => {
const day = datetimeUtility.getDayName(new Date('07/21/2016'));
expect(day).toBe('Thursday');
});
it('should return Friday', () => {
const day = datetimeUtility.getDayName(new Date('07/22/2016'));
expect(day).toBe('Friday');
});
it('should return Saturday', () => {
const day = datetimeUtility.getDayName(new Date('07/23/2016'));
expect(day).toBe('Saturday');
});
});
......@@ -63,6 +70,7 @@ describe('Date time utils', () => {
const firstDay = new Date('07/01/2016');
const secondDay = new Date('07/08/2016');
const difference = datetimeUtility.getDayDifference(firstDay, secondDay);
expect(difference).toBe(7);
});
......@@ -70,6 +78,7 @@ describe('Date time utils', () => {
const firstDay = new Date('07/01/2016');
const secondDay = new Date('08/01/2016');
const difference = datetimeUtility.getDayDifference(firstDay, secondDay);
expect(difference).toBe(31);
});
......@@ -77,6 +86,7 @@ describe('Date time utils', () => {
const firstDay = new Date('07/02/2015');
const secondDay = new Date('07/01/2016');
const difference = datetimeUtility.getDayDifference(firstDay, secondDay);
expect(difference).toBe(365);
});
});
......@@ -156,6 +166,7 @@ describe('getTimeframeWindowFrom', () => {
new Date(2018, 4, 31),
];
const timeframe = datetimeUtility.getTimeframeWindowFrom(startDate, 5);
expect(timeframe.length).toBe(5);
timeframe.forEach((timeframeItem, index) => {
expect(timeframeItem.getFullYear()).toBe(mockTimeframe[index].getFullYear());
......
......@@ -60,6 +60,7 @@ describe('Deploy keys app component', () => {
expect(textContent('.js-deployKeys-tab-available_project_keys')).toContain(
'Privately accessible deploy keys',
);
expect(textContent('.js-deployKeys-tab-public_keys')).toContain(
'Publicly accessible deploy keys',
);
......@@ -67,9 +68,11 @@ describe('Deploy keys app component', () => {
expect(textContent('.js-deployKeys-tab-enabled_keys .badge')).toBe(
`${vm.store.keys.enabled_keys.length}`,
);
expect(textContent('.js-deployKeys-tab-available_project_keys .badge')).toBe(
`${vm.store.keys.available_project_keys.length}`,
);
expect(textContent('.js-deployKeys-tab-public_keys .badge')).toBe(
`${vm.store.keys.public_keys.length}`,
);
......
......@@ -82,6 +82,7 @@ describe('Deploy keys key', () => {
it('shows expandable button if more than two projects', () => {
const labels = vm.$el.querySelectorAll('.deploy-project-label');
expect(labels.length).toBe(2);
expect(labels[1].textContent).toContain('others');
expect(labels[1].getAttribute('data-original-title')).toContain('Expand');
......@@ -93,6 +94,7 @@ describe('Deploy keys key', () => {
Vue.nextTick(() => {
const labels = vm.$el.querySelectorAll('.deploy-project-label');
expect(labels.length).toBe(length);
expect(labels[1].textContent).not.toContain(`+${length} others`);
expect(labels[1].getAttribute('data-original-title')).not.toContain('Expand');
......@@ -105,6 +107,7 @@ describe('Deploy keys key', () => {
Vue.nextTick(() => {
const labels = vm.$el.querySelectorAll('.deploy-project-label');
expect(labels.length).toBe(2);
expect(labels[1].textContent).toContain(
vm.deployKey.deploy_keys_projects[1].project.full_name,
......
......@@ -26,6 +26,7 @@ describe('New discussion', () => {
it('creates new discussion', () => {
expect(Object.keys(CommentsStore.state).length).toBe(0);
createDiscussion();
expect(Object.keys(CommentsStore.state).length).toBe(1);
});
......@@ -34,6 +35,7 @@ describe('New discussion', () => {
createDiscussion(2);
const discussion = CommentsStore.state['a'];
expect(Object.keys(discussion.notes).length).toBe(2);
});
});
......@@ -46,6 +48,7 @@ describe('Get note', () => {
it('gets note by ID', () => {
const note = CommentsStore.get('a', 1);
expect(note).toBeDefined();
expect(note.id).toBe(1);
});
......@@ -59,17 +62,20 @@ describe('Delete discussion', () => {
it('deletes discussion by ID', () => {
CommentsStore.delete('a', 1);
expect(Object.keys(CommentsStore.state).length).toBe(0);
});
it('deletes discussion when no more notes', () => {
createDiscussion();
createDiscussion(2);
expect(Object.keys(CommentsStore.state).length).toBe(1);
expect(Object.keys(CommentsStore.state['a'].notes).length).toBe(2);
CommentsStore.delete('a', 1);
CommentsStore.delete('a', 2);
expect(Object.keys(CommentsStore.state).length).toBe(0);
});
});
......@@ -84,6 +90,7 @@ describe('Update note', () => {
CommentsStore.update('a', 1, false, 'test');
const note = CommentsStore.get('a', 1);
expect(note.resolved).toBe(false);
});
});
......@@ -96,6 +103,7 @@ describe('Discussion resolved', () => {
it('is resolved with single note', () => {
const discussion = CommentsStore.state['a'];
expect(discussion.isResolved()).toBe(true);
});
......@@ -118,6 +126,7 @@ describe('Discussion resolved', () => {
createDiscussion(2, false);
discussion.resolveAllNotes();
expect(discussion.isResolved()).toBe(true);
});
......@@ -126,6 +135,7 @@ describe('Discussion resolved', () => {
createDiscussion(2);
discussion.unResolveAllNotes();
expect(discussion.isResolved()).toBe(false);
});
});
......@@ -98,6 +98,7 @@ describe('diff_file_header', () => {
props.discussionPath = 'link://to/discussion';
vm = mountComponentWithStore(Component, { props, store });
const href = vm.$el.querySelector('.js-title-wrapper').getAttribute('href');
expect(href).toBe(vm.discussionPath);
});
});
......@@ -270,6 +271,7 @@ describe('diff_file_header', () => {
it('displays an file icon in the title', () => {
vm = mountComponentWithStore(Component, { props, store });
expect(vm.$el.querySelector('svg.js-file-icon use').getAttribute('xlink:href')).toContain(
'ruby',
);
......@@ -312,6 +314,7 @@ describe('diff_file_header', () => {
vm = mountComponentWithStore(Component, { props, store });
const button = vm.$el.querySelector('.btn-clipboard');
expect(button).not.toBe(null);
expect(button.dataset.clipboardText).toBe('{"text":"files/ruby/popen.rb","gfm":"`files/ruby/popen.rb`"}');
});
......@@ -323,6 +326,7 @@ describe('diff_file_header', () => {
vm = mountComponentWithStore(Component, { props, store });
const { fileMode } = vm.$refs;
expect(fileMode).not.toBe(undefined);
expect(fileMode).toContainText(props.diffFile.aMode);
expect(fileMode).toContainText(props.diffFile.bMode);
......@@ -334,6 +338,7 @@ describe('diff_file_header', () => {
vm = mountComponentWithStore(Component, { props, store });
const { fileMode } = vm.$refs;
expect(fileMode).toBe(undefined);
});
});
......
......@@ -97,6 +97,7 @@ describe('DiffFile', () => {
expect(vm.$el.innerText).toContain(
'This source diff could not be displayed because it is too large',
);
expect(vm.$el.querySelector('.js-too-large-diff')).toBeDefined();
expect(vm.$el.querySelector('.js-too-large-diff a').href.indexOf(BLOB_LINK)).toBeGreaterThan(-1);
......
......@@ -23,6 +23,7 @@ describe('DiffGutterAvatars', () => {
it('should return false when all discussions are not expanded', () => {
component.discussions[0].expanded = false;
expect(component.discussionsExpanded).toEqual(false);
});
});
......@@ -56,6 +57,7 @@ describe('DiffGutterAvatars', () => {
it('should return empty string if there is no discussion', () => {
component.discussions = [];
expect(component.moreText).toEqual('');
});
});
......
......@@ -31,12 +31,14 @@ describe('DiffLineGutterContent', () => {
it('should prepend # to lineCode', () => {
const lineCode = 'LC_42';
const component = createComponent();
expect(component.lineHref).toEqual(`#${lineCode}`);
});
it('should return # if there is no lineCode', () => {
const component = createComponent();
component.line.lineCode = '';
expect(component.lineHref).toEqual('#');
});
});
......@@ -44,6 +46,7 @@ describe('DiffLineGutterContent', () => {
describe('discussions, hasDiscussions, shouldShowAvatarsOnGutter', () => {
it('should return empty array when there is no discussion', () => {
const component = createComponent();
expect(component.hasDiscussions).toEqual(false);
expect(component.shouldShowAvatarsOnGutter).toEqual(false);
});
......
......@@ -36,6 +36,7 @@ describe('DiffLineNoteForm', () => {
spyOn(window, 'confirm').and.returnValue(false);
component.handleCancelCommentForm(true, true);
expect(window.confirm).toHaveBeenCalled();
});
......@@ -43,9 +44,11 @@ describe('DiffLineNoteForm', () => {
spyOn(window, 'confirm').and.returnValue(false);
component.handleCancelCommentForm(true, false);
expect(window.confirm).not.toHaveBeenCalled();
component.handleCancelCommentForm(false, true);
expect(window.confirm).not.toHaveBeenCalled();
});
......@@ -60,6 +63,7 @@ describe('DiffLineNoteForm', () => {
expect(component.cancelCommentForm).toHaveBeenCalledWith({
lineCode: diffLines[0].lineCode,
});
expect(component.resetAutoSave).toHaveBeenCalled();
done();
......
......@@ -52,11 +52,13 @@ describe('Diffs Module Getters', () => {
describe('areAllFilesCollapsed', () => {
it('returns true when all files are collapsed', () => {
localState.diffFiles = [{ collapsed: true }, { collapsed: true }];
expect(getters.areAllFilesCollapsed(localState)).toEqual(true);
});
it('returns false when at least one file is not collapsed', () => {
localState.diffFiles = [{ collapsed: false }, { collapsed: true }];
expect(getters.areAllFilesCollapsed(localState)).toEqual(false);
});
});
......@@ -244,6 +246,7 @@ describe('Diffs Module Getters', () => {
it('returns false when no line discussions were found', () => {
line.discussions = [];
expect(getters.shouldRenderInlineCommentRow(localState)(line)).toEqual(false);
});
......@@ -288,6 +291,7 @@ describe('Diffs Module Getters', () => {
it('returns null if no matching file is found', () => {
localState.diffFiles = [];
expect(getters.getDiffFileByHash(localState)('123')).toBeUndefined();
});
});
......
......@@ -12,6 +12,7 @@ describe('DiffsStoreMutations', () => {
const projectPath = '/root/project';
mutations[types.SET_BASE_CONFIG](state, { endpoint, projectPath });
expect(state.endpoint).toEqual(endpoint);
expect(state.projectPath).toEqual(projectPath);
});
......@@ -22,6 +23,7 @@ describe('DiffsStoreMutations', () => {
const state = {};
mutations[types.SET_LOADING](state, false);
expect(state.isLoading).toEqual(false);
});
});
......@@ -48,6 +50,7 @@ describe('DiffsStoreMutations', () => {
const state = {};
mutations[types.SET_DIFF_VIEW_TYPE](state, INLINE_DIFF_VIEW_TYPE);
expect(state.diffViewType).toEqual(INLINE_DIFF_VIEW_TYPE);
});
});
......@@ -58,6 +61,7 @@ describe('DiffsStoreMutations', () => {
const lineCode = 'FDE';
mutations[types.ADD_COMMENT_FORM_LINE](state, { lineCode });
expect(state.diffLineCommentForms[lineCode]).toBeTruthy();
});
});
......@@ -68,9 +72,11 @@ describe('DiffsStoreMutations', () => {
const lineCode = 'FDE';
mutations[types.ADD_COMMENT_FORM_LINE](state, { lineCode });
expect(state.diffLineCommentForms[lineCode]).toBeTruthy();
mutations[types.REMOVE_COMMENT_FORM_LINE](state, { lineCode });
expect(state.diffLineCommentForms[lineCode]).toBeUndefined();
});
});
......@@ -83,6 +89,7 @@ describe('DiffsStoreMutations', () => {
const state = { expandAllFiles: true, diffFiles: [diffFile] };
mutations[types.EXPAND_ALL_FILES](state);
expect(state.diffFiles[0].collapsed).toEqual(false);
});
});
......@@ -118,11 +125,13 @@ describe('DiffsStoreMutations', () => {
options.lineNumbers,
options.params.bottom,
);
expect(lineRefSpy).toHaveBeenCalledWith(
options.contextLines,
options.lineNumbers,
options.params.bottom,
);
expect(addContextLinesSpy).toHaveBeenCalledWith({
inlineLines: diffFile.highlightedDiffLines,
parallelLines: diffFile.parallelDiffLines,
......@@ -142,6 +151,7 @@ describe('DiffsStoreMutations', () => {
const data = { diff_files: [{ file_hash: fileHash, extra_field: 1, existingField: 1 }] };
mutations[types.ADD_COLLAPSED_DIFFS](state, { file: state.diffFiles[1], data });
expect(spy).toHaveBeenCalledWith(data, { deep: true });
expect(state.diffFiles[1].fileHash).toEqual(fileHash);
......@@ -345,6 +355,7 @@ describe('DiffsStoreMutations', () => {
fileHash: 'ABC',
lineCode: 'ABC_1',
});
expect(state.diffFiles[0].parallelDiffLines[0].left.discussions.length).toEqual(0);
expect(state.diffFiles[0].highlightedDiffLines[0].discussions.length).toEqual(0);
});
......
......@@ -62,10 +62,12 @@ describe('DiffsStoreUtils', () => {
const atParallelIndex = diffFile.parallelDiffLines[parallelIndex];
utils.removeMatchLine(diffFile, lineNumbers, false);
expect(diffFile.highlightedDiffLines[inlineIndex]).not.toEqual(atInlineIndex);
expect(diffFile.parallelDiffLines[parallelIndex]).not.toEqual(atParallelIndex);
utils.removeMatchLine(diffFile, lineNumbers, true);
expect(diffFile.highlightedDiffLines[inlineIndex + 1]).not.toEqual(atInlineIndex);
expect(diffFile.parallelDiffLines[parallelIndex + 1]).not.toEqual(atParallelIndex);
});
......@@ -87,11 +89,13 @@ describe('DiffsStoreUtils', () => {
};
utils.addContextLines(options);
expect(inlineLines[inlineLines.length - 1]).toEqual(contextLines[0]);
expect(parallelLines[parallelLines.length - 1]).toEqual(normalizedParallelLine);
delete options.bottom;
utils.addContextLines(options);
expect(inlineLines[inlineIndex]).toEqual(contextLines[0]);
expect(parallelLines[parallelIndex]).toEqual(normalizedParallelLine);
});
......@@ -274,6 +278,7 @@ describe('DiffsStoreUtils', () => {
};
utils.trimFirstCharOfLineContent(lineObj);
expect(lineObj).toEqual({ discussions: [], richText: ' diff' });
});
......@@ -288,19 +293,23 @@ describe('DiffsStoreUtils', () => {
utils.prepareDiffData(preparedDiff);
const firstParallelDiffLine = preparedDiff.diffFiles[0].parallelDiffLines[2];
expect(firstParallelDiffLine.left.discussions.length).toBe(0);
expect(firstParallelDiffLine.left).not.toHaveAttr('text');
expect(firstParallelDiffLine.right.discussions.length).toBe(0);
expect(firstParallelDiffLine.right).not.toHaveAttr('text');
const firstParallelChar = firstParallelDiffLine.right.richText.charAt(0);
expect(firstParallelChar).not.toBe(' ');
expect(firstParallelChar).not.toBe('+');
expect(firstParallelChar).not.toBe('-');
const checkLine = preparedDiff.diffFiles[0].highlightedDiffLines[0];
expect(checkLine.discussions.length).toBe(0);
expect(checkLine).not.toHaveAttr('text');
const firstChar = checkLine.richText.charAt(0);
expect(firstChar).not.toBe(' ');
expect(firstChar).not.toBe('+');
expect(firstChar).not.toBe('-');
......
......@@ -15,9 +15,13 @@ describe('DirtySubmitCollection', () => {
expect(submit.disabled).toBe(true);
return setInput(input, `${originalValue} changes`)
.then(() => expect(submit.disabled).toBe(false))
.then(() => {
expect(submit.disabled).toBe(false);
})
.then(() => setInput(input, originalValue))
.then(() => expect(submit.disabled).toBe(true))
.then(() => {
expect(submit.disabled).toBe(true);
})
.then(done)
.catch(done.fail);
});
......
......@@ -12,9 +12,13 @@ describe('DirtySubmitForm', () => {
expect(submit.disabled).toBe(true);
return setInput(input, `${originalValue} changes`)
.then(() => expect(submit.disabled).toBe(false))
.then(() => {
expect(submit.disabled).toBe(false);
})
.then(() => setInput(input, originalValue))
.then(() => expect(submit.disabled).toBe(true))
.then(() => {
expect(submit.disabled).toBe(true);
})
.then(done)
.catch(done.fail);
});
......
......@@ -8,6 +8,7 @@ describe('Ajax', () => {
describe('is not configured', () => {
it('passes the data through', () => {
const data = ['data'];
expect(Ajax.preprocessing(config, data)).toEqual(data);
});
});
......@@ -22,13 +23,17 @@ describe('Ajax', () => {
it('calls preprocessing', () => {
Ajax.preprocessing(config, []);
expect(config.preprocessing.calls.count()).toBe(1);
});
it('overrides AjaxCache', () => {
spyOn(AjaxCache, 'override').and.callFake((endpoint, results) => expect(results).toEqual(processedArray));
spyOn(AjaxCache, 'override').and.callFake((endpoint, results) => {
expect(results).toEqual(processedArray);
});
Ajax.preprocessing(config, []);
expect(AjaxCache.override.calls.count()).toBe(1);
});
});
......
......@@ -375,6 +375,7 @@ describe('gl_emoji', () => {
'',
'1.0',
);
expect(isSupported).toBeTruthy();
});
......@@ -384,6 +385,7 @@ describe('gl_emoji', () => {
'',
'1.0',
);
expect(isSupported).toBeFalsy();
});
......@@ -397,6 +399,7 @@ describe('gl_emoji', () => {
emojiFixtureMap[emojiKey].moji,
emojiFixtureMap[emojiKey].unicodeVersion,
);
expect(isSupported).toBeTruthy();
});
......@@ -408,6 +411,7 @@ describe('gl_emoji', () => {
emojiFixtureMap[emojiKey].moji,
emojiFixtureMap[emojiKey].unicodeVersion,
);
expect(isSupported).toBeFalsy();
});
......@@ -421,6 +425,7 @@ describe('gl_emoji', () => {
emojiFixtureMap[emojiKey].moji,
emojiFixtureMap[emojiKey].unicodeVersion,
);
expect(isSupported).toBeFalsy();
});
......@@ -446,6 +451,7 @@ describe('gl_emoji', () => {
emojiFixtureMap[emojiKey].moji,
emojiFixtureMap[emojiKey].unicodeVersion,
);
expect(isSupported).toBeFalsy();
});
......@@ -463,6 +469,7 @@ describe('gl_emoji', () => {
emojiFixtureMap[emojiKey].moji,
emojiFixtureMap[emojiKey].unicodeVersion,
);
expect(isSupported).toBeTruthy();
});
......@@ -480,6 +487,7 @@ describe('gl_emoji', () => {
emojiFixtureMap[emojiKey].moji,
emojiFixtureMap[emojiKey].unicodeVersion,
);
expect(isSupported).toBeFalsy();
});
});
......
......@@ -94,6 +94,7 @@ describe('Environment', () => {
spyOn(component, 'updateContent');
setTimeout(() => {
component.$el.querySelector('.gl-pagination li:nth-child(5) a').click();
expect(component.updateContent).toHaveBeenCalledWith({ scope: 'available', page: '2' });
done();
}, 0);
......
......@@ -17,23 +17,27 @@ describe('Store', () => {
it('should store environments', () => {
store.storeEnvironments(serverData);
expect(store.state.environments.length).toEqual(serverData.length);
expect(store.state.environments[0]).toEqual(environmentsList[0]);
});
it('should store available count', () => {
store.storeAvailableCount(2);
expect(store.state.availableCounter).toEqual(2);
});
it('should store stopped count', () => {
store.storeStoppedCount(2);
expect(store.state.stoppedCounter).toEqual(2);
});
describe('store environments', () => {
it('should store environments', () => {
store.storeEnvironments(serverData);
expect(store.state.environments.length).toEqual(serverData.length);
});
......@@ -45,6 +49,7 @@ describe('Store', () => {
};
store.storeEnvironments([environment]);
expect(store.state.environments[0].isFolder).toEqual(true);
expect(store.state.environments[0].folderName).toEqual('bar');
});
......@@ -61,17 +66,20 @@ describe('Store', () => {
};
store.storeEnvironments([environment]);
expect(store.state.environments[0].last_deployment).toEqual({});
expect(store.state.environments[0].isStoppable).toEqual(true);
});
it('should store latest.name when the environment is not a folder', () => {
store.storeEnvironments(serverData);
expect(store.state.environments[0].name).toEqual(serverData[0].latest.name);
});
it('should store root level name when environment is a folder', () => {
store.storeEnvironments(serverData);
expect(store.state.environments[1].folderName).toEqual(serverData[1].name);
});
});
......@@ -81,9 +89,11 @@ describe('Store', () => {
store.storeEnvironments(serverData);
store.toggleFolder(store.state.environments[1]);
expect(store.state.environments[1].isOpen).toEqual(true);
store.toggleFolder(store.state.environments[1]);
expect(store.state.environments[1].isOpen).toEqual(false);
});
......@@ -91,9 +101,11 @@ describe('Store', () => {
store.storeEnvironments(serverData);
store.toggleFolder(store.state.environments[1]);
expect(store.state.environments[1].isOpen).toEqual(true);
store.storeEnvironments(serverData);
expect(store.state.environments[1].isOpen).toEqual(true);
});
});
......@@ -116,6 +128,7 @@ describe('Store', () => {
expect(store.state.environments[1].children.length).toEqual(serverData.length);
// poll
store.storeEnvironments(serverData);
expect(store.state.environments[1].children.length).toEqual(serverData.length);
});
});
......@@ -141,6 +154,7 @@ describe('Store', () => {
};
store.setPagination(pagination);
expect(store.state.paginationInformation).toEqual(expectedResult);
});
});
......@@ -150,6 +164,7 @@ describe('Store', () => {
store.storeEnvironments(serverData);
store.toggleFolder(store.state.environments[1]);
expect(store.getOpenFolders()[0]).toEqual(store.state.environments[1]);
});
});
......
......@@ -14,6 +14,7 @@ describe('feature highlight helper', () => {
describe('getSelector', () => {
it('returns js-feature-highlight selector', () => {
const highlightId = 'highlightId';
expect(getSelector(highlightId)).toEqual(`.js-feature-highlight[data-highlight=${highlightId}]`);
});
});
......
......@@ -63,6 +63,7 @@ describe('feature highlight', () => {
it('setup show.bs.popover', () => {
$(selector).trigger('show.bs.popover');
expect(window.addEventListener).toHaveBeenCalledWith('scroll', jasmine.any(Function), { once: true });
});
......@@ -73,6 +74,7 @@ describe('feature highlight', () => {
it('displays popover', () => {
expect(document.querySelector(selector).getAttribute('aria-describedby')).toBeFalsy();
$(selector).trigger('mouseenter');
expect(document.querySelector(selector).getAttribute('aria-describedby')).toBeTruthy();
});
......
......@@ -47,6 +47,7 @@ describe('RecentSearchesDropdownContent', () => {
expect(el.querySelector('.dropdown-info-note')).toBeDefined();
const items = el.querySelectorAll('.filtered-search-history-dropdown-item');
expect(items.length).toEqual(propsDataWithoutItems.items.length);
});
});
......@@ -65,11 +66,13 @@ describe('RecentSearchesDropdownContent', () => {
it('should render recent search items', () => {
const items = el.querySelectorAll('.filtered-search-history-dropdown-item');
expect(items.length).toEqual(propsDataWithItems.items.length);
expect(trimMarkupWhitespace(items[0].querySelector('.filtered-search-history-dropdown-search-token').textContent)).toEqual('foo');
const item1Tokens = items[1].querySelectorAll('.filtered-search-history-dropdown-token');
expect(item1Tokens.length).toEqual(2);
expect(item1Tokens[0].querySelector('.name').textContent).toEqual('author:');
expect(item1Tokens[0].querySelector('.value').textContent).toEqual('@root');
......@@ -132,12 +135,14 @@ describe('RecentSearchesDropdownContent', () => {
it('with items', () => {
vm = createComponent(propsDataWithItems);
const { hasItems } = vm;
expect(hasItems).toEqual(true);
});
it('with no items', () => {
vm = createComponent(propsDataWithoutItems);
const { hasItems } = vm;
expect(hasItems).toEqual(false);
});
});
......@@ -161,6 +166,7 @@ describe('RecentSearchesDropdownContent', () => {
it('emits event', () => {
expect(onRecentSearchesItemSelectedSpy).not.toHaveBeenCalled();
vm.onItemActivated('something');
expect(onRecentSearchesItemSelectedSpy).toHaveBeenCalledWith('something');
});
});
......@@ -182,6 +188,7 @@ describe('RecentSearchesDropdownContent', () => {
it('emits event', () => {
expect(onRequestClearRecentSearchesSpy).not.toHaveBeenCalled();
vm.onRequestClearRecentSearches({ stopPropagation: () => {} });
expect(onRequestClearRecentSearchesSpy).toHaveBeenCalled();
});
});
......
......@@ -92,6 +92,7 @@ describe('Dropdown User', () => {
it('hides the current user from dropdown', () => {
const currentUserElement = findCurrentUserElement();
expect(currentUserElement).not.toBe(null);
dropdown.hideCurrentUser();
......@@ -102,6 +103,7 @@ describe('Dropdown User', () => {
it('does nothing if no user is logged in', () => {
const currentUserElement = findCurrentUserElement();
currentUserElement.parentNode.removeChild(currentUserElement);
expect(findCurrentUserElement()).toBe(null);
dropdown.hideCurrentUser();
......
......@@ -10,24 +10,29 @@ describe('Dropdown Utils', () => {
describe('getEscapedText', () => {
it('should return same word when it has no space', () => {
const escaped = DropdownUtils.getEscapedText('textWithoutSpace');
expect(escaped).toBe('textWithoutSpace');
});
it('should escape with double quotes', () => {
let escaped = DropdownUtils.getEscapedText('text with space');
expect(escaped).toBe('"text with space"');
escaped = DropdownUtils.getEscapedText('won\'t fix');
expect(escaped).toBe('"won\'t fix"');
});
it('should escape with single quotes', () => {
const escaped = DropdownUtils.getEscapedText('won"t fix');
expect(escaped).toBe('\'won"t fix\'');
});
it('should escape with single quotes by default', () => {
const escaped = DropdownUtils.getEscapedText('won"t\' fix');
expect(escaped).toBe('\'won"t\' fix\'');
});
});
......@@ -50,6 +55,7 @@ describe('Dropdown Utils', () => {
input.value = 'roo';
const updatedItem = DropdownUtils.filterWithSymbol('@', input, item);
expect(updatedItem.droplab_hidden).toBe(false);
});
......@@ -57,6 +63,7 @@ describe('Dropdown Utils', () => {
input.value = '@roo';
const updatedItem = DropdownUtils.filterWithSymbol('@', input, item);
expect(updatedItem.droplab_hidden).toBe(false);
});
......@@ -69,6 +76,7 @@ describe('Dropdown Utils', () => {
input.value = '"';
const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
expect(updatedItem.droplab_hidden).toBe(false);
});
......@@ -76,6 +84,7 @@ describe('Dropdown Utils', () => {
input.value = '~"';
const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
expect(updatedItem.droplab_hidden).toBe(false);
});
......@@ -83,6 +92,7 @@ describe('Dropdown Utils', () => {
input.value = '"community con';
const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
expect(updatedItem.droplab_hidden).toBe(false);
});
......@@ -90,6 +100,7 @@ describe('Dropdown Utils', () => {
input.value = '~"community con';
const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
expect(updatedItem.droplab_hidden).toBe(false);
});
......@@ -97,6 +108,7 @@ describe('Dropdown Utils', () => {
input.value = '\'';
const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
expect(updatedItem.droplab_hidden).toBe(false);
});
......@@ -104,6 +116,7 @@ describe('Dropdown Utils', () => {
input.value = '~\'';
const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
expect(updatedItem.droplab_hidden).toBe(false);
});
......@@ -111,6 +124,7 @@ describe('Dropdown Utils', () => {
input.value = '\'community con';
const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
expect(updatedItem.droplab_hidden).toBe(false);
});
......@@ -118,6 +132,7 @@ describe('Dropdown Utils', () => {
input.value = '~\'community con';
const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
expect(updatedItem.droplab_hidden).toBe(false);
});
});
......@@ -152,17 +167,20 @@ describe('Dropdown Utils', () => {
let updatedItem = DropdownUtils.filterHint(config(), {
hint: 'label',
});
expect(updatedItem.droplab_hidden).toBe(false);
input.value = 'o';
updatedItem = DropdownUtils.filterHint(config(), {
hint: 'label',
});
expect(updatedItem.droplab_hidden).toBe(true);
});
it('should return droplab_hidden false when item has no hint', () => {
const updatedItem = DropdownUtils.filterHint(config(), {}, '');
expect(updatedItem.droplab_hidden).toBe(false);
});
......@@ -172,6 +190,7 @@ describe('Dropdown Utils', () => {
hint: 'label',
type: 'array',
});
expect(updatedItem.droplab_hidden).toBe(false);
});
......@@ -180,12 +199,14 @@ describe('Dropdown Utils', () => {
let updatedItem = DropdownUtils.filterHint(config(), {
hint: 'milestone',
});
expect(updatedItem.droplab_hidden).toBe(true);
updatedItem = DropdownUtils.filterHint(config(), {
hint: 'milestone',
type: 'string',
});
expect(updatedItem.droplab_hidden).toBe(true);
});
});
......@@ -205,6 +226,7 @@ describe('Dropdown Utils', () => {
};
const updated = DropdownUtils.mergeDuplicateLabels(dataMap, newLabel);
expect(updated[newLabel.title]).toEqual(newLabel);
});
......@@ -215,6 +237,7 @@ describe('Dropdown Utils', () => {
};
const updated = DropdownUtils.mergeDuplicateLabels(dataMap, duplicate);
expect(updated.label.multipleColors).toEqual([dataMap.label.color, duplicate.color]);
});
});
......@@ -222,21 +245,25 @@ describe('Dropdown Utils', () => {
describe('duplicateLabelColor', () => {
it('should linear-gradient 2 colors', () => {
const gradient = DropdownUtils.duplicateLabelColor(['#FFFFFF', '#000000']);
expect(gradient).toEqual('linear-gradient(#FFFFFF 0%, #FFFFFF 50%, #000000 50%, #000000 100%)');
});
it('should linear-gradient 3 colors', () => {
const gradient = DropdownUtils.duplicateLabelColor(['#FFFFFF', '#000000', '#333333']);
expect(gradient).toEqual('linear-gradient(#FFFFFF 0%, #FFFFFF 33%, #000000 33%, #000000 66%, #333333 66%, #333333 100%)');
});
it('should linear-gradient 4 colors', () => {
const gradient = DropdownUtils.duplicateLabelColor(['#FFFFFF', '#000000', '#333333', '#DDDDDD']);
expect(gradient).toEqual('linear-gradient(#FFFFFF 0%, #FFFFFF 25%, #000000 25%, #000000 50%, #333333 50%, #333333 75%, #DDDDDD 75%, #DDDDDD 100%)');
});
it('should not linear-gradient more than 4 colors', () => {
const gradient = DropdownUtils.duplicateLabelColor(['#FFFFFF', '#000000', '#333333', '#DDDDDD', '#EEEEEE']);
expect(gradient.indexOf('#EEEEEE')).toBe(-1);
});
});
......@@ -244,6 +271,7 @@ describe('Dropdown Utils', () => {
describe('duplicateLabelPreprocessing', () => {
it('should set preprocessed to true', () => {
const results = DropdownUtils.duplicateLabelPreprocessing([]);
expect(results.preprocessed).toEqual(true);
});
......@@ -298,6 +326,7 @@ describe('Dropdown Utils', () => {
};
DropdownUtils.setDataValueIfSelected(null, selected);
expect(FilteredSearchDropdownManager.addWordToInput.calls.count()).toEqual(1);
});
......@@ -308,6 +337,7 @@ describe('Dropdown Utils', () => {
};
const result = DropdownUtils.setDataValueIfSelected(null, selected);
expect(result).toBe(true);
});
......@@ -317,6 +347,7 @@ describe('Dropdown Utils', () => {
};
const result = DropdownUtils.setDataValueIfSelected(null, selected);
expect(result).toBe(false);
});
});
......
......@@ -134,6 +134,7 @@ describe('Filtered Search Manager', function () {
};
manager.searchState(e);
expect(FilteredSearchManager.prototype.search).not.toHaveBeenCalled();
});
......@@ -149,6 +150,7 @@ describe('Filtered Search Manager', function () {
};
manager.searchState(e);
expect(FilteredSearchManager.prototype.search).toHaveBeenCalledWith('opened');
});
});
......@@ -304,6 +306,7 @@ describe('Filtered Search Manager', function () {
);
tokensContainer.querySelector('.js-visual-token .remove-token').click();
expect(tokensContainer.querySelector('.js-visual-token')).toEqual(null);
});
......@@ -437,11 +440,13 @@ describe('Filtered Search Manager', function () {
it('toggles on focus', () => {
input.focus();
expect(document.querySelector('.filtered-search-box').classList.contains('focus')).toEqual(true);
});
it('toggles on blur', () => {
input.blur();
expect(document.querySelector('.filtered-search-box').classList.contains('focus')).toEqual(false);
});
});
......
......@@ -51,11 +51,13 @@ describe('Filtered Search Token Keys', () => {
describe('searchByKey', () => {
it('should return null when key not found', () => {
const tokenKey = new FilteredSearchTokenKeys(tokenKeys).searchByKey('notakey');
expect(tokenKey).toBeNull();
});
it('should return tokenKey when found by key', () => {
const result = new FilteredSearchTokenKeys(tokenKeys).searchByKey(tokenKeys[0].key);
expect(result).toEqual(tokenKeys[0]);
});
});
......@@ -63,11 +65,13 @@ describe('Filtered Search Token Keys', () => {
describe('searchBySymbol', () => {
it('should return null when symbol not found', () => {
const tokenKey = new FilteredSearchTokenKeys(tokenKeys).searchBySymbol('notasymbol');
expect(tokenKey).toBeNull();
});
it('should return tokenKey when found by symbol', () => {
const result = new FilteredSearchTokenKeys(tokenKeys).searchBySymbol(tokenKeys[0].symbol);
expect(result).toEqual(tokenKeys[0]);
});
});
......@@ -75,16 +79,19 @@ describe('Filtered Search Token Keys', () => {
describe('searchByKeyParam', () => {
it('should return null when key param not found', () => {
const tokenKey = new FilteredSearchTokenKeys(tokenKeys).searchByKeyParam('notakeyparam');
expect(tokenKey).toBeNull();
});
it('should return tokenKey when found by key param', () => {
const result = new FilteredSearchTokenKeys(tokenKeys).searchByKeyParam(`${tokenKeys[0].key}_${tokenKeys[0].param}`);
expect(result).toEqual(tokenKeys[0]);
});
it('should return alternative tokenKey when found by key param', () => {
const result = new FilteredSearchTokenKeys(tokenKeys).searchByKeyParam(`${tokenKeys[0].key}_${tokenKeys[0].param}`);
expect(result).toEqual(tokenKeys[0]);
});
});
......@@ -92,12 +99,14 @@ describe('Filtered Search Token Keys', () => {
describe('searchByConditionUrl', () => {
it('should return null when condition url not found', () => {
const condition = new FilteredSearchTokenKeys([], [], conditions).searchByConditionUrl(null);
expect(condition).toBeNull();
});
it('should return condition when found by url', () => {
const result = new FilteredSearchTokenKeys([], [], conditions)
.searchByConditionUrl(conditions[0].url);
expect(result).toBe(conditions[0]);
});
});
......@@ -106,12 +115,14 @@ describe('Filtered Search Token Keys', () => {
it('should return null when condition tokenKey and value not found', () => {
const condition = new FilteredSearchTokenKeys([], [], conditions)
.searchByConditionKeyValue(null, null);
expect(condition).toBeNull();
});
it('should return condition when found by tokenKey and value', () => {
const result = new FilteredSearchTokenKeys([], [], conditions)
.searchByConditionKeyValue(conditions[0].tokenKey, conditions[0].value);
expect(result).toEqual(conditions[0]);
});
});
......
......@@ -7,6 +7,7 @@ describe('Filtered Search Tokenizer', () => {
describe('processTokens', () => {
it('returns for input containing only search value', () => {
const results = FilteredSearchTokenizer.processTokens('searchTerm', allowedKeys);
expect(results.searchToken).toBe('searchTerm');
expect(results.tokens.length).toBe(0);
expect(results.lastToken).toBe(results.searchToken);
......@@ -15,6 +16,7 @@ describe('Filtered Search Tokenizer', () => {
it('returns for input containing only tokens', () => {
const results = FilteredSearchTokenizer
.processTokens('author:@root label:~"Very Important" milestone:%v1.0 assignee:none', allowedKeys);
expect(results.searchToken).toBe('');
expect(results.tokens.length).toBe(4);
expect(results.tokens[3]).toBe(results.lastToken);
......@@ -39,6 +41,7 @@ describe('Filtered Search Tokenizer', () => {
it('returns for input starting with search value and ending with tokens', () => {
const results = FilteredSearchTokenizer
.processTokens('searchTerm anotherSearchTerm milestone:none', allowedKeys);
expect(results.searchToken).toBe('searchTerm anotherSearchTerm');
expect(results.tokens.length).toBe(1);
expect(results.tokens[0]).toBe(results.lastToken);
......@@ -83,6 +86,7 @@ describe('Filtered Search Tokenizer', () => {
it('returns for input containing search value in between tokens', () => {
const results = FilteredSearchTokenizer
.processTokens('author:@root searchTerm assignee:none anotherSearchTerm label:~Doing', allowedKeys);
expect(results.searchToken).toBe('searchTerm anotherSearchTerm');
expect(results.tokens.length).toBe(3);
expect(results.tokens[2]).toBe(results.lastToken);
......@@ -102,6 +106,7 @@ describe('Filtered Search Tokenizer', () => {
it('returns search value for invalid tokens', () => {
const results = FilteredSearchTokenizer.processTokens('fake:token', allowedKeys);
expect(results.lastToken).toBe('fake:token');
expect(results.searchToken).toBe('fake:token');
expect(results.tokens.length).toEqual(0);
......@@ -109,6 +114,7 @@ describe('Filtered Search Tokenizer', () => {
it('returns search value and token for mix of valid and invalid tokens', () => {
const results = FilteredSearchTokenizer.processTokens('label:real fake:token', allowedKeys);
expect(results.tokens.length).toEqual(1);
expect(results.tokens[0].key).toBe('label');
expect(results.tokens[0].value).toBe('real');
......@@ -119,12 +125,14 @@ describe('Filtered Search Tokenizer', () => {
it('returns search value for invalid symbols', () => {
const results = FilteredSearchTokenizer.processTokens('std::includes', allowedKeys);
expect(results.lastToken).toBe('std::includes');
expect(results.searchToken).toBe('std::includes');
});
it('removes duplicated values', () => {
const results = FilteredSearchTokenizer.processTokens('label:~foo label:~foo', allowedKeys);
expect(results.tokens.length).toBe(1);
expect(results.tokens[0].key).toBe('label');
expect(results.tokens[0].value).toBe('foo');
......
......@@ -131,6 +131,7 @@ describe('Filtered Search Visual Tokens', () => {
describe('getEndpointWithQueryParams', () => {
it('returns `endpoint` string as is when second param `endpointQueryParams` is undefined, null or empty string', () => {
const endpoint = 'foo/bar/labels.json';
expect(subject.getEndpointWithQueryParams(endpoint)).toBe(endpoint);
expect(subject.getEndpointWithQueryParams(endpoint, null)).toBe(endpoint);
expect(subject.getEndpointWithQueryParams(endpoint, '')).toBe(endpoint);
......@@ -161,6 +162,7 @@ describe('Filtered Search Visual Tokens', () => {
`);
const selected = tokensContainer.querySelector('.js-visual-token .selected');
expect(selected.classList.contains('selected')).toEqual(true);
subject.unselectTokens();
......@@ -675,6 +677,7 @@ describe('Filtered Search Visual Tokens', () => {
subject.moveInputToTheRight();
const token = tokensContainer.children[1];
expect(token.querySelector('.value').innerText).toEqual('~bug');
});
});
......@@ -712,6 +715,7 @@ describe('Filtered Search Visual Tokens', () => {
expect(tokenValueElement.innerText).toBe(tokenValue);
expect(updateUserTokenAppearanceSpy.calls.count()).toBe(1);
const expectedArgs = [tokenValueContainer, tokenValueElement, tokenValue];
expect(updateUserTokenAppearanceSpy.calls.argsFor(0)).toEqual(expectedArgs);
expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
});
......@@ -727,6 +731,7 @@ describe('Filtered Search Visual Tokens', () => {
expect(tokenValueElement.innerText).toBe(tokenValue);
expect(updateLabelTokenColorSpy.calls.count()).toBe(1);
const expectedArgs = [tokenValueContainer, tokenValue];
expect(updateLabelTokenColorSpy.calls.argsFor(0)).toEqual(expectedArgs);
expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
});
......@@ -814,6 +819,7 @@ describe('Filtered Search Visual Tokens', () => {
expect(tokenValueContainer.dataset.originalValue).toBe(tokenValue);
expect(tokenValueElement.innerText.trim()).toBe(dummyUser.name);
const avatar = tokenValueElement.querySelector('img.avatar');
expect(avatar.src).toBe(dummyUser.avatar_url);
expect(avatar.alt).toBe('');
})
......@@ -837,6 +843,7 @@ describe('Filtered Search Visual Tokens', () => {
.then(() => {
expect(tokenValueElement.innerText.trim()).toBe(dummyUser.name);
tokenValueElement.querySelector('.avatar').remove();
expect(tokenValueElement.innerHTML.trim()).toBe(_.escape(dummyUser.name));
})
.then(done)
......@@ -854,23 +861,27 @@ describe('Filtered Search Visual Tokens', () => {
it('should set backgroundColor', () => {
const originalBackgroundColor = bugLabelToken.style.backgroundColor;
const token = subject.setTokenStyle(bugLabelToken, 'blue', 'white');
expect(token.style.backgroundColor).toEqual('blue');
expect(token.style.backgroundColor).not.toEqual(originalBackgroundColor);
});
it('should not set backgroundColor when it is a linear-gradient', () => {
const token = subject.setTokenStyle(bugLabelToken, 'linear-gradient(135deg, red, blue)', 'white');
expect(token.style.backgroundColor).toEqual(bugLabelToken.style.backgroundColor);
});
it('should set textColor', () => {
const token = subject.setTokenStyle(bugLabelToken, 'white', 'black');
expect(token.style.color).toEqual('black');
expect(token.style.color).not.toEqual(originalTextColor);
});
it('should add inverted class when textColor is #FFFFFF', () => {
const token = subject.setTokenStyle(bugLabelToken, 'black', '#FFFFFF');
expect(token.style.color).toEqual('rgb(255, 255, 255)');
expect(token.style.color).not.toEqual(originalTextColor);
expect(token.querySelector('.remove-token').classList.contains('inverted')).toEqual(true);
......@@ -894,14 +905,17 @@ describe('Filtered Search Visual Tokens', () => {
describe('not preprocessed before', () => {
it('returns preprocessed labels', () => {
let labels = [];
expect(labels.preprocessed).not.toEqual(true);
labels = FilteredSearchVisualTokens.preprocessLabel(endpoint, labels);
expect(labels.preprocessed).toEqual(true);
});
it('overrides AjaxCache with preprocessed results', () => {
spyOn(AjaxCache, 'override').and.callFake(() => {});
FilteredSearchVisualTokens.preprocessLabel(endpoint, []);
expect(AjaxCache.override.calls.count()).toEqual(1);
});
});
......@@ -982,6 +996,7 @@ describe('Filtered Search Visual Tokens', () => {
const { tokenValueContainer, tokenValueElement } = findElements(missingLabelToken);
const tokenValue = tokenValueElement.innerText;
const matchingLabel = findLabel(tokenValue);
expect(matchingLabel).toBe(undefined);
subject.updateLabelTokenColor(tokenValueContainer, tokenValue)
......
......@@ -92,6 +92,7 @@ describe('RecentSearchesService', () => {
const items = ['foo', 'bar'];
service.save(items);
const newLocalStorageValue = window.localStorage.getItem(service.localStorageKey);
expect(JSON.parse(newLocalStorageValue)).toEqual(items);
});
});
......
......@@ -39,6 +39,7 @@ describe('Flash', () => {
expect(
el.querySelector('.flash-text').classList.contains('container-fluid'),
).toBeTruthy();
expect(
el.querySelector('.flash-text').classList.contains('container-limited'),
).toBeTruthy();
......@@ -59,6 +60,7 @@ describe('Flash', () => {
expect(
el.style['transition-property'],
).toBe('opacity');
expect(
el.style['transition-duration'],
).toBe('0.3s');
......@@ -78,6 +80,7 @@ describe('Flash', () => {
expect(
el.style.opacity,
).toBe('');
expect(
el.style.transition,
).toBe('');
......@@ -166,6 +169,7 @@ describe('Flash', () => {
expect(
flashEl,
).toBeNull();
expect(
document.querySelector('.flash-alert'),
).toBeNull();
......
......@@ -30,9 +30,11 @@ describe('FrequentItemsListItemComponent', () => {
describe('hasAvatar', () => {
it('should return `true` or `false` if whether avatar is present or not', () => {
vm.avatarUrl = 'path/to/avatar.png';
expect(vm.hasAvatar).toBe(true);
vm.avatarUrl = null;
expect(vm.hasAvatar).toBe(false);
});
});
......@@ -40,11 +42,13 @@ describe('FrequentItemsListItemComponent', () => {
describe('highlightedItemName', () => {
it('should enclose part of project name in <b> & </b> which matches with `matcher` prop', () => {
vm.matcher = 'lab';
expect(vm.highlightedItemName).toContain('<b>Lab</b>');
});
it('should return project name as it is if `matcher` is not available', () => {
vm.matcher = null;
expect(vm.highlightedItemName).toBe(mockProject.name);
});
});
......@@ -52,11 +56,13 @@ describe('FrequentItemsListItemComponent', () => {
describe('truncatedNamespace', () => {
it('should truncate project name from namespace string', () => {
vm.namespace = 'platform / nokia-3310';
expect(vm.truncatedNamespace).toBe('platform');
});
it('should truncate namespace string from the middle if it includes more than two groups in path', () => {
vm.namespace = 'platform / hardware / broadcom / Wifi Group / Mobile Chipset / nokia-3310';
expect(vm.truncatedNamespace).toBe('platform / ... / Mobile Chipset');
});
});
......
......@@ -30,9 +30,11 @@ describe('FrequentItemsListComponent', () => {
describe('isListEmpty', () => {
it('should return `true` or `false` representing whether if `items` is empty or not with projects', () => {
vm.items = [];
expect(vm.isListEmpty).toBe(true);
vm.items = mockFrequentProjects;
expect(vm.isListEmpty).toBe(false);
});
});
......@@ -40,9 +42,11 @@ describe('FrequentItemsListComponent', () => {
describe('fetched item messages', () => {
it('should return appropriate empty list message based on value of `localStorageFailed` prop with projects', () => {
vm.isFetchFailed = true;
expect(vm.listEmptyMessage).toBe('This feature requires browser localStorage support');
vm.isFetchFailed = false;
expect(vm.listEmptyMessage).toBe('Projects you visit often will appear here');
});
});
......@@ -51,9 +55,11 @@ describe('FrequentItemsListComponent', () => {
it('should return appropriate empty list message based on value of `searchFailed` prop with projects', () => {
vm.hasSearchQuery = true;
vm.isFetchFailed = true;
expect(vm.listEmptyMessage).toBe('Something went wrong on our end.');
vm.isFetchFailed = false;
expect(vm.listEmptyMessage).toBe('Sorry, no projects matched your search');
});
});
......
......@@ -26,6 +26,7 @@ describe('FrequentItemsSearchInputComponent', () => {
spyOn(vm.$refs.search, 'focus');
vm.setFocus();
expect(vm.$refs.search.focus).toHaveBeenCalled();
});
});
......
......@@ -70,8 +70,10 @@ describe('glDropdown', function describeDropdown() {
it('should open on click', () => {
initDropDown.call(this, false);
expect(this.dropdownContainerElement).not.toHaveClass('show');
this.dropdownButtonElement.click();
expect(this.dropdownContainerElement).toHaveClass('show');
});
......@@ -141,9 +143,12 @@ describe('glDropdown', function describeDropdown() {
navigateWithKeys('enter', null, () => {
expect(this.dropdownContainerElement).not.toHaveClass('show');
const link = $(`${ITEM_SELECTOR}:eq(${randomIndex}) a`, this.$dropdownMenuElement);
expect(link).toHaveClass('is-active');
const linkedLocation = link.attr('href');
if (linkedLocation && linkedLocation !== '#') expect(visitUrl).toHaveBeenCalledWith(linkedLocation);
if (linkedLocation && linkedLocation !== '#') {
expect(visitUrl).toHaveBeenCalledWith(linkedLocation);
}
});
});
});
......@@ -155,6 +160,7 @@ describe('glDropdown', function describeDropdown() {
which: ARROW_KEYS.ESC,
keyCode: ARROW_KEYS.ESC
});
expect(this.dropdownContainerElement).not.toHaveClass('show');
});
});
......@@ -170,17 +176,20 @@ describe('glDropdown', function describeDropdown() {
expect(dropdownMenu.className.indexOf('is-loading')).not.toBe(-1);
remoteCallback();
expect(dropdownMenu.className.indexOf('is-loading')).toBe(-1);
});
it('should not focus search input while remote task is not complete', () => {
expect($(document.activeElement)).not.toEqual($(SEARCH_INPUT_SELECTOR));
remoteCallback();
expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR));
});
it('should focus search input after remote task is complete', () => {
remoteCallback();
expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR));
});
......@@ -193,6 +202,7 @@ describe('glDropdown', function describeDropdown() {
});
this.dropdownButtonElement.click();
this.dropdownContainerElement.trigger('transitionend');
expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR));
});
});
......@@ -202,6 +212,7 @@ describe('glDropdown', function describeDropdown() {
initDropDown.call(this, false, true);
this.dropdownButtonElement.click();
this.dropdownContainerElement.trigger('transitionend');
expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR));
});
});
......@@ -213,11 +224,13 @@ describe('glDropdown', function describeDropdown() {
.trigger('focus')
.val('g')
.trigger('input');
expect($searchInput.val()).toEqual('g');
this.dropdownButtonElement.trigger('hidden.bs.dropdown');
$searchInput
.trigger('blur')
.trigger('focus');
expect($searchInput.val()).toEqual('g');
});
......@@ -240,6 +253,7 @@ describe('glDropdown', function describeDropdown() {
const html = dropdown.renderItem(dummyData, null, null);
const link = html.querySelector('a');
expect(link).toHaveClass('is-active');
});
......@@ -251,6 +265,7 @@ describe('glDropdown', function describeDropdown() {
const html = dropdown.renderItem(dummyData, null, null);
const link = html.querySelector('a');
expect(link).not.toHaveClass('is-active');
});
});
......@@ -271,10 +286,12 @@ describe('glDropdown', function describeDropdown() {
// select item the first time
this.dropdownButtonElement.click();
$item.click();
expect($item).toHaveClass('is-active');
// select item the second time
this.dropdownButtonElement.click();
$item.click();
expect($item).toHaveClass('is-active');
expect($('.dropdown-toggle-text')).toHaveText(this.projectsData[0].id.toString());
......
......@@ -19,6 +19,7 @@ describe('GL Style Field Errors', function() {
expect(this.$form.length).toBe(1);
expect(this.fieldErrors).toBeDefined();
const { inputs } = this.fieldErrors.state;
expect(inputs.length).toBe(4);
});
......@@ -31,6 +32,7 @@ describe('GL Style Field Errors', function() {
const customErrors = this.fieldErrors.state.inputs.filter((input) => {
return input.inputElement.hasClass(customErrorFlag);
});
expect(customErrors.length).toBe(0);
});
......@@ -40,6 +42,7 @@ describe('GL Style Field Errors', function() {
this.$form.find('.alphanumberic').val('?---*').keyup();
const errorsShown = this.$form.find('.gl-field-error-outline');
expect(errorsShown.length).toBe(0);
});
......@@ -51,6 +54,7 @@ describe('GL Style Field Errors', function() {
this.$form.submit();
const errorsShown = this.$form.find('.gl-field-error-outline');
expect(errorsShown.length).toBe(4);
});
......@@ -68,30 +72,35 @@ describe('GL Style Field Errors', function() {
// Then invalid input
emailInputElement.val('not-a-valid-email').keyup();
expect(emailInputElement).toHaveClass('gl-field-error-outline');
expect(fieldState.empty).toBe(false);
expect(fieldState.valid).toBe(false);
// Then valid input
emailInputElement.val('email@gitlab.com').keyup();
expect(emailInputElement).not.toHaveClass('gl-field-error-outline');
expect(fieldState.empty).toBe(false);
expect(fieldState.valid).toBe(true);
// Then invalid input
emailInputElement.val('not-a-valid-email').keyup();
expect(emailInputElement).toHaveClass('gl-field-error-outline');
expect(fieldState.empty).toBe(false);
expect(fieldState.valid).toBe(false);
// Then empty input
emailInputElement.val('').keyup();
expect(emailInputElement).toHaveClass('gl-field-error-outline');
expect(fieldState.empty).toBe(true);
expect(fieldState.valid).toBe(false);
// Then valid input
emailInputElement.val('email@gitlab.com').keyup();
expect(emailInputElement).not.toHaveClass('gl-field-error-outline');
expect(fieldState.empty).toBe(false);
expect(fieldState.valid).toBe(true);
......
......@@ -101,6 +101,7 @@ describe('GLForm', () => {
spyOn($.prototype, 'outerHeight').and.returnValue(200);
spyOn($.prototype, 'data').and.returnValue(200);
spyOn(autosize, 'destroy');
expect(this.glForm.destroyAutosize()).toBeUndefined();
expect(autosize.destroy).not.toHaveBeenCalled();
});
......
......@@ -69,6 +69,7 @@ describe('GpgBadges', () => {
.then(() => {
expect(document.querySelector('.js-loading-gpg-badge:empty')).toBe(null);
const spinners = document.querySelectorAll('.js-loading-gpg-badge i.fa.fa-spinner.fa-spin');
expect(spinners.length).toBe(1);
done();
})
......@@ -82,6 +83,7 @@ describe('GpgBadges', () => {
.then(() => {
expect(document.querySelector('.js-loading-gpg-badge')).toBe(null);
const parentContainer = document.querySelector('.parent-container');
expect(parentContainer.innerHTML.trim()).toEqual(dummyBadgeHtml);
done();
})
......
......@@ -10,6 +10,7 @@ describe("ContributorsGraph", function () {
describe("#set_x_domain", function () {
it("set the x_domain", function () {
ContributorsGraph.set_x_domain(20);
expect(ContributorsGraph.prototype.x_domain).toEqual(20);
});
});
......@@ -17,6 +18,7 @@ describe("ContributorsGraph", function () {
describe("#set_y_domain", function () {
it("sets the y_domain", function () {
ContributorsGraph.set_y_domain([{ commits: 30 }]);
expect(ContributorsGraph.prototype.y_domain).toEqual([0, 30]);
});
});
......@@ -24,6 +26,7 @@ describe("ContributorsGraph", function () {
describe("#init_x_domain", function () {
it("sets the initial x_domain", function () {
ContributorsGraph.init_x_domain([{ date: "2013-01-31" }, { date: "2012-01-31" }]);
expect(ContributorsGraph.prototype.x_domain).toEqual(["2012-01-31", "2013-01-31"]);
});
});
......@@ -31,6 +34,7 @@ describe("ContributorsGraph", function () {
describe("#init_y_domain", function () {
it("sets the initial y_domain", function () {
ContributorsGraph.init_y_domain([{ commits: 30 }]);
expect(ContributorsGraph.prototype.y_domain).toEqual([0, 30]);
});
});
......@@ -40,6 +44,7 @@ describe("ContributorsGraph", function () {
spyOn(ContributorsGraph, "init_x_domain");
spyOn(ContributorsGraph, "init_y_domain");
ContributorsGraph.init_domain();
expect(ContributorsGraph.init_x_domain).toHaveBeenCalled();
expect(ContributorsGraph.init_y_domain).toHaveBeenCalled();
});
......@@ -48,6 +53,7 @@ describe("ContributorsGraph", function () {
describe("#set_dates", function () {
it("sets the dates", function () {
ContributorsGraph.set_dates("2013-12-01");
expect(ContributorsGraph.prototype.dates).toEqual("2013-12-01");
});
});
......@@ -59,6 +65,7 @@ describe("ContributorsGraph", function () {
instance.x = d3.scaleTime().range([0, 100]).clamp(true);
spyOn(instance.x, 'domain');
instance.set_x_domain();
expect(instance.x.domain).toHaveBeenCalledWith(20);
});
});
......@@ -70,6 +77,7 @@ describe("ContributorsGraph", function () {
instance.y = d3.scaleLinear().range([100, 0]).nice();
spyOn(instance.y, 'domain');
instance.set_y_domain();
expect(instance.y.domain).toHaveBeenCalledWith(30);
});
});
......@@ -80,6 +88,7 @@ describe("ContributorsGraph", function () {
spyOn(instance, 'set_x_domain');
spyOn(instance, 'set_y_domain');
instance.set_domain();
expect(instance.set_x_domain).toHaveBeenCalled();
expect(instance.set_y_domain).toHaveBeenCalled();
});
......@@ -89,6 +98,7 @@ describe("ContributorsGraph", function () {
it("sets the data", function () {
var instance = new ContributorsGraph();
instance.set_data("20");
expect(instance.data).toEqual("20");
});
});
......@@ -114,6 +124,7 @@ describe("ContributorsMasterGraph", function () {
it("plucks the date field from data collection", function () {
var graph = new ContributorsMasterGraph();
var data = [{ date: "2013-01-01" }, { date: "2012-12-15" }];
expect(graph.get_dates(data)).toEqual(["2013-01-01", "2012-12-15"]);
});
});
......@@ -125,6 +136,7 @@ describe("ContributorsMasterGraph", function () {
var data = [{ date: "2013-01-01" }, { date: "2012-12-15" }];
var correct = [{ date: parseDate(data[0].date) }, { date: parseDate(data[1].date) }];
graph.parse_dates(data);
expect(data).toEqual(correct);
});
});
......
......@@ -28,6 +28,7 @@ describe("ContributorsStatGraphUtil", function () {
}
]
};
expect(ContributorsStatGraphUtil.parse_log(fake_log)).toEqual(correct_parsed_log);
});
});
......@@ -40,18 +41,21 @@ describe("ContributorsStatGraphUtil", function () {
it("calls #store_commits", function () {
spyOn(ContributorsStatGraphUtil, 'store_commits');
ContributorsStatGraphUtil.store_data(fake_entry, fake_total, fake_by_author);
expect(ContributorsStatGraphUtil.store_commits).toHaveBeenCalled();
});
it("calls #store_additions", function () {
spyOn(ContributorsStatGraphUtil, 'store_additions');
ContributorsStatGraphUtil.store_data(fake_entry, fake_total, fake_by_author);
expect(ContributorsStatGraphUtil.store_additions).toHaveBeenCalled();
});
it("calls #store_deletions", function () {
spyOn(ContributorsStatGraphUtil, 'store_deletions');
ContributorsStatGraphUtil.store_data(fake_entry, fake_total, fake_by_author);
expect(ContributorsStatGraphUtil.store_deletions).toHaveBeenCalled();
});
});
......@@ -72,12 +76,14 @@ describe("ContributorsStatGraphUtil", function () {
it("adds 1 to current test_field in collection", function () {
var fake_collection = { test_field: 10 };
ContributorsStatGraphUtil.add(fake_collection, "test_field", 1);
expect(fake_collection.test_field).toEqual(11);
});
it("inits and adds 1 if test_field in collection is not defined", function () {
var fake_collection = {};
ContributorsStatGraphUtil.add(fake_collection, "test_field", 1);
expect(fake_collection.test_field).toEqual(1);
});
});
......@@ -111,6 +117,7 @@ describe("ContributorsStatGraphUtil", function () {
var fake_date = "2013-10-02";
var fake_collection = {};
ContributorsStatGraphUtil.add_date(fake_date, fake_collection);
expect(fake_collection[fake_date].date).toEqual("2013-10-02");
});
});
......@@ -121,6 +128,7 @@ describe("ContributorsStatGraphUtil", function () {
var fake_author_collection = {};
var fake_email_collection = {};
ContributorsStatGraphUtil.add_author(fake_author, fake_author_collection, fake_email_collection);
expect(fake_author_collection[fake_author.author_name].author_name).toEqual("Author");
expect(fake_email_collection[fake_author.author_email].author_name).toEqual("Author");
});
......@@ -148,6 +156,7 @@ describe("ContributorsStatGraphUtil", function () {
{ date: "2013-05-08", commits: 3 },
{ date: "2013-05-09", commits: 1 }
];
expect(ContributorsStatGraphUtil.get_total_data(fake_parsed_log, "commits")).toEqual(correct_total_data);
});
});
......@@ -160,6 +169,7 @@ describe("ContributorsStatGraphUtil", function () {
];
ContributorsStatGraphUtil.pick_field(fake_parsed_log_total, "commits");
var correct_pick_field_data = [{ date: "2013-05-09", commits: 1 }, { date: "2013-05-08", commits: 3 }];
expect(ContributorsStatGraphUtil.pick_field(fake_parsed_log_total, "commits")).toEqual(correct_pick_field_data);
});
});
......@@ -186,6 +196,7 @@ describe("ContributorsStatGraphUtil", function () {
{ author_name: "Dmitriy Zaporozhets", author_email: "dzaporozhets@email.com", dates: { "2013-05-08": 3 }, deletions: 7, additions: 54, "commits": 3 },
{ author_name: "Karlo Soriano", author_email: "karlo@email.com", dates: { "2013-05-09": 1 }, deletions: 0, additions: 471, commits: 1 }
];
expect(ContributorsStatGraphUtil.get_author_data(fake_parsed_log, "commits")).toEqual(correct_author_data);
});
});
......@@ -196,6 +207,7 @@ describe("ContributorsStatGraphUtil", function () {
"2013-05-09": { date: "2013-05-09", additions: 471, deletions: 0, commits: 1 }
};
var correct_parsed_log = { author_name: "Karlo Soriano", author_email: "karlo@email.com", dates: { "2013-05-09": 1 }, deletions: 0, additions: 471, commits: 1 };
expect(ContributorsStatGraphUtil.parse_log_entry(fake_log_entry, 'commits', null)).toEqual(correct_parsed_log);
});
});
......@@ -208,11 +220,13 @@ describe("ContributorsStatGraphUtil", function () {
it("returns true if date is in range", function () {
var date_range = [new Date("2013-01-01"), new Date("2013-12-12")];
expect(ContributorsStatGraphUtil.in_range(date, date_range)).toEqual(true);
});
it("returns false if date is not in range", function () {
var date_range = [new Date("1999-12-01"), new Date("2000-12-01")];
expect(ContributorsStatGraphUtil.in_range(date, date_range)).toEqual(false);
});
});
......
......@@ -76,6 +76,7 @@ describe('AppComponent', () => {
spyOn(vm.store, 'getGroups');
const { groups } = vm;
expect(vm.store.getGroups).toHaveBeenCalled();
expect(groups).not.toBeDefined();
});
......@@ -86,6 +87,7 @@ describe('AppComponent', () => {
spyOn(vm.store, 'getPaginationInfo');
const { pageInfo } = vm;
expect(vm.store.getPaginationInfo).toHaveBeenCalled();
expect(pageInfo).not.toBeDefined();
});
......@@ -154,6 +156,7 @@ describe('AppComponent', () => {
spyOn(vm, 'updateGroups').and.callThrough();
vm.fetchAllGroups();
expect(vm.isLoading).toBe(true);
expect(vm.fetchGroups).toHaveBeenCalled();
setTimeout(() => {
......@@ -168,6 +171,7 @@ describe('AppComponent', () => {
spyOn(vm, 'updateGroups').and.callThrough();
vm.fetchAllGroups();
expect(vm.fetchGroups).toHaveBeenCalledWith({
page: null,
filterGroupsBy: null,
......@@ -191,6 +195,7 @@ describe('AppComponent', () => {
spyOn($, 'scrollTo');
vm.fetchPage(2, null, null, true);
expect(vm.isLoading).toBe(true);
expect(vm.fetchGroups).toHaveBeenCalledWith({
page: 2,
......@@ -210,6 +215,7 @@ describe('AppComponent', () => {
jasmine.any(String),
jasmine.any(String),
);
expect(vm.updateGroups).toHaveBeenCalled();
done();
}, 0);
......@@ -230,6 +236,7 @@ describe('AppComponent', () => {
spyOn(vm.store, 'setGroupChildren');
vm.toggleChildren(groupItem);
expect(groupItem.isChildrenLoading).toBe(true);
expect(vm.fetchGroups).toHaveBeenCalledWith({
parentId: groupItem.id,
......@@ -245,6 +252,7 @@ describe('AppComponent', () => {
groupItem.children = mockRawChildren;
vm.toggleChildren(groupItem);
expect(vm.fetchGroups).not.toHaveBeenCalled();
expect(groupItem.isOpen).toBe(true);
});
......@@ -254,6 +262,7 @@ describe('AppComponent', () => {
groupItem.isOpen = true;
vm.toggleChildren(groupItem);
expect(vm.fetchGroups).not.toHaveBeenCalled();
expect(groupItem.isOpen).toBe(false);
});
......@@ -262,6 +271,7 @@ describe('AppComponent', () => {
spyOn(vm, 'fetchGroups').and.returnValue(returnServicePromise({}, true));
vm.toggleChildren(groupItem);
expect(groupItem.isChildrenLoading).toBe(true);
setTimeout(() => {
expect(groupItem.isChildrenLoading).toBe(false);
......@@ -273,18 +283,22 @@ describe('AppComponent', () => {
describe('showLeaveGroupModal', () => {
it('caches candidate group (as props) which is to be left', () => {
const group = Object.assign({}, mockParentGroupItem);
expect(vm.targetGroup).toBe(null);
expect(vm.targetParentGroup).toBe(null);
vm.showLeaveGroupModal(group, mockParentGroupItem);
expect(vm.targetGroup).not.toBe(null);
expect(vm.targetParentGroup).not.toBe(null);
});
it('updates props which show modal confirmation dialog', () => {
const group = Object.assign({}, mockParentGroupItem);
expect(vm.showModal).toBe(false);
expect(vm.groupLeaveConfirmationMessage).toBe('');
vm.showLeaveGroupModal(group, mockParentGroupItem);
expect(vm.showModal).toBe(true);
expect(vm.groupLeaveConfirmationMessage).toBe(
`Are you sure you want to leave the "${group.fullName}" group?`,
......@@ -296,8 +310,10 @@ describe('AppComponent', () => {
it('hides modal confirmation which is shown before leaving the group', () => {
const group = Object.assign({}, mockParentGroupItem);
vm.showLeaveGroupModal(group, mockParentGroupItem);
expect(vm.showModal).toBe(true);
vm.hideLeaveGroupModal();
expect(vm.showModal).toBe(false);
});
});
......@@ -323,6 +339,7 @@ describe('AppComponent', () => {
spyOn($, 'scrollTo');
vm.leaveGroup();
expect(vm.showModal).toBe(false);
expect(vm.targetGroup.isBeingRemoved).toBe(true);
expect(vm.service.leaveGroup).toHaveBeenCalledWith(vm.targetGroup.leavePath);
......@@ -343,6 +360,7 @@ describe('AppComponent', () => {
spyOn(window, 'Flash');
vm.leaveGroup();
expect(vm.targetGroup.isBeingRemoved).toBe(true);
expect(vm.service.leaveGroup).toHaveBeenCalledWith(childGroupItem.leavePath);
setTimeout(() => {
......@@ -362,6 +380,7 @@ describe('AppComponent', () => {
spyOn(window, 'Flash');
vm.leaveGroup(childGroupItem, groupItem);
expect(vm.targetGroup.isBeingRemoved).toBe(true);
expect(vm.service.leaveGroup).toHaveBeenCalledWith(childGroupItem.leavePath);
setTimeout(() => {
......@@ -378,6 +397,7 @@ describe('AppComponent', () => {
spyOn(vm.store, 'setPaginationInfo');
vm.updatePagination(mockRawPageInfo);
expect(vm.store.setPaginationInfo).toHaveBeenCalledWith(mockRawPageInfo);
});
});
......@@ -387,6 +407,7 @@ describe('AppComponent', () => {
spyOn(vm.store, 'setGroups');
vm.updateGroups(mockGroups);
expect(vm.store.setGroups).toHaveBeenCalledWith(mockGroups);
});
......@@ -394,14 +415,17 @@ describe('AppComponent', () => {
spyOn(vm.store, 'setSearchedGroups');
vm.updateGroups(mockGroups, true);
expect(vm.store.setSearchedGroups).toHaveBeenCalledWith(mockGroups);
});
it('should set `isSearchEmpty` prop based on groups count', () => {
vm.updateGroups(mockGroups);
expect(vm.isSearchEmpty).toBe(false);
vm.updateGroups([]);
expect(vm.isSearchEmpty).toBe(true);
});
});
......@@ -497,6 +521,7 @@ describe('AppComponent', () => {
vm.showModal = true;
Vue.nextTick(() => {
const modalDialogEl = vm.$el.querySelector('.modal');
expect(modalDialogEl).not.toBe(null);
expect(modalDialogEl.querySelector('.modal-title').innerText.trim()).toBe('Are you sure?');
expect(modalDialogEl.querySelector('.btn.btn-warning').innerText.trim()).toBe('Leave');
......
......@@ -59,6 +59,7 @@ describe('GroupFolderComponent', () => {
const newVm = createComponent(mockGroups, parentGroup);
newVm.$mount();
expect(newVm.$el.querySelector('li.group-row a.has-more-items')).toBeDefined();
newVm.$destroy();
});
......
......@@ -57,11 +57,13 @@ describe('GroupItemComponent', () => {
group.childrenCount = 5;
newVm = createComponent(group);
expect(newVm.hasChildren).toBeTruthy();
newVm.$destroy();
group.childrenCount = 0;
newVm = createComponent(group);
expect(newVm.hasChildren).toBeFalsy();
newVm.$destroy();
});
......@@ -74,11 +76,13 @@ describe('GroupItemComponent', () => {
group.avatarUrl = null;
newVm = createComponent(group);
expect(newVm.hasAvatar).toBeFalsy();
newVm.$destroy();
group.avatarUrl = '/uploads/group_avatar.png';
newVm = createComponent(group);
expect(newVm.hasAvatar).toBeTruthy();
newVm.$destroy();
});
......@@ -91,11 +95,13 @@ describe('GroupItemComponent', () => {
group.type = 'group';
newVm = createComponent(group);
expect(newVm.isGroup).toBeTruthy();
newVm.$destroy();
group.type = 'project';
newVm = createComponent(group);
expect(newVm.isGroup).toBeFalsy();
newVm.$destroy();
});
......@@ -127,6 +133,7 @@ describe('GroupItemComponent', () => {
spyOn(eventHub, '$emit');
vm.onClickRowGroup(event);
expect(eventHub.$emit).toHaveBeenCalledWith('toggleChildren', vm.group);
});
......
......@@ -42,6 +42,7 @@ describe('GroupsComponent', () => {
spyOn(eventHub, '$emit').and.stub();
vm.change(2);
expect(eventHub.$emit).toHaveBeenCalledWith('fetchPage', 2, jasmine.any(Object), jasmine.any(Object), jasmine.any(Object));
});
});
......
......@@ -30,6 +30,7 @@ describe('ItemActionsComponent', () => {
it('emits `showLeaveGroupModal` event with `group` and `parentGroup` props', () => {
spyOn(eventHub, '$emit');
vm.onLeaveGroup();
expect(eventHub.$emit).toHaveBeenCalledWith('showLeaveGroupModal', vm.group, vm.parentGroup);
});
});
......@@ -46,6 +47,7 @@ describe('ItemActionsComponent', () => {
const newVm = createComponent(group);
const editBtn = newVm.$el.querySelector('a.edit-group');
expect(editBtn).toBeDefined();
expect(editBtn.classList.contains('no-expand')).toBeTruthy();
expect(editBtn.getAttribute('href')).toBe(group.editPath);
......@@ -63,6 +65,7 @@ describe('ItemActionsComponent', () => {
const newVm = createComponent(group);
const leaveBtn = newVm.$el.querySelector('a.leave-group');
expect(leaveBtn).toBeDefined();
expect(leaveBtn.classList.contains('no-expand')).toBeTruthy();
expect(leaveBtn.getAttribute('href')).toBe(group.leavePath);
......
......@@ -16,6 +16,7 @@ describe('ItemCaretComponent', () => {
describe('template', () => {
it('should render component template correctly', () => {
const vm = createComponent();
expect(vm.$el.classList.contains('folder-caret')).toBeTruthy();
expect(vm.$el.querySelectorAll('svg').length).toBe(1);
vm.$destroy();
......@@ -23,12 +24,14 @@ describe('ItemCaretComponent', () => {
it('should render caret down icon if `isGroupOpen` prop is `true`', () => {
const vm = createComponent(true);
expect(vm.$el.querySelector('svg use').getAttribute('xlink:href')).toContain('angle-down');
vm.$destroy();
});
it('should render caret right icon if `isGroupOpen` prop is `false`', () => {
const vm = createComponent();
expect(vm.$el.querySelector('svg use').getAttribute('xlink:href')).toContain('angle-right');
vm.$destroy();
});
......
......@@ -25,6 +25,7 @@ describe('ItemStatsComponent', () => {
Object.keys(VISIBILITY_TYPE_ICON).forEach((visibility) => {
const item = Object.assign({}, mockParentGroupItem, { visibility });
const vm = createComponent(item);
expect(vm.visibilityIcon).toBe(VISIBILITY_TYPE_ICON[visibility]);
vm.$destroy();
});
......@@ -39,6 +40,7 @@ describe('ItemStatsComponent', () => {
type: ITEM_TYPE.GROUP,
});
const vm = createComponent(item);
expect(vm.visibilityTooltip).toBe(GROUP_VISIBILITY_TYPE[visibility]);
vm.$destroy();
});
......@@ -51,6 +53,7 @@ describe('ItemStatsComponent', () => {
type: ITEM_TYPE.PROJECT,
});
const vm = createComponent(item);
expect(vm.visibilityTooltip).toBe(PROJECT_VISIBILITY_TYPE[visibility]);
vm.$destroy();
});
......@@ -64,11 +67,13 @@ describe('ItemStatsComponent', () => {
item = Object.assign({}, mockParentGroupItem, { type: ITEM_TYPE.PROJECT });
vm = createComponent(item);
expect(vm.isProject).toBeTruthy();
vm.$destroy();
item = Object.assign({}, mockParentGroupItem, { type: ITEM_TYPE.GROUP });
vm = createComponent(item);
expect(vm.isProject).toBeFalsy();
vm.$destroy();
});
......@@ -81,11 +86,13 @@ describe('ItemStatsComponent', () => {
item = Object.assign({}, mockParentGroupItem, { type: ITEM_TYPE.GROUP });
vm = createComponent(item);
expect(vm.isGroup).toBeTruthy();
vm.$destroy();
item = Object.assign({}, mockParentGroupItem, { type: ITEM_TYPE.PROJECT });
vm = createComponent(item);
expect(vm.isGroup).toBeFalsy();
vm.$destroy();
});
......@@ -105,6 +112,7 @@ describe('ItemStatsComponent', () => {
const vm = createComponent();
const visibilityIconEl = vm.$el.querySelector('.item-visibility');
expect(visibilityIconEl).not.toBe(null);
expect(visibilityIconEl.dataset.originalTitle).toBe(vm.visibilityTooltip);
expect(visibilityIconEl.querySelectorAll('svg').length).toBeGreaterThan(0);
......@@ -120,6 +128,7 @@ describe('ItemStatsComponent', () => {
const vm = createComponent(item);
const projectStarIconEl = vm.$el.querySelector('.project-stars');
expect(projectStarIconEl).not.toBeNull();
expect(projectStarIconEl.querySelectorAll('svg').length).toBeGreaterThan(0);
expect(projectStarIconEl.querySelectorAll('.stat-value').length).toBeGreaterThan(0);
......
......@@ -29,11 +29,13 @@ describe('ItemStatsValueComponent', () => {
describe('isValuePresent', () => {
it('returns true if non-empty `value` is present', () => {
vm = createComponent(Object.assign({}, itemConfig, { value: 10 }));
expect(vm.isValuePresent).toBeTruthy();
});
it('returns false if empty `value` is present', () => {
vm = createComponent(itemConfig);
expect(vm.isValuePresent).toBeFalsy();
});
......
......@@ -18,6 +18,7 @@ describe('ItemTypeIconComponent', () => {
it('should render component template correctly', () => {
const vm = createComponent();
vm.$mount();
expect(vm.$el.classList.contains('item-type-icon')).toBeTruthy();
vm.$destroy();
});
......@@ -27,11 +28,13 @@ describe('ItemTypeIconComponent', () => {
vm = createComponent(ITEM_TYPE.GROUP, true);
vm.$mount();
expect(vm.$el.querySelector('use').getAttribute('xlink:href')).toContain('folder-open');
vm.$destroy();
vm = createComponent(ITEM_TYPE.GROUP);
vm.$mount();
expect(vm.$el.querySelector('use').getAttribute('xlink:href')).toContain('folder');
vm.$destroy();
});
......@@ -41,11 +44,13 @@ describe('ItemTypeIconComponent', () => {
vm = createComponent(ITEM_TYPE.PROJECT);
vm.$mount();
expect(vm.$el.querySelector('use').getAttribute('xlink:href')).toContain('bookmark');
vm.$destroy();
vm = createComponent(ITEM_TYPE.GROUP);
vm.$mount();
expect(vm.$el.querySelector('use').getAttribute('xlink:href')).not.toContain('bookmark');
vm.$destroy();
});
......
......@@ -24,9 +24,11 @@ describe('GroupsService', () => {
};
service.getGroups(55, 2, 'git', 'created_asc', true);
expect(service.groups.get).toHaveBeenCalledWith({ parent_id: 55 });
service.getGroups(null, 2, 'git', 'created_asc', true);
expect(service.groups.get).toHaveBeenCalledWith(queryParams);
});
});
......@@ -36,6 +38,7 @@ describe('GroupsService', () => {
spyOn(Vue.http, 'delete').and.stub();
service.leaveGroup(mockParentGroupItem.leavePath);
expect(Vue.http.delete).toHaveBeenCalledWith(mockParentGroupItem.leavePath);
});
});
......
......@@ -11,12 +11,14 @@ describe('ProjectsStore', () => {
let store;
store = new GroupsStore();
expect(Object.keys(store.state).length).toBe(2);
expect(Array.isArray(store.state.groups)).toBeTruthy();
expect(Object.keys(store.state.pageInfo).length).toBe(0);
expect(store.hideProjects).not.toBeDefined();
store = new GroupsStore(true);
expect(store.hideProjects).toBeTruthy();
});
});
......@@ -27,6 +29,7 @@ describe('ProjectsStore', () => {
spyOn(store, 'formatGroupItem').and.callThrough();
store.setGroups(mockGroups);
expect(store.state.groups.length).toBe(mockGroups.length);
expect(store.formatGroupItem).toHaveBeenCalledWith(jasmine.any(Object));
expect(Object.keys(store.state.groups[0]).indexOf('fullName')).toBeGreaterThan(-1);
......@@ -39,6 +42,7 @@ describe('ProjectsStore', () => {
spyOn(store, 'formatGroupItem').and.callThrough();
store.setSearchedGroups(mockSearchedGroups);
expect(store.state.groups.length).toBe(mockSearchedGroups.length);
expect(store.formatGroupItem).toHaveBeenCalledWith(jasmine.any(Object));
expect(Object.keys(store.state.groups[0]).indexOf('fullName')).toBeGreaterThan(-1);
......@@ -52,6 +56,7 @@ describe('ProjectsStore', () => {
spyOn(store, 'formatGroupItem').and.callThrough();
store.setGroupChildren(mockParentGroupItem, mockRawChildren);
expect(store.formatGroupItem).toHaveBeenCalledWith(jasmine.any(Object));
expect(mockParentGroupItem.children.length).toBe(1);
expect(Object.keys(mockParentGroupItem.children[0]).indexOf('fullName')).toBeGreaterThan(-1);
......@@ -65,6 +70,7 @@ describe('ProjectsStore', () => {
const store = new GroupsStore();
store.setPaginationInfo(mockRawPageInfo);
expect(store.state.pageInfo.perPage).toBe(10);
expect(store.state.pageInfo.page).toBe(10);
expect(store.state.pageInfo.total).toBe(10);
......@@ -81,6 +87,7 @@ describe('ProjectsStore', () => {
store = new GroupsStore();
updatedGroupItem = store.formatGroupItem(mockRawChildren[0]);
expect(Object.keys(updatedGroupItem).indexOf('fullName')).toBeGreaterThan(-1);
expect(updatedGroupItem.childrenCount).toBe(mockRawChildren[0].children_count);
expect(updatedGroupItem.isChildrenLoading).toBe(false);
......@@ -88,6 +95,7 @@ describe('ProjectsStore', () => {
store = new GroupsStore(true);
updatedGroupItem = store.formatGroupItem(mockRawChildren[0]);
expect(Object.keys(updatedGroupItem).indexOf('fullName')).toBeGreaterThan(-1);
expect(updatedGroupItem.childrenCount).toBe(mockRawChildren[0].subgroup_count);
});
......@@ -104,6 +112,7 @@ describe('ProjectsStore', () => {
const childItem = store.state.groups[0].children[0];
store.removeGroup(childItem, store.state.groups[0]);
expect(store.state.groups[0].children.length).toBe(0);
});
});
......
......@@ -21,16 +21,19 @@ describe('Header', function () {
it('should update todos-count after receiving the todo:toggle event', () => {
triggerToggle('5');
expect($(todosPendingCount).text()).toEqual('5');
});
it('should hide todos-count when it is 0', () => {
triggerToggle('0');
expect(isTodosCountHidden()).toEqual(true);
});
it('should show todos-count when it is more than 0', () => {
triggerToggle('10');
expect(isTodosCountHidden()).toEqual(false);
});
......
......@@ -29,6 +29,7 @@ describe('IDE branch item', () => {
it('renders branch name and timeago', () => {
const timeText = getTimeago().format(TEST_BRANCH.committedDate);
expect(vm.$el).toContainText(TEST_BRANCH.name);
expect(vm.$el.querySelector('time')).toHaveText(timeText);
expect(vm.$el.querySelector('.ic-mobile-issue-close')).toBe(null);
......@@ -36,6 +37,7 @@ describe('IDE branch item', () => {
it('renders link to branch', () => {
const expectedHref = router.resolve(`/project/${TEST_PROJECT_ID}/edit/${TEST_BRANCH.name}`).href;
expect(vm.$el).toMatch('a');
expect(vm.$el).toHaveAttr('href', expectedHref);
});
......
......@@ -76,6 +76,7 @@ describe('IDE commit message field', () => {
expect(vm.$el.querySelector('.highlights span').textContent).toContain(
'text less than 50 chars',
);
expect(vm.$el.querySelector('mark').style.display).toBe('none');
})
.then(done)
......@@ -92,6 +93,7 @@ describe('IDE commit message field', () => {
expect(vm.$el.querySelector('.highlights span').textContent).toContain(
'text less than 50 chars that should not highlighte',
);
expect(vm.$el.querySelector('mark').style.display).not.toBe('none');
expect(vm.$el.querySelector('mark').textContent).toBe(
'd. text more than 50 should be highlighted',
......
......@@ -50,9 +50,11 @@ describe('ideStatusBar', () => {
expect(vm.commitAgeUpdate).not.toHaveBeenCalled();
jasmine.clock().tick(1100);
expect(vm.commitAgeUpdate.calls.count()).toEqual(1);
jasmine.clock().tick(1000);
expect(vm.commitAgeUpdate.calls.count()).toEqual(2);
});
});
......
......@@ -30,6 +30,7 @@ describe('IDE merge request item', () => {
it('renders link with href', () => {
const expectedHref = router.resolve(`/project/${vm.item.projectPathWithNamespace}/merge_requests/${vm.item.iid}`).href;
expect(vm.$el).toMatch('a');
expect(vm.$el).toHaveAttr('href', expectedHref);
});
......
......@@ -36,6 +36,7 @@ describe('new dropdown component', () => {
it('renders new file, upload and new directory links', () => {
const buttons = vm.$el.querySelectorAll('.dropdown-menu button');
expect(buttons[0].textContent.trim()).toBe('New file');
expect(buttons[1].textContent.trim()).toBe('Upload file');
expect(buttons[2].textContent.trim()).toBe('New directory');
......
......@@ -52,6 +52,7 @@ describe('RepoEditor', () => {
it('renders only an edit tab', done => {
Vue.nextTick(() => {
const tabs = vm.$el.querySelectorAll('.ide-mode-tabs .nav-links li');
expect(tabs.length).toBe(1);
expect(tabs[0].textContent.trim()).toBe('Edit');
......@@ -72,6 +73,7 @@ describe('RepoEditor', () => {
it('renders an Edit and a Preview Tab', done => {
Vue.nextTick(() => {
const tabs = vm.$el.querySelectorAll('.ide-mode-tabs .nav-links li');
expect(tabs.length).toBe(2);
expect(tabs[0].textContent.trim()).toBe('Edit');
expect(tabs[1].textContent.trim()).toBe('Preview Markdown');
......@@ -109,6 +111,7 @@ describe('RepoEditor', () => {
it('renders an Edit and a Preview Tab', done => {
Vue.nextTick(() => {
const tabs = vm.$el.querySelectorAll('.ide-mode-tabs .nav-links li');
expect(tabs.length).toBe(2);
expect(tabs[0].textContent.trim()).toBe('Review');
expect(tabs[1].textContent.trim()).toBe('Preview Markdown');
......
......@@ -85,10 +85,12 @@ describe('IDE shared/TokenedInput', () => {
vm.value = '';
vm.onBackspace();
expect(vm.$emit).not.toHaveBeenCalled();
expect(vm.backspaceCount).toEqual(1);
vm.onBackspace();
expect(vm.$emit).toHaveBeenCalledWith('removeToken', TEST_TOKENS[TEST_TOKENS.length - 1]);
expect(vm.backspaceCount).toEqual(0);
});
......
......@@ -311,6 +311,7 @@ describe('IDE store merge request actions', () => {
file: store.state.entries[change.new_path],
mrChange: change,
});
expect(store.dispatch).toHaveBeenCalledWith('getFileData', {
path: change.new_path,
makeFileActive: i === 0,
......
......@@ -71,6 +71,7 @@ describe('Multi-file store tree actions', () => {
.dispatch('getFiles', basicCallParameters)
.then(() => {
projectTree = store.state.trees['abcproject/master'];
expect(projectTree.tree.length).toBe(2);
expect(projectTree.tree[0].type).toBe('tree');
expect(projectTree.tree[0].tree[1].name).toBe('fileinfolder.js');
......
......@@ -45,6 +45,7 @@ describe('IDE store merge request mutations', () => {
});
const newMr = localState.projects.abcproject.mergeRequests[1];
expect(newMr.changes.diff).toBe('abc');
});
});
......@@ -58,6 +59,7 @@ describe('IDE store merge request mutations', () => {
});
const newMr = localState.projects.abcproject.mergeRequests[1];
expect(newMr.versions.length).toBe(1);
expect(newMr.versions[0].id).toBe(123);
});
......
......@@ -90,6 +90,7 @@ describe('badge helper', () => {
it('should create icon comment button', () => {
const iconEl = buttonEl.querySelector('svg');
expect(iconEl).toBeDefined();
});
});
......
......@@ -29,9 +29,11 @@ describe('commentIndicatorHelper', () => {
it('should contain image-comment-dark svg', () => {
const svgEl = buttonEl.querySelector('svg');
expect(svgEl).toBeDefined();
const svgLink = svgEl.querySelector('use').getAttribute('xlink:href');
expect(svgLink.indexOf('image-comment-dark')).not.toBe(-1);
});
});
......@@ -40,6 +42,7 @@ describe('commentIndicatorHelper', () => {
describe('removeCommentIndicator', () => {
it('should return removed false if there is no comment-indicator', () => {
const result = commentIndicatorHelper.removeCommentIndicator(containerEl);
expect(result.removed).toEqual(false);
});
......@@ -84,6 +87,7 @@ describe('commentIndicatorHelper', () => {
it('should set commentIndicator coordinates', () => {
const commentIndicatorEl = containerEl.querySelector('.comment-indicator');
expect(commentIndicatorEl.style.left).toEqual(`${coordinate.x}px`);
expect(commentIndicatorEl.style.top).toEqual(`${coordinate.y}px`);
});
......@@ -96,6 +100,7 @@ describe('commentIndicatorHelper', () => {
it('should addCommentIndicator', () => {
const buttonEl = containerEl.querySelector('.comment-indicator');
expect(buttonEl).toBeDefined();
expect(buttonEl.style.left).toEqual(`${coordinate.x}px`);
expect(buttonEl.style.top).toEqual(`${coordinate.y}px`);
......
......@@ -92,6 +92,7 @@ describe('domHelper', () => {
it('should force formEl to display none', () => {
const formEl = element.querySelector('.discussion-form');
expect(formEl.style.display).toEqual('none');
});
});
......@@ -111,6 +112,7 @@ describe('domHelper', () => {
it('should force formEl to display block', () => {
const formEl = element.querySelector('.discussion-form');
expect(formEl.style.display).toEqual('block');
});
});
......
......@@ -57,6 +57,7 @@ describe('utilsHelper', () => {
it('should return actual image properties', () => {
const { actual } = result;
expect(actual.x).toEqual(imageMeta.x);
expect(actual.y).toEqual(imageMeta.y);
expect(actual.width).toEqual(imageMeta.width);
......@@ -65,6 +66,7 @@ describe('utilsHelper', () => {
it('should return browser image properties', () => {
const { browser } = result;
expect(browser.x).toBeDefined();
expect(browser.y).toBeDefined();
expect(browser.width).toBeDefined();
......@@ -106,6 +108,7 @@ describe('utilsHelper', () => {
const result = utilsHelper.getTargetSelection(event);
const { browser } = result;
expect(browser.x).toEqual(event.offsetX);
expect(browser.y).toEqual(event.offsetY);
expect(browser.width).toEqual(imageProperties.width);
......@@ -117,6 +120,7 @@ describe('utilsHelper', () => {
const result = utilsHelper.getTargetSelection(event);
const { actual } = result;
expect(actual.x).toEqual(100);
expect(actual.y).toEqual(100);
expect(actual.width).toEqual(imageProperties.naturalWidth);
......@@ -127,24 +131,28 @@ describe('utilsHelper', () => {
it('should return x = 0 if x < 0', () => {
const event = generateEvent(-5, 50);
const result = utilsHelper.getTargetSelection(event);
expect(result.browser.x).toEqual(0);
});
it('should return x = width if x > width', () => {
const event = generateEvent(1000, 50);
const result = utilsHelper.getTargetSelection(event);
expect(result.browser.x).toEqual(imageProperties.width);
});
it('should return y = 0 if y < 0', () => {
const event = generateEvent(50, -10);
const result = utilsHelper.getTargetSelection(event);
expect(result.browser.y).toEqual(0);
});
it('should return y = height if y > height', () => {
const event = generateEvent(50, 1000);
const result = utilsHelper.getTargetSelection(event);
expect(result.browser.y).toEqual(imageProperties.height);
});
});
......@@ -178,6 +186,7 @@ describe('utilsHelper', () => {
`;
const imageDiff = utilsHelper.initImageDiff(fileEl, true, false);
expect(ImageDiff.prototype.init).toHaveBeenCalled();
expect(imageDiff.canCreateNote).toEqual(true);
expect(imageDiff.renderCommentBadge).toEqual(false);
......@@ -191,6 +200,7 @@ describe('utilsHelper', () => {
`;
const replacedImageDiff = utilsHelper.initImageDiff(fileEl, false, true);
expect(ReplacedImageDiff.prototype.init).toHaveBeenCalled();
expect(replacedImageDiff.canCreateNote).toEqual(false);
expect(replacedImageDiff.renderCommentBadge).toEqual(true);
......
......@@ -15,6 +15,7 @@ describe('ImageBadge', () => {
}));
const { actual } = imageBadge;
expect(actual.x).toEqual(imageMeta.x);
expect(actual.y).toEqual(imageMeta.y);
expect(actual.width).toEqual(imageMeta.width);
......@@ -27,6 +28,7 @@ describe('ImageBadge', () => {
}));
const { browser } = imageBadge;
expect(browser.x).toEqual(imageMeta.x);
expect(browser.y).toEqual(imageMeta.y);
expect(browser.width).toEqual(imageMeta.width);
......@@ -35,11 +37,13 @@ describe('ImageBadge', () => {
it('should save noteId', () => {
const imageBadge = new ImageBadge(options);
expect(imageBadge.noteId).toEqual(noteId);
});
it('should save discussionId', () => {
const imageBadge = new ImageBadge(options);
expect(imageBadge.discussionId).toEqual(discussionId);
});
......@@ -52,6 +56,7 @@ describe('ImageBadge', () => {
it('should return defaultimageMeta if actual property is not provided', () => {
const { actual } = imageBadge;
expect(actual.x).toEqual(0);
expect(actual.y).toEqual(0);
expect(actual.width).toEqual(0);
......@@ -60,6 +65,7 @@ describe('ImageBadge', () => {
it('should return defaultimageMeta if browser property is not provided', () => {
const { browser } = imageBadge;
expect(browser.x).toEqual(0);
expect(browser.y).toEqual(0);
expect(browser.width).toEqual(0);
......
......@@ -117,11 +117,13 @@ describe('ImageDiff', () => {
it('should register click event delegation to js-diff-notes-toggle', () => {
element.querySelector('.js-diff-notes-toggle').click();
expect(imageDiffHelper.toggleCollapsed).toHaveBeenCalled();
});
it('should register click event delegation to comment-indicator', () => {
element.querySelector('.comment-indicator').click();
expect(imageDiffHelper.commentIndicatorOnClick).toHaveBeenCalled();
});
});
......@@ -147,6 +149,7 @@ describe('ImageDiff', () => {
it('should registers load eventListener', () => {
const loadEvent = new Event('load');
imageEl.dispatchEvent(loadEvent);
expect(imageDiff.renderBadges).toHaveBeenCalled();
});
});
......@@ -164,24 +167,28 @@ describe('ImageDiff', () => {
it('should register click.imageDiff event', () => {
const event = new CustomEvent('click.imageDiff');
element.dispatchEvent(event);
expect(imageDiff.imageClicked).toHaveBeenCalled();
});
it('should register blur.imageDiff event', () => {
const event = new CustomEvent('blur.imageDiff');
element.dispatchEvent(event);
expect(imageDiffHelper.removeCommentIndicator).toHaveBeenCalled();
});
it('should register addBadge.imageDiff event', () => {
const event = new CustomEvent('addBadge.imageDiff');
element.dispatchEvent(event);
expect(imageDiff.addBadge).toHaveBeenCalled();
});
it('should register removeBadge.imageDiff event', () => {
const event = new CustomEvent('removeBadge.imageDiff');
element.dispatchEvent(event);
expect(imageDiff.removeBadge).toHaveBeenCalled();
});
});
......@@ -197,6 +204,7 @@ describe('ImageDiff', () => {
it('should not register click.imageDiff event', () => {
const event = new CustomEvent('click.imageDiff');
element.dispatchEvent(event);
expect(imageDiff.imageClicked).not.toHaveBeenCalled();
});
});
......@@ -240,6 +248,7 @@ describe('ImageDiff', () => {
it('should call renderBadge for each discussionEl', () => {
const discussionEls = element.querySelectorAll('.note-container .discussion-notes .notes');
expect(imageDiff.renderBadge.calls.count()).toEqual(discussionEls.length);
});
});
......@@ -336,6 +345,7 @@ describe('ImageDiff', () => {
describe('cascade badge count', () => {
it('should update next imageBadgeEl value', () => {
const imageBadgeEls = imageDiff.imageFrameEl.querySelectorAll('.badge');
expect(imageBadgeEls[0].innerText).toEqual('1');
expect(imageBadgeEls[1].innerText).toEqual('2');
expect(imageBadgeEls.length).toEqual(2);
......
......@@ -32,6 +32,7 @@ describe('initDiscussionTab', () => {
it('should call initImageDiff for each diffFileEls', () => {
spyOn(imageDiffHelper, 'initImageDiff').and.callFake(() => {});
initDiscussionTab();
expect(imageDiffHelper.initImageDiff.calls.count()).toEqual(2);
});
});
......@@ -58,6 +58,7 @@ describe('ReplacedImageDiff', () => {
it('should extend ImageDiff', () => {
replacedImageDiff = new ReplacedImageDiff(element);
expect(replacedImageDiff instanceof ImageDiff).toEqual(true);
});
......@@ -72,6 +73,7 @@ describe('ReplacedImageDiff', () => {
it('should set imageFrameEls', () => {
const { imageFrameEls } = replacedImageDiff;
expect(imageFrameEls).toBeDefined();
expect(imageFrameEls[viewTypes.TWO_UP]).toEqual(element.querySelector('.two-up .js-image-frame'));
expect(imageFrameEls[viewTypes.SWIPE]).toEqual(element.querySelector('.swipe .js-image-frame'));
......@@ -80,6 +82,7 @@ describe('ReplacedImageDiff', () => {
it('should set viewModesEls', () => {
const { viewModesEls } = replacedImageDiff;
expect(viewModesEls).toBeDefined();
expect(viewModesEls[viewTypes.TWO_UP]).toEqual(element.querySelector('.view-modes-menu .two-up'));
expect(viewModesEls[viewTypes.SWIPE]).toEqual(element.querySelector('.view-modes-menu .swipe'));
......@@ -97,6 +100,7 @@ describe('ReplacedImageDiff', () => {
describe('currentView', () => {
it('should set currentView', () => {
replacedImageDiff.init(viewTypes.ONION_SKIN);
expect(replacedImageDiff.currentView).toEqual(viewTypes.ONION_SKIN);
});
......@@ -121,6 +125,7 @@ describe('ReplacedImageDiff', () => {
it('should set imageEls', () => {
replacedImageDiff.generateImageEls();
const { imageEls } = replacedImageDiff;
expect(imageEls).toBeDefined();
expect(imageEls[viewTypes.TWO_UP]).toEqual(element.querySelector('.two-up img'));
expect(imageEls[viewTypes.SWIPE]).toEqual(element.querySelector('.swipe img'));
......@@ -138,6 +143,7 @@ describe('ReplacedImageDiff', () => {
it('should call super.bindEvents', () => {
replacedImageDiff.bindEvents();
expect(ImageDiff.prototype.bindEvents).toHaveBeenCalled();
});
......@@ -184,6 +190,7 @@ describe('ReplacedImageDiff', () => {
expect(replacedImageDiff.imageEl).toEqual(element.querySelector('.two-up img'));
replacedImageDiff.currentView = viewTypes.SWIPE;
expect(replacedImageDiff.imageEl).toEqual(element.querySelector('.swipe img'));
});
});
......@@ -199,6 +206,7 @@ describe('ReplacedImageDiff', () => {
expect(replacedImageDiff.imageFrameEl).toEqual(element.querySelector('.two-up .js-image-frame'));
replacedImageDiff.currentView = viewTypes.ONION_SKIN;
expect(replacedImageDiff.imageFrameEl).toEqual(element.querySelector('.onion-skin .js-image-frame'));
});
});
......@@ -248,6 +256,7 @@ describe('ReplacedImageDiff', () => {
it('should call renderNewView', () => {
jasmine.clock().tick(251);
expect(replacedImageDiff.renderNewView).toHaveBeenCalled();
});
});
......
......@@ -63,6 +63,7 @@ describe('Importer Status', () => {
})
.then(() => {
const flashMessage = document.querySelector('.flash-text');
expect(flashMessage.textContent.trim()).toEqual('An error occurred while importing project: You forgot your lunch');
done();
})
......
......@@ -68,6 +68,7 @@ describe('IntegrationSettingsForm', () => {
integrationSettingsForm.canTestService = true;
integrationSettingsForm.toggleSubmitBtnLabel(true);
expect(integrationSettingsForm.$submitBtnLabel.text()).toEqual('Test settings and save changes');
});
......@@ -75,14 +76,17 @@ describe('IntegrationSettingsForm', () => {
integrationSettingsForm.canTestService = false;
integrationSettingsForm.toggleSubmitBtnLabel(false);
expect(integrationSettingsForm.$submitBtnLabel.text()).toEqual('Save changes');
integrationSettingsForm.toggleSubmitBtnLabel(true);
expect(integrationSettingsForm.$submitBtnLabel.text()).toEqual('Save changes');
integrationSettingsForm.canTestService = true;
integrationSettingsForm.toggleSubmitBtnLabel(false);
expect(integrationSettingsForm.$submitBtnLabel.text()).toEqual('Save changes');
});
});
......@@ -149,6 +153,7 @@ describe('IntegrationSettingsForm', () => {
integrationSettingsForm.testSettings(formData)
.then(() => {
const $flashContainer = $('.flash-container');
expect($flashContainer.find('.flash-text').text().trim()).toEqual('Test failed. some error');
expect($flashContainer.find('.flash-action')).toBeDefined();
expect($flashContainer.find('.flash-action').text().trim()).toEqual('Save anyway');
......@@ -170,6 +175,7 @@ describe('IntegrationSettingsForm', () => {
integrationSettingsForm.testSettings(formData)
.then(() => {
const $flashContainer = $('.flash-container');
expect($flashContainer.find('.flash-text').text().trim()).toEqual('Validations failed. some error');
expect($flashContainer.find('.flash-action')).toBeDefined();
expect($flashContainer.find('.flash-action').text().trim()).toEqual('');
......@@ -208,6 +214,7 @@ describe('IntegrationSettingsForm', () => {
integrationSettingsForm.testSettings(formData)
.then(() => {
const $flashAction = $('.flash-container .flash-action');
expect($flashAction).toBeDefined();
$flashAction.get(0).click();
......
......@@ -8,6 +8,7 @@ describe('Issuable', () => {
describe('initBulkUpdate', () => {
it('should not set bulkUpdateSidebar', () => {
Issuable = new IssuableIndex('issue_');
expect(Issuable.bulkUpdateSidebar).not.toBeDefined();
});
......@@ -17,6 +18,7 @@ describe('Issuable', () => {
document.body.appendChild(element);
Issuable = new IssuableIndex('issue_');
expect(Issuable.bulkUpdateSidebar).toBeDefined();
});
});
......
......@@ -258,6 +258,7 @@ describe('Issuable output', () => {
expect(
eventHub.$emit,
).toHaveBeenCalledWith('close.form');
expect(
window.Flash,
).toHaveBeenCalledWith('Error updating issue');
......@@ -276,6 +277,7 @@ describe('Issuable output', () => {
expect(
eventHub.$emit,
).toHaveBeenCalledWith('close.form');
expect(
window.Flash,
).toHaveBeenCalledWith('Error updating merge request');
......@@ -383,6 +385,7 @@ describe('Issuable output', () => {
expect(
eventHub.$emit,
).toHaveBeenCalledWith('close.form');
expect(
window.Flash,
).toHaveBeenCalledWith('Error deleting issue');
......@@ -422,6 +425,7 @@ describe('Issuable output', () => {
it('should render if showInlineEditButton', () => {
vm.showInlineEditButton = true;
expect(vm.$el.querySelector('.title-container .note-action-button')).toBeDefined();
});
});
......
......@@ -146,6 +146,7 @@ describe('Edit Actions components', () => {
expect(
eventHub.$emit,
).not.toHaveBeenCalledWith('delete.issuable');
expect(
vm.$el.querySelector('.btn-danger .fa'),
).toBeNull();
......
......@@ -86,12 +86,14 @@ describe('Title component', () => {
it('should not show if canUpdate is false', () => {
vm.showInlineEditButton = true;
vm.canUpdate = false;
expect(vm.$el.querySelector('.btn-edit')).toBeNull();
});
it('should show if showInlineEditButton and canUpdate', () => {
vm.showInlineEditButton = true;
vm.canUpdate = true;
expect(vm.$el.querySelector('.btn-edit')).toBeDefined();
});
......@@ -101,6 +103,7 @@ describe('Title component', () => {
Vue.nextTick(() => {
vm.$el.querySelector('.btn-edit').click();
expect(eventHub.$emit).toHaveBeenCalledWith('open.form');
});
});
......
......@@ -15,6 +15,7 @@ describe('Issue', function() {
function expectErrorMessage() {
const $flashMessage = $('div.flash-alert');
expect($flashMessage).toExist();
expect($flashMessage).toBeVisible();
expect($flashMessage).toHaveText('Unable to update this issue at this time.');
......@@ -23,6 +24,7 @@ describe('Issue', function() {
function expectIssueState(isIssueOpen) {
expectVisibility($boxClosed, !isIssueOpen);
expectVisibility($boxOpen, isIssueOpen);
expect($btn).toHaveText(isIssueOpen ? 'Close issue' : 'Reopen issue');
}
......@@ -32,6 +34,7 @@ describe('Issue', function() {
}
const $available = Issue.$btnNewBranch.find('.available');
expect($available).toHaveText('New branch');
if (!isPending && canCreate) {
......@@ -41,6 +44,7 @@ describe('Issue', function() {
}
const $unavailable = Issue.$btnNewBranch.find('.unavailable');
expect($unavailable).toHaveText('New branch unavailable');
if (!isPending && !canCreate) {
......@@ -60,14 +64,17 @@ describe('Issue', function() {
function findElements(isIssueInitiallyOpen) {
$boxClosed = $('div.status-box-issue-closed');
expect($boxClosed).toExist();
expect($boxClosed).toHaveText('Closed');
$boxOpen = $('div.status-box-open');
expect($boxOpen).toExist();
expect($boxOpen).toHaveText('Open');
$btn = $('.js-issuable-close-button');
expect($btn).toExist();
expect($btn).toHaveText(isIssueInitiallyOpen ? 'Close issue' : 'Reopen issue');
}
......@@ -135,6 +142,7 @@ describe('Issue', function() {
setTimeout(() => {
expectIssueState(!isIssueInitiallyOpen);
expect(this.$triggeredButton.get(0).getAttribute('disabled')).toBeNull();
expect(this.$projectIssuesCounter.text()).toBe(isIssueInitiallyOpen ? '1,000' : '1,002');
expectNewBranchButtonState(false, !isIssueInitiallyOpen);
......@@ -153,8 +161,10 @@ describe('Issue', function() {
setTimeout(() => {
expectIssueState(isIssueInitiallyOpen);
expect(this.$triggeredButton.get(0).getAttribute('disabled')).toBeNull();
expectErrorMessage();
expect(this.$projectIssuesCounter.text()).toBe('1,001');
expectNewBranchButtonState(false, isIssueInitiallyOpen);
......@@ -170,8 +180,10 @@ describe('Issue', function() {
setTimeout(() => {
expectIssueState(isIssueInitiallyOpen);
expect(this.$triggeredButton.get(0).getAttribute('disabled')).toBeNull();
expectErrorMessage();
expect(this.$projectIssuesCounter.text()).toBe('1,001');
expectNewBranchButtonState(false, isIssueInitiallyOpen);
......
......@@ -34,6 +34,7 @@ describe('Commit block', () => {
expect(vm.$el.querySelector('.js-commit-sha').getAttribute('href')).toEqual(
props.commit.commit_path,
);
expect(vm.$el.querySelector('.js-commit-sha').textContent.trim()).toEqual(
props.commit.short_id,
);
......@@ -55,6 +56,7 @@ describe('Commit block', () => {
expect(vm.$el.querySelector('.js-link-commit').getAttribute('href')).toEqual(
props.mergeRequest.path,
);
expect(vm.$el.querySelector('.js-link-commit').textContent.trim()).toEqual(
`!${props.mergeRequest.iid}`,
);
......
......@@ -56,6 +56,7 @@ describe('Empty State', () => {
vm = mountComponent(Component, {
...props,
});
expect(vm.$el.querySelector('.js-job-empty-state-content')).toBeNull();
});
});
......@@ -84,6 +85,7 @@ describe('Empty State', () => {
...props,
content,
});
expect(vm.$el.querySelector('.js-job-empty-state-action')).toBeNull();
});
});
......
......@@ -54,6 +54,7 @@ describe('Environments block', () => {
expect(vm.$el.textContent.trim()).toEqual(
'This job is an out-of-date deployment to environment. View the most recent deployment #deployment.',
);
expect(vm.$el.querySelector('.js-job-deployment-link').getAttribute('href')).toEqual('bar');
});
});
......@@ -110,6 +111,7 @@ describe('Environments block', () => {
expect(vm.$el.textContent.trim()).toEqual(
'This job is creating a deployment to environment and will overwrite the latest deployment.',
);
expect(vm.$el.querySelector('.js-job-deployment-link').getAttribute('href')).toEqual('foo');
});
});
......@@ -139,6 +141,7 @@ describe('Environments block', () => {
},
iconStatus: status,
});
expect(vm.$el.querySelector('.js-environment-link')).toBeNull();
});
});
......
......@@ -199,6 +199,7 @@ describe('Job log controllers', () => {
isScrollingDown: false,
isTraceSizeVisible: true,
});
expect(vm.$el.querySelector('.js-scroll-bottom').className).not.toContain('animate');
});
});
......
......@@ -74,6 +74,7 @@ describe('Sidebar details block', () => {
expect(vm.$el.querySelector('.js-new-issue').getAttribute('href')).toEqual(
job.new_issue_path,
);
expect(vm.$el.querySelector('.js-new-issue').textContent.trim()).toEqual('New issue');
});
......
......@@ -46,6 +46,7 @@ describe('Job Store Getters', () => {
it('returns created_at key', () => {
const created = '2018-08-31T16:20:49.023Z';
localState.job.created_at = created;
expect(getters.headerTime(localState)).toEqual(created);
});
});
......@@ -64,6 +65,7 @@ describe('Job Store Getters', () => {
describe('without status & with callout message', () => {
it('returns false', () => {
localState.job.callout_message = 'Callout message';
expect(getters.shouldRenderCalloutMessage(localState)).toEqual(false);
});
});
......@@ -81,6 +83,7 @@ describe('Job Store Getters', () => {
describe('when started equals null', () => {
it('returns false', () => {
localState.job.started = null;
expect(getters.shouldRenderTriggeredLabel(localState)).toEqual(false);
});
});
......@@ -88,6 +91,7 @@ describe('Job Store Getters', () => {
describe('when started equals string', () => {
it('returns true', () => {
localState.job.started = '2018-08-31T16:20:49.023Z';
expect(getters.shouldRenderTriggeredLabel(localState)).toEqual(true);
});
});
......@@ -103,6 +107,7 @@ describe('Job Store Getters', () => {
describe('with an empty object for `deployment_status`', () => {
it('returns false', () => {
localState.job.deployment_status = {};
expect(getters.hasEnvironment(localState)).toEqual(false);
});
});
......
......@@ -15,6 +15,7 @@ describe('Jobs Store Mutations', () => {
describe('SET_JOB_ENDPOINT', () => {
it('should set jobEndpoint', () => {
mutations[types.SET_JOB_ENDPOINT](stateCopy, 'job/21312321.json');
expect(stateCopy.jobEndpoint).toEqual('job/21312321.json');
});
});
......@@ -22,6 +23,7 @@ describe('Jobs Store Mutations', () => {
describe('REQUEST_STATUS_FAVICON', () => {
it('should set fetchingStatusFavicon to true', () => {
mutations[types.REQUEST_STATUS_FAVICON](stateCopy);
expect(stateCopy.fetchingStatusFavicon).toEqual(true);
});
});
......@@ -29,6 +31,7 @@ describe('Jobs Store Mutations', () => {
describe('RECEIVE_STATUS_FAVICON_SUCCESS', () => {
it('should set fetchingStatusFavicon to false', () => {
mutations[types.RECEIVE_STATUS_FAVICON_SUCCESS](stateCopy);
expect(stateCopy.fetchingStatusFavicon).toEqual(false);
});
});
......@@ -36,6 +39,7 @@ describe('Jobs Store Mutations', () => {
describe('RECEIVE_STATUS_FAVICON_ERROR', () => {
it('should set fetchingStatusFavicon to false', () => {
mutations[types.RECEIVE_STATUS_FAVICON_ERROR](stateCopy);
expect(stateCopy.fetchingStatusFavicon).toEqual(false);
});
});
......@@ -48,6 +52,7 @@ describe('Jobs Store Mutations', () => {
mutations[types.RECEIVE_TRACE_SUCCESS](stateCopy, {
state: stateLog,
});
expect(stateCopy.traceState).toEqual(stateLog);
});
});
......@@ -77,6 +82,7 @@ describe('Jobs Store Mutations', () => {
size: 511846,
complete: true,
});
expect(stateCopy.trace).toEqual(html);
expect(stateCopy.traceSize).toEqual(511846);
expect(stateCopy.isTraceComplete).toEqual(true);
......@@ -86,6 +92,7 @@ describe('Jobs Store Mutations', () => {
describe('STOP_POLLING_TRACE', () => {
it('sets isTraceComplete to true', () => {
mutations[types.STOP_POLLING_TRACE](stateCopy);
expect(stateCopy.isTraceComplete).toEqual(true);
});
});
......@@ -93,6 +100,7 @@ describe('Jobs Store Mutations', () => {
describe('RECEIVE_TRACE_ERROR', () => {
it('resets trace state and sets error to true', () => {
mutations[types.RECEIVE_TRACE_ERROR](stateCopy);
expect(stateCopy.isLoadingTrace).toEqual(false);
expect(stateCopy.isTraceComplete).toEqual(true);
expect(stateCopy.hasTraceError).toEqual(true);
......@@ -110,29 +118,35 @@ describe('Jobs Store Mutations', () => {
describe('RECEIVE_JOB_SUCCESS', () => {
it('sets is loading to false', () => {
mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321 });
expect(stateCopy.isLoading).toEqual(false);
});
it('sets hasError to false', () => {
mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321 });
expect(stateCopy.hasError).toEqual(false);
});
it('sets job data', () => {
mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321 });
expect(stateCopy.job).toEqual({ id: 1312321 });
});
it('sets selectedStage when the selectedStage is More', () => {
expect(stateCopy.selectedStage).toEqual('More');
mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321, stage: 'deploy' });
expect(stateCopy.selectedStage).toEqual('deploy');
});
it('does not set selectedStage when the selectedStage is not More', () => {
stateCopy.selectedStage = 'notify'
expect(stateCopy.selectedStage).toEqual('notify');
mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321, stage: 'deploy' });
expect(stateCopy.selectedStage).toEqual('notify');
});
});
......@@ -178,6 +192,7 @@ describe('Jobs Store Mutations', () => {
describe('REQUEST_STAGES', () => {
it('sets isLoadingStages to true', () => {
mutations[types.REQUEST_STAGES](stateCopy);
expect(stateCopy.isLoadingStages).toEqual(true);
});
});
......@@ -213,11 +228,13 @@ describe('Jobs Store Mutations', () => {
describe('REQUEST_JOBS_FOR_STAGE', () => {
it('sets isLoadingStages to true', () => {
mutations[types.REQUEST_JOBS_FOR_STAGE](stateCopy, { name: 'deploy' });
expect(stateCopy.isLoadingJobs).toEqual(true);
});
it('sets selectedStage', () => {
mutations[types.REQUEST_JOBS_FOR_STAGE](stateCopy, { name: 'deploy' });
expect(stateCopy.selectedStage).toEqual('deploy');
})
});
......
......@@ -42,6 +42,7 @@ describe('common_utils', () => {
it('should remove the question mark from the search params', () => {
const paramsArray = commonUtils.urlParamsToArray('?test=thing');
expect(paramsArray[0][0]).not.toBe('?');
});
});
......@@ -121,6 +122,7 @@ describe('common_utils', () => {
commonUtils.handleLocationHash();
expectGetElementIdToHaveBeenCalledWith('test');
expect(window.scrollY).toBe(document.getElementById('test').offsetTop);
document.getElementById('parent').remove();
......@@ -139,6 +141,7 @@ describe('common_utils', () => {
expectGetElementIdToHaveBeenCalledWith('test');
expectGetElementIdToHaveBeenCalledWith('user-content-test');
expect(window.scrollY).toBe(document.getElementById('user-content-test').offsetTop);
document.getElementById('parent').remove();
......@@ -159,6 +162,7 @@ describe('common_utils', () => {
expectGetElementIdToHaveBeenCalledWith('test');
expectGetElementIdToHaveBeenCalledWith('user-content-test');
expect(window.scrollY).toBe(document.getElementById('user-content-test').offsetTop - 50);
expect(window.scrollBy).toHaveBeenCalledWith(0, -50);
......@@ -222,20 +226,24 @@ describe('common_utils', () => {
it('should return valid parameter', () => {
const value = commonUtils.getParameterByName('scope');
expect(commonUtils.getParameterByName('p')).toEqual('2');
expect(value).toBe('all');
});
it('should return invalid parameter', () => {
const value = commonUtils.getParameterByName('fakeParameter');
expect(value).toBe(null);
});
it('should return valid paramentes if URL is provided', () => {
let value = commonUtils.getParameterByName('foo', 'http://cocteau.twins/?foo=bar');
expect(value).toBe('bar');
value = commonUtils.getParameterByName('manan', 'http://cocteau.twins/?foo=bar&manan=canchu');
expect(value).toBe('canchu');
});
});
......@@ -395,6 +403,7 @@ describe('common_utils', () => {
})
).catch(done.fail)).then((respBackoff) => {
const timeouts = window.setTimeout.calls.allArgs().map(([, timeout]) => timeout);
expect(timeouts).toEqual([2000, 4000]);
expect(respBackoff).toBe(expectedResponseValue);
done();
......@@ -405,6 +414,7 @@ describe('common_utils', () => {
commonUtils.backOff(next => next(), 64000)
.catch((errBackoffResp) => {
const timeouts = window.setTimeout.calls.allArgs().map(([, timeout]) => timeout);
expect(timeouts).toEqual([2000, 4000, 8000, 16000, 32000, 32000]);
expect(errBackoffResp instanceof Error).toBe(true);
expect(errBackoffResp.message).toBe('BACKOFF_TIMEOUT');
......@@ -450,6 +460,7 @@ describe('common_utils', () => {
const favicon = document.getElementById('favicon');
favicon.setAttribute('href', 'new/favicon');
commonUtils.resetFavicon();
expect(document.getElementById('favicon').getAttribute('href')).toEqual('default/favicon');
});
});
......@@ -507,6 +518,7 @@ describe('common_utils', () => {
commonUtils.setCiStatusFavicon(BUILD_URL)
.catch(() => {
const favicon = document.getElementById('favicon');
expect(favicon.getAttribute('href')).toEqual(faviconDataUrl);
done();
});
......@@ -520,6 +532,7 @@ describe('common_utils', () => {
commonUtils.setCiStatusFavicon(BUILD_URL)
.then(() => {
const favicon = document.getElementById('favicon');
expect(favicon.getAttribute('href')).toEqual(faviconWithOverlayDataUrl);
done();
})
......
......@@ -18,6 +18,7 @@ describe('DOM Utils', () => {
it('adds class if element exists', () => {
const childElement = parentElement.querySelector('.child');
expect(childElement).not.toBe(null);
addClassIfElementExists(childElement, className);
......@@ -27,6 +28,7 @@ describe('DOM Utils', () => {
it('does not throw if element does not exist', () => {
const childElement = parentElement.querySelector('.other-child');
expect(childElement).toBe(null);
addClassIfElementExists(childElement, className);
......
......@@ -10,6 +10,7 @@ describe('Number Utils', () => {
const formattedNumber = formatRelevantDigits('1000.1234567');
const rightFromDecimal = formattedNumber.split('.')[1];
const leftFromDecimal = formattedNumber.split('.')[0];
expect(rightFromDecimal.length).toBe(4);
expect(leftFromDecimal.length).toBe(4);
});
......@@ -18,6 +19,7 @@ describe('Number Utils', () => {
const formattedNumber = formatRelevantDigits('0.1234567');
const rightFromDecimal = formattedNumber.split('.')[1];
const leftFromDecimal = formattedNumber.split('.')[0];
expect(rightFromDecimal.length).toBe(3);
expect(leftFromDecimal.length).toBe(1);
});
......@@ -26,6 +28,7 @@ describe('Number Utils', () => {
const formattedNumber = formatRelevantDigits('10.1234567');
const rightFromDecimal = formattedNumber.split('.')[1];
const leftFromDecimal = formattedNumber.split('.')[0];
expect(rightFromDecimal.length).toBe(2);
expect(leftFromDecimal.length).toBe(2);
});
......@@ -34,6 +37,7 @@ describe('Number Utils', () => {
const formattedNumber = formatRelevantDigits('100.1234567');
const rightFromDecimal = formattedNumber.split('.')[1];
const leftFromDecimal = formattedNumber.split('.')[0];
expect(rightFromDecimal.length).toBe(1);
expect(leftFromDecimal.length).toBe(3);
});
......
......@@ -54,6 +54,7 @@ describe('sticky', () => {
expect(
el.classList.remove,
).toHaveBeenCalledWith('is-stuck');
expect(
el.classList.contains('is-stuck'),
).toBeFalsy();
......
......@@ -95,6 +95,7 @@ describe('init markdown', () => {
select });
const expectedText = text.replace(selected, `[${selected}](url)`);
expect(textArea.value).toEqual(expectedText);
expect(textArea.selectionStart).toEqual(expectedText.indexOf(select));
expect(textArea.selectionEnd).toEqual(expectedText.indexOf(select) + select.length);
......@@ -114,6 +115,7 @@ describe('init markdown', () => {
select });
const expectedText = initialValue.replace(selected, `[${selected}](url)`);
expect(textArea.value).toEqual(expectedText);
expect(textArea.selectionStart).toEqual(expectedText.lastIndexOf(select));
expect(textArea.selectionEnd).toEqual(expectedText.lastIndexOf(select) + select.length);
......
/* eslint-disable no-var, prefer-template, no-else-return, dot-notation, no-return-assign, no-new, one-var, no-underscore-dangle */
/* eslint-disable no-var, prefer-template, no-else-return, dot-notation, no-return-assign, no-new, no-underscore-dangle */
import $ from 'jquery';
import LineHighlighter from '~/line_highlighter';
......@@ -27,39 +27,42 @@ import LineHighlighter from '~/line_highlighter';
describe('behavior', function() {
it('highlights one line given in the URL hash', function() {
new LineHighlighter({ hash: '#L13' });
return expect($('#LC13')).toHaveClass(this.css);
expect($('#LC13')).toHaveClass(this.css);
});
it('highlights one line given in the URL hash with given CSS class name', function() {
const hiliter = new LineHighlighter({ hash: '#L13', highlightLineClass: 'hilite' });
expect(hiliter.highlightLineClass).toBe('hilite');
expect($('#LC13')).toHaveClass('hilite');
expect($('#LC13')).not.toHaveClass('hll');
});
it('highlights a range of lines given in the URL hash', function() {
var line, results;
var line;
new LineHighlighter({ hash: '#L5-25' });
expect($("." + this.css).length).toBe(21);
results = [];
for (line = 5; line <= 25; line += 1) {
results.push(expect($("#LC" + line)).toHaveClass(this.css));
expect($("#LC" + line)).toHaveClass(this.css);
}
return results;
});
it('scrolls to the first highlighted line on initial load', function() {
var spy;
spy = spyOn($, 'scrollTo');
new LineHighlighter({ hash: '#L5-25' });
return expect(spy).toHaveBeenCalledWith('#L5', jasmine.anything());
expect(spy).toHaveBeenCalledWith('#L5', jasmine.anything());
});
it('discards click events', function() {
var spy;
spy = spyOnEvent('a[data-line-number]', 'click');
clickLine(13);
return expect(spy).toHaveBeenPrevented();
expect(spy).toHaveBeenPrevented();
});
it('handles garbage input from the hash', function() {
......@@ -67,7 +70,8 @@ import LineHighlighter from '~/line_highlighter';
func = function() {
return new LineHighlighter({ fileHolderSelector: '#blob-content-holder' });
};
return expect(func).not.toThrow();
expect(func).not.toThrow();
});
});
......@@ -76,30 +80,36 @@ import LineHighlighter from '~/line_highlighter';
var spy;
spy = spyOn(this["class"], 'setHash').and.callThrough();
$('#L13 i').mousedown().click();
expect(spy).toHaveBeenCalledWith(13);
return expect($('#LC13')).toHaveClass(this.css);
expect($('#LC13')).toHaveClass(this.css);
});
describe('without shiftKey', function() {
it('highlights one line when clicked', function() {
clickLine(13);
return expect($('#LC13')).toHaveClass(this.css);
expect($('#LC13')).toHaveClass(this.css);
});
it('unhighlights previously highlighted lines', function() {
clickLine(13);
clickLine(20);
expect($('#LC13')).not.toHaveClass(this.css);
return expect($('#LC20')).toHaveClass(this.css);
expect($('#LC20')).toHaveClass(this.css);
});
return it('sets the hash', function() {
it('sets the hash', function() {
var spy;
spy = spyOn(this["class"], 'setHash').and.callThrough();
clickLine(13);
return expect(spy).toHaveBeenCalledWith(13);
expect(spy).toHaveBeenCalledWith(13);
});
});
return describe('with shiftKey', function() {
describe('with shiftKey', function() {
it('sets the hash', function() {
var spy;
spy = spyOn(this["class"], 'setHash').and.callThrough();
......@@ -107,8 +117,9 @@ import LineHighlighter from '~/line_highlighter';
clickLine(20, {
shiftKey: true
});
expect(spy).toHaveBeenCalledWith(13);
return expect(spy).toHaveBeenCalledWith(13, 20);
expect(spy).toHaveBeenCalledWith(13, 20);
});
describe('without existing highlight', function() {
......@@ -116,80 +127,82 @@ import LineHighlighter from '~/line_highlighter';
clickLine(13, {
shiftKey: true
});
expect($('#LC13')).toHaveClass(this.css);
return expect($("." + this.css).length).toBe(1);
expect($("." + this.css).length).toBe(1);
});
return it('sets the hash', function() {
it('sets the hash', function() {
var spy;
spy = spyOn(this["class"], 'setHash');
clickLine(13, {
shiftKey: true
});
return expect(spy).toHaveBeenCalledWith(13);
expect(spy).toHaveBeenCalledWith(13);
});
});
describe('with existing single-line highlight', function() {
it('uses existing line as last line when target is lesser', function() {
var line, results;
var line;
clickLine(20);
clickLine(15, {
shiftKey: true
});
expect($("." + this.css).length).toBe(6);
results = [];
for (line = 15; line <= 20; line += 1) {
results.push(expect($("#LC" + line)).toHaveClass(this.css));
expect($("#LC" + line)).toHaveClass(this.css);
}
return results;
});
return it('uses existing line as first line when target is greater', function() {
var line, results;
it('uses existing line as first line when target is greater', function() {
var line;
clickLine(5);
clickLine(10, {
shiftKey: true
});
expect($("." + this.css).length).toBe(6);
results = [];
for (line = 5; line <= 10; line += 1) {
results.push(expect($("#LC" + line)).toHaveClass(this.css));
expect($("#LC" + line)).toHaveClass(this.css);
}
return results;
});
});
return describe('with existing multi-line highlight', function() {
describe('with existing multi-line highlight', function() {
beforeEach(function() {
clickLine(10, {
shiftKey: true
});
return clickLine(13, {
clickLine(13, {
shiftKey: true
});
});
it('uses target as first line when it is less than existing first line', function() {
var line, results;
var line;
clickLine(5, {
shiftKey: true
});
expect($("." + this.css).length).toBe(6);
results = [];
for (line = 5; line <= 10; line += 1) {
results.push(expect($("#LC" + line)).toHaveClass(this.css));
expect($("#LC" + line)).toHaveClass(this.css);
}
return results;
});
return it('uses target as last line when it is greater than existing first line', function() {
var line, results;
it('uses target as last line when it is greater than existing first line', function() {
var line;
clickLine(15, {
shiftKey: true
});
expect($("." + this.css).length).toBe(6);
results = [];
for (line = 10; line <= 15; line += 1) {
results.push(expect($("#LC" + line)).toHaveClass(this.css));
expect($("#LC" + line)).toHaveClass(this.css);
}
return results;
});
});
});
......@@ -197,47 +210,58 @@ import LineHighlighter from '~/line_highlighter';
describe('hashToRange', function() {
beforeEach(function() {
return this.subject = this["class"].hashToRange;
this.subject = this["class"].hashToRange;
});
it('extracts a single line number from the hash', function() {
return expect(this.subject('#L5')).toEqual([5, null]);
expect(this.subject('#L5')).toEqual([5, null]);
});
it('extracts a range of line numbers from the hash', function() {
return expect(this.subject('#L5-15')).toEqual([5, 15]);
expect(this.subject('#L5-15')).toEqual([5, 15]);
});
return it('returns [null, null] when the hash is not a line number', function() {
return expect(this.subject('#foo')).toEqual([null, null]);
it('returns [null, null] when the hash is not a line number', function() {
expect(this.subject('#foo')).toEqual([null, null]);
});
});
describe('highlightLine', function() {
beforeEach(function() {
return this.subject = this["class"].highlightLine;
this.subject = this["class"].highlightLine;
});
it('highlights the specified line', function() {
this.subject(13);
return expect($('#LC13')).toHaveClass(this.css);
expect($('#LC13')).toHaveClass(this.css);
});
return it('accepts a String-based number', function() {
it('accepts a String-based number', function() {
this.subject('13');
return expect($('#LC13')).toHaveClass(this.css);
expect($('#LC13')).toHaveClass(this.css);
});
});
return describe('setHash', function() {
describe('setHash', function() {
beforeEach(function() {
return this.subject = this["class"].setHash;
this.subject = this["class"].setHash;
});
it('sets the location hash for a single line', function() {
this.subject(5);
return expect(this.spies.__setLocationHash__).toHaveBeenCalledWith('#L5');
expect(this.spies.__setLocationHash__).toHaveBeenCalledWith('#L5');
});
return it('sets the location hash for a range', function() {
it('sets the location hash for a range', function() {
this.subject(5, 15);
return expect(this.spies.__setLocationHash__).toHaveBeenCalledWith('#L5-15');
expect(this.spies.__setLocationHash__).toHaveBeenCalledWith('#L5-15');
});
});
});
......
......@@ -4,6 +4,7 @@ describe('locale', () => {
describe('ensureSingleLine', () => {
it('should remove newlines at the start of the string', () => {
const result = 'Test';
expect(ensureSingleLine(`\n${result}`)).toBe(result);
expect(ensureSingleLine(`\t\n\t${result}`)).toBe(result);
expect(ensureSingleLine(`\r\n${result}`)).toBe(result);
......@@ -14,6 +15,7 @@ describe('locale', () => {
it('should remove newlines at the end of the string', () => {
const result = 'Test';
expect(ensureSingleLine(`${result}\n`)).toBe(result);
expect(ensureSingleLine(`${result}\t\n\t`)).toBe(result);
expect(ensureSingleLine(`${result}\r\n`)).toBe(result);
......@@ -24,6 +26,7 @@ describe('locale', () => {
it('should replace newlines in the middle of the string with a single space', () => {
const result = 'Test';
expect(ensureSingleLine(`${result}\n${result}`)).toBe(`${result} ${result}`);
expect(ensureSingleLine(`${result}\t\n\t${result}`)).toBe(`${result} ${result}`);
expect(ensureSingleLine(`${result}\r\n${result}`)).toBe(`${result} ${result}`);
......
......@@ -37,7 +37,8 @@ import IssuablesHelper from '~/helpers/issuables_helper';
$('input[type=checkbox]')
.attr('checked', true)[0]
.dispatchEvent(changeEvent);
return expect($('.js-task-list-field').val()).toBe('- [x] Task List Item');
expect($('.js-task-list-field').val()).toBe('- [x] Task List Item');
});
it('submits an ajax request on tasklist:changed', done => {
......
......@@ -61,6 +61,7 @@ describe('Mini Pipeline Graph Dropdown', () => {
new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents();
document.querySelector('.js-builds-dropdown-button').click();
expect(ajaxSpy.calls.allArgs()[0][0]).toEqual('foobar');
});
......
......@@ -107,6 +107,7 @@ describe('Dashboard', () => {
setTimeout(() => {
const dropdownMenuEnvironments = component.$el.querySelectorAll('.dropdown-menu ul li a');
expect(dropdownMenuEnvironments.length).toEqual(component.store.environmentsData.length);
done();
});
......@@ -124,6 +125,7 @@ describe('Dashboard', () => {
const dropdownIsActiveElement = component.$el.querySelectorAll(
'.dropdown-menu ul li a.is-active',
);
expect(dropdownIsActiveElement.length).toEqual(1);
expect(dropdownIsActiveElement[0].textContent.trim()).toEqual(
component.currentEnvironmentName,
......
......@@ -45,9 +45,11 @@ describe('Monitoring Paths', () => {
});
component.lineStyle = 'dashed';
expect(component.strokeDashArray).toBe('3, 1');
component.lineStyle = 'dotted';
expect(component.strokeDashArray).toBe('1, 1');
});
});
......
......@@ -49,6 +49,7 @@ describe('Graph', () => {
});
const transformedHeight = `${component.graphHeight - 100}`;
expect(component.axisTransform.indexOf(transformedHeight)).not.toEqual(-1);
});
......@@ -62,6 +63,7 @@ describe('Graph', () => {
});
const viewBoxArray = component.outerViewBox.split(' ');
expect(typeof component.outerViewBox).toEqual('string');
expect(viewBoxArray[2]).toEqual(component.graphWidth.toString());
expect(viewBoxArray[3]).toEqual((component.graphHeight - 50).toString());
......@@ -99,6 +101,7 @@ describe('Graph', () => {
component.seriesUnderMouse = component.timeSeries;
component.positionFlag();
expect(component.currentData).toBe(component.timeSeries[0].values[10]);
});
});
......@@ -17,6 +17,7 @@ describe('MonitoringStore', function () {
it('contains deployment data', () => {
this.store.storeDeploymentData(deploymentData);
expect(this.store.deploymentData).toBeDefined();
expect(this.store.deploymentData.length).toEqual(3);
expect(typeof this.store.deploymentData[0]).toEqual('object');
......@@ -24,6 +25,7 @@ describe('MonitoringStore', function () {
it('only stores environment data that contains deployments', () => {
this.store.storeEnvironmentsData(environmentData);
expect(this.store.environmentsData.length).toEqual(2);
});
});
......@@ -5,14 +5,14 @@ import NewBranchForm from '~/new_branch_form';
(function() {
describe('Branch', function() {
return describe('create a new branch', function() {
describe('create a new branch', function() {
var expectToHaveError, fillNameWith;
preloadFixtures('branches/new_branch.html.raw');
fillNameWith = function(value) {
return $('.js-branch-name').val(value).trigger('blur');
};
expectToHaveError = function(error) {
return expect($('.js-branch-name-error span').text()).toEqual(error);
expect($('.js-branch-name-error span').text()).toEqual(error);
};
beforeEach(function() {
loadFixtures('branches/new_branch.html.raw');
......@@ -164,28 +164,35 @@ import NewBranchForm from '~/new_branch_form';
it("removes the error message when is a valid name", function() {
fillNameWith('foo?bar');
expect($('.js-branch-name-error span').length).toEqual(1);
fillNameWith('foobar');
return expect($('.js-branch-name-error span').length).toEqual(0);
expect($('.js-branch-name-error span').length).toEqual(0);
});
it("can have dashes anywhere", function() {
fillNameWith('-foo-bar-zoo-');
return expect($('.js-branch-name-error span').length).toEqual(0);
expect($('.js-branch-name-error span').length).toEqual(0);
});
it("can have underscores anywhere", function() {
fillNameWith('_foo_bar_zoo_');
return expect($('.js-branch-name-error span').length).toEqual(0);
expect($('.js-branch-name-error span').length).toEqual(0);
});
it("can have numbers anywhere", function() {
fillNameWith('1foo2bar3zoo4');
return expect($('.js-branch-name-error span').length).toEqual(0);
expect($('.js-branch-name-error span').length).toEqual(0);
});
return it("can be only letters", function() {
it("can be only letters", function() {
fillNameWith('foo');
return expect($('.js-branch-name-error span').length).toEqual(0);
expect($('.js-branch-name-error span').length).toEqual(0);
});
});
});
......
......@@ -51,6 +51,7 @@ describe('issue_comment_form component', () => {
spyOn(vm, 'stopPolling');
vm.handleSave();
expect(vm.isSubmitting).toEqual(true);
expect(vm.note).toEqual('');
expect(vm.saveNote).toHaveBeenCalled();
......@@ -77,10 +78,14 @@ describe('issue_comment_form component', () => {
vm.handleSave();
Vue.nextTick()
.then(() => expect(actionButton.disabled).toBeTruthy())
.then(() => {
expect(actionButton.disabled).toBeTruthy();
})
.then(saveNotePromise)
.then(Vue.nextTick)
.then(() => expect(actionButton.disabled).toBeFalsy())
.then(() => {
expect(actionButton.disabled).toBeFalsy();
})
.then(done)
.catch(done.fail);
});
......@@ -121,6 +126,7 @@ describe('issue_comment_form component', () => {
it('should link to markdown docs', () => {
const { markdownDocsPath } = notesDataMock;
expect(vm.$el.querySelector(`a[href="${markdownDocsPath}"]`).textContent.trim()).toEqual(
'Markdown',
);
......@@ -128,6 +134,7 @@ describe('issue_comment_form component', () => {
it('should link to quick actions docs', () => {
const { quickActionsDocsPath } = notesDataMock;
expect(
vm.$el.querySelector(`a[href="${quickActionsDocsPath}"]`).textContent.trim(),
).toEqual('quick actions');
......@@ -215,6 +222,7 @@ describe('issue_comment_form component', () => {
expect(vm.$el.querySelector('.btn-comment-and-close').textContent.trim()).toEqual(
'Comment & close issue',
);
expect(vm.$el.querySelector('.js-note-discard')).toBeDefined();
done();
});
......
......@@ -223,6 +223,7 @@ describe('note_app', () => {
it('should render markdown docs url', () => {
const { markdownDocsPath } = mockData.notesDataMock;
expect(vm.$el.querySelector(`a[href="${markdownDocsPath}"]`).textContent.trim()).toEqual(
'Markdown',
);
......@@ -230,6 +231,7 @@ describe('note_app', () => {
it('should render quick action docs url', () => {
const { quickActionsDocsPath } = mockData.notesDataMock;
expect(vm.$el.querySelector(`a[href="${quickActionsDocsPath}"]`).textContent.trim()).toEqual(
'quick actions',
);
......
......@@ -76,6 +76,7 @@ describe('issue_note_form component', () => {
it('should link to markdown docs', () => {
const { markdownDocsPath } = notesDataMock;
expect(vm.$el.querySelector(`a[href="${markdownDocsPath}"]`).textContent.trim()).toEqual(
'Markdown',
);
......
......@@ -144,6 +144,7 @@ describe('noteable_discussion component', () => {
};
const note = vm.componentData(data);
expect(note).toEqual(data.notes[0]);
});
......@@ -155,6 +156,7 @@ describe('noteable_discussion component', () => {
};
const note = vm.componentData(data);
expect(note).toEqual(data);
});
});
......
......@@ -36,6 +36,7 @@ describe('issue_note', () => {
it('should render note header content', () => {
const el = vm.$el.querySelector('.note-header .note-header-author-name');
expect(el.textContent.trim()).toEqual(note.author.name);
});
......
......@@ -205,6 +205,7 @@ describe('Getters Notes Store', () => {
'123',
'456',
]);
expect(getters.unresolvedDiscussionsIdsOrdered(state, localGetters)(undefined)).toEqual([
'123',
'456',
......
......@@ -30,11 +30,13 @@ describe('Notes Store mutations', () => {
expect(state).toEqual({
discussions: [noteData],
});
expect(state.discussions.length).toBe(1);
});
it('should not add the same note to the notes array', () => {
mutations.ADD_NEW_NOTE(state, note);
expect(state.discussions.length).toBe(1);
});
});
......@@ -106,6 +108,7 @@ describe('Notes Store mutations', () => {
};
mutations.SET_NOTES_DATA(state, notesDataMock);
expect(state.notesData).toEqual(notesDataMock);
});
});
......@@ -117,6 +120,7 @@ describe('Notes Store mutations', () => {
};
mutations.SET_NOTEABLE_DATA(state, noteableDataMock);
expect(state.noteableData).toEqual(noteableDataMock);
});
});
......@@ -128,6 +132,7 @@ describe('Notes Store mutations', () => {
};
mutations.SET_USER_DATA(state, userDataMock);
expect(state.userData).toEqual(userDataMock);
});
});
......@@ -151,6 +156,7 @@ describe('Notes Store mutations', () => {
};
mutations.SET_INITIAL_DISCUSSIONS(state, [note, legacyNote]);
expect(state.discussions[0].id).toEqual(note.id);
expect(state.discussions[1].notes[0].note).toBe(legacyNote.notes[0].note);
expect(state.discussions[2].notes[0].note).toBe(legacyNote.notes[1].note);
......@@ -200,6 +206,7 @@ describe('Notes Store mutations', () => {
};
mutations.SET_LAST_FETCHED_AT(state, 'timestamp');
expect(state.lastFetchedAt).toEqual('timestamp');
});
});
......@@ -211,6 +218,7 @@ describe('Notes Store mutations', () => {
};
mutations.SET_TARGET_NOTE_HASH(state, 'hash');
expect(state.targetNoteHash).toEqual('hash');
});
});
......@@ -221,6 +229,7 @@ describe('Notes Store mutations', () => {
discussions: [],
};
mutations.SHOW_PLACEHOLDER_NOTE(state, note);
expect(state.discussions[0].isPlaceholderNote).toEqual(true);
});
});
......@@ -261,6 +270,7 @@ describe('Notes Store mutations', () => {
awardName: 'bath_tone3',
};
mutations.TOGGLE_AWARD(state, data);
expect(state.discussions[0].award_emoji.length).toEqual(2);
});
});
......@@ -316,6 +326,7 @@ describe('Notes Store mutations', () => {
};
mutations.CLOSE_ISSUE(state);
expect(state.noteableData.state).toEqual('closed');
});
});
......@@ -333,6 +344,7 @@ describe('Notes Store mutations', () => {
};
mutations.REOPEN_ISSUE(state);
expect(state.noteableData.state).toEqual('reopened');
});
});
......@@ -350,6 +362,7 @@ describe('Notes Store mutations', () => {
};
mutations.TOGGLE_STATE_BUTTON_LOADING(state, true);
expect(state.isToggleStateButtonLoading).toEqual(true);
});
......@@ -365,6 +378,7 @@ describe('Notes Store mutations', () => {
};
mutations.TOGGLE_STATE_BUTTON_LOADING(state, false);
expect(state.isToggleStateButtonLoading).toEqual(false);
});
});
......@@ -376,6 +390,7 @@ describe('Notes Store mutations', () => {
};
mutations.SET_NOTES_FETCHED_STATE(state, true);
expect(state.isNotesFetched).toEqual(true);
});
});
......
......@@ -123,9 +123,11 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
it('autosizes after comment submission', function() {
$(textarea).text('This is an example comment note');
expect(this.autoSizeSpy).not.toHaveBeenTriggered();
$('.js-comment-button').click();
expect(this.autoSizeSpy).toHaveBeenTriggered();
});
......@@ -136,6 +138,7 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
deferred.reject();
$('.js-comment-button').click();
expect($(textarea).val()).toEqual('A comment with `markup`.');
});
});
......@@ -538,6 +541,7 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
mockNotesPost();
$('.js-comment-button').click();
expect($notesContainer.find('.note.being-posted').length).toBeGreaterThan(0);
});
......@@ -556,6 +560,7 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
describe('postComment', () => {
it('disables the submit button', done => {
const $submitButton = $form.find('.js-comment-submit-button');
expect($submitButton).not.toBeDisabled();
const dummyEvent = {
preventDefault() {},
......@@ -637,6 +642,7 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
.then(timeoutPromise)
.then(() => {
const $updatedNoteEl = $notesContainer.find(`#note_${note.id}`);
expect($updatedNoteEl.hasClass('.being-posted')).toEqual(false); // Remove being-posted visuals
expect(
$updatedNoteEl
......@@ -644,6 +650,7 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
.text()
.trim(),
).toEqual(sampleComment); // See if comment reverted back to original
expect($('.flash-container').is(':visible')).toEqual(true); // Flash error message shown
done();
......@@ -749,6 +756,7 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
const $updatedNoteEl = $notesContainer
.find(`#note_${note.id}`)
.find('.js-task-list-container');
expect(
$updatedNoteEl
.find('.note-text')
......@@ -860,6 +868,7 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
it('should return executing quick action description when note has single quick action', () => {
const sampleComment = '/close';
expect(this.notes.getQuickActionDescription(sampleComment, availableQuickActions)).toBe(
'Applying command to close this issue',
);
......@@ -867,6 +876,7 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
it('should return generic multiple quick action description when note has multiple quick actions', () => {
const sampleComment = '/close\n/title [Duplicate] Issue foobar';
expect(this.notes.getQuickActionDescription(sampleComment, availableQuickActions)).toBe(
'Applying multiple commands',
);
......@@ -874,6 +884,7 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
it('should return generic quick action description when available quick actions list is not populated', () => {
const sampleComment = '/close\n/title [Duplicate] Issue foobar';
expect(this.notes.getQuickActionDescription(sampleComment)).toBe('Applying command');
});
});
......@@ -907,6 +918,7 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
$tempNote.find('.timeline-icon > a, .note-header-info > a').each(function() {
expect($(this).attr('href')).toEqual(`/${currentUsername}`);
});
expect($tempNote.find('.timeline-icon .avatar').attr('src')).toEqual(currentUserAvatar);
expect($tempNote.find('.timeline-content').hasClass('discussion')).toBeFalsy();
expect(
......@@ -915,12 +927,14 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
.text()
.trim(),
).toEqual(currentUserFullname);
expect(
$tempNoteHeader
.find('.note-headline-light')
.text()
.trim(),
).toEqual(`@${currentUsername}`);
expect(
$tempNote
.find('.note-body .note-text p')
......@@ -953,6 +967,7 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
currentUserAvatar,
});
const $tempNoteHeader = $tempNote.find('.note-header');
expect(
$tempNoteHeader
.find('.d-none.d-sm-inline-block')
......
......@@ -30,6 +30,7 @@ describe('pager', () => {
const href = `${gl.TEST_HOST}/some_list.json`;
setFixtures(`<div class="content_list" data-href="${href}"></div>`);
Pager.init();
expect(Pager.url).toBe(href);
});
......@@ -37,12 +38,14 @@ describe('pager', () => {
const href = `${gl.TEST_HOST}/some_list`;
spyOnDependency(Pager, 'removeParams').and.returnValue(href);
Pager.init();
expect(Pager.url).toBe(href);
});
it('should get initial offset from query parameter', () => {
window.history.replaceState({}, null, '?offset=100');
Pager.init();
expect(Pager.offset).toBe(100);
});
......@@ -51,6 +54,7 @@ describe('pager', () => {
const href = `${gl.TEST_HOST}/some_list?filter=test`;
const removeParams = spyOnDependency(Pager, 'removeParams').and.returnValue(href);
Pager.init();
expect(removeParams).toHaveBeenCalledWith(['limit', 'offset']);
expect(Pager.url).toEqual(href);
});
......@@ -132,6 +136,7 @@ describe('pager', () => {
offset: 100,
},
});
expect(url).toBe('/some_list');
done();
......
......@@ -8,7 +8,9 @@ describe('Abuse Reports', () => {
let $messages;
const assertMaxLength = $message => expect($message.text().length).toEqual(MAX_MESSAGE_LENGTH);
const assertMaxLength = $message => {
expect($message.text().length).toEqual(MAX_MESSAGE_LENGTH);
};
const findMessage = searchText => $messages.filter(
(index, element) => element.innerText.indexOf(searchText) > -1,
).first();
......@@ -23,18 +25,21 @@ describe('Abuse Reports', () => {
it('should truncate long messages', () => {
const $longMessage = findMessage('LONG MESSAGE');
expect($longMessage.data('originalMessage')).toEqual(jasmine.anything());
assertMaxLength($longMessage);
});
it('should not truncate short messages', () => {
const $shortMessage = findMessage('SHORT MESSAGE');
expect($shortMessage.data('originalMessage')).not.toEqual(jasmine.anything());
});
it('should allow clicking a truncated message to expand and collapse the full message', () => {
const $longMessage = findMessage('LONG MESSAGE');
$longMessage.click();
expect($longMessage.data('originalMessage').length).toEqual($longMessage.text().length);
$longMessage.click();
assertMaxLength($longMessage);
......
......@@ -24,6 +24,7 @@ describe('AccountAndLimits', () => {
it('is checked', (done) => {
if (!$userDefaultExternal.prop('checked')) $userDefaultExternal.click();
expect($userDefaultExternal.prop('checked')).toBeTruthy();
expect($userInternalRegex.placeholder).toEqual(PLACEHOLDER_USER_EXTERNAL_DEFAULT_TRUE);
expect($userInternalRegex.readOnly).toBeFalsy();
......
......@@ -81,6 +81,7 @@ describe('EmojiMenu', () => {
'mouseenter focus',
jasmine.anything(),
);
expect(emojiMenu.registerEventListener).toHaveBeenCalledWith(
'on',
jasmine.anything(),
......@@ -107,6 +108,7 @@ describe('EmojiMenu', () => {
it('renders the menu with custom menu class', () => {
const menuElement = () =>
document.body.querySelector(`.emoji-menu.${dummyMenuClass} .emoji-menu-content`);
expect(menuElement()).toBe(null);
emojiMenu.createEmojiMenu();
......
......@@ -85,6 +85,7 @@ describe('Interval Pattern Input Component', function () {
it('prop initialCronInterval is set', function () {
const defaultInitialCronInterval = '';
expect(this.intervalPatternComponent.initialCronInterval).toBe(defaultInitialCronInterval);
});
......@@ -148,6 +149,7 @@ describe('Interval Pattern Input Component', function () {
Vue.nextTick(() => {
const intervalWithSpaceAppended = `${cronIntervalPresets.everyMonth} `;
expect(this.intervalPatternComponent.cronInterval).toBe(intervalWithSpaceAppended);
expect(this.intervalPatternComponent.$el.querySelector('.cron-interval-input').value).toBe(intervalWithSpaceAppended);
done();
......
......@@ -34,6 +34,7 @@ describe('Page component', () => {
page: testPage,
number: 1,
});
expect(vm.rendering).toBe(true);
promise
......
......@@ -20,6 +20,7 @@ describe('Pipeline Store', () => {
it('should store received object', () => {
store.storePipeline({ foo: 'bar' });
expect(store.state.pipeline).toEqual({ foo: 'bar' });
});
});
......
......@@ -38,6 +38,7 @@ describe('Pipeline Url Component', () => {
expect(component.$el.querySelector('.js-pipeline-url-link').getAttribute('href')).toEqual(
'foo',
);
expect(component.$el.querySelector('.js-pipeline-url-link span').textContent).toEqual('#1');
});
......@@ -66,6 +67,7 @@ describe('Pipeline Url Component', () => {
expect(component.$el.querySelector('.js-pipeline-url-user').getAttribute('href')).toEqual(
mockData.pipeline.user.web_url,
);
expect(image.getAttribute('data-original-title')).toEqual(mockData.pipeline.user.name);
expect(image.getAttribute('src')).toEqual(`${mockData.pipeline.user.avatar_url}?width=20`);
});
......@@ -105,6 +107,7 @@ describe('Pipeline Url Component', () => {
expect(component.$el.querySelector('.js-pipeline-url-yaml').textContent).toContain(
'yaml invalid',
);
expect(component.$el.querySelector('.js-pipeline-url-stuck').textContent).toContain('stuck');
});
......
......@@ -31,11 +31,13 @@ describe('Pipelines Actions dropdown', () => {
it('renders a dropdown with the provided actions', () => {
const dropdownItems = vm.$el.querySelectorAll('.dropdown-menu li');
expect(dropdownItems.length).toEqual(actions.length);
});
it("renders a disabled action when it's not playable", () => {
const dropdownItem = vm.$el.querySelector('.dropdown-menu li:last-child button');
expect(dropdownItem).toBeDisabled();
});
});
......
......@@ -371,18 +371,23 @@ describe('Pipelines', () => {
expect(
vm.$el.querySelector('.js-pipelines-tab-pending').textContent.trim(),
).toContain('Pending');
expect(
vm.$el.querySelector('.js-pipelines-tab-all').textContent.trim(),
).toContain('All');
expect(
vm.$el.querySelector('.js-pipelines-tab-running').textContent.trim(),
).toContain('Running');
expect(
vm.$el.querySelector('.js-pipelines-tab-finished').textContent.trim(),
).toContain('Finished');
expect(
vm.$el.querySelector('.js-pipelines-tab-branches').textContent.trim(),
).toContain('Branches');
expect(
vm.$el.querySelector('.js-pipelines-tab-tags').textContent.trim(),
).toContain('Tags');
......@@ -415,6 +420,7 @@ describe('Pipelines', () => {
vm.$nextTick(() => {
vm.$el.querySelector('.js-next-button a').click();
expect(vm.updateContent).toHaveBeenCalledWith({ scope: 'all', page: '2' });
done();
......
......@@ -16,12 +16,14 @@ describe('Pipelines Store', () => {
describe('storePipelines', () => {
it('should use the default parameter if none is provided', () => {
store.storePipelines();
expect(store.state.pipelines).toEqual([]);
});
it('should store the provided array', () => {
const array = [{ id: 1, status: 'running' }, { id: 2, status: 'success' }];
store.storePipelines(array);
expect(store.state.pipelines).toEqual(array);
});
});
......@@ -29,6 +31,7 @@ describe('Pipelines Store', () => {
describe('storeCount', () => {
it('should use the default parameter if none is provided', () => {
store.storeCount();
expect(store.state.count).toEqual({});
});
......@@ -43,6 +46,7 @@ describe('Pipelines Store', () => {
describe('storePagination', () => {
it('should use the default parameter if none is provided', () => {
store.storePagination();
expect(store.state.pageInfo).toEqual({});
});
......@@ -66,6 +70,7 @@ describe('Pipelines Store', () => {
};
store.storePagination(pagination);
expect(store.state.pageInfo).toEqual(expectedResult);
});
});
......
......@@ -37,6 +37,7 @@ describe('Pipelines Table Row', () => {
it('should render a table row', () => {
component = buildComponent(pipeline);
expect(component.$el.getAttribute('class')).toContain('gl-responsive-table-row');
});
......@@ -97,6 +98,7 @@ describe('Pipelines Table Row', () => {
component = buildComponent(pipeline);
const commitLink = component.$el.querySelector('.branch-commit .commit-sha');
expect(commitLink.getAttribute('href')).toEqual(pipeline.commit.commit_path);
});
......@@ -177,6 +179,7 @@ describe('Pipelines Table Row', () => {
expect(component.$el.querySelector('.js-pipelines-retry-button')).not.toBeNull();
expect(component.$el.querySelector('.js-pipelines-cancel-button')).not.toBeNull();
const dropdownMenu = component.$el.querySelectorAll('.dropdown-menu');
expect(dropdownMenu).toContainText(scheduledJobAction.name);
});
......@@ -186,6 +189,7 @@ describe('Pipelines Table Row', () => {
});
component.$el.querySelector('.js-pipelines-retry-button').click();
expect(component.isRetrying).toEqual(true);
});
......
......@@ -54,6 +54,7 @@ describe('Pipelines Table', () => {
viewType: 'root',
},
}).$mount();
expect(component.$el.querySelectorAll('.commit.gl-responsive-table-row').length).toEqual(0);
});
});
......
......@@ -53,6 +53,7 @@ describe('Pipelines stage component', () => {
expect(
component.$el.querySelector('.js-builds-dropdown-container ul').textContent.trim(),
).toContain(stageReply.latest_statuses[0].name);
expect(eventHub.$emit).toHaveBeenCalledWith('clickedDropdown');
done();
}, 0);
......
......@@ -122,11 +122,13 @@ describe('prettyTime methods', () => {
describe('abbreviateTime', () => {
it('should abbreviate stringified times for weeks', () => {
const fullTimeString = '1w 3d 4h 5m';
expect(abbreviateTime(fullTimeString)).toBe('1w');
});
it('should abbreviate stringified times for non-weeks', () => {
const fullTimeString = '0w 3d 4h 5m';
expect(abbreviateTime(fullTimeString)).toBe('3d');
});
});
......
......@@ -53,6 +53,7 @@ describe('DeleteAccountModal component', () => {
expect(vm.enteredPassword).toBe(input.value);
expect(submitButton).toHaveAttr('disabled', 'disabled');
submitButton.click();
expect(form.submit).not.toHaveBeenCalled();
})
.then(done)
......@@ -70,6 +71,7 @@ describe('DeleteAccountModal component', () => {
expect(vm.enteredPassword).toBe(input.value);
expect(submitButton).not.toHaveAttr('disabled', 'disabled');
submitButton.click();
expect(form.submit).toHaveBeenCalled();
})
.then(done)
......@@ -103,6 +105,7 @@ describe('DeleteAccountModal component', () => {
expect(vm.enteredUsername).toBe(input.value);
expect(submitButton).toHaveAttr('disabled', 'disabled');
submitButton.click();
expect(form.submit).not.toHaveBeenCalled();
})
.then(done)
......@@ -120,6 +123,7 @@ describe('DeleteAccountModal component', () => {
expect(vm.enteredUsername).toBe(input.value);
expect(submitButton).not.toHaveAttr('disabled', 'disabled');
submitButton.click();
expect(form.submit).toHaveBeenCalled();
})
.then(done)
......
......@@ -113,6 +113,7 @@ describe('UpdateUsername component', () => {
Vue.nextTick()
.then(() => {
confirmModalBtn.click();
expect(axios.put).toHaveBeenCalledWith(actionUrl, { user: { username: newUsername } });
})
.then(done)
......
......@@ -48,6 +48,7 @@ describe('GkeProjectIdDropdown', () => {
it('returns project billing validation text', () => {
vm.setIsValidatingProjectBilling(true);
expect(vm.toggleText).toBe(LABELS.VALIDATING_PROJECT_BILLING);
});
......
......@@ -29,6 +29,7 @@ describe('table registry', () => {
it('should render registry tag', () => {
const textRendered = vm.$el.querySelector('.table tbody tr').textContent.trim().replace(/\s\s+/g, ' ');
expect(textRendered).toContain(repoPropsData.list[0].tag);
expect(textRendered).toContain(repoPropsData.list[0].shortRevision);
expect(textRendered).toContain(repoPropsData.list[0].layers);
......
......@@ -18,6 +18,7 @@ describe('Mutations Registry Store', () => {
it('should set the main endpoint', () => {
const expectedState = Object.assign({}, mockState, { endpoint: 'foo' });
mutations[types.SET_MAIN_ENDPOINT](mockState, 'foo');
expect(mockState).toEqual(expectedState);
});
});
......@@ -25,6 +26,7 @@ describe('Mutations Registry Store', () => {
describe('SET_REPOS_LIST', () => {
it('should set a parsed repository list', () => {
mutations[types.SET_REPOS_LIST](mockState, reposServerResponse);
expect(mockState.repos).toEqual(parsedReposServerResponse);
});
});
......@@ -32,6 +34,7 @@ describe('Mutations Registry Store', () => {
describe('TOGGLE_MAIN_LOADING', () => {
it('should set a parsed repository list', () => {
mutations[types.TOGGLE_MAIN_LOADING](mockState);
expect(mockState.isLoading).toEqual(true);
});
});
......@@ -75,6 +78,7 @@ describe('Mutations Registry Store', () => {
});
mutations[types.TOGGLE_REGISTRY_LIST_LOADING](mockState, mockState.repos[0]);
expect(mockState.repos[0].isLoading).toEqual(true);
});
});
......
......@@ -42,6 +42,7 @@ describe('Grouped Test Reports App', () => {
expect(vm.$el.textContent).toContain(
'rspec:pg found no changed test results out of 8 total tests',
);
expect(vm.$el.textContent).toContain(
'java ant found no changed test results out of 3 total tests',
);
......@@ -88,6 +89,7 @@ describe('Grouped Test Reports App', () => {
expect(vm.$el.textContent).toContain(
'rspec:pg found 2 failed test results out of 8 total tests',
);
expect(vm.$el.textContent).toContain('New');
expect(vm.$el.textContent).toContain(
'java ant found no changed test results out of 3 total tests',
......@@ -115,6 +117,7 @@ describe('Grouped Test Reports App', () => {
expect(vm.$el.textContent).toContain(
'rspec:pg found 1 failed test result and 2 fixed test results out of 8 total tests',
);
expect(vm.$el.textContent).toContain('New');
expect(vm.$el.textContent).toContain(
' java ant found 1 failed test result out of 3 total tests',
......@@ -151,6 +154,7 @@ describe('Grouped Test Reports App', () => {
expect(vm.$el.querySelector('.js-mr-code-resolved-issues').textContent).toContain(
resolvedFailures.suites[0].resolved_failures[0].name,
);
expect(vm.$el.querySelector('.js-mr-code-resolved-issues').textContent).toContain(
resolvedFailures.suites[0].resolved_failures[1].name,
);
......
......@@ -97,6 +97,7 @@ describe('Report section', () => {
successText: 'Code quality improved on 1 point and degraded on 1 point',
hasIssues: false,
});
expect(vm.$el.textContent.trim()).toEqual('Loading codeclimate report');
});
});
......@@ -169,6 +170,7 @@ describe('Report section', () => {
successText: 'Code quality improved on 1 point and degraded on 1 point',
hasIssues: false,
});
expect(vm.$el.textContent.trim()).toEqual('Failed to load codeclimate report');
});
});
......
......@@ -29,6 +29,7 @@ describe('Test Issue body', () => {
spyOn(vm, 'openModal');
vm.$el.querySelector('button').click();
expect(vm.openModal).toHaveBeenCalledWith({
issue: commonProps.issue,
});
......
......@@ -13,6 +13,7 @@ describe('Reports Store Mutations', () => {
describe('SET_ENDPOINT', () => {
it('should set endpoint', () => {
mutations[types.SET_ENDPOINT](stateCopy, 'endpoint.json');
expect(stateCopy.endpoint).toEqual('endpoint.json');
});
});
......@@ -20,6 +21,7 @@ describe('Reports Store Mutations', () => {
describe('REQUEST_REPORTS', () => {
it('should set isLoading to true', () => {
mutations[types.REQUEST_REPORTS](stateCopy);
expect(stateCopy.isLoading).toEqual(true);
});
});
......
......@@ -111,6 +111,7 @@ describe('Search autocomplete dropdown', () => {
if (issuesPath) {
const issuesAssignedToMeLink = `a[href="${issuesPath}/?assignee_id=${userId}"]`;
const issuesIHaveCreatedLink = `a[href="${issuesPath}/?author_id=${userId}"]`;
expect(list.find(issuesAssignedToMeLink).length).toBe(1);
expect(list.find(issuesAssignedToMeLink).text()).toBe('Issues assigned to me');
expect(list.find(issuesIHaveCreatedLink).length).toBe(1);
......@@ -118,6 +119,7 @@ describe('Search autocomplete dropdown', () => {
}
const mrsAssignedToMeLink = `a[href="${mrsPath}/?assignee_id=${userId}"]`;
const mrsIHaveCreatedLink = `a[href="${mrsPath}/?author_id=${userId}"]`;
expect(list.find(mrsAssignedToMeLink).length).toBe(1);
expect(list.find(mrsAssignedToMeLink).text()).toBe('Merge requests assigned to me');
expect(list.find(mrsIHaveCreatedLink).length).toBe(1);
......@@ -185,7 +187,8 @@ describe('Search autocomplete dropdown', () => {
widget.searchInput.triggerHandler('focus');
list = widget.wrap.find('.dropdown-menu').find('ul');
link = "a[href='" + projectIssuesPath + '/?assignee_id=' + userId + "']";
return expect(list.find(link).length).toBe(0);
expect(list.find(link).length).toBe(0);
});
it('should not submit the search form when selecting an autocomplete row with the keyboard', function() {
......
......@@ -119,6 +119,7 @@ describe('popover', () => {
spyOn($.fn, 'init').and.callFake(selector => (selector === '.popover:hover' ? fakeJquery : $.fn));
spyOn(togglePopover, 'call');
mouseleave();
expect(togglePopover.call).toHaveBeenCalledWith(jasmine.any(Object), false);
});
......@@ -130,6 +131,7 @@ describe('popover', () => {
spyOn($.fn, 'init').and.callFake(selector => (selector === '.popover:hover' ? fakeJquery : $.fn));
spyOn(togglePopover, 'call');
mouseleave();
expect(togglePopover.call).not.toHaveBeenCalledWith(false);
});
});
......@@ -140,6 +142,7 @@ describe('popover', () => {
it('shows popover', () => {
spyOn(togglePopover, 'call').and.returnValue(false);
mouseenter.call(context);
expect(togglePopover.call).toHaveBeenCalledWith(jasmine.any(Object), true);
});
......@@ -156,6 +159,7 @@ describe('popover', () => {
spyOn(togglePopover, 'call').and.returnValue(false);
const spy = spyOn($.fn, 'on').and.callFake(() => {});
mouseenter.call(context);
expect(spy).not.toHaveBeenCalled();
});
});
......
......@@ -22,6 +22,7 @@ describe('Assignee component', () => {
}).$mount();
const collapsed = component.$el.querySelector('.sidebar-collapsed-icon');
expect(collapsed.childElementCount).toEqual(1);
expect(collapsed.children[0].getAttribute('aria-label')).toEqual('No Assignee');
expect(collapsed.children[0].classList.contains('fa')).toEqual(true);
......@@ -67,6 +68,7 @@ describe('Assignee component', () => {
spyOn(component, '$emit');
component.$el.querySelector('.assign-yourself .btn-link').click();
expect(component.$emit).toHaveBeenCalledWith('assign-self');
});
});
......@@ -85,6 +87,7 @@ describe('Assignee component', () => {
const collapsed = component.$el.querySelector('.sidebar-collapsed-icon');
const assignee = collapsed.children[0];
expect(collapsed.childElementCount).toEqual(1);
expect(assignee.querySelector('.avatar').getAttribute('src')).toEqual(UsersMock.user.avatar);
expect(assignee.querySelector('.avatar').getAttribute('alt')).toEqual(`${UsersMock.user.name}'s avatar`);
......@@ -138,14 +141,17 @@ describe('Assignee component', () => {
}).$mount();
const collapsed = component.$el.querySelector('.sidebar-collapsed-icon');
expect(collapsed.childElementCount).toEqual(2);
const first = collapsed.children[0];
expect(first.querySelector('.avatar').getAttribute('src')).toEqual(users[0].avatar);
expect(first.querySelector('.avatar').getAttribute('alt')).toEqual(`${users[0].name}'s avatar`);
expect(first.querySelector('.author').innerText.trim()).toEqual(users[0].name);
const second = collapsed.children[1];
expect(second.querySelector('.avatar').getAttribute('src')).toEqual(users[1].avatar);
expect(second.querySelector('.avatar').getAttribute('alt')).toEqual(`${users[1].name}'s avatar`);
expect(second.querySelector('.author').innerText.trim()).toEqual(users[1].name);
......@@ -162,14 +168,17 @@ describe('Assignee component', () => {
}).$mount();
const collapsed = component.$el.querySelector('.sidebar-collapsed-icon');
expect(collapsed.childElementCount).toEqual(2);
const first = collapsed.children[0];
expect(first.querySelector('.avatar').getAttribute('src')).toEqual(users[0].avatar);
expect(first.querySelector('.avatar').getAttribute('alt')).toEqual(`${users[0].name}'s avatar`);
expect(first.querySelector('.author').innerText.trim()).toEqual(users[0].name);
const second = collapsed.children[1];
expect(second.querySelector('.avatar-counter').innerText.trim()).toEqual('+2');
});
......@@ -200,6 +209,7 @@ describe('Assignee component', () => {
expect(component.$el.querySelectorAll('.user-item').length).toEqual(component.defaultRenderCount);
expect(component.$el.querySelector('.user-list-more')).not.toBe(null);
const usersLabelExpectation = users.length - component.defaultRenderCount;
expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim())
.not.toBe(`+${usersLabelExpectation} more`);
component.toggleShowLess();
......
......@@ -88,6 +88,7 @@ describe('Issuable Time Tracker', () => {
Vue.nextTick(() => {
expect(vm.showComparisonState).toBe(true);
const $comparisonPane = vm.$el.querySelector('.time-tracking-comparison-pane');
expect($comparisonPane).toBeVisible();
done();
});
......
......@@ -182,6 +182,7 @@ describe('Participants', function () {
const participantsIconEl = vm.$el.querySelector('.sidebar-collapsed-icon');
participantsIconEl.click();
expect(vm.$emit).toHaveBeenCalledWith('toggleSidebar');
});
});
......
......@@ -39,6 +39,7 @@ describe('sidebar assignees', () => {
it('calls the mediator when saves the assignees', () => {
vm.saveAssignees();
expect(mediator.saveAssignees).toHaveBeenCalled();
});
......@@ -51,6 +52,7 @@ describe('sidebar assignees', () => {
it('hides assignees until fetched', (done) => {
const currentAssignee = sidebarAssigneesEl.querySelector('.value');
expect(currentAssignee).toBe(null);
vm.store.isFetching.assignees = false;
......
......@@ -56,11 +56,13 @@ describe('Sidebar store', function () {
it('adds a new assignee', () => {
this.store.addAssignee(ASSIGNEE);
expect(this.store.assignees.length).toEqual(1);
});
it('removes an assignee', () => {
this.store.removeAssignee(ASSIGNEE);
expect(this.store.assignees.length).toEqual(0);
});
......@@ -69,14 +71,17 @@ describe('Sidebar store', function () {
this.store.addAssignee(ASSIGNEE);
foundAssignee = this.store.findAssignee(ASSIGNEE);
expect(foundAssignee).toBeDefined();
expect(foundAssignee).toEqual(ASSIGNEE);
foundAssignee = this.store.findAssignee(ANOTHER_ASSINEE);
expect(foundAssignee).toBeUndefined();
});
it('removes all assignees', () => {
this.store.removeAllAssignees();
expect(this.store.assignees.length).toEqual(0);
});
......@@ -108,6 +113,7 @@ describe('Sidebar store', function () {
};
this.store.setAssigneeData(users);
expect(this.store.isFetching.assignees).toBe(false);
expect(this.store.assignees.length).toEqual(3);
});
......@@ -128,6 +134,7 @@ describe('Sidebar store', function () {
it('set time tracking data', () => {
this.store.setTimeTrackingData(Mock.time);
expect(this.store.timeEstimate).toEqual(Mock.time.time_estimate);
expect(this.store.totalTimeSpent).toEqual(Mock.time.total_time_spent);
expect(this.store.humanTimeEstimate).toEqual(Mock.time.human_time_estimate);
......
......@@ -47,6 +47,7 @@ describe('Subscriptions', function () {
spyOn(vm, '$emit');
vm.toggleSubscription();
expect(eventHub.$emit).toHaveBeenCalledWith('toggleSubscription', jasmine.any(Object));
expect(vm.$emit).toHaveBeenCalledWith('toggleSubscription', jasmine.any(Object));
});
......@@ -56,6 +57,7 @@ describe('Subscriptions', function () {
spyOn(vm, '$emit');
vm.onClickCollapsedIcon();
expect(vm.$emit).toHaveBeenCalledWith('toggleSidebar');
});
});
......@@ -103,6 +103,7 @@ describe('SidebarTodo', () => {
it('emits `toggleTodo` event on component', () => {
spyOn(vm, '$emit');
vm.handleButtonClick();
expect(vm.$emit).toHaveBeenCalledWith('toggleTodo');
});
});
......@@ -118,6 +119,7 @@ describe('SidebarTodo', () => {
container: 'body',
boundary: 'viewport',
};
expect(vm.$el.nodeName).toBe('BUTTON');
const elDataAttrs = vm.$el.dataset;
......@@ -128,6 +130,7 @@ describe('SidebarTodo', () => {
it('renders button label element when `collapsed` prop is `false`', () => {
const buttonLabelEl = vm.$el.querySelector('span.issuable-todo-inner');
expect(buttonLabelEl).not.toBeNull();
expect(buttonLabelEl.innerText.trim()).toBe('Mark todo as done');
});
......@@ -137,6 +140,7 @@ describe('SidebarTodo', () => {
Vue.nextTick()
.then(() => {
const buttonIconEl = vm.$el.querySelector('svg');
expect(buttonIconEl).not.toBeNull();
expect(buttonIconEl.querySelector('use').getAttribute('xlink:href')).toContain('todo-done');
})
......@@ -149,6 +153,7 @@ describe('SidebarTodo', () => {
Vue.nextTick()
.then(() => {
const loadingEl = vm.$el.querySelector('span.loading-container');
expect(loadingEl).not.toBeNull();
})
.then(done)
......
......@@ -66,6 +66,7 @@ describe('SmartInterval', function () {
waitForPromises()
.then(() => {
const currentInterval = smartInterval.getCurrentInterval();
expect(currentInterval).toBe(smartInterval.cfg.maxInterval);
})
.then(done)
......@@ -82,6 +83,7 @@ describe('SmartInterval', function () {
waitForPromises()
.then(() => {
const oneInterval = smartInterval.cfg.startingInterval * DEFAULT_INCREMENT_FACTOR;
expect(smartInterval.getCurrentInterval()).toEqual(oneInterval);
})
.then(done)
......@@ -126,6 +128,7 @@ describe('SmartInterval', function () {
waitForPromises()
.then(() => {
const { intervalId } = interval.state;
expect(intervalId).toBeTruthy();
})
.then(done)
......@@ -212,6 +215,7 @@ describe('SmartInterval', function () {
waitForPromises()
.then(() => {
$(document).triggerHandler('beforeunload');
expect(interval.state.intervalId).toBeUndefined();
expect(interval.getCurrentInterval()).toBe(interval.cfg.startingInterval);
})
......@@ -221,6 +225,7 @@ describe('SmartInterval', function () {
it('should execute callback before first interval', function () {
const interval = createDefaultSmartInterval({ immediateExecution: true });
expect(interval.cfg.immediateExecution).toBeFalsy();
});
});
......
......@@ -15,13 +15,16 @@ describe('Syntax Highlighter', function() {
beforeEach(function() {
return setFixtures('<div class="js-syntax-highlight"></div>');
});
return it('applies syntax highlighting', function() {
it('applies syntax highlighting', function() {
stubUserColorScheme('monokai');
syntaxHighlight($('.js-syntax-highlight'));
return expect($('.js-syntax-highlight')).toHaveClass('monokai');
expect($('.js-syntax-highlight')).toHaveClass('monokai');
});
});
return describe('on a parent element', function() {
describe('on a parent element', function() {
beforeEach(function() {
return setFixtures("<div class=\"parent\">\n <div class=\"js-syntax-highlight\"></div>\n <div class=\"foo\"></div>\n <div class=\"js-syntax-highlight\"></div>\n</div>");
});
......@@ -29,16 +32,19 @@ describe('Syntax Highlighter', function() {
it('applies highlighting to all applicable children', function() {
stubUserColorScheme('monokai');
syntaxHighlight($('.parent'));
expect($('.parent, .foo')).not.toHaveClass('monokai');
return expect($('.monokai').length).toBe(2);
expect($('.monokai').length).toBe(2);
});
return it('prevents an infinite loop when no matches exist', function() {
it('prevents an infinite loop when no matches exist', function() {
var highlight;
setFixtures('<div></div>');
highlight = function() {
return syntaxHighlight($('div'));
};
return expect(highlight).not.toThrow();
expect(highlight).not.toThrow();
});
});
});
......@@ -51,10 +51,12 @@ describe('U2FAuthenticate', function () {
it('allows authenticating via a U2F device', () => {
const inProgressMessage = this.container.find('p');
expect(inProgressMessage.text()).toContain('Trying to communicate with your device');
this.u2fDevice.respondToAuthenticateRequest({
deviceData: 'this is data from the device',
});
expect(this.component.renderAuthenticated).toHaveBeenCalledWith('{"deviceData":"this is data from the device"}');
});
......@@ -66,7 +68,8 @@ describe('U2FAuthenticate', function () {
errorCode: 'error!',
});
const errorMessage = this.container.find('p');
return expect(errorMessage.text()).toContain('There was a problem communicating with your device');
expect(errorMessage.text()).toContain('There was a problem communicating with your device');
});
return it('allows retrying authentication after an error', () => {
let setupButton = this.container.find('#js-login-u2f-device');
......@@ -81,6 +84,7 @@ describe('U2FAuthenticate', function () {
this.u2fDevice.respondToAuthenticateRequest({
deviceData: 'this is data from the device',
});
expect(this.component.renderAuthenticated).toHaveBeenCalledWith('{"deviceData":"this is data from the device"}');
});
});
......
......@@ -16,20 +16,23 @@ describe('U2FRegister', function () {
it('allows registering a U2F device', () => {
const setupButton = this.container.find('#js-setup-u2f-device');
expect(setupButton.text()).toBe('Set up new U2F device');
setupButton.trigger('click');
const inProgressMessage = this.container.children('p');
expect(inProgressMessage.text()).toContain('Trying to communicate with your device');
this.u2fDevice.respondToRegisterRequest({
deviceData: 'this is data from the device',
});
const registeredMessage = this.container.find('p');
const deviceResponse = this.container.find('#js-device-response');
expect(registeredMessage.text()).toContain('Your device was successfully set up!');
return expect(deviceResponse.val()).toBe('{"deviceData":"this is data from the device"}');
expect(deviceResponse.val()).toBe('{"deviceData":"this is data from the device"}');
});
return describe('errors', () => {
describe('errors', () => {
it('doesn\'t allow the same device to be registered twice (for the same user', () => {
const setupButton = this.container.find('#js-setup-u2f-device');
setupButton.trigger('click');
......@@ -37,7 +40,8 @@ describe('U2FRegister', function () {
errorCode: 4,
});
const errorMessage = this.container.find('p');
return expect(errorMessage.text()).toContain('already been registered with us');
expect(errorMessage.text()).toContain('already been registered with us');
});
it('displays an error message for other errors', () => {
......@@ -47,10 +51,11 @@ describe('U2FRegister', function () {
errorCode: 'error!',
});
const errorMessage = this.container.find('p');
return expect(errorMessage.text()).toContain('There was a problem communicating with your device');
expect(errorMessage.text()).toContain('There was a problem communicating with your device');
});
return it('allows retrying registration after an error', () => {
it('allows retrying registration after an error', () => {
let setupButton = this.container.find('#js-setup-u2f-device');
setupButton.trigger('click');
this.u2fDevice.respondToRegisterRequest({
......@@ -64,7 +69,8 @@ describe('U2FRegister', function () {
deviceData: 'this is data from the device',
});
const registeredMessage = this.container.find('p');
return expect(registeredMessage.text()).toContain('Your device was successfully set up!');
expect(registeredMessage.text()).toContain('Your device was successfully set up!');
});
});
});
......@@ -4,41 +4,49 @@ describe('U2F Utils', () => {
describe('canInjectU2fApi', () => {
it('returns false for Chrome < 41', () => {
const userAgent = 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.28 Safari/537.36';
expect(canInjectU2fApi(userAgent)).toBe(false);
});
it('returns true for Chrome >= 41', () => {
const userAgent = 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36';
expect(canInjectU2fApi(userAgent)).toBe(true);
});
it('returns false for Opera < 40', () => {
const userAgent = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 OPR/32.0.1948.25';
expect(canInjectU2fApi(userAgent)).toBe(false);
});
it('returns true for Opera >= 40', () => {
const userAgent = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36 OPR/43.0.2442.991';
expect(canInjectU2fApi(userAgent)).toBe(true);
});
it('returns false for Safari', () => {
const userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/603.2.4 (KHTML, like Gecko) Version/10.1.1 Safari/603.2.4';
expect(canInjectU2fApi(userAgent)).toBe(false);
});
it('returns false for Chrome on Android', () => {
const userAgent = 'Mozilla/5.0 (Linux; Android 7.0; VS988 Build/NRD90U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3145.0 Mobile Safari/537.36';
expect(canInjectU2fApi(userAgent)).toBe(false);
});
it('returns false for Chrome on iOS', () => {
const userAgent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) CriOS/56.0.2924.75 Mobile/14E5239e Safari/602.1';
expect(canInjectU2fApi(userAgent)).toBe(false);
});
it('returns false for Safari on iOS', () => {
const userAgent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A356 Safari/604.1';
expect(canInjectU2fApi(userAgent)).toBe(false);
});
});
......
......@@ -39,6 +39,7 @@ describe('Deployment component', () => {
describe('deployTimeago', () => {
it('return formatted date', () => {
const readable = getTimeago().format(deploymentMockData.deployed_at);
expect(vm.deployTimeago).toEqual(readable);
});
});
......
......@@ -41,6 +41,7 @@ describe('MRWidgetHeader', () => {
statusPath: 'abc',
},
});
expect(vm.shouldShowCommitsBehindText).toEqual(false);
});
});
......@@ -165,6 +166,7 @@ describe('MRWidgetHeader', () => {
vm = mountComponent(Component, { mr });
const link = vm.$el.querySelector('.js-web-ide');
expect(link.classList.contains('disabled')).toBe(true);
expect(link.getAttribute('href')).toBeNull();
});
......
......@@ -186,9 +186,11 @@ describe('MemoryUsage', () => {
expect(
el.querySelector('.js-usage-info.usage-info-loading'),
).toBeDefined();
expect(
el.querySelector('.js-usage-info .usage-info-load-spinner'),
).toBeDefined();
expect(el.querySelector('.js-usage-info').innerText).toContain(
messages.loadingMetrics,
);
......@@ -219,6 +221,7 @@ describe('MemoryUsage', () => {
expect(
el.querySelector('.js-usage-info.usage-info-failed'),
).toBeDefined();
expect(el.querySelector('.js-usage-info').innerText).toContain(
messages.loadFailed,
);
......@@ -235,6 +238,7 @@ describe('MemoryUsage', () => {
expect(
el.querySelector('.js-usage-info.usage-info-unavailable'),
).toBeDefined();
expect(el.querySelector('.js-usage-info').innerText).toContain(
messages.metricsUnavailable,
);
......
......@@ -40,6 +40,7 @@ describe('Merge request widget rebase component', () => {
it('it should render rebase button and warning message', () => {
const text = vm.$el.querySelector('.rebase-state-find-class-convention span').textContent.trim();
expect(text).toContain('Fast-forward merge is not possible.');
expect(text).toContain('Rebase the source branch onto the target branch or merge target');
expect(text).toContain('branch into source branch to allow this merge request to be merged.');
......
......@@ -19,16 +19,19 @@ describe('MRWidgetRelatedLinks', () => {
describe('closesText', () => {
it('returns Closes text for open merge request', () => {
vm = createComponent({ state: 'open', relatedLinks: {} });
expect(vm.closesText).toEqual('Closes');
});
it('returns correct text for closed merge request', () => {
vm = createComponent({ state: 'closed', relatedLinks: {} });
expect(vm.closesText).toEqual('Did not close');
});
it('returns correct tense for merged request', () => {
vm = createComponent({ state: 'merged', relatedLinks: {} });
expect(vm.closesText).toEqual('Closed');
});
});
......
......@@ -17,6 +17,7 @@ describe('MR widget status icon component', () => {
describe('while loading', () => {
it('renders loading icon', () => {
vm = mountComponent(Component, { status: 'loading' });
expect(vm.$el.querySelector('.mr-widget-icon i').classList).toContain('fa-spinner');
});
});
......@@ -24,6 +25,7 @@ describe('MR widget status icon component', () => {
describe('with status icon', () => {
it('renders ci status icon', () => {
vm = mountComponent(Component, { status: 'failed' });
expect(vm.$el.querySelector('.js-ci-status-icon-failed')).not.toBeNull();
});
});
......@@ -31,6 +33,7 @@ describe('MR widget status icon component', () => {
describe('with disabled button', () => {
it('renders a disabled button', () => {
vm = mountComponent(Component, { status: 'failed', showDisabledButton: true });
expect(vm.$el.querySelector('.js-disabled-merge-button').textContent.trim()).toEqual('Merge');
});
});
......@@ -38,6 +41,7 @@ describe('MR widget status icon component', () => {
describe('without disabled button', () => {
it('does not render a disabled button', () => {
vm = mountComponent(Component, { status: 'failed' });
expect(vm.$el.querySelector('.js-disabled-merge-button')).toBeNull();
});
});
......
......@@ -43,6 +43,7 @@ describe('MRWidgetFailedToMerge', () => {
expect(vm.timerText).toEqual('Refreshing in 10 seconds to show the updated status...');
vm.timer = 1;
expect(vm.timerText).toEqual('Refreshing in a second to show the updated status...');
});
});
......@@ -73,6 +74,7 @@ describe('MRWidgetFailedToMerge', () => {
expect(vm.isRefreshing).toEqual(false);
vm.refresh();
expect(vm.isRefreshing).toEqual(true);
expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
expect(eventHub.$emit).toHaveBeenCalledWith('EnablePolling');
......
......@@ -42,22 +42,27 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
it('should return false when user id is not the same with who set the MWPS', () => {
vm.mr.mergeUserId = 2;
expect(vm.canRemoveSourceBranch).toBeFalsy();
vm.mr.currentUserId = 2;
expect(vm.canRemoveSourceBranch).toBeTruthy();
vm.mr.currentUserId = 3;
expect(vm.canRemoveSourceBranch).toBeFalsy();
});
it('should return false when shouldRemoveSourceBranch set to false', () => {
vm.mr.shouldRemoveSourceBranch = true;
expect(vm.canRemoveSourceBranch).toBeFalsy();
});
it('should return false if user is not able to remove the source branch', () => {
vm.mr.canRemoveSourceBranch = false;
expect(vm.canRemoveSourceBranch).toBeFalsy();
});
});
......@@ -133,6 +138,7 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
Vue.nextTick(() => {
const normalizedText = vm.$el.innerText.replace(/\s+/g, ' ');
expect(normalizedText).toContain('The source branch will be removed');
expect(normalizedText).not.toContain('The source branch will not be removed');
done();
......
......@@ -63,23 +63,27 @@ describe('MRWidgetMerged', () => {
describe('shouldShowRemoveSourceBranch', () => {
it('returns true when sourceBranchRemoved is false', () => {
vm.mr.sourceBranchRemoved = false;
expect(vm.shouldShowRemoveSourceBranch).toEqual(true);
});
it('returns false wehn sourceBranchRemoved is true', () => {
vm.mr.sourceBranchRemoved = true;
expect(vm.shouldShowRemoveSourceBranch).toEqual(false);
});
it('returns false when canRemoveSourceBranch is false', () => {
vm.mr.sourceBranchRemoved = false;
vm.mr.canRemoveSourceBranch = false;
expect(vm.shouldShowRemoveSourceBranch).toEqual(false);
});
it('returns false when is making request', () => {
vm.mr.canRemoveSourceBranch = true;
vm.isMakingRequest = true;
expect(vm.shouldShowRemoveSourceBranch).toEqual(false);
});
......@@ -87,6 +91,7 @@ describe('MRWidgetMerged', () => {
vm.mr.isRemovingSourceBranch = true;
vm.mr.canRemoveSourceBranch = true;
vm.isMakingRequest = true;
expect(vm.shouldShowRemoveSourceBranch).toEqual(false);
});
});
......@@ -94,17 +99,21 @@ describe('MRWidgetMerged', () => {
describe('shouldShowSourceBranchRemoving', () => {
it('should correct value when fields changed', () => {
vm.mr.sourceBranchRemoved = false;
expect(vm.shouldShowSourceBranchRemoving).toEqual(false);
vm.mr.sourceBranchRemoved = true;
expect(vm.shouldShowRemoveSourceBranch).toEqual(false);
vm.mr.sourceBranchRemoved = false;
vm.isMakingRequest = true;
expect(vm.shouldShowSourceBranchRemoving).toEqual(true);
vm.isMakingRequest = false;
vm.mr.isRemovingSourceBranch = true;
expect(vm.shouldShowSourceBranchRemoving).toEqual(true);
});
});
......@@ -124,6 +133,7 @@ describe('MRWidgetMerged', () => {
vm.removeSourceBranch();
setTimeout(() => {
const args = eventHub.$emit.calls.argsFor(0);
expect(vm.isMakingRequest).toEqual(true);
expect(args[0]).toEqual('MRWidgetUpdateRequested');
expect(args[1]).not.toThrow();
......
......@@ -27,6 +27,7 @@ describe('MRWidgetMerging', () => {
expect(
vm.$el.querySelector('.mr-info-list').textContent.trim().replace(/\s\s+/g, ' ').replace(/[\r\n]+/g, ' '),
).toEqual('The changes will be merged into branch');
expect(
vm.$el.querySelector('a').getAttribute('href'),
).toEqual('/branch-path');
......
......@@ -20,6 +20,7 @@ describe('MRWidgetMissingBranch', () => {
expect(vm.missingBranchName).toEqual('source');
vm.mr.sourceBranchRemoved = false;
expect(vm.missingBranchName).toEqual('target');
});
});
......
......@@ -76,11 +76,13 @@ describe('ReadyToMerge', () => {
describe('shouldShowMergeWhenPipelineSucceedsText', () => {
it('should return true with active pipeline', () => {
vm.mr.isPipelineActive = true;
expect(vm.shouldShowMergeWhenPipelineSucceedsText).toBeTruthy();
});
it('should return false with inactive pipeline', () => {
vm.mr.isPipelineActive = false;
expect(vm.shouldShowMergeWhenPipelineSucceedsText).toBeFalsy();
});
});
......@@ -95,6 +97,7 @@ describe('ReadyToMerge', () => {
it('should return message without description', () => {
vm.useCommitMessageWithDescription = true;
expect(vm.commitMessageLinkTitle).toEqual(withoutDesc);
});
});
......@@ -102,11 +105,13 @@ describe('ReadyToMerge', () => {
describe('status', () => {
it('defaults to success', () => {
vm.mr.pipeline = true;
expect(vm.status).toEqual('success');
});
it('returns failed when MR has CI but also has an unknown status', () => {
vm.mr.hasCI = true;
expect(vm.status).toEqual('failed');
});
......@@ -117,12 +122,14 @@ describe('ReadyToMerge', () => {
it('returns pending when pipeline is active', () => {
vm.mr.pipeline = {};
vm.mr.isPipelineActive = true;
expect(vm.status).toEqual('pending');
});
it('returns failed when pipeline is failed', () => {
vm.mr.pipeline = {};
vm.mr.isPipelineFailed = true;
expect(vm.status).toEqual('failed');
});
});
......@@ -138,17 +145,20 @@ describe('ReadyToMerge', () => {
it('returns success class for success status', () => {
vm.mr.pipeline = true;
expect(vm.mergeButtonClass).toEqual(defaultClass);
});
it('returns info class for pending status', () => {
vm.mr.pipeline = {};
vm.mr.isPipelineActive = true;
expect(vm.mergeButtonClass).toEqual(inActionClass);
});
it('returns failed class for failed status', () => {
vm.mr.hasCI = true;
expect(vm.mergeButtonClass).toEqual(failedClass);
});
});
......@@ -160,22 +170,26 @@ describe('ReadyToMerge', () => {
it('shows tick for success status', () => {
vm.mr.pipeline = true;
expect(vm.iconClass).toEqual('success');
});
it('shows tick for pending status', () => {
vm.mr.pipeline = {};
vm.mr.isPipelineActive = true;
expect(vm.iconClass).toEqual('success');
});
it('shows warning icon for failed status', () => {
vm.mr.hasCI = true;
expect(vm.iconClass).toEqual('warning');
});
it('shows warning icon for merge not allowed', () => {
vm.mr.hasCI = true;
expect(vm.iconClass).toEqual('warning');
});
});
......@@ -187,12 +201,14 @@ describe('ReadyToMerge', () => {
it('should return Merge in progress', () => {
vm.isMergingImmediately = true;
expect(vm.mergeButtonText).toEqual('Merge in progress');
});
it('should return Merge when pipeline succeeds', () => {
vm.isMergingImmediately = false;
vm.mr.isPipelineActive = true;
expect(vm.mergeButtonText).toEqual('Merge when pipeline succeeds');
});
});
......@@ -204,12 +220,14 @@ describe('ReadyToMerge', () => {
it('should return true when pipeline active', () => {
vm.mr.isPipelineActive = true;
expect(vm.shouldShowMergeOptionsDropdown).toBeTruthy();
});
it('should return false when pipeline active but only merge when pipeline succeeds set in project options', () => {
vm.mr.isPipelineActive = true;
vm.mr.onlyAllowMergeIfPipelineSucceeds = true;
expect(vm.shouldShowMergeOptionsDropdown).toBeFalsy();
});
});
......@@ -217,24 +235,28 @@ describe('ReadyToMerge', () => {
describe('isMergeButtonDisabled', () => {
it('should return false with initial data', () => {
vm.mr.isMergeAllowed = true;
expect(vm.isMergeButtonDisabled).toBeFalsy();
});
it('should return true when there is no commit message', () => {
vm.mr.isMergeAllowed = true;
vm.commitMessage = '';
expect(vm.isMergeButtonDisabled).toBeTruthy();
});
it('should return true if merge is not allowed', () => {
vm.mr.isMergeAllowed = false;
vm.mr.onlyAllowMergeIfPipelineSucceeds = true;
expect(vm.isMergeButtonDisabled).toBeTruthy();
});
it('should return true when the vm instance is making request', () => {
vm.mr.isMergeAllowed = true;
vm.isMakingRequest = true;
expect(vm.isMergeButtonDisabled).toBeTruthy();
});
});
......@@ -245,24 +267,28 @@ describe('ReadyToMerge', () => {
it('should return false when an external pipeline is running and required to succeed', () => {
vm.mr.isMergeAllowed = false;
vm.mr.isPipelineActive = false;
expect(vm.shouldShowMergeControls()).toBeFalsy();
});
it('should return true when the build succeeded or build not required to succeed', () => {
vm.mr.isMergeAllowed = true;
vm.mr.isPipelineActive = false;
expect(vm.shouldShowMergeControls()).toBeTruthy();
});
it('should return true when showing the MWPS button and a pipeline is running that needs to be successful', () => {
vm.mr.isMergeAllowed = false;
vm.mr.isPipelineActive = true;
expect(vm.shouldShowMergeControls()).toBeTruthy();
});
it('should return true when showing the MWPS button but not required for the pipeline to succeed', () => {
vm.mr.isMergeAllowed = true;
vm.mr.isPipelineActive = true;
expect(vm.shouldShowMergeControls()).toBeTruthy();
});
});
......@@ -272,9 +298,11 @@ describe('ReadyToMerge', () => {
expect(vm.useCommitMessageWithDescription).toBeFalsy();
expect(vm.commitMessage).toEqual(commitMessage);
vm.updateCommitMessage();
expect(vm.useCommitMessageWithDescription).toBeTruthy();
expect(vm.commitMessage).toEqual(commitMessageWithDescription);
vm.updateCommitMessage();
expect(vm.useCommitMessageWithDescription).toBeFalsy();
expect(vm.commitMessage).toEqual(commitMessage);
});
......@@ -284,6 +312,7 @@ describe('ReadyToMerge', () => {
it('should toggle showCommitMessageEditor flag', () => {
expect(vm.showCommitMessageEditor).toBeFalsy();
vm.toggleCommitMessageEditor();
expect(vm.showCommitMessageEditor).toBeTruthy();
});
});
......@@ -309,6 +338,7 @@ describe('ReadyToMerge', () => {
expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
const params = vm.service.merge.calls.argsFor(0)[0];
expect(params.sha).toEqual(vm.mr.sha);
expect(params.commit_message).toEqual(vm.mr.commitMessage);
expect(params.should_remove_source_branch).toBeFalsy();
......@@ -328,6 +358,7 @@ describe('ReadyToMerge', () => {
expect(eventHub.$emit).toHaveBeenCalledWith('FailedToMerge', undefined);
const params = vm.service.merge.calls.argsFor(0)[0];
expect(params.should_remove_source_branch).toBeTruthy();
expect(params.merge_when_pipeline_succeeds).toBeFalsy();
done();
......@@ -345,6 +376,7 @@ describe('ReadyToMerge', () => {
expect(vm.initiateMergePolling).toHaveBeenCalled();
const params = vm.service.merge.calls.argsFor(0)[0];
expect(params.should_remove_source_branch).toBeTruthy();
expect(params.merge_when_pipeline_succeeds).toBeFalsy();
done();
......@@ -356,6 +388,7 @@ describe('ReadyToMerge', () => {
it('should call simplePoll', () => {
const simplePoll = spyOnDependency(ReadyToMerge, 'simplePoll');
vm.initiateMergePolling();
expect(simplePoll).toHaveBeenCalled();
});
});
......@@ -403,6 +436,7 @@ describe('ReadyToMerge', () => {
setTimeout(() => {
const statusBox = document.querySelector('.status-box');
expect(statusBox.classList.contains('status-box-mr-merged')).toBeTruthy();
expect(statusBox.textContent).toContain('Merged');
......@@ -459,6 +493,7 @@ describe('ReadyToMerge', () => {
const simplePoll = spyOnDependency(ReadyToMerge, 'simplePoll');
vm.initiateRemoveSourceBranchPolling();
expect(eventHub.$emit).toHaveBeenCalledWith('SetBranchRemoveFlag', [true]);
expect(simplePoll).toHaveBeenCalled();
});
......@@ -485,9 +520,11 @@ describe('ReadyToMerge', () => {
expect(vm.service.poll).toHaveBeenCalled();
const args = eventHub.$emit.calls.argsFor(0);
expect(args[0]).toEqual('MRWidgetUpdateRequested');
expect(args[1]).toBeDefined();
args[1]();
expect(eventHub.$emit).toHaveBeenCalledWith('SetBranchRemoveFlag', [false]);
expect(cpc).toBeFalsy();
......@@ -518,6 +555,7 @@ describe('ReadyToMerge', () => {
describe('when user can merge but cannot delete branch', () => {
it('should be disabled in the rendered output', () => {
const checkboxElement = vm.$el.querySelector('#remove-source-branch-input');
expect(checkboxElement).toBeNull();
});
});
......@@ -537,6 +575,7 @@ describe('ReadyToMerge', () => {
it('should be enabled in rendered output', () => {
const checkboxElement = customVm.$el.querySelector('#remove-source-branch-input');
expect(checkboxElement).not.toBeNull();
});
});
......
......@@ -33,6 +33,7 @@ describe('Wip', () => {
describe('data', () => {
it('should have default data', () => {
const vm = createComponent();
expect(vm.isMakingRequest).toBeFalsy();
});
});
......
......@@ -46,6 +46,7 @@ describe('mrWidgetOptions', () => {
it('should return conflicts component', () => {
vm.mr.state = 'conflicts';
expect(vm.componentName).toEqual('mr-widget-conflicts');
});
});
......@@ -57,6 +58,7 @@ describe('mrWidgetOptions', () => {
it('should return true for a state which requires help widget', () => {
vm.mr.state = 'conflicts';
expect(vm.shouldRenderMergeHelp).toBeTruthy();
});
});
......@@ -82,6 +84,7 @@ describe('mrWidgetOptions', () => {
it('should return true if there is relatedLinks in MR', () => {
Vue.set(vm.mr, 'relatedLinks', {});
expect(vm.shouldRenderRelatedLinks).toBeTruthy();
});
});
......@@ -223,18 +226,23 @@ describe('mrWidgetOptions', () => {
vm.bindEventHubListeners();
eventHub.$emit('SetBranchRemoveFlag', ['flag']);
expect(vm.mr.isRemovingSourceBranch).toEqual('flag');
eventHub.$emit('FailedToMerge');
expect(vm.mr.state).toEqual('failedToMerge');
eventHub.$emit('UpdateWidgetData', mockData);
expect(vm.mr.setData).toHaveBeenCalledWith(mockData);
eventHub.$emit('EnablePolling');
expect(vm.resumePolling).toHaveBeenCalled();
eventHub.$emit('DisablePolling');
expect(vm.stopPolling).toHaveBeenCalled();
const listenersWithServiceRequest = {
......@@ -253,9 +261,11 @@ describe('mrWidgetOptions', () => {
});
listenersWithServiceRequest.MRWidgetUpdateRequested();
expect(vm.checkStatus).toHaveBeenCalled();
listenersWithServiceRequest.FetchActionsContent();
expect(vm.fetchActionsContent).toHaveBeenCalled();
});
});
......@@ -352,6 +362,7 @@ describe('mrWidgetOptions', () => {
spyOn(vm.pollingInterval, 'resume');
vm.resumePolling();
expect(vm.pollingInterval.resume).toHaveBeenCalled();
});
});
......@@ -361,6 +372,7 @@ describe('mrWidgetOptions', () => {
spyOn(vm.pollingInterval, 'stopTimer');
vm.stopPolling();
expect(vm.pollingInterval.stopTimer).toHaveBeenCalled();
});
});
......
......@@ -20,46 +20,60 @@ describe('getStateKey', () => {
work_in_progress: false,
};
const bound = getStateKey.bind(context, data);
expect(bound()).toEqual(null);
context.canBeMerged = true;
expect(bound()).toEqual('readyToMerge');
context.canMerge = false;
expect(bound()).toEqual('notAllowedToMerge');
context.mergeWhenPipelineSucceeds = true;
expect(bound()).toEqual('mergeWhenPipelineSucceeds');
context.hasSHAChanged = true;
expect(bound()).toEqual('shaMismatch');
context.isPipelineBlocked = true;
expect(bound()).toEqual('pipelineBlocked');
context.hasMergeableDiscussionsState = true;
expect(bound()).toEqual('unresolvedDiscussions');
context.onlyAllowMergeIfPipelineSucceeds = true;
context.isPipelineFailed = true;
expect(bound()).toEqual('pipelineFailed');
data.work_in_progress = true;
expect(bound()).toEqual('workInProgress');
data.has_conflicts = true;
expect(bound()).toEqual('conflicts');
context.mergeStatus = 'unchecked';
expect(bound()).toEqual('checking');
data.commits_count = 0;
expect(bound()).toEqual('nothingToMerge');
data.branch_missing = true;
expect(bound()).toEqual('missingBranch');
data.project_archived = true;
expect(bound()).toEqual('archived');
});
});
......@@ -12,32 +12,38 @@ describe('MergeRequestStore', () => {
it('should set hasSHAChanged when the diff SHA changes', () => {
store.setData({ ...mockData, diff_head_sha: 'a-different-string' });
expect(store.hasSHAChanged).toBe(true);
});
it('should not set hasSHAChanged when other data changes', () => {
store.setData({ ...mockData, work_in_progress: !mockData.work_in_progress });
expect(store.hasSHAChanged).toBe(false);
});
describe('isPipelinePassing', () => {
it('is true when the CI status is `success`', () => {
store.setData({ ...mockData, ci_status: 'success' });
expect(store.isPipelinePassing).toBe(true);
});
it('is true when the CI status is `success_with_warnings`', () => {
store.setData({ ...mockData, ci_status: 'success_with_warnings' });
expect(store.isPipelinePassing).toBe(true);
});
it('is false when the CI status is `failed`', () => {
store.setData({ ...mockData, ci_status: 'failed' });
expect(store.isPipelinePassing).toBe(false);
});
it('is false when the CI status is anything except `success`', () => {
store.setData({ ...mockData, ci_status: 'foobarbaz' });
expect(store.isPipelinePassing).toBe(false);
});
});
......@@ -45,11 +51,13 @@ describe('MergeRequestStore', () => {
describe('isPipelineSkipped', () => {
it('should set isPipelineSkipped=true when the CI status is `skipped`', () => {
store.setData({ ...mockData, ci_status: 'skipped' });
expect(store.isPipelineSkipped).toBe(true);
});
it('should set isPipelineSkipped=false when the CI status is anything except `skipped`', () => {
store.setData({ ...mockData, ci_status: 'foobarbaz' });
expect(store.isPipelineSkipped).toBe(false);
});
});
......@@ -57,11 +65,13 @@ describe('MergeRequestStore', () => {
describe('isNothingToMergeState', () => {
it('returns true when nothingToMerge', () => {
store.state = stateKey.nothingToMerge;
expect(store.isNothingToMergeState).toEqual(true);
});
it('returns false when not nothingToMerge', () => {
store.state = 'state';
expect(store.isNothingToMergeState).toEqual(false);
});
});
......
......@@ -83,6 +83,7 @@ describe('CI Badge Link Component', () => {
it('should render each status badge', () => {
Object.keys(statuses).map((status) => {
vm = mountComponent(CIBadge, { status: statuses[status] });
expect(vm.$el.getAttribute('href')).toEqual(statuses[status].details_path);
expect(vm.$el.textContent.trim()).toEqual(statuses[status].text);
expect(vm.$el.getAttribute('class')).toEqual(`ci-status ci-${statuses[status].group}`);
......@@ -93,6 +94,7 @@ describe('CI Badge Link Component', () => {
it('should not render label', () => {
vm = mountComponent(CIBadge, { status: statuses.canceled, showText: false });
expect(vm.$el.textContent.trim()).toEqual('');
});
});
......@@ -44,6 +44,7 @@ describe('clipboard button', () => {
title: 'Copy this value into Clipboard!',
cssClass: 'btn-danger',
});
expect(vm.$el.getAttribute('data-clipboard-text')).toEqual(
'{"text":"copy me","gfm":"`path/to/file`"}',
);
......
......@@ -78,6 +78,7 @@ describe('Commit component', () => {
expect(component.$el.querySelector('.commit-sha').getAttribute('href')).toEqual(
props.commitUrl,
);
expect(component.$el.querySelector('.commit-sha').textContent).toContain(props.shortSha);
});
......@@ -100,6 +101,7 @@ describe('Commit component', () => {
.querySelector('.commit-title .avatar-image-container img')
.getAttribute('data-original-title'),
).toContain(props.author.username);
expect(
component.$el
.querySelector('.commit-title .avatar-image-container img')
......@@ -112,6 +114,7 @@ describe('Commit component', () => {
expect(component.$el.querySelector('a.commit-row-message').getAttribute('href')).toEqual(
props.commitUrl,
);
expect(component.$el.querySelector('a.commit-row-message').textContent).toContain(
props.title,
);
......
......@@ -55,6 +55,7 @@ describe('DiffViewer', () => {
expect(vm.$el.querySelector('.deleted .file-info').textContent.trim()).toContain(
'testold.abc',
);
expect(vm.$el.querySelector('.deleted .btn.btn-default').textContent.trim()).toContain(
'Download',
);
......
......@@ -55,6 +55,7 @@ describe('ImageDiffViewer', () => {
expect(vm.$el.querySelector('.added .image_file img').getAttribute('src')).toBe(
GREEN_BOX_IMAGE_URL,
);
expect(vm.$el.querySelector('.deleted .image_file img').getAttribute('src')).toBe(
RED_BOX_IMAGE_URL,
);
......@@ -63,6 +64,7 @@ describe('ImageDiffViewer', () => {
expect(vm.$el.querySelector('.view-modes-menu li:nth-child(2)').textContent.trim()).toBe(
'Swipe',
);
expect(vm.$el.querySelector('.view-modes-menu li:nth-child(3)').textContent.trim()).toBe(
'Onion skin',
);
......
......@@ -55,6 +55,7 @@ describe('DropdownButtonComponent', () => {
it('renders dropdown toggle text element', () => {
const dropdownToggleTextEl = vm.$el.querySelector('.dropdown-toggle-text');
expect(dropdownToggleTextEl).not.toBeNull();
expect(dropdownToggleTextEl.innerText.trim()).toBe(defaultLabel);
});
......
......@@ -63,6 +63,7 @@ describe('File Icon component', () => {
});
const { classList } = vm.$el.querySelector('i');
expect(classList.contains('fa')).toEqual(true);
expect(classList.contains('fa-spin')).toEqual(true);
expect(classList.contains('fa-spinner')).toEqual(true);
......@@ -79,6 +80,7 @@ describe('File Icon component', () => {
const { classList } = vm.$el.firstChild;
const containsSizeClass = classList.contains('s120');
const containsCustomClass = classList.contains('extraclasses');
expect(containsSizeClass).toBe(true);
expect(containsCustomClass).toBe(true);
});
......
......@@ -48,6 +48,7 @@ describe('GlModal', () => {
it('sets the modal title', () => {
const modalTitle = vm.$el.querySelector('.modal-title');
expect(modalTitle.innerHTML.trim()).toBe(props.headerTitleText);
});
});
......@@ -63,6 +64,7 @@ describe('GlModal', () => {
it('sets the primary button class', () => {
const primaryButton = vm.$el.querySelector('.modal-footer button:last-of-type');
expect(primaryButton).toHaveClass(`btn-${props.footerPrimaryButtonVariant}`);
});
});
......@@ -78,6 +80,7 @@ describe('GlModal', () => {
it('sets the primary button text', () => {
const primaryButton = vm.$el.querySelector('.modal-footer button:last-of-type');
expect(primaryButton.innerHTML.trim()).toBe(props.footerPrimaryButtonText);
});
});
......@@ -173,6 +176,7 @@ describe('GlModal', () => {
it('sets the modal body', () => {
const modalBody = vm.$el.querySelector('.modal-body');
expect(modalBody.innerHTML).toBe(slotContent);
});
});
......@@ -184,6 +188,7 @@ describe('GlModal', () => {
it('sets the modal header', () => {
const modalHeader = vm.$el.querySelector('.modal-header');
expect(modalHeader.innerHTML).toBe(slotContent);
});
});
......@@ -195,6 +200,7 @@ describe('GlModal', () => {
it('sets the modal title', () => {
const modalTitle = vm.$el.querySelector('.modal-title');
expect(modalTitle.innerHTML).toBe(slotContent);
});
});
......@@ -206,6 +212,7 @@ describe('GlModal', () => {
it('sets the modal footer', () => {
const modalFooter = vm.$el.querySelector('.modal-footer');
expect(modalFooter.innerHTML).toBe(slotContent);
});
});
......
......@@ -48,6 +48,7 @@ describe('Sprite Icon Component', function () {
const { classList } = icon.$el;
const containsSizeClass = classList.contains('s32');
const containsCustomClass = classList.contains('extraclasses');
expect(containsSizeClass).toBe(true);
expect(containsCustomClass).toBe(true);
});
......
......@@ -69,6 +69,7 @@ describe('LoadingButton', function () {
describe('container class', () => {
it('should default to btn btn-align-content', () => {
vm = mountComponent(LoadingButton, {});
expect(vm.$el.classList.contains('btn')).toEqual(true);
expect(vm.$el.classList.contains('btn-align-content')).toEqual(true);
});
......@@ -77,6 +78,7 @@ describe('LoadingButton', function () {
vm = mountComponent(LoadingButton, {
containerClass: 'test-class',
});
expect(vm.$el.classList.contains('btn')).toEqual(false);
expect(vm.$el.classList.contains('btn-align-content')).toEqual(false);
expect(vm.$el.classList.contains('test-class')).toEqual(true);
......
......@@ -52,6 +52,7 @@ describe('MemoryGraph', () => {
it('should show human readable median value based on provided median timestamp', () => {
vm.deploymentTime = mockMedian;
const formattedMedian = vm.getFormattedMedian;
expect(formattedMedian.indexOf('Deployed')).toBeGreaterThan(-1);
expect(formattedMedian.indexOf('ago')).toBeGreaterThan(-1);
});
......@@ -62,6 +63,7 @@ describe('MemoryGraph', () => {
describe('getMedianMetricIndex', () => {
it('should return index of closest metric timestamp to that of median', () => {
const matchingIndex = vm.getMedianMetricIndex(mockMedian, mockMetrics);
expect(matchingIndex).toBe(mockMedianIndex);
});
});
......@@ -69,6 +71,7 @@ describe('MemoryGraph', () => {
describe('getGraphPlotValues', () => {
it('should return Object containing values to plot graph', () => {
const plotValues = vm.getGraphPlotValues(mockMedian, mockMetrics);
expect(plotValues.pathD).toBeDefined();
expect(Array.isArray(plotValues.pathD)).toBeTruthy();
......@@ -101,16 +104,19 @@ describe('MemoryGraph', () => {
Vue.nextTick(() => {
const svgEl = el.querySelector('svg');
expect(svgEl).toBeDefined();
expect(svgEl.getAttribute('height')).toBe(defaultHeight);
expect(svgEl.getAttribute('width')).toBe(defaultWidth);
const pathEl = el.querySelector('path');
expect(pathEl).toBeDefined();
expect(pathEl.getAttribute('d')).toBe(`M ${pathD}`);
expect(pathEl.getAttribute('viewBox')).toBe(`0 0 ${pathViewBox.lineWidth} ${pathViewBox.diff}`);
const circleEl = el.querySelector('circle');
expect(circleEl).toBeDefined();
expect(circleEl.getAttribute('r')).toBe('1.5');
expect(circleEl.getAttribute('transform')).toBe('translate(0 -1)');
......
......@@ -56,6 +56,7 @@ describe('navigation tabs component', () => {
it('should trigger onTabClick', () => {
spyOn(vm, '$emit');
vm.$el.querySelector('.js-pipelines-tab-pending').click();
expect(vm.$emit).toHaveBeenCalledWith('onChangeTab', 'pending');
});
});
......@@ -26,6 +26,7 @@ describe('issue placeholder system note component', () => {
expect(vm.$el.querySelector('.user-avatar-link').getAttribute('href')).toEqual(
userDataMock.path,
);
expect(vm.$el.querySelector('.user-avatar-link img').getAttribute('src')).toEqual(
`${userDataMock.avatar_url}?width=40`,
);
......@@ -37,6 +38,7 @@ describe('issue placeholder system note component', () => {
expect(vm.$el.querySelector('.note-header-info a').getAttribute('href')).toEqual(
userDataMock.path,
);
expect(
vm.$el.querySelector('.note-header-info .note-headline-light').textContent.trim(),
).toEqual(`@${userDataMock.username}`);
......
......@@ -39,11 +39,11 @@ describe('Pagination links component', () => {
});
it('should provide translated text to GitLab UI pagination', () => {
Object.entries(translations).forEach(entry =>
Object.entries(translations).forEach(entry => {
expect(
destinationComponent[entry[0]],
).toBe(entry[1]),
);
destinationComponent[entry[0]],
).toBe(entry[1])
});
});
it('should pass change to GitLab UI pagination', () => {
......
......@@ -53,6 +53,7 @@ describe('Panel Resizer component', () => {
triggerEvent('mousedown', vm.$el);
triggerEvent('mousemove', document);
triggerEvent('mouseup', document);
expect(vm.$emit.calls.allArgs()).toEqual([['resize-start', 100], ['update:size', 100], ['resize-end', 100]]);
expect(vm.size).toBe(100);
});
......
......@@ -24,6 +24,7 @@ describe('datePicker', () => {
vm.$on('hidePicker', hidePicker);
vm.$el.querySelector('.dropdown-menu-toggle').click();
expect(hidePicker).toHaveBeenCalled();
});
});
......@@ -30,6 +30,7 @@ describe('collapsedCalendarIcon', () => {
vm.$on('click', click);
vm.$el.click();
expect(click).toHaveBeenCalled();
});
});
......@@ -30,11 +30,13 @@ describe('collapsedGroupedDatePicker', () => {
it('should emit when sidebar is toggled', () => {
vm.$el.querySelector('.gutter-toggle').click();
expect(vm.toggleSidebar).toHaveBeenCalled();
});
it('should emit when collapsed-calendar-icon is clicked', () => {
vm.$el.querySelector('.sidebar-collapsed-icon').click();
expect(vm.toggleSidebar).toHaveBeenCalled();
});
});
......@@ -48,6 +50,7 @@ describe('collapsedGroupedDatePicker', () => {
it('should render both collapsed-calendar-icon', () => {
const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
expect(icons.length).toEqual(2);
expect(icons[0].innerText.trim()).toEqual('Jul 17 2016');
expect(icons[1].innerText.trim()).toEqual('Jul 17 2017');
......@@ -62,6 +65,7 @@ describe('collapsedGroupedDatePicker', () => {
it('should render minDate in collapsed-calendar-icon', () => {
const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
expect(icons.length).toEqual(1);
expect(icons[0].innerText.trim()).toEqual('From Jul 17 2016');
});
......@@ -75,6 +79,7 @@ describe('collapsedGroupedDatePicker', () => {
it('should render maxDate in collapsed-calendar-icon', () => {
const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
expect(icons.length).toEqual(1);
expect(icons[0].innerText.trim()).toEqual('Until Jul 17 2017');
});
......@@ -83,6 +88,7 @@ describe('collapsedGroupedDatePicker', () => {
describe('no dates', () => {
it('should render None', () => {
const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
expect(icons.length).toEqual(1);
expect(icons[0].innerText.trim()).toEqual('None');
});
......
......@@ -17,6 +17,7 @@ describe('sidebarDatePicker', () => {
vm.$on('toggleCollapse', toggleCollapse);
vm.$el.querySelector('.issuable-sidebar-header .gutter-toggle').click();
expect(toggleCollapse).toHaveBeenCalled();
});
......@@ -62,6 +63,7 @@ describe('sidebarDatePicker', () => {
vm.isLoading = false;
Vue.nextTick(() => {
vm.$el.querySelector('.title .btn-blank').click();
expect(vm.editing).toEqual(true);
done();
});
......@@ -92,6 +94,7 @@ describe('sidebarDatePicker', () => {
vm.$on('saveDate', saveDate);
vm.$el.querySelector('.value-content .btn-blank').click();
expect(saveDate).toHaveBeenCalled();
});
});
......@@ -111,6 +114,7 @@ describe('sidebarDatePicker', () => {
vm.$on('toggleCollapse', toggleCollapse);
vm.$el.querySelector('.title .gutter-toggle').click();
expect(toggleCollapse).toHaveBeenCalled();
});
});
......
......@@ -33,6 +33,7 @@ describe('BaseComponent', () => {
it('returns correct string when showCreate prop is `false`', () => {
const mockConfigNonEditable = Object.assign({}, mockConfig, { showCreate: false });
const vmNonEditable = createComponent(mockConfigNonEditable);
expect(vmNonEditable.hiddenInputName).toBe('label_id[]');
vmNonEditable.$destroy();
});
......@@ -46,6 +47,7 @@ describe('BaseComponent', () => {
it('return `Create group label` when `isProject` prop is false', () => {
const mockConfigGroup = Object.assign({}, mockConfig, { isProject: false });
const vmGroup = createComponent(mockConfigGroup);
expect(vmGroup.createLabelTitle).toBe('Create group label');
vmGroup.$destroy();
});
......@@ -59,6 +61,7 @@ describe('BaseComponent', () => {
it('return `Manage group labels` when `isProject` prop is false', () => {
const mockConfigGroup = Object.assign({}, mockConfig, { isProject: false });
const vmGroup = createComponent(mockConfigGroup);
expect(vmGroup.manageLabelsTitle).toBe('Manage group labels');
vmGroup.$destroy();
});
......@@ -70,6 +73,7 @@ describe('BaseComponent', () => {
it('emits onLabelClick event with label and list of labels as params', () => {
spyOn(vm, '$emit');
vm.handleClick(mockLabels[0]);
expect(vm.$emit).toHaveBeenCalledWith('onLabelClick', mockLabels[0]);
});
});
......@@ -78,6 +82,7 @@ describe('BaseComponent', () => {
it('emits toggleCollapse event on component', () => {
spyOn(vm, '$emit');
vm.handleCollapsedValueClick();
expect(vm.$emit).toHaveBeenCalledWith('toggleCollapse');
});
});
......@@ -86,6 +91,7 @@ describe('BaseComponent', () => {
it('emits onDropdownClose event on component', () => {
spyOn(vm, '$emit');
vm.handleDropdownHidden();
expect(vm.$emit).toHaveBeenCalledWith('onDropdownClose');
});
});
......@@ -114,6 +120,7 @@ describe('BaseComponent', () => {
it('renders `.dropdown-menu` element', () => {
const dropdownMenuEl = vm.$el.querySelector('.dropdown-menu');
expect(dropdownMenuEl).not.toBeNull();
expect(dropdownMenuEl.querySelector('.dropdown-page-one')).not.toBeNull();
expect(dropdownMenuEl.querySelector('.dropdown-content')).not.toBeNull();
......
......@@ -34,6 +34,7 @@ describe('DropdownButtonComponent', () => {
it('returns text as `Label` when `labels` prop is empty array', () => {
const mockEmptyLabels = Object.assign({}, componentConfig, { labels: [] });
const vmEmptyLabels = createComponent(mockEmptyLabels);
expect(vmEmptyLabels.dropdownToggleText).toBe('Label');
vmEmptyLabels.$destroy();
});
......@@ -43,6 +44,7 @@ describe('DropdownButtonComponent', () => {
labels: mockLabels.concat(mockLabels),
});
const vmMoreLabels = createComponent(mockMoreLabels);
expect(vmMoreLabels.dropdownToggleText).toBe('Foo Label +1 more');
vmMoreLabels.$destroy();
});
......@@ -69,12 +71,14 @@ describe('DropdownButtonComponent', () => {
it('renders dropdown toggle text element', () => {
const dropdownToggleTextEl = vm.$el.querySelector('.dropdown-toggle-text');
expect(dropdownToggleTextEl).not.toBeNull();
expect(dropdownToggleTextEl.innerText.trim()).toBe('Foo Label');
});
it('renders dropdown button icon', () => {
const dropdownIconEl = vm.$el.querySelector('i.fa');
expect(dropdownIconEl).not.toBeNull();
expect(dropdownIconEl.classList.contains('fa-chevron-down')).toBe(true);
});
......
......@@ -39,12 +39,14 @@ describe('DropdownCreateLabelComponent', () => {
it('renders `Go back` button on component header', () => {
const backButtonEl = vm.$el.querySelector('.dropdown-title button.dropdown-title-button.dropdown-menu-back');
expect(backButtonEl).not.toBe(null);
expect(backButtonEl.querySelector('.fa-arrow-left')).not.toBe(null);
});
it('renders component header element as `Create new label` when `headerTitle` prop is not provided', () => {
const headerEl = vm.$el.querySelector('.dropdown-title');
expect(headerEl.innerText.trim()).toContain('Create new label');
});
......@@ -52,12 +54,14 @@ describe('DropdownCreateLabelComponent', () => {
const headerTitle = 'Create project label';
const vmWithHeaderTitle = createComponent(headerTitle);
const headerEl = vmWithHeaderTitle.$el.querySelector('.dropdown-title');
expect(headerEl.innerText.trim()).toContain(headerTitle);
vmWithHeaderTitle.$destroy();
});
it('renders `Close` button on component header', () => {
const closeButtonEl = vm.$el.querySelector('.dropdown-title button.dropdown-title-button.dropdown-menu-close');
expect(closeButtonEl).not.toBe(null);
expect(closeButtonEl.querySelector('.fa-times.dropdown-menu-close-icon')).not.toBe(null);
});
......@@ -69,10 +73,12 @@ describe('DropdownCreateLabelComponent', () => {
it('renders suggested colors list elements', () => {
const colorsListContainerEl = vm.$el.querySelector('.suggest-colors.suggest-colors-dropdown');
expect(colorsListContainerEl).not.toBe(null);
expect(colorsListContainerEl.querySelectorAll('a').length).toBe(mockSuggestedColors.length);
const colorItemEl = colorsListContainerEl.querySelectorAll('a')[0];
expect(colorItemEl.dataset.color).toBe(vm.suggestedColors[0]);
expect(colorItemEl.getAttribute('style')).toBe('background-color: rgb(0, 51, 204);');
});
......@@ -86,6 +92,7 @@ describe('DropdownCreateLabelComponent', () => {
it('renders component action buttons', () => {
const createBtnEl = vm.$el.querySelector('button.js-new-label-btn');
const cancelBtnEl = vm.$el.querySelector('button.js-cancel-label-btn');
expect(createBtnEl).not.toBe(null);
expect(createBtnEl.innerText.trim()).toBe('Create');
expect(cancelBtnEl.innerText.trim()).toBe('Cancel');
......
......@@ -36,6 +36,7 @@ describe('DropdownFooterComponent', () => {
describe('template', () => {
it('renders link element with `Create new label` when `createLabelTitle` prop is not provided', () => {
const createLabelEl = vm.$el.querySelector('.dropdown-footer-list .dropdown-toggle-page');
expect(createLabelEl).not.toBeNull();
expect(createLabelEl.innerText.trim()).toBe('Create new label');
});
......@@ -43,12 +44,14 @@ describe('DropdownFooterComponent', () => {
it('renders link element with value of `createLabelTitle` prop', () => {
const vmWithCreateLabelTitle = createComponent(mockConfig.labelsWebUrl, createLabelTitle);
const createLabelEl = vmWithCreateLabelTitle.$el.querySelector('.dropdown-footer-list .dropdown-toggle-page');
expect(createLabelEl.innerText.trim()).toBe(createLabelTitle);
vmWithCreateLabelTitle.$destroy();
});
it('renders link element with `Manage labels` when `manageLabelsTitle` prop is not provided', () => {
const manageLabelsEl = vm.$el.querySelector('.dropdown-footer-list .dropdown-external-link');
expect(manageLabelsEl).not.toBeNull();
expect(manageLabelsEl.getAttribute('href')).toBe(vm.labelsWebUrl);
expect(manageLabelsEl.innerText.trim()).toBe('Manage labels');
......@@ -61,6 +64,7 @@ describe('DropdownFooterComponent', () => {
manageLabelsTitle,
);
const manageLabelsEl = vmWithManageLabelsTitle.$el.querySelector('.dropdown-footer-list .dropdown-external-link');
expect(manageLabelsEl.innerText.trim()).toBe(manageLabelsTitle);
vmWithManageLabelsTitle.$destroy();
});
......
......@@ -24,11 +24,13 @@ describe('DropdownHeaderComponent', () => {
describe('template', () => {
it('renders header text element', () => {
const headerEl = vm.$el.querySelector('.dropdown-title span');
expect(headerEl.innerText.trim()).toBe('Assign labels');
});
it('renders `Close` button element', () => {
const closeBtnEl = vm.$el.querySelector('.dropdown-title button.dropdown-title-button.dropdown-menu-close');
expect(closeBtnEl).not.toBeNull();
expect(closeBtnEl.querySelector('.fa-times.dropdown-menu-close-icon')).not.toBeNull();
});
......
......@@ -24,6 +24,7 @@ describe('DropdownSearchInputComponent', () => {
describe('template', () => {
it('renders input element with type `search`', () => {
const inputEl = vm.$el.querySelector('input.dropdown-input-field');
expect(inputEl).not.toBeNull();
expect(inputEl.getAttribute('type')).toBe('search');
});
......
......@@ -35,6 +35,7 @@ describe('DropdownTitleComponent', () => {
it('renders `Edit` button element', () => {
const editBtnEl = vm.$el.querySelector('button.edit-link.js-sidebar-dropdown-toggle');
expect(editBtnEl).not.toBeNull();
expect(editBtnEl.innerText.trim()).toBe('Edit');
});
......
......@@ -29,12 +29,14 @@ describe('DropdownValueCollapsedComponent', () => {
describe('labelsList', () => {
it('returns empty text when `labels` prop is empty array', () => {
const vmEmptyLabels = createComponent([]);
expect(vmEmptyLabels.labelsList).toBe('');
vmEmptyLabels.$destroy();
});
it('returns labels names separated by coma when `labels` prop has more than one item', () => {
const vmMoreLabels = createComponent(mockLabels.concat(mockLabels));
expect(vmMoreLabels.labelsList).toBe('Foo Label, Foo Label');
vmMoreLabels.$destroy();
});
......@@ -46,6 +48,7 @@ describe('DropdownValueCollapsedComponent', () => {
}
const vmMoreLabels = createComponent(mockMoreLabels);
expect(vmMoreLabels.labelsList).toBe('Foo Label, Foo Label, Foo Label, Foo Label, Foo Label, and 2 more');
vmMoreLabels.$destroy();
});
......@@ -61,6 +64,7 @@ describe('DropdownValueCollapsedComponent', () => {
it('emits onValueClick event on component', () => {
spyOn(vm, '$emit');
vm.handleClick();
expect(vm.$emit).toHaveBeenCalledWith('onValueClick');
});
});
......
......@@ -33,6 +33,7 @@ describe('DropdownValueComponent', () => {
describe('isEmpty', () => {
it('returns true if `labels` prop is empty', () => {
const vmEmptyLabels = createComponent([]);
expect(vmEmptyLabels.isEmpty).toBe(true);
vmEmptyLabels.$destroy();
});
......@@ -73,6 +74,7 @@ describe('DropdownValueComponent', () => {
it('render slot content inside component when `labels` prop is empty', () => {
const vmEmptyLabels = createComponent([]);
expect(vmEmptyLabels.$el.querySelector('.text-secondary').innerText.trim()).toBe(mockConfig.emptyValueText);
vmEmptyLabels.$destroy();
});
......@@ -83,6 +85,7 @@ describe('DropdownValueComponent', () => {
it('renders label element with tooltip and styles based on label details', () => {
const labelEl = vm.$el.querySelector('a span.badge.color-label');
expect(labelEl).not.toBeNull();
expect(labelEl.dataset.placement).toBe('bottom');
expect(labelEl.dataset.container).toBe('body');
......
......@@ -72,6 +72,7 @@ describe('StackedProgressBarComponent', () => {
it('renders empty state when count is unavailable', () => {
const vmX = createComponent({ totalCount: 0, successCount: 0, failureCount: 0 });
expect(vmX.$el.querySelectorAll('.status-unavailable').length).not.toBe(0);
vmX.$destroy();
});
......
......@@ -72,6 +72,7 @@ describe('Pagination component', () => {
});
component.$el.querySelector('.js-previous-button a').click();
expect(spy).toHaveBeenCalledWith(1);
});
});
......
......@@ -25,6 +25,7 @@ describe('Time ago with tooltip component', () => {
expect(
vm.$el.getAttribute('data-original-title'),
).toEqual(formatDate('2017-05-08T14:57:39.781Z'));
expect(vm.$el.getAttribute('data-placement')).toEqual('top');
const timeago = getTimeago();
......
......@@ -51,9 +51,11 @@ describe('Toggle Button', () => {
it('sets aria-label representing toggle state', () => {
vm.value = true;
expect(vm.ariaLabel).toEqual('Toggle Status: ON');
vm.value = false;
expect(vm.ariaLabel).toEqual('Toggle Status: OFF');
});
......
......@@ -59,6 +59,7 @@ describe('User Avatar Link Component', function () {
it('should only render image tag in link', function () {
const childElements = this.userAvatarLink.$el.childNodes;
expect(childElements[0].tagName).toBe('IMG');
// Vue will render the hidden component as <!---->
......
......@@ -46,12 +46,14 @@ describe('ZenMode', () => {
it('should not call dropzone if element is not dropzone valid', () => {
$('.div-dropzone').addClass('js-invalid-dropzone');
exitZen();
expect(dropzoneForElementSpy.calls.count()).toEqual(0);
});
it('should call dropzone if element is dropzone valid', () => {
$('.div-dropzone').removeClass('js-invalid-dropzone');
exitZen();
expect(dropzoneForElementSpy.calls.count()).toEqual(2);
});
});
......@@ -60,12 +62,14 @@ describe('ZenMode', () => {
it('pauses Mousetrap', () => {
const mouseTrapPauseSpy = spyOn(Mousetrap, 'pause');
enterZen();
expect(mouseTrapPauseSpy).toHaveBeenCalled();
});
it('removes textarea styling', () => {
$('.notes-form textarea').attr('style', 'height: 400px');
enterZen();
expect($('.notes-form textarea')).not.toHaveAttr('style');
});
});
......@@ -75,6 +79,7 @@ describe('ZenMode', () => {
it('exits on Escape', () => {
escapeKeydown();
expect($('.notes-form .zen-backdrop')).not.toHaveClass('fullscreen');
});
});
......@@ -85,12 +90,14 @@ describe('ZenMode', () => {
it('unpauses Mousetrap', () => {
const mouseTrapUnpauseSpy = spyOn(Mousetrap, 'unpause');
exitZen();
expect(mouseTrapUnpauseSpy).toHaveBeenCalled();
});
it('restores the scroll position', () => {
spyOn(zen, 'scrollTo');
exitZen();
expect(zen.scrollTo).toHaveBeenCalled();
});
});
......
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