Commit 0d6b1f91 authored by Stanislav Lashmanov's avatar Stanislav Lashmanov

Refactor nextTick to use direct import from Vue package

RFC: https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/47
parent b568065f
......@@ -19,7 +19,7 @@ async function files(store, count) {
const copies = Array(count).fill(file);
store.state.diffs.diffFiles.push(...copies);
return nextTick();
await nextTick();
}
describe('CollapsedFilesWarning', () => {
......@@ -84,7 +84,7 @@ describe('CollapsedFilesWarning', () => {
getAlertCloseButton().element.click();
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.find('[data-testid="root"]').exists()).toBe(false);
});
......
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import getDiffWithCommit from 'test_fixtures/merge_request_diffs/with_commit.json';
import setWindowLocation from 'helpers/set_window_location_helper';
......@@ -232,14 +232,13 @@ describe('CompareVersions', () => {
expect(link.element.getAttribute('href')).toEqual(PREV_COMMIT_URL);
});
it('triggers the correct Vuex action on click', () => {
it('triggers the correct Vuex action on click', async () => {
const link = getPrevCommitNavElement();
link.trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.vm.moveToNeighboringCommit).toHaveBeenCalledWith({
direction: 'previous',
});
await nextTick();
expect(wrapper.vm.moveToNeighboringCommit).toHaveBeenCalledWith({
direction: 'previous',
});
});
......@@ -267,13 +266,12 @@ describe('CompareVersions', () => {
expect(link.element.getAttribute('href')).toEqual(NEXT_COMMIT_URL);
});
it('triggers the correct Vuex action on click', () => {
it('triggers the correct Vuex action on click', async () => {
const link = getNextCommitNavElement();
link.trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.vm.moveToNeighboringCommit).toHaveBeenCalledWith({ direction: 'next' });
});
await nextTick();
expect(wrapper.vm.moveToNeighboringCommit).toHaveBeenCalledWith({ direction: 'next' });
});
it('renders a disabled button when there is no next commit', () => {
......
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import { cloneDeep } from 'lodash';
import Vuex from 'vuex';
......@@ -125,30 +125,27 @@ describe('DiffFileHeader component', () => {
expect(findCollapseIcon().props('name')).toBe(icon);
});
it('when header is clicked emits toggleFile', () => {
it('when header is clicked emits toggleFile', async () => {
createComponent();
findHeader().trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted().toggleFile).toBeDefined();
});
await nextTick();
expect(wrapper.emitted().toggleFile).toBeDefined();
});
it('when collapseIcon is clicked emits toggleFile', () => {
it('when collapseIcon is clicked emits toggleFile', async () => {
createComponent({ props: { collapsible: true } });
findCollapseIcon().vm.$emit('click', new Event('click'));
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted().toggleFile).toBeDefined();
});
await nextTick();
expect(wrapper.emitted().toggleFile).toBeDefined();
});
it('when other element in header is clicked does not emits toggleFile', () => {
it('when other element in header is clicked does not emits toggleFile', async () => {
createComponent({ props: { collapsible: true } });
findTitleLink().trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted().toggleFile).not.toBeDefined();
});
await nextTick();
expect(wrapper.emitted().toggleFile).not.toBeDefined();
});
describe('copy to clipboard', () => {
......
......@@ -160,7 +160,7 @@ describe('DiffFile', () => {
last,
}));
await wrapper.vm.$nextTick();
await nextTick();
expect(eventHub.$emit).toHaveBeenCalledTimes(events.length);
events.forEach((event) => {
......@@ -184,13 +184,13 @@ describe('DiffFile', () => {
makeFileAutomaticallyCollapsed(store);
await wrapper.vm.$nextTick(); // Wait for store updates to flow into the component
await nextTick(); // Wait for store updates to flow into the component
toggleFile(wrapper);
await wrapper.vm.$nextTick(); // Wait for the load to resolve
await wrapper.vm.$nextTick(); // Wait for the idleCallback
await wrapper.vm.$nextTick(); // Wait for nextTick inside postRender
await nextTick(); // Wait for the load to resolve
await nextTick(); // Wait for the idleCallback
await nextTick(); // Wait for nextTick inside postRender
expect(eventHub.$emit).toHaveBeenCalledTimes(2);
expect(eventHub.$emit).toHaveBeenCalledWith(EVT_PERF_MARK_FIRST_DIFF_FILE_SHOWN);
......@@ -214,7 +214,7 @@ describe('DiffFile', () => {
markFileToBeRendered(store);
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.find(DiffContentComponent).exists()).toBe(true);
});
......@@ -264,7 +264,7 @@ describe('DiffFile', () => {
it('performs the normal file toggle when the file is collapsed', async () => {
makeFileAutomaticallyCollapsed(store);
await wrapper.vm.$nextTick();
await nextTick();
eventHub.$emit(EVT_EXPAND_ALL_FILES);
......@@ -274,7 +274,7 @@ describe('DiffFile', () => {
it('does nothing when the file is not collapsed', async () => {
eventHub.$emit(EVT_EXPAND_ALL_FILES);
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.vm.handleToggle).not.toHaveBeenCalled();
});
......@@ -286,7 +286,7 @@ describe('DiffFile', () => {
});
it('should not have any content at all', async () => {
await wrapper.vm.$nextTick();
await nextTick();
expect(findDiffContentArea(wrapper).element.children.length).toBe(0);
});
......@@ -392,7 +392,7 @@ describe('DiffFile', () => {
readableText,
});
await wrapper.vm.$nextTick();
await nextTick();
toggleFile(wrapper);
};
......@@ -440,7 +440,7 @@ describe('DiffFile', () => {
makeFileAutomaticallyCollapsed(store);
wrapper.vm.requestDiff();
await wrapper.vm.$nextTick();
await nextTick();
expect(findLoader(wrapper).exists()).toBe(true);
});
......@@ -451,7 +451,7 @@ describe('DiffFile', () => {
({ wrapper, store } = createComponent({ file: getUnreadableFile() }));
makeFileAutomaticallyCollapsed(store);
await wrapper.vm.$nextTick();
await nextTick();
expect(findDiffContentArea(wrapper).html()).toContain(
'Files with large changes are collapsed by default.',
......@@ -470,7 +470,7 @@ describe('DiffFile', () => {
markFileToBeRendered(store);
changeViewerType(store, mode);
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.classes('has-body')).toBe(true);
expect(wrapper.find(DiffContentComponent).exists()).toBe(true);
......@@ -496,7 +496,7 @@ describe('DiffFile', () => {
},
});
await wrapper.vm.$nextTick();
await nextTick();
const button = wrapper.find('[data-testid="blob-button"]');
......@@ -521,7 +521,7 @@ describe('DiffFile', () => {
({ wrapper, store } = createComponent({ file, props: { viewDiffsFileByFile: true } }));
await wrapper.vm.$nextTick();
await nextTick();
expect(findLoader(wrapper).exists()).toBe(true);
});
......
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import DiffGutterAvatars from '~/diffs/components/diff_gutter_avatars.vue';
import discussionsMockData from '../mock_data/diff_discussions';
......@@ -35,12 +36,11 @@ describe('DiffGutterAvatars', () => {
expect(findCollapseButton().exists()).toBe(true);
});
it('should emit toggleDiscussions event on button click', () => {
it('should emit toggleDiscussions event on button click', async () => {
findCollapseButton().trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted().toggleLineDiscussions).toBeTruthy();
});
await nextTick();
expect(wrapper.emitted().toggleLineDiscussions).toBeTruthy();
});
});
......@@ -65,20 +65,18 @@ describe('DiffGutterAvatars', () => {
expect(findMoreCount().text()).toBe('+2');
});
it('should emit toggleDiscussions event on avatars click', () => {
it('should emit toggleDiscussions event on avatars click', async () => {
findUserAvatars().at(0).trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted().toggleLineDiscussions).toBeTruthy();
});
await nextTick();
expect(wrapper.emitted().toggleLineDiscussions).toBeTruthy();
});
it('should emit toggleDiscussions event on more count text click', () => {
it('should emit toggleDiscussions event on more count text click', async () => {
findMoreCount().trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted().toggleLineDiscussions).toBeTruthy();
});
await nextTick();
expect(wrapper.emitted().toggleLineDiscussions).toBeTruthy();
});
});
......
import { shallowMount, mount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import TreeList from '~/diffs/components/tree_list.vue';
import createStore from '~/diffs/store/modules';
......@@ -91,12 +91,11 @@ describe('Diffs tree list component', () => {
expect(getFileRows().at(1).html()).toContain('app');
});
it('hides file stats', () => {
it('hides file stats', async () => {
wrapper.setProps({ hideFileStats: true });
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find('.file-row-stats').exists()).toBe(false);
});
await nextTick();
expect(wrapper.find('.file-row-stats').exists()).toBe(false);
});
it('calls toggleTreeOpen when clicking folder', () => {
......@@ -117,20 +116,18 @@ describe('Diffs tree list component', () => {
});
});
it('renders as file list when renderTreeList is false', () => {
it('renders as file list when renderTreeList is false', async () => {
wrapper.vm.$store.state.diffs.renderTreeList = false;
return wrapper.vm.$nextTick().then(() => {
expect(getFileRows()).toHaveLength(1);
});
await nextTick();
expect(getFileRows()).toHaveLength(1);
});
it('renders file paths when renderTreeList is false', () => {
it('renders file paths when renderTreeList is false', async () => {
wrapper.vm.$store.state.diffs.renderTreeList = false;
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find('.file-row').html()).toContain('index.js');
});
await nextTick();
expect(wrapper.find('.file-row').html()).toContain('index.js');
});
});
......@@ -142,14 +139,13 @@ describe('Diffs tree list component', () => {
store.state.diffs.viewedDiffFileIds = viewedDiffFileIds;
});
it('passes the viewedDiffFileIds to the FileTree', () => {
it('passes the viewedDiffFileIds to the FileTree', async () => {
createComponent(shallowMount);
return wrapper.vm.$nextTick().then(() => {
// Have to use $attrs['viewed-files'] because we are passing down an object
// and attributes('') stringifies values (e.g. [object])...
expect(wrapper.find(FileTree).vm.$attrs['viewed-files']).toBe(viewedDiffFileIds);
});
await nextTick();
// Have to use $attrs['viewed-files'] because we are passing down an object
// and attributes('') stringifies values (e.g. [object])...
expect(wrapper.find(FileTree).vm.$attrs['viewed-files']).toBe(viewedDiffFileIds);
});
});
});
import { GlAlert, GlModal } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import CanaryUpdateModal from '~/environments/components/canary_update_modal.vue';
import updateCanaryIngress from '~/environments/graphql/mutations/update_canary_ingress.mutation.graphql';
......@@ -86,7 +87,7 @@ describe('/environments/components/canary_update_modal.vue', () => {
mutate.mockResolvedValue({ data: { environmentsCanaryIngressUpdate: { errors: [] } } });
modal.vm.$emit('primary');
await wrapper.vm.$nextTick();
await nextTick();
expect(findAlert().exists()).toBe(false);
});
......@@ -95,7 +96,7 @@ describe('/environments/components/canary_update_modal.vue', () => {
mutate.mockResolvedValue({ data: { environmentsCanaryIngressUpdate: { errors: ['error'] } } });
modal.vm.$emit('primary');
await wrapper.vm.$nextTick();
await nextTick();
expect(findAlert().text()).toBe('error');
});
......@@ -105,7 +106,7 @@ describe('/environments/components/canary_update_modal.vue', () => {
modal.vm.$emit('primary');
await waitForPromises();
await wrapper.vm.$nextTick();
await nextTick();
expect(findAlert().text()).toBe('Something went wrong. Please try again later');
});
......@@ -114,12 +115,12 @@ describe('/environments/components/canary_update_modal.vue', () => {
mutate.mockResolvedValue({ data: { environmentsCanaryIngressUpdate: { errors: ['error'] } } });
modal.vm.$emit('primary');
await wrapper.vm.$nextTick();
await nextTick();
const alert = findAlert();
alert.vm.$emit('dismiss');
await wrapper.vm.$nextTick();
await nextTick();
expect(alert.exists()).toBe(false);
});
......
import { GlTooltip, GlIcon, GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import CanaryIngress from '~/environments/components/canary_ingress.vue';
import DeployBoard from '~/environments/components/deploy_board.vue';
import { deployBoardMockData, environment } from './mock_data';
......@@ -24,7 +24,7 @@ describe('Deploy Board', () => {
describe('with valid data', () => {
beforeEach((done) => {
wrapper = createComponent();
wrapper.vm.$nextTick(done);
nextTick(done);
});
it('should render percentage with completion value provided', () => {
......@@ -79,7 +79,7 @@ describe('Deploy Board', () => {
isEmpty: true,
logsPath,
});
wrapper.vm.$nextTick(done);
nextTick(done);
});
it('should render the empty state', () => {
......@@ -98,7 +98,7 @@ describe('Deploy Board', () => {
isEmpty: false,
logsPath,
});
wrapper.vm.$nextTick(done);
nextTick(done);
});
it('should render loading spinner', () => {
......@@ -116,7 +116,7 @@ describe('Deploy Board', () => {
deployBoardData: deployBoardMockData,
});
({ statuses } = wrapper.vm);
wrapper.vm.$nextTick(done);
nextTick(done);
});
it('with all the possible statuses', () => {
......
import { GlDropdown, GlDropdownItem, GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import { TEST_HOST } from 'helpers/test_constants';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
......@@ -108,7 +108,7 @@ describe('EnvironmentActions Component', () => {
jest.spyOn(window, 'confirm').mockImplementation(() => confirm);
findDropdownItem(scheduledJobAction).vm.$emit('click');
await wrapper.vm.$nextTick();
await nextTick();
};
beforeEach(() => {
......
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import CanaryUpdateModal from '~/environments/components/canary_update_modal.vue';
import DeployBoard from '~/environments/components/deploy_board.vue';
import EnvironmentTable from '~/environments/components/environments_table.vue';
......@@ -181,7 +182,7 @@ describe('Environment table', () => {
});
wrapper.find(DeployBoard).vm.$emit('changeCanaryWeight', 40);
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.find(CanaryUpdateModal).props()).toMatchObject({
weight: 40,
......
import { GlTabs } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import Container from '~/environments/components/container.vue';
import DeployBoard from '~/environments/components/deploy_board.vue';
......@@ -186,14 +187,13 @@ describe('Environment', () => {
expect(wrapper.find('.folder-icon[data-testid="chevron-right-icon"]').exists()).toBe(false);
});
it('should close an opened folder', () => {
it('should close an opened folder', async () => {
expect(wrapper.find('.folder-icon[data-testid="chevron-down-icon"]').exists()).toBe(true);
// close folder
wrapper.find('.folder-name').trigger('click');
wrapper.vm.$nextTick(() => {
expect(wrapper.find('.folder-icon[data-testid="chevron-down-icon"]').exists()).toBe(false);
});
await nextTick();
expect(wrapper.find('.folder-icon[data-testid="chevron-down-icon"]').exists()).toBe(false);
});
it('should show children environments', () => {
......
......@@ -8,7 +8,7 @@ import {
GlSprintf,
} from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import {
severityLevel,
......@@ -139,32 +139,30 @@ describe('ErrorDetails', () => {
mountComponent();
});
it('when before timeout, still shows loading', () => {
it('when before timeout, still shows loading', async () => {
Date.now.mockReturnValue(endTime - 1);
wrapper.vm.onNoApolloResult();
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
expect(createFlash).not.toHaveBeenCalled();
expect(mocks.$apollo.queries.error.stopPolling).not.toHaveBeenCalled();
});
await nextTick();
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
expect(createFlash).not.toHaveBeenCalled();
expect(mocks.$apollo.queries.error.stopPolling).not.toHaveBeenCalled();
});
it('when timeout is hit and no apollo result, stops loading and shows flash', () => {
it('when timeout is hit and no apollo result, stops loading and shows flash', async () => {
Date.now.mockReturnValue(endTime + 1);
wrapper.vm.onNoApolloResult();
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.find(GlLink).exists()).toBe(false);
expect(createFlash).toHaveBeenCalledWith({
message: 'Could not connect to Sentry. Refresh the page to try again.',
type: 'warning',
});
expect(mocks.$apollo.queries.error.stopPolling).toHaveBeenCalled();
await nextTick();
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.find(GlLink).exists()).toBe(false);
expect(createFlash).toHaveBeenCalledWith({
message: 'Could not connect to Sentry. Refresh the page to try again.',
type: 'warning',
});
expect(mocks.$apollo.queries.error.stopPolling).toHaveBeenCalled();
});
});
......@@ -224,7 +222,7 @@ describe('ErrorDetails', () => {
});
describe('Badges', () => {
it('should show language and error level badges', () => {
it('should show language and error level badges', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
......@@ -232,12 +230,11 @@ describe('ErrorDetails', () => {
tags: { level: 'error', logger: 'ruby' },
},
});
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.findAll(GlBadge).length).toBe(2);
});
await nextTick();
expect(wrapper.findAll(GlBadge).length).toBe(2);
});
it('should NOT show the badge if the tag is not present', () => {
it('should NOT show the badge if the tag is not present', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
......@@ -245,14 +242,13 @@ describe('ErrorDetails', () => {
tags: { level: 'error' },
},
});
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.findAll(GlBadge).length).toBe(1);
});
await nextTick();
expect(wrapper.findAll(GlBadge).length).toBe(1);
});
it.each(Object.keys(severityLevel))(
'should set correct severity level variant for %s badge',
(level) => {
async (level) => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
......@@ -260,15 +256,14 @@ describe('ErrorDetails', () => {
tags: { level: severityLevel[level] },
},
});
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find(GlBadge).props('variant')).toEqual(
severityLevelVariant[severityLevel[level]],
);
});
await nextTick();
expect(wrapper.find(GlBadge).props('variant')).toEqual(
severityLevelVariant[severityLevel[level]],
);
},
);
it('should fallback for ERROR severityLevelVariant when severityLevel is unknown', () => {
it('should fallback for ERROR severityLevelVariant when severityLevel is unknown', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
......@@ -276,32 +271,29 @@ describe('ErrorDetails', () => {
tags: { level: 'someNewErrorLevel' },
},
});
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find(GlBadge).props('variant')).toEqual(
severityLevelVariant[severityLevel.ERROR],
);
});
await nextTick();
expect(wrapper.find(GlBadge).props('variant')).toEqual(
severityLevelVariant[severityLevel.ERROR],
);
});
});
describe('Stacktrace', () => {
it('should show stacktrace', () => {
it('should show stacktrace', async () => {
store.state.details.loadingStacktrace = false;
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.find(Stacktrace).exists()).toBe(true);
expect(findAlert().exists()).toBe(false);
});
await nextTick();
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.find(Stacktrace).exists()).toBe(true);
expect(findAlert().exists()).toBe(false);
});
it('should NOT show stacktrace if no entries and show Alert message', () => {
it('should NOT show stacktrace if no entries and show Alert message', async () => {
store.state.details.loadingStacktrace = false;
store.getters = { 'details/sentryUrl': () => 'sentry.io', 'details/stacktrace': () => [] };
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.find(Stacktrace).exists()).toBe(false);
expect(findAlert().text()).toBe('No stack trace for this error');
});
await nextTick();
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.find(Stacktrace).exists()).toBe(false);
expect(findAlert().text()).toBe('No stack trace for this error');
});
});
......@@ -338,10 +330,10 @@ describe('ErrorDetails', () => {
});
describe('when error is unresolved', () => {
beforeEach(() => {
beforeEach(async () => {
store.state.details.errorStatus = errorStatus.UNRESOLVED;
return wrapper.vm.$nextTick();
await nextTick();
});
it('displays Ignore and Resolve buttons', () => {
......@@ -365,10 +357,10 @@ describe('ErrorDetails', () => {
});
describe('when error is ignored', () => {
beforeEach(() => {
beforeEach(async () => {
store.state.details.errorStatus = errorStatus.IGNORED;
return wrapper.vm.$nextTick();
await nextTick();
});
it('displays Undo Ignore and Resolve buttons', () => {
......@@ -392,10 +384,10 @@ describe('ErrorDetails', () => {
});
describe('when error is resolved', () => {
beforeEach(() => {
beforeEach(async () => {
store.state.details.errorStatus = errorStatus.RESOLVED;
return wrapper.vm.$nextTick();
await nextTick();
});
it('displays Ignore and Unresolve buttons', () => {
......@@ -417,7 +409,7 @@ describe('ErrorDetails', () => {
);
});
it('should show alert with closed issueId', () => {
it('should show alert with closed issueId', async () => {
const closedIssueId = 123;
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
......@@ -426,10 +418,9 @@ describe('ErrorDetails', () => {
closedIssueId,
});
return wrapper.vm.$nextTick().then(() => {
expect(findAlert().exists()).toBe(true);
expect(findAlert().text()).toContain(`#${closedIssueId}`);
});
await nextTick();
expect(findAlert().exists()).toBe(true);
expect(findAlert().text()).toContain(`#${closedIssueId}`);
});
});
});
......@@ -495,7 +486,7 @@ describe('ErrorDetails', () => {
'/gitlab-org/gitlab-test/commit/7975be0116940bf2ad4321f79d02a55c5f7779aa';
const findGitLabCommitLink = () => wrapper.find(`[href$="${gitlabCommitPath}"]`);
it('should display a link', () => {
it('should display a link', async () => {
mocks.$apollo.queries.error.loading = false;
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
......@@ -505,12 +496,11 @@ describe('ErrorDetails', () => {
gitlabCommitPath,
},
});
return wrapper.vm.$nextTick().then(() => {
expect(findGitLabCommitLink().exists()).toBe(true);
});
await nextTick();
expect(findGitLabCommitLink().exists()).toBe(true);
});
it('should not display a link', () => {
it('should not display a link', async () => {
mocks.$apollo.queries.error.loading = false;
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
......@@ -519,9 +509,8 @@ describe('ErrorDetails', () => {
gitlabCommit: null,
},
});
return wrapper.vm.$nextTick().then(() => {
expect(findGitLabCommitLink().exists()).toBe(false);
});
await nextTick();
expect(findGitLabCommitLink().exists()).toBe(false);
});
});
......
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import ErrorTrackingActions from '~/error_tracking/components/error_tracking_actions.vue';
describe('Error Tracking Actions', () => {
......@@ -37,13 +38,12 @@ describe('Error Tracking Actions', () => {
const findButtons = () => wrapper.findAll(GlButton);
describe('when error status is unresolved', () => {
it('renders the correct actions buttons to allow ignore and resolve', () => {
it('renders the correct actions buttons to allow ignore and resolve', async () => {
expect(findButtons().exists()).toBe(true);
return wrapper.vm.$nextTick().then(() => {
expect(findButtons().at(0).attributes('title')).toBe('Ignore');
expect(findButtons().at(1).attributes('title')).toBe('Resolve');
});
await nextTick();
expect(findButtons().at(0).attributes('title')).toBe('Ignore');
expect(findButtons().at(1).attributes('title')).toBe('Resolve');
});
});
......@@ -52,12 +52,11 @@ describe('Error Tracking Actions', () => {
mountComponent({ error: { status: 'ignored' } });
});
it('renders the correct action button to undo ignore', () => {
it('renders the correct action button to undo ignore', async () => {
expect(findButtons().exists()).toBe(true);
return wrapper.vm.$nextTick().then(() => {
expect(findButtons().at(0).attributes('title')).toBe('Undo Ignore');
});
await nextTick();
expect(findButtons().at(0).attributes('title')).toBe('Undo Ignore');
});
});
......@@ -66,12 +65,11 @@ describe('Error Tracking Actions', () => {
mountComponent({ error: { status: 'resolved' } });
});
it('renders the correct action button to undo unresolve', () => {
it('renders the correct action button to undo unresolve', async () => {
expect(findButtons().exists()).toBe(true);
return wrapper.vm.$nextTick().then(() => {
expect(findButtons().at(1).attributes('title')).toBe('Unresolve');
});
await nextTick();
expect(findButtons().at(1).attributes('title')).toBe('Unresolve');
});
});
});
import { GlEmptyState, GlLoadingIcon, GlFormInput, GlPagination, GlDropdown } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import stubChildren from 'helpers/stub_children';
import ErrorTrackingActions from '~/error_tracking/components/error_tracking_actions.vue';
......@@ -316,15 +316,14 @@ describe('ErrorTrackingList', () => {
expect(findRecentSearchesDropdown().text()).toContain("You don't have any recent searches");
});
it('shows items', () => {
it('shows items', async () => {
store.state.list.recentSearches = ['great', 'search'];
return wrapper.vm.$nextTick().then(() => {
const dropdownItems = wrapper.findAll('.filtered-search-box li');
expect(dropdownItems.length).toBe(3);
expect(dropdownItems.at(0).text()).toBe('great');
expect(dropdownItems.at(1).text()).toBe('search');
});
await nextTick();
const dropdownItems = wrapper.findAll('.filtered-search-box li');
expect(dropdownItems.length).toBe(3);
expect(dropdownItems.at(0).text()).toBe('great');
expect(dropdownItems.at(1).text()).toBe('search');
});
describe('clear', () => {
......@@ -336,23 +335,21 @@ describe('ErrorTrackingList', () => {
expect(clearRecentButton().exists()).toBe(false);
});
it('is visible when list has items', () => {
it('is visible when list has items', async () => {
store.state.list.recentSearches = ['some', 'searches'];
return wrapper.vm.$nextTick().then(() => {
expect(clearRecentButton().exists()).toBe(true);
expect(clearRecentButton().text()).toBe('Clear recent searches');
});
await nextTick();
expect(clearRecentButton().exists()).toBe(true);
expect(clearRecentButton().text()).toBe('Clear recent searches');
});
it('clears items on click', () => {
it('clears items on click', async () => {
store.state.list.recentSearches = ['some', 'searches'];
return wrapper.vm.$nextTick().then(() => {
clearRecentButton().vm.$emit('click');
await nextTick();
clearRecentButton().vm.$emit('click');
expect(actions.clearRecentSearches).toHaveBeenCalledTimes(1);
});
expect(actions.clearRecentSearches).toHaveBeenCalledTimes(1);
});
});
});
......@@ -387,7 +384,7 @@ describe('ErrorTrackingList', () => {
describe('and the user is not on the first page', () => {
describe('and the previous button is clicked', () => {
beforeEach(() => {
beforeEach(async () => {
store.state.list.loading = false;
mountComponent({
stubs: {
......@@ -398,7 +395,7 @@ describe('ErrorTrackingList', () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ pageValue: 2 });
return wrapper.vm.$nextTick();
await nextTick();
});
it('fetches the previous page of results', () => {
......
......@@ -79,12 +79,11 @@ describe('error tracking settings app', () => {
expect(wrapper.find('.js-error-tracking-button').attributes('disabled')).toBeFalsy();
});
it('disables the button when saving', () => {
it('disables the button when saving', async () => {
store.state.settingsLoading = true;
return wrapper.vm.$nextTick(() => {
expect(wrapper.find('.js-error-tracking-button').attributes('disabled')).toBeTruthy();
});
await nextTick();
expect(wrapper.find('.js-error-tracking-button').attributes('disabled')).toBeTruthy();
});
});
......
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import { pick, clone } from 'lodash';
import Vuex from 'vuex';
import ProjectDropdown from '~/error_tracking_settings/components/project_dropdown.vue';
......@@ -63,10 +63,10 @@ describe('error tracking settings project dropdown', () => {
});
describe('populated project list', () => {
beforeEach(() => {
beforeEach(async () => {
wrapper.setProps({ projects: clone(projectList), hasProjects: true });
return wrapper.vm.$nextTick();
await nextTick();
});
it('renders the dropdown', () => {
......@@ -83,9 +83,9 @@ describe('error tracking settings project dropdown', () => {
describe('selected project', () => {
const selectedProject = clone(projectList[0]);
beforeEach(() => {
beforeEach(async () => {
wrapper.setProps({ projects: clone(projectList), selectedProject, hasProjects: true });
return wrapper.vm.$nextTick();
await nextTick();
});
it('does not show helper text', () => {
......@@ -95,13 +95,13 @@ describe('error tracking settings project dropdown', () => {
});
describe('invalid project selected', () => {
beforeEach(() => {
beforeEach(async () => {
wrapper.setProps({
projects: clone(projectList),
selectedProject: staleProject,
isProjectInvalid: true,
});
return wrapper.vm.$nextTick();
await nextTick();
});
it('displays a error', () => {
......
import { GlModal, GlSprintf, GlAlert } from '@gitlab/ui';
import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import Component from '~/feature_flags/components/configure_feature_flags_modal.vue';
......@@ -56,7 +57,7 @@ describe('Configure Feature Flags Modal', () => {
it('should emit a `token` event when clicking on the Primary action', async () => {
findGlModal().vm.$emit('secondary', mockEvent);
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.emitted('token')).toEqual([[]]);
expect(mockEvent.preventDefault).toHaveBeenCalled();
});
......@@ -64,7 +65,7 @@ describe('Configure Feature Flags Modal', () => {
it('should clear the project name input after generating the token', async () => {
findProjectNameInput().vm.$emit('input', provide.projectName);
findGlModal().vm.$emit('primary', mockEvent);
await wrapper.vm.$nextTick();
await nextTick();
expect(findProjectNameInput().attributes('value')).toBe('');
});
......@@ -116,7 +117,7 @@ describe('Configure Feature Flags Modal', () => {
it('should enable the secondary action', async () => {
findProjectNameInput().vm.$emit('input', provide.projectName);
await wrapper.vm.$nextTick();
await nextTick();
const [{ disabled }] = findSecondaryAction().attributes;
expect(disabled).toBe(false);
});
......
import { GlToggle, GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { mockTracking } from 'helpers/tracking_helper';
import waitForPromises from 'helpers/wait_for_promises';
......@@ -12,6 +12,7 @@ import createStore from '~/feature_flags/store/edit';
import axios from '~/lib/utils/axios_utils';
Vue.use(Vuex);
describe('Edit feature flag form', () => {
let wrapper;
let mock;
......@@ -66,13 +67,12 @@ describe('Edit feature flag form', () => {
});
describe('with error', () => {
it('should render the error', () => {
it('should render the error', async () => {
store.dispatch('receiveUpdateFeatureFlagError', { message: ['The name is required'] });
return wrapper.vm.$nextTick(() => {
const warningGlAlert = findWarningGlAlert();
expect(warningGlAlert.exists()).toEqual(true);
expect(warningGlAlert.text()).toContain('The name is required');
});
await nextTick();
const warningGlAlert = findWarningGlAlert();
expect(warningGlAlert.exists()).toEqual(true);
expect(warningGlAlert.text()).toContain('The name is required');
});
});
......
import { GlAlert, GlEmptyState, GlLink, GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import EmptyState from '~/feature_flags/components/empty_state.vue';
const DEFAULT_PROPS = {
......@@ -123,7 +124,7 @@ describe('feature_flags/components/feature_flags_tab.vue', () => {
beforeEach(async () => {
wrapper = factory();
await wrapper.vm.$nextTick();
await nextTick();
slot = wrapper.find('[data-testid="test-slot"]');
});
......
import { GlLoadingIcon, GlButton, GlSearchBoxByType } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import { TEST_HOST } from 'spec/test_constants';
import EnvironmentsDropdown from '~/feature_flags/components/environments_dropdown.vue';
......@@ -54,7 +55,7 @@ describe('Feature flags > Environments dropdown ', () => {
factory();
findEnvironmentSearchInput().vm.$emit('focus');
await waitForPromises();
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.find('.dropdown-content > ul').exists()).toBe(true);
expect(wrapper.findAll('.dropdown-content > ul > li').exists()).toBe(true);
});
......@@ -66,7 +67,7 @@ describe('Feature flags > Environments dropdown ', () => {
factory();
findEnvironmentSearchInput().vm.$emit('keyup');
await waitForPromises();
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.find('.dropdown-content > ul').exists()).toBe(true);
expect(wrapper.findAll('.dropdown-content > ul > li').exists()).toBe(true);
});
......@@ -80,7 +81,7 @@ describe('Feature flags > Environments dropdown ', () => {
findEnvironmentSearchInput().vm.$emit('focus');
findEnvironmentSearchInput().vm.$emit('input', 'production');
await waitForPromises();
await wrapper.vm.$nextTick();
await nextTick();
});
it('sets filter value', () => {
......@@ -103,7 +104,7 @@ describe('Feature flags > Environments dropdown ', () => {
.filter((b) => b.text() === 'production')
.at(0);
button.vm.$emit('click');
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.emitted('selectEnvironment')).toEqual([['production']]);
});
});
......@@ -111,7 +112,7 @@ describe('Feature flags > Environments dropdown ', () => {
describe('on click clear button', () => {
beforeEach(async () => {
wrapper.find(GlButton).vm.$emit('click');
await wrapper.vm.$nextTick();
await nextTick();
});
it('resets filter value', () => {
......@@ -132,12 +133,12 @@ describe('Feature flags > Environments dropdown ', () => {
findEnvironmentSearchInput().vm.$emit('focus');
findEnvironmentSearchInput().vm.$emit('input', 'production');
await waitForPromises();
await wrapper.vm.$nextTick();
await nextTick();
});
it('emits create event', async () => {
wrapper.findAll(GlButton).at(0).vm.$emit('click');
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.emitted('createClicked')).toEqual([['production']]);
});
});
......
import { GlAlert, GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import MockAdapter from 'axios-mock-adapter';
import Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
......@@ -172,7 +172,7 @@ describe('Feature flags', () => {
factory();
await waitForPromises();
await wrapper.vm.$nextTick();
await nextTick();
emptyState = wrapper.findComponent(GlEmptyState);
});
......
import { GlToggle, GlBadge } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { trimText } from 'helpers/text_helper';
import { mockTracking } from 'helpers/tracking_helper';
import FeatureFlagsTable from '~/feature_flags/components/feature_flags_table.vue';
......@@ -148,13 +149,12 @@ describe('Feature flag table', () => {
});
});
it('should trigger a toggle event', () => {
it('should trigger a toggle event', async () => {
toggle.vm.$emit('change');
const flag = { ...props.featureFlags[0], active: !props.featureFlags[0].active };
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted('toggle-flag')).toEqual([[flag]]);
});
await nextTick();
expect(wrapper.emitted('toggle-flag')).toEqual([[flag]]);
});
it('tracks a click', () => {
......
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import Api from '~/api';
import Form from '~/feature_flags/components/form.vue';
......@@ -126,28 +127,26 @@ describe('feature flag form', () => {
expect(wrapper.findAll(Strategy)).toHaveLength(2);
});
it('adds an all users strategy when clicking the Add button', () => {
it('adds an all users strategy when clicking the Add button', async () => {
wrapper.find(GlButton).vm.$emit('click');
return wrapper.vm.$nextTick().then(() => {
const strategies = wrapper.findAll(Strategy);
await nextTick();
const strategies = wrapper.findAll(Strategy);
expect(strategies).toHaveLength(3);
expect(strategies.at(2).props('strategy')).toEqual(allUsersStrategy);
});
expect(strategies).toHaveLength(3);
expect(strategies.at(2).props('strategy')).toEqual(allUsersStrategy);
});
it('should remove a strategy on delete', () => {
it('should remove a strategy on delete', async () => {
const strategy = {
type: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
parameters: { percentage: '30' },
scopes: [],
};
wrapper.find(Strategy).vm.$emit('delete');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.findAll(Strategy)).toHaveLength(1);
expect(wrapper.find(Strategy).props('strategy')).not.toEqual(strategy);
});
await nextTick();
expect(wrapper.findAll(Strategy)).toHaveLength(1);
expect(wrapper.find(Strategy).props('strategy')).not.toEqual(strategy);
});
});
});
import { GlLoadingIcon, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import NewEnvironmentsDropdown from '~/feature_flags/components/new_environments_dropdown.vue';
import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status';
......@@ -47,16 +48,13 @@ describe('New Environments Dropdown', () => {
describe('with empty results', () => {
let item;
beforeEach(() => {
beforeEach(async () => {
axiosMock.onGet(TEST_HOST).reply(200, []);
wrapper.find(GlSearchBoxByType).vm.$emit('focus');
wrapper.find(GlSearchBoxByType).vm.$emit('input', TEST_SEARCH);
return axios
.waitForAll()
.then(() => wrapper.vm.$nextTick())
.then(() => {
item = wrapper.find(GlDropdownItem);
});
await axios.waitForAll();
await nextTick();
item = wrapper.find(GlDropdownItem);
});
it('should display a Create item label', () => {
......
import { GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { TEST_HOST } from 'spec/test_constants';
import Form from '~/feature_flags/components/form.vue';
......@@ -51,13 +51,12 @@ describe('New feature flag form', () => {
});
describe('with error', () => {
it('should render the error', () => {
it('should render the error', async () => {
store.dispatch('receiveCreateFeatureFlagError', { message: ['The name is required'] });
return wrapper.vm.$nextTick(() => {
const warningGlAlert = findWarningGlAlert();
expect(warningGlAlert.at(0).exists()).toBe(true);
expect(warningGlAlert.at(0).text()).toContain('The name is required');
});
await nextTick();
const warningGlAlert = findWarningGlAlert();
expect(warningGlAlert.at(0).exists()).toBe(true);
expect(warningGlAlert.at(0).text()).toContain('The name is required');
});
});
......
import { GlFormInput, GlFormSelect } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import FlexibleRollout from '~/feature_flags/components/strategies/flexible_rollout.vue';
import ParameterFormGroup from '~/feature_flags/components/strategies/parameter_form_group.vue';
import { PERCENT_ROLLOUT_GROUP_ID } from '~/feature_flags/constants';
......@@ -51,7 +52,7 @@ describe('feature_flags/components/strategies/flexible_rollout.vue', () => {
it('emits a change when the percentage value changes', async () => {
percentageInput.setValue('75');
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.emitted('change')).toEqual([
[
{
......
import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import Api from '~/api';
import GitlabUserList from '~/feature_flags/components/strategies/gitlab_user_list.vue';
......@@ -71,7 +71,7 @@ describe('~/feature_flags/components/strategies/gitlab_user_list.vue', () => {
);
const searchWrapper = wrapper.find(GlSearchBoxByType);
searchWrapper.vm.$emit('input', 'new');
await wrapper.vm.$nextTick();
await nextTick();
const loadingIcon = wrapper.find(GlLoadingIcon);
expect(loadingIcon.exists()).toBe(true);
......@@ -79,7 +79,7 @@ describe('~/feature_flags/components/strategies/gitlab_user_list.vue', () => {
r({ data: [userList] });
await wrapper.vm.$nextTick();
await nextTick();
expect(loadingIcon.exists()).toBe(false);
});
......
import { GlFormInput } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import ParameterFormGroup from '~/feature_flags/components/strategies/parameter_form_group.vue';
import PercentRollout from '~/feature_flags/components/strategies/percent_rollout.vue';
import { PERCENT_ROLLOUT_GROUP_ID } from '~/feature_flags/constants';
......@@ -39,7 +40,7 @@ describe('~/feature_flags/components/strategies/percent_rollout.vue', () => {
it('emits a change when the value changes', async () => {
input.setValue('75');
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.emitted('change')).toEqual([
[{ parameters: { percentage: '75', groupId: PERCENT_ROLLOUT_GROUP_ID } }],
]);
......
import { GlAlert, GlFormSelect, GlLink, GlToken, GlButton } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import { last } from 'lodash';
import Vuex from 'vuex';
import Api from '~/api';
......@@ -85,11 +85,11 @@ describe('Feature flags strategy', () => {
let propsData;
let strategy;
beforeEach(() => {
beforeEach(async () => {
strategy = { name, parameters: {}, scopes: [] };
propsData = { strategy, index: 0 };
factory({ propsData, provide });
return wrapper.vm.$nextTick();
await nextTick();
});
it('should set the select to match the strategy name', () => {
......@@ -138,19 +138,18 @@ describe('Feature flags strategy', () => {
factory({ propsData, provide });
});
it('should revert to all-environments scope when last scope is removed', () => {
it('should revert to all-environments scope when last scope is removed', async () => {
const token = wrapper.find(GlToken);
token.vm.$emit('close');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.findAll(GlToken)).toHaveLength(0);
expect(last(wrapper.emitted('change'))).toEqual([
{
name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
parameters: { percentage: '50', groupId: PERCENT_ROLLOUT_GROUP_ID },
scopes: [{ environmentScope: '*' }],
},
]);
});
await nextTick();
expect(wrapper.findAll(GlToken)).toHaveLength(0);
expect(last(wrapper.emitted('change'))).toEqual([
{
name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
parameters: { percentage: '50', groupId: PERCENT_ROLLOUT_GROUP_ID },
scopes: [{ environmentScope: '*' }],
},
]);
});
});
......@@ -167,56 +166,52 @@ describe('Feature flags strategy', () => {
factory({ propsData, provide });
});
it('should change the parameters if a different strategy is chosen', () => {
it('should change the parameters if a different strategy is chosen', async () => {
const select = wrapper.find(GlFormSelect);
select.setValue(ROLLOUT_STRATEGY_ALL_USERS);
return wrapper.vm.$nextTick().then(() => {
expect(last(wrapper.emitted('change'))).toEqual([
{
name: ROLLOUT_STRATEGY_ALL_USERS,
parameters: {},
scopes: [{ environmentScope: '*' }],
},
]);
});
await nextTick();
expect(last(wrapper.emitted('change'))).toEqual([
{
name: ROLLOUT_STRATEGY_ALL_USERS,
parameters: {},
scopes: [{ environmentScope: '*' }],
},
]);
});
it('should display selected scopes', () => {
it('should display selected scopes', async () => {
const dropdown = wrapper.find(NewEnvironmentsDropdown);
dropdown.vm.$emit('add', 'production');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.findAll(GlToken)).toHaveLength(1);
expect(wrapper.find(GlToken).text()).toBe('production');
});
await nextTick();
expect(wrapper.findAll(GlToken)).toHaveLength(1);
expect(wrapper.find(GlToken).text()).toBe('production');
});
it('should display all selected scopes', () => {
it('should display all selected scopes', async () => {
const dropdown = wrapper.find(NewEnvironmentsDropdown);
dropdown.vm.$emit('add', 'production');
dropdown.vm.$emit('add', 'staging');
return wrapper.vm.$nextTick().then(() => {
const tokens = wrapper.findAll(GlToken);
expect(tokens).toHaveLength(2);
expect(tokens.at(0).text()).toBe('production');
expect(tokens.at(1).text()).toBe('staging');
});
await nextTick();
const tokens = wrapper.findAll(GlToken);
expect(tokens).toHaveLength(2);
expect(tokens.at(0).text()).toBe('production');
expect(tokens.at(1).text()).toBe('staging');
});
it('should emit selected scopes', () => {
it('should emit selected scopes', async () => {
const dropdown = wrapper.find(NewEnvironmentsDropdown);
dropdown.vm.$emit('add', 'production');
return wrapper.vm.$nextTick().then(() => {
expect(last(wrapper.emitted('change'))).toEqual([
{
name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
parameters: { percentage: '50', groupId: PERCENT_ROLLOUT_GROUP_ID },
scopes: [
{ environmentScope: '*', shouldBeDestroyed: true },
{ environmentScope: 'production' },
],
},
]);
});
await nextTick();
expect(last(wrapper.emitted('change'))).toEqual([
{
name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
parameters: { percentage: '50', groupId: PERCENT_ROLLOUT_GROUP_ID },
scopes: [
{ environmentScope: '*', shouldBeDestroyed: true },
{ environmentScope: 'production' },
],
},
]);
});
it('should emit a delete if the delete button is clicked', () => {
......@@ -236,39 +231,36 @@ describe('Feature flags strategy', () => {
factory({ propsData, provide });
});
it('should display selected scopes', () => {
it('should display selected scopes', async () => {
const dropdown = wrapper.find(NewEnvironmentsDropdown);
dropdown.vm.$emit('add', 'production');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.findAll(GlToken)).toHaveLength(1);
expect(wrapper.find(GlToken).text()).toBe('production');
});
await nextTick();
expect(wrapper.findAll(GlToken)).toHaveLength(1);
expect(wrapper.find(GlToken).text()).toBe('production');
});
it('should display all selected scopes', () => {
it('should display all selected scopes', async () => {
const dropdown = wrapper.find(NewEnvironmentsDropdown);
dropdown.vm.$emit('add', 'production');
dropdown.vm.$emit('add', 'staging');
return wrapper.vm.$nextTick().then(() => {
const tokens = wrapper.findAll(GlToken);
expect(tokens).toHaveLength(2);
expect(tokens.at(0).text()).toBe('production');
expect(tokens.at(1).text()).toBe('staging');
});
await nextTick();
const tokens = wrapper.findAll(GlToken);
expect(tokens).toHaveLength(2);
expect(tokens.at(0).text()).toBe('production');
expect(tokens.at(1).text()).toBe('staging');
});
it('should emit selected scopes', () => {
it('should emit selected scopes', async () => {
const dropdown = wrapper.find(NewEnvironmentsDropdown);
dropdown.vm.$emit('add', 'production');
return wrapper.vm.$nextTick().then(() => {
expect(last(wrapper.emitted('change'))).toEqual([
{
name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
parameters: { percentage: '50', groupId: PERCENT_ROLLOUT_GROUP_ID },
scopes: [{ environmentScope: 'production' }],
},
]);
});
await nextTick();
expect(last(wrapper.emitted('change'))).toEqual([
{
name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
parameters: { percentage: '50', groupId: PERCENT_ROLLOUT_GROUP_ID },
scopes: [{ environmentScope: 'production' }],
},
]);
});
});
});
......
import { GlPopover, GlLink, GlButton } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { POPOVER_TARGET_ID } from '~/feature_highlight/constants';
import { dismiss } from '~/feature_highlight/feature_highlight_helper';
import FeatureHighlightPopover from '~/feature_highlight/feature_highlight_popover.vue';
......@@ -71,7 +72,7 @@ describe('feature_highlight/feature_highlight_popover', () => {
it('hides the popover target', async () => {
await findDismissButton().trigger('click');
findPopover().vm.$emit('hidden');
await wrapper.vm.$nextTick();
await nextTick();
expect(findPopoverTarget().exists()).toBe(false);
});
......
import MockAdapter from 'axios-mock-adapter';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import { mountExtended } from 'helpers/vue_test_utils_helper';
......@@ -97,7 +97,7 @@ describe('Frequent Items App Component', () => {
triggerDropdownOpen();
store.state[TEST_VUEX_MODULE].isLoadingItems = true;
await wrapper.vm.$nextTick();
await nextTick();
const loading = findLoading();
......@@ -119,7 +119,7 @@ describe('Frequent Items App Component', () => {
expect(findFrequentItems().length).toBe(1);
triggerDropdownOpen();
await wrapper.vm.$nextTick();
await nextTick();
expect(findFrequentItems().length).toBe(expectedResult.length);
expect(findFrequentItemsList().props()).toEqual({
......@@ -135,7 +135,7 @@ describe('Frequent Items App Component', () => {
mock.onGet(/\/api\/v4\/projects.json(.*)$/).replyOnce(200, mockSearchedProjects.data);
setSearch('gitlab');
await wrapper.vm.$nextTick();
await nextTick();
expect(findLoading().exists()).toBe(true);
......
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import frequentItemsListComponent from '~/frequent_items/components/frequent_items_list.vue';
import frequentItemsListItemComponent from '~/frequent_items/components/frequent_items_list_item.vue';
......@@ -44,7 +44,7 @@ describe('FrequentItemsListComponent', () => {
wrapper.setProps({
items: mockFrequentProjects,
});
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.vm.isListEmpty).toBe(false);
});
......@@ -63,7 +63,7 @@ describe('FrequentItemsListComponent', () => {
wrapper.setProps({
isFetchFailed: false,
});
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.vm.listEmptyMessage).toBe('Projects you visit often will appear here');
});
......@@ -81,7 +81,7 @@ describe('FrequentItemsListComponent', () => {
wrapper.setProps({
isFetchFailed: false,
});
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.vm.listEmptyMessage).toBe('Sorry, no projects matched your search');
});
......@@ -89,25 +89,23 @@ describe('FrequentItemsListComponent', () => {
});
describe('template', () => {
it('should render component element with list of projects', () => {
it('should render component element with list of projects', async () => {
createComponent();
return wrapper.vm.$nextTick(() => {
expect(wrapper.classes('frequent-items-list-container')).toBe(true);
expect(wrapper.findAll({ ref: 'frequentItemsList' })).toHaveLength(1);
expect(wrapper.findAll(frequentItemsListItemComponent)).toHaveLength(5);
});
await nextTick();
expect(wrapper.classes('frequent-items-list-container')).toBe(true);
expect(wrapper.findAll({ ref: 'frequentItemsList' })).toHaveLength(1);
expect(wrapper.findAll(frequentItemsListItemComponent)).toHaveLength(5);
});
it('should render component element with empty message', () => {
it('should render component element with empty message', async () => {
createComponent({
items: [],
});
return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.$el.querySelectorAll('li.section-empty')).toHaveLength(1);
expect(wrapper.findAll(frequentItemsListItemComponent)).toHaveLength(0);
});
await nextTick();
expect(wrapper.vm.$el.querySelectorAll('li.section-empty')).toHaveLength(1);
expect(wrapper.findAll(frequentItemsListItemComponent)).toHaveLength(0);
});
});
});
import { GlSearchBoxByType } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import searchComponent from '~/frequent_items/components/frequent_items_search_input.vue';
......@@ -61,7 +61,7 @@ describe('FrequentItemsSearchInputComponent', () => {
findSearchBoxByType().vm.$emit('input', value);
await wrapper.vm.$nextTick();
await nextTick();
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'type_search_query', {
label: 'projects_dropdown_frequent_items_search_input',
......
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import createFlash from '~/flash';
......@@ -93,29 +94,28 @@ describe('grafana integration component', () => {
},
];
it('submits form on click', () => {
it('submits form on click', async () => {
axios.patch.mockResolvedValue();
findSubmitButton(wrapper).trigger('click');
expect(axios.patch).toHaveBeenCalledWith(...endpointRequest);
return wrapper.vm.$nextTick().then(() => expect(refreshCurrentPage).toHaveBeenCalled());
await nextTick();
expect(refreshCurrentPage).toHaveBeenCalled();
});
it('creates flash banner on error', () => {
it('creates flash banner on error', async () => {
const message = 'mockErrorMessage';
axios.patch.mockRejectedValue({ response: { data: { message } } });
findSubmitButton().trigger('click');
expect(axios.patch).toHaveBeenCalledWith(...endpointRequest);
return wrapper.vm
.$nextTick()
.then(jest.runAllTicks)
.then(() =>
expect(createFlash).toHaveBeenCalledWith({
message: `There was an error saving your changes. ${message}`,
}),
);
await nextTick();
await jest.runAllTicks();
expect(createFlash).toHaveBeenCalledWith({
message: `There was an error saving your changes. ${message}`,
});
});
});
});
......
import { GlLoadingIcon, GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAxiosAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import SharedRunnersForm from '~/group_settings/components/shared_runners_form.vue';
import axios from '~/lib/utils/axios_utils';
......@@ -76,7 +77,7 @@ describe('group_settings/components/shared_runners_form', () => {
findEnabledToggle().vm.$emit('change', true);
await wrapper.vm.$nextTick();
await nextTick();
expect(isLoadingIconVisible()).toBe(true);
......
import { GlBanner } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import InviteMembersBanner from '~/groups/components/invite_members_banner.vue';
import eventHub from '~/invite_members/event_hub';
......@@ -140,7 +141,7 @@ describe('InviteMembersBanner', () => {
expect(wrapper.find(GlBanner).exists()).toBe(true);
wrapper.find(GlBanner).vm.$emit('close');
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.find(GlBanner).exists()).toBe(false);
});
});
......
import { GlSearchBoxByType } from '@gitlab/ui';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import HeaderSearchApp from '~/header_search/components/app.vue';
......@@ -202,7 +202,7 @@ describe('HeaderSearchApp', () => {
expect(findHeaderSearchDropdown().exists()).toBe(false);
findHeaderSearchInput().vm.$emit('focus');
await wrapper.vm.$nextTick();
await nextTick();
expect(findHeaderSearchDropdown().exists()).toBe(true);
});
......@@ -211,7 +211,7 @@ describe('HeaderSearchApp', () => {
expect(findHeaderSearchDropdown().exists()).toBe(false);
findHeaderSearchInput().vm.$emit('click');
await wrapper.vm.$nextTick();
await nextTick();
expect(findHeaderSearchDropdown().exists()).toBe(true);
});
......@@ -265,7 +265,7 @@ describe('HeaderSearchApp', () => {
expect(findHeaderSearchDropdown().exists()).toBe(true);
findDropdownKeyboardNavigation().vm.$emit('tab');
await wrapper.vm.$nextTick();
await nextTick();
expect(findHeaderSearchDropdown().exists()).toBe(false);
});
......@@ -284,7 +284,7 @@ describe('HeaderSearchApp', () => {
it(`when currentFocusIndex changes to ${MOCK_INDEX} updates the data to searchOptions[${MOCK_INDEX}]`, async () => {
findDropdownKeyboardNavigation().vm.$emit('change', MOCK_INDEX);
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.vm.currentFocusedOption).toBe(MOCK_DEFAULT_SEARCH_OPTIONS[MOCK_INDEX]);
});
});
......@@ -299,7 +299,7 @@ describe('HeaderSearchApp', () => {
it('onKey-enter submits a search', async () => {
findHeaderSearchInput().vm.$emit('keydown', new KeyboardEvent({ key: ENTER_KEY }));
await wrapper.vm.$nextTick();
await nextTick();
expect(visitUrl).toHaveBeenCalledWith(MOCK_SEARCH_QUERY);
});
......@@ -316,7 +316,7 @@ describe('HeaderSearchApp', () => {
it('onKey-enter clicks the selected dropdown item rather than submitting a search', async () => {
findDropdownKeyboardNavigation().vm.$emit('change', MOCK_INDEX);
await wrapper.vm.$nextTick();
await nextTick();
findHeaderSearchInput().vm.$emit('keydown', new KeyboardEvent({ key: ENTER_KEY }));
expect(visitUrl).toHaveBeenCalledWith(MOCK_DEFAULT_SEARCH_OPTIONS[MOCK_INDEX].url);
});
......
import { GlDropdownItem, GlLoadingIcon, GlAvatar } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import HeaderSearchAutocompleteItems from '~/header_search/components/header_search_autocomplete_items.vue';
import {
......@@ -143,7 +143,7 @@ describe('HeaderSearchAutocompleteItems', () => {
wrapper.setProps({ currentFocusedOption: MOCK_SORTED_AUTOCOMPLETE_OPTIONS[0] });
await wrapper.vm.$nextTick();
await nextTick();
expect(scrollSpy).toHaveBeenCalledWith(false);
scrollSpy.mockRestore();
......
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import Item from '~/ide/components/branches/item.vue';
import List from '~/ide/components/branches/search_list.vue';
......@@ -50,13 +50,12 @@ describe('IDE branches search list', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
it('renders branches not found when search is not empty and branches list is empty', () => {
it('renders branches not found when search is not empty and branches list is empty', async () => {
createComponent({ branches: [] });
wrapper.find('input[type="search"]').setValue('something');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.text()).toContain(__('No branches found'));
});
await nextTick();
expect(wrapper.text()).toContain(__('No branches found'));
});
describe('with branches', () => {
......
import { GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import { stubComponent } from 'helpers/stub_component';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import waitForPromises from 'helpers/wait_for_promises';
......@@ -98,7 +98,7 @@ describe('IDE commit form', () => {
it(`at view=${viewFn.name}, ${buttonFn.name} has disabled=${disabled} tooltip=${tooltip}`, async () => {
viewFn();
await wrapper.vm.$nextTick();
await nextTick();
expect(buttonFn()).toEqual({
disabled,
......@@ -116,7 +116,7 @@ describe('IDE commit form', () => {
goToEditView();
await wrapper.vm.$nextTick();
await nextTick();
});
it('renders commit button in compact mode', () => {
......@@ -135,7 +135,7 @@ describe('IDE commit form', () => {
it('when begin commit button is clicked, shows form', async () => {
findBeginCommitButton().vm.$emit('click');
await wrapper.vm.$nextTick();
await nextTick();
expect(findForm().exists()).toBe(true);
});
......@@ -143,7 +143,7 @@ describe('IDE commit form', () => {
it('when begin commit button is clicked, sets activity view', async () => {
findBeginCommitButton().vm.$emit('click');
await wrapper.vm.$nextTick();
await nextTick();
expect(store.state.currentActivityView).toBe(leftSidebarViews.commit.name);
});
......@@ -153,14 +153,14 @@ describe('IDE commit form', () => {
setLastCommitMessage('test');
goToEditView();
await wrapper.vm.$nextTick();
await nextTick();
expect(findForm().exists()).toBe(true);
// Now test that it collapses when lastCommitMsg is cleared
setLastCommitMessage('');
await wrapper.vm.$nextTick();
await nextTick();
expect(findForm().exists()).toBe(false);
});
......@@ -177,7 +177,7 @@ describe('IDE commit form', () => {
goToCommitView();
await wrapper.vm.$nextTick();
await nextTick();
});
afterEach(() => {
......@@ -188,12 +188,12 @@ describe('IDE commit form', () => {
expect(findForm().exists()).toBe(false);
store.state.stagedFiles = [];
await wrapper.vm.$nextTick();
await nextTick();
expect(findForm().exists()).toBe(false);
store.state.stagedFiles.push('test');
await wrapper.vm.$nextTick();
await nextTick();
expect(findForm().exists()).toBe(false);
});
......@@ -208,7 +208,7 @@ describe('IDE commit form', () => {
goToCommitView();
await wrapper.vm.$nextTick();
await nextTick();
});
it('shows form', () => {
......@@ -222,7 +222,7 @@ describe('IDE commit form', () => {
describe('when no changed files', () => {
beforeEach(async () => {
store.state.stagedFiles = [];
await wrapper.vm.$nextTick();
await nextTick();
});
it('hides form', () => {
......@@ -231,7 +231,7 @@ describe('IDE commit form', () => {
it('expands again when staged files are added', async () => {
store.state.stagedFiles.push('test');
await wrapper.vm.$nextTick();
await nextTick();
expect(findForm().exists()).toBe(true);
});
......@@ -240,7 +240,7 @@ describe('IDE commit form', () => {
it('updates commitMessage in store on input', async () => {
setCommitMessageInput('testing commit message');
await wrapper.vm.$nextTick();
await nextTick();
expect(store.state.commit.commitMessage).toBe('testing commit message');
});
......@@ -253,14 +253,14 @@ describe('IDE commit form', () => {
it('resets commitMessage when clicking discard button', async () => {
setCommitMessageInput('testing commit message');
await wrapper.vm.$nextTick();
await nextTick();
expect(findCommitMessageInput().props('text')).toBe('testing commit message');
// Test that commitMessage is cleared on click
findDiscardDraftButton().vm.$emit('click');
await wrapper.vm.$nextTick();
await nextTick();
expect(findCommitMessageInput().props('text')).toBe('');
});
......@@ -274,11 +274,11 @@ describe('IDE commit form', () => {
goToCommitView();
await wrapper.vm.$nextTick();
await nextTick();
setCommitMessageInput('testing commit message');
await wrapper.vm.$nextTick();
await nextTick();
jest.spyOn(store, 'dispatch').mockResolvedValue();
});
......@@ -291,7 +291,7 @@ describe('IDE commit form', () => {
it('when cannot push code, submitting does nothing', async () => {
store.state.projects.abcproject.userPermissions.pushCode = false;
await wrapper.vm.$nextTick();
await nextTick();
submitForm();
......@@ -309,7 +309,7 @@ describe('IDE commit form', () => {
const error = createError();
store.state.commit.commitError = error;
await wrapper.vm.$nextTick();
await nextTick();
expect(modal.vm.show).toHaveBeenCalled();
expect(modal.props()).toMatchObject({
......@@ -342,7 +342,7 @@ describe('IDE commit form', () => {
async ({ commitError, expectedActions }) => {
store.state.commit.commitError = commitError('test message');
await wrapper.vm.$nextTick();
await nextTick();
wrapper.find(GlModal).vm.$emit('ok');
......
import { GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import ErrorMessage from '~/ide/components/error_message.vue';
......@@ -86,19 +86,15 @@ describe('IDE error message component', () => {
expect(actionMock).toHaveBeenCalledWith(message.actionPayload);
});
it('does not dispatch action when already loading', () => {
it('does not dispatch action when already loading', async () => {
findActionButton().trigger('click');
actionMock.mockReset();
return wrapper.vm.$nextTick(() => {
findActionButton().trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(actionMock).not.toHaveBeenCalled();
});
});
findActionButton().trigger('click');
await nextTick();
expect(actionMock).not.toHaveBeenCalled();
});
it('shows loading icon when loading', () => {
it('shows loading icon when loading', async () => {
let resolveAction;
actionMock.mockImplementation(
() =>
......@@ -108,19 +104,16 @@ describe('IDE error message component', () => {
);
findActionButton().trigger('click');
return wrapper.vm.$nextTick(() => {
expect(wrapper.find(GlLoadingIcon).isVisible()).toBe(true);
resolveAction();
});
await nextTick();
expect(wrapper.find(GlLoadingIcon).isVisible()).toBe(true);
resolveAction();
});
it('hides loading icon when operation finishes', () => {
it('hides loading icon when operation finishes', async () => {
findActionButton().trigger('click');
return actionMock()
.then(() => wrapper.vm.$nextTick())
.then(() => {
expect(wrapper.find(GlLoadingIcon).isVisible()).toBe(false);
});
await actionMock();
await nextTick();
expect(wrapper.find(GlLoadingIcon).isVisible()).toBe(false);
});
});
});
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import $ from 'jquery';
import Vuex from 'vuex';
import Dropdown from '~/ide/components/file_templates/dropdown.vue';
......@@ -54,15 +54,14 @@ describe('IDE file templates dropdown component', () => {
wrapper = null;
});
it('calls clickItem on click', () => {
it('calls clickItem on click', async () => {
const itemData = { name: 'test.yml ' };
createComponent({ props: { data: [itemData] } });
const item = findItemButtons().at(0);
item.trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted().click[0][0]).toBe(itemData);
});
await nextTick();
expect(wrapper.emitted().click[0][0]).toBe(itemData);
});
it('renders dropdown title', () => {
......@@ -111,7 +110,7 @@ describe('IDE file templates dropdown component', () => {
expect(items.wrappers.map((x) => x.text())).toEqual(templates.map((x) => x.name));
});
it('searches template data', () => {
it('searches template data', async () => {
const templates = [{ name: 'match 1' }, { name: 'other' }, { name: 'match 2' }];
const matches = ['match 1', 'match 2'];
createComponent({
......@@ -119,12 +118,11 @@ describe('IDE file templates dropdown component', () => {
state: { templates },
});
findSearch().setValue('match');
return wrapper.vm.$nextTick().then(() => {
const items = findItemButtons();
await nextTick();
const items = findItemButtons();
expect(items.length).toBe(matches.length);
expect(items.wrappers.map((x) => x.text())).toEqual(matches);
});
expect(items.length).toBe(matches.length);
expect(items.wrappers.map((x) => x.text())).toEqual(matches);
});
it('does not render input when `searchable` is true & `showLoading` is true', () => {
......@@ -159,17 +157,16 @@ describe('IDE file templates dropdown component', () => {
expect(findSearch().exists()).toBe(true);
});
it('searches data', () => {
it('searches data', async () => {
const data = [{ name: 'match 1' }, { name: 'other' }, { name: 'match 2' }];
const matches = ['match 1', 'match 2'];
createComponent({ props: { searchable: true, data } });
findSearch().setValue('match');
return wrapper.vm.$nextTick().then(() => {
const items = findItemButtons();
await nextTick();
const items = findItemButtons();
expect(items.length).toBe(matches.length);
expect(items.wrappers.map((x) => x.text())).toEqual(matches);
});
expect(items.length).toBe(matches.length);
expect(items.wrappers.map((x) => x.text())).toEqual(matches);
});
});
});
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import FileRowExtra from '~/ide/components/file_row_extra.vue';
import IdeFileRow from '~/ide/components/ide_file_row.vue';
......@@ -43,7 +43,7 @@ describe('Ide File Row component', () => {
const findFileRow = () => wrapper.find(FileRow);
const hasDropdownOpen = () => findFileRowExtra().props('dropdownOpen');
it('fileRow component has listeners', () => {
it('fileRow component has listeners', async () => {
const toggleTreeOpen = jest.fn();
createComponent(
{},
......@@ -56,9 +56,8 @@ describe('Ide File Row component', () => {
findFileRow().vm.$emit('toggleTreeOpen');
return wrapper.vm.$nextTick().then(() => {
expect(toggleTreeOpen).toHaveBeenCalled();
});
await nextTick();
expect(toggleTreeOpen).toHaveBeenCalled();
});
describe('default', () => {
......@@ -85,32 +84,30 @@ describe('Ide File Row component', () => {
});
describe('with open dropdown', () => {
beforeEach(() => {
beforeEach(async () => {
createComponent();
findFileRowExtra().vm.$emit('toggle', true);
return wrapper.vm.$nextTick();
await nextTick();
});
it('shows open dropdown', () => {
expect(hasDropdownOpen()).toBe(true);
});
it('hides dropdown when mouseleave', () => {
it('hides dropdown when mouseleave', async () => {
findFileRow().vm.$emit('mouseleave');
return wrapper.vm.$nextTick().then(() => {
expect(hasDropdownOpen()).toEqual(false);
});
await nextTick();
expect(hasDropdownOpen()).toEqual(false);
});
it('hides dropdown on toggle', () => {
it('hides dropdown on toggle', async () => {
findFileRowExtra().vm.$emit('toggle', false);
return wrapper.vm.$nextTick().then(() => {
expect(hasDropdownOpen()).toEqual(false);
});
await nextTick();
expect(hasDropdownOpen()).toEqual(false);
});
});
});
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { keepAlive } from 'helpers/keep_alive_component_helper';
import { trimText } from 'helpers/text_helper';
......@@ -74,14 +74,14 @@ describe('IDE review mode', () => {
});
describe('merge request', () => {
beforeEach(() => {
beforeEach(async () => {
store.state.currentMergeRequestId = '1';
store.state.projects.abcproject.mergeRequests['1'] = {
iid: 123,
web_url: 'testing123',
};
return wrapper.vm.$nextTick();
await nextTick();
});
it('renders edit dropdown', () => {
......@@ -91,7 +91,7 @@ describe('IDE review mode', () => {
it('renders merge request link & IID', async () => {
store.state.viewer = 'mrdiff';
await wrapper.vm.$nextTick();
await nextTick();
expect(trimText(wrapper.text())).toContain('Merge request (!123)');
});
......@@ -99,7 +99,7 @@ describe('IDE review mode', () => {
it('changes text to latest changes when viewer is not mrdiff', async () => {
store.state.viewer = 'diff';
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.text()).toContain('Latest changes');
});
......
import { GlSkeletonLoading } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
import IdeReview from '~/ide/components/ide_review.vue';
......@@ -45,7 +45,7 @@ describe('IdeSidebar', () => {
store.state.loading = true;
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.findAll(GlSkeletonLoading)).toHaveLength(3);
});
......@@ -60,7 +60,7 @@ describe('IdeSidebar', () => {
store.state.currentActivityView = leftSidebarViews.review.name;
await waitForPromises();
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.find(IdeTree).exists()).toBe(false);
expect(wrapper.find(IdeReview).exists()).toBe(true);
......@@ -68,7 +68,7 @@ describe('IdeSidebar', () => {
store.state.currentActivityView = leftSidebarViews.commit.name;
await waitForPromises();
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.find(IdeTree).exists()).toBe(false);
expect(wrapper.find(IdeReview).exists()).toBe(false);
......@@ -84,7 +84,7 @@ describe('IdeSidebar', () => {
view,
});
await waitForPromises();
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.find(IdeTree).exists()).toBe(tree);
expect(wrapper.find(IdeReview).exists()).toBe(review);
......@@ -99,7 +99,7 @@ describe('IdeSidebar', () => {
store.state.currentActivityView = leftSidebarViews.commit.name;
await waitForPromises();
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.find(IdeTree).exists()).toBe(false);
expect(wrapper.find(RepoCommitSection).exists()).toBe(true);
......@@ -107,7 +107,7 @@ describe('IdeSidebar', () => {
store.state.currentActivityView = leftSidebarViews.edit.name;
await waitForPromises();
await wrapper.vm.$nextTick();
await nextTick();
// reference to the elements remains the same, meaning the components were kept alive
expect(wrapper.find(IdeTree).element).toEqual(ideTreeComponent);
......
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import Item from '~/ide/components/jobs/item.vue';
import Stage from '~/ide/components/jobs/stage.vue';
import { stages, jobs } from '../../mock_data';
......@@ -47,23 +48,21 @@ describe('IDE pipeline stage', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
it('emits toggleCollaped event with stage id when clicking header', () => {
it('emits toggleCollaped event with stage id when clicking header', async () => {
const id = 5;
createComponent({ stage: { ...defaultProps.stage, id } });
findHeader().trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted().toggleCollapsed[0][0]).toBe(id);
});
await nextTick();
expect(wrapper.emitted().toggleCollapsed[0][0]).toBe(id);
});
it('emits clickViewLog entity with job', () => {
it('emits clickViewLog entity with job', async () => {
const [job] = defaultProps.stage.jobs;
createComponent();
wrapper.findAll(Item).at(0).vm.$emit('clickViewLog', job);
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted().clickViewLog[0][0]).toBe(job);
});
await nextTick();
expect(wrapper.emitted().clickViewLog[0][0]).toBe(job);
});
it('renders stage details & icon', () => {
......
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import Item from '~/ide/components/merge_requests/item.vue';
import List from '~/ide/components/merge_requests/list.vue';
......@@ -66,33 +66,28 @@ describe('IDE merge requests list', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
it('renders no search results text when search is not empty', () => {
it('renders no search results text when search is not empty', async () => {
createComponent();
findTokenedInput().vm.$emit('input', 'something');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.text()).toContain('No merge requests found');
});
await nextTick();
expect(wrapper.text()).toContain('No merge requests found');
});
it('clicking on search type, sets currentSearchType and loads merge requests', () => {
it('clicking on search type, sets currentSearchType and loads merge requests', async () => {
createComponent();
findTokenedInput().vm.$emit('focus');
return wrapper.vm
.$nextTick()
.then(() => {
findSearchTypeButtons().at(0).trigger('click');
return wrapper.vm.$nextTick();
})
.then(() => {
const searchType = wrapper.vm.$options.searchTypes[0];
await nextTick();
findSearchTypeButtons().at(0).trigger('click');
expect(findTokenedInput().props('tokens')).toEqual([searchType]);
expect(fetchMergeRequestsMock).toHaveBeenCalledWith(expect.any(Object), {
type: searchType.type,
search: '',
});
});
await nextTick();
const searchType = wrapper.vm.$options.searchTypes[0];
expect(findTokenedInput().props('tokens')).toEqual([searchType]);
expect(fetchMergeRequestsMock).toHaveBeenCalledWith(expect.any(Object), {
type: searchType.type,
search: '',
});
});
describe('with merge requests', () => {
......@@ -119,16 +114,15 @@ describe('IDE merge requests list', () => {
});
describe('when searching merge requests', () => {
it('calls `loadMergeRequests` on input in search field', () => {
it('calls `loadMergeRequests` on input in search field', async () => {
createComponent(defaultStateWithMergeRequests);
const input = findTokenedInput();
input.vm.$emit('input', 'something');
return wrapper.vm.$nextTick().then(() => {
expect(fetchMergeRequestsMock).toHaveBeenCalledWith(expect.any(Object), {
search: 'something',
type: '',
});
await nextTick();
expect(fetchMergeRequestsMock).toHaveBeenCalledWith(expect.any(Object), {
search: 'something',
type: '',
});
});
});
......@@ -143,9 +137,9 @@ describe('IDE merge requests list', () => {
});
describe('without search value', () => {
beforeEach(() => {
beforeEach(async () => {
input.vm.$emit('focus');
return wrapper.vm.$nextTick();
await nextTick();
});
it('shows search types', () => {
......@@ -155,22 +149,20 @@ describe('IDE merge requests list', () => {
);
});
it('hides search types when search changes', () => {
it('hides search types when search changes', async () => {
input.vm.$emit('input', 'something');
return wrapper.vm.$nextTick().then(() => {
expect(findSearchTypeButtons().exists()).toBe(false);
});
await nextTick();
expect(findSearchTypeButtons().exists()).toBe(false);
});
describe('with search type', () => {
beforeEach(() => {
beforeEach(async () => {
findSearchTypeButtons().at(0).trigger('click');
return wrapper.vm
.$nextTick()
.then(() => input.vm.$emit('focus'))
.then(() => wrapper.vm.$nextTick());
await nextTick();
await input.vm.$emit('focus');
await nextTick();
});
it('does not show search types', () => {
......@@ -180,10 +172,10 @@ describe('IDE merge requests list', () => {
});
describe('with search value', () => {
beforeEach(() => {
beforeEach(async () => {
input.vm.$emit('input', 'something');
input.vm.$emit('focus');
return wrapper.vm.$nextTick();
await nextTick();
});
it('does not show search types', () => {
......
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import CollapsibleSidebar from '~/ide/components/panes/collapsible_sidebar.vue';
import RightPane from '~/ide/components/panes/right.vue';
......@@ -86,19 +86,18 @@ describe('ide/components/panes/right.vue', () => {
createComponent();
});
it('adds terminal tab', () => {
it('adds terminal tab', async () => {
store.state.terminal.isVisible = true;
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find(CollapsibleSidebar).props('extensionTabs')).toEqual(
expect.arrayContaining([
expect.objectContaining({
show: true,
title: 'Terminal',
}),
]),
);
});
await nextTick();
expect(wrapper.find(CollapsibleSidebar).props('extensionTabs')).toEqual(
expect.arrayContaining([
expect.objectContaining({
show: true,
title: 'Terminal',
}),
]),
);
});
it('hides terminal tab when not visible', () => {
......
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import smooshpack from 'smooshpack';
import Vuex from 'vuex';
import Clientside from '~/ide/components/preview/clientside.vue';
......@@ -351,39 +351,36 @@ describe('IDE clientside preview', () => {
});
describe('template', () => {
it('renders ide-preview element when showPreview is true', () => {
it('renders ide-preview element when showPreview is true', async () => {
createComponent({ getters: { packageJson: dummyPackageJson } });
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ loading: false });
return wrapper.vm.$nextTick(() => {
expect(wrapper.find('#ide-preview').exists()).toBe(true);
});
await nextTick();
expect(wrapper.find('#ide-preview').exists()).toBe(true);
});
it('renders empty state', () => {
it('renders empty state', async () => {
createComponent();
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ loading: false });
return wrapper.vm.$nextTick(() => {
expect(wrapper.text()).toContain(
'Preview your web application using Web IDE client-side evaluation.',
);
});
await nextTick();
expect(wrapper.text()).toContain(
'Preview your web application using Web IDE client-side evaluation.',
);
});
it('renders loading icon', () => {
it('renders loading icon', async () => {
createComponent();
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ loading: true });
return wrapper.vm.$nextTick(() => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
await nextTick();
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
});
......
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { listen } from 'codesandbox-api';
import { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import ClientsideNavigator from '~/ide/components/preview/navigator.vue';
......@@ -29,31 +30,28 @@ describe('IDE clientside preview navigator', () => {
wrapper.destroy();
});
it('renders readonly URL bar', () => {
it('renders readonly URL bar', async () => {
listenHandler({ type: 'urlchange', url: manager.bundlerURL });
return wrapper.vm.$nextTick(() => {
expect(wrapper.find('input[readonly]').element.value).toBe('/');
});
await nextTick();
expect(wrapper.find('input[readonly]').element.value).toBe('/');
});
it('renders loading icon by default', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
it('removes loading icon when done event is fired', () => {
it('removes loading icon when done event is fired', async () => {
listenHandler({ type: 'done' });
return wrapper.vm.$nextTick(() => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
});
await nextTick();
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
});
it('does not count visiting same url multiple times', () => {
it('does not count visiting same url multiple times', async () => {
listenHandler({ type: 'done' });
listenHandler({ type: 'done', url: `${TEST_HOST}/url1` });
listenHandler({ type: 'done', url: `${TEST_HOST}/url1` });
return wrapper.vm.$nextTick().then(() => {
expect(findBackButton().attributes('disabled')).toBe('disabled');
});
await nextTick();
expect(findBackButton().attributes('disabled')).toBe('disabled');
});
it('unsubscribes from listen on destroy', () => {
......@@ -64,107 +62,93 @@ describe('IDE clientside preview navigator', () => {
});
describe('back button', () => {
beforeEach(() => {
beforeEach(async () => {
listenHandler({ type: 'done' });
listenHandler({ type: 'urlchange', url: TEST_HOST });
return wrapper.vm.$nextTick();
await nextTick();
});
it('is disabled by default', () => {
expect(findBackButton().attributes('disabled')).toBe('disabled');
});
it('is enabled when there is previous entry', () => {
it('is enabled when there is previous entry', async () => {
listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` });
return wrapper.vm.$nextTick().then(() => {
findBackButton().trigger('click');
expect(findBackButton().attributes('disabled')).toBeFalsy();
});
await nextTick();
findBackButton().trigger('click');
expect(findBackButton().attributes('disabled')).toBeFalsy();
});
it('is disabled when there is no previous entry', () => {
it('is disabled when there is no previous entry', async () => {
listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` });
return wrapper.vm
.$nextTick()
.then(() => {
findBackButton().trigger('click');
return wrapper.vm.$nextTick();
})
.then(() => {
expect(findBackButton().attributes('disabled')).toBe('disabled');
});
await nextTick();
findBackButton().trigger('click');
await nextTick();
expect(findBackButton().attributes('disabled')).toBe('disabled');
});
it('updates manager iframe src', () => {
it('updates manager iframe src', async () => {
listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` });
listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url2` });
return wrapper.vm.$nextTick().then(() => {
findBackButton().trigger('click');
await nextTick();
findBackButton().trigger('click');
expect(manager.iframe.src).toBe(`${TEST_HOST}/url1`);
});
expect(manager.iframe.src).toBe(`${TEST_HOST}/url1`);
});
});
describe('forward button', () => {
beforeEach(() => {
beforeEach(async () => {
listenHandler({ type: 'done' });
listenHandler({ type: 'urlchange', url: TEST_HOST });
return wrapper.vm.$nextTick();
await nextTick();
});
it('is disabled by default', () => {
expect(findForwardButton().attributes('disabled')).toBe('disabled');
});
it('is enabled when there is next entry', () => {
it('is enabled when there is next entry', async () => {
listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` });
return wrapper.vm
.$nextTick()
.then(() => {
findBackButton().trigger('click');
return wrapper.vm.$nextTick();
})
.then(() => {
expect(findForwardButton().attributes('disabled')).toBeFalsy();
});
await nextTick();
findBackButton().trigger('click');
await nextTick();
expect(findForwardButton().attributes('disabled')).toBeFalsy();
});
it('is disabled when there is no next entry', () => {
it('is disabled when there is no next entry', async () => {
listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` });
return wrapper.vm
.$nextTick()
.then(() => {
findBackButton().trigger('click');
return wrapper.vm.$nextTick();
})
.then(() => {
findForwardButton().trigger('click');
return wrapper.vm.$nextTick();
})
.then(() => {
expect(findForwardButton().attributes('disabled')).toBe('disabled');
});
await nextTick();
findBackButton().trigger('click');
await nextTick();
findForwardButton().trigger('click');
await nextTick();
expect(findForwardButton().attributes('disabled')).toBe('disabled');
});
it('updates manager iframe src', () => {
it('updates manager iframe src', async () => {
listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url1` });
listenHandler({ type: 'urlchange', url: `${TEST_HOST}/url2` });
return wrapper.vm.$nextTick().then(() => {
findBackButton().trigger('click');
await nextTick();
findBackButton().trigger('click');
expect(manager.iframe.src).toBe(`${TEST_HOST}/url1`);
});
expect(manager.iframe.src).toBe(`${TEST_HOST}/url1`);
});
});
describe('refresh button', () => {
const url = `${TEST_HOST}/some_url`;
beforeEach(() => {
beforeEach(async () => {
listenHandler({ type: 'done' });
listenHandler({ type: 'urlchange', url });
return wrapper.vm.$nextTick();
await nextTick();
});
it('calls refresh with current path', () => {
......
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import RepoTabs from '~/ide/components/repo_tabs.vue';
import { createStore } from '~/ide/stores';
......@@ -29,17 +29,14 @@ describe('RepoTabs', () => {
wrapper.destroy();
});
it('renders a list of tabs', (done) => {
it('renders a list of tabs', async () => {
store.state.openFiles[0].active = true;
wrapper.vm.$nextTick(() => {
const tabs = [...wrapper.vm.$el.querySelectorAll('.multi-file-tab')];
await nextTick();
const tabs = [...wrapper.vm.$el.querySelectorAll('.multi-file-tab')];
expect(tabs.length).toEqual(2);
expect(tabs[0].parentNode.classList.contains('active')).toEqual(true);
expect(tabs[1].parentNode.classList.contains('active')).toEqual(false);
done();
});
expect(tabs.length).toEqual(2);
expect(tabs[0].parentNode.classList.contains('active')).toEqual(true);
expect(tabs[1].parentNode.classList.contains('active')).toEqual(false);
});
});
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import ResizablePanel from '~/ide/components/resizable_panel.vue';
import { SIDE_LEFT, SIDE_RIGHT } from '~/ide/constants';
......@@ -99,15 +99,14 @@ describe('~/ide/components/resizable_panel', () => {
});
});
it('when resizer emits update:size, changes inline width', () => {
it('when resizer emits update:size, changes inline width', async () => {
const newSize = TEST_WIDTH - 100;
const resizer = findResizer();
resizer.vm.$emit('update:size', newSize);
return wrapper.vm.$nextTick().then(() => {
expect(findInlineStyle()).toBe(createInlineStyle(newSize));
});
await nextTick();
expect(findInlineStyle()).toBe(createInlineStyle(newSize));
});
});
});
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import TerminalSession from '~/ide/components/terminal/session.vue';
import Terminal from '~/ide/components/terminal/terminal.vue';
......@@ -67,32 +67,30 @@ describe('IDE TerminalSession', () => {
});
[STARTING, PENDING, RUNNING].forEach((status) => {
it(`show stop button when status is ${status}`, () => {
it(`show stop button when status is ${status}`, async () => {
state.session = { status };
factory();
const button = findButton();
button.vm.$emit('click');
return wrapper.vm.$nextTick().then(() => {
expect(button.text()).toEqual('Stop Terminal');
expect(actions.stopSession).toHaveBeenCalled();
});
await nextTick();
expect(button.text()).toEqual('Stop Terminal');
expect(actions.stopSession).toHaveBeenCalled();
});
});
[STOPPING, STOPPED].forEach((status) => {
it(`show stop button when status is ${status}`, () => {
it(`show stop button when status is ${status}`, async () => {
state.session = { status };
factory();
const button = findButton();
button.vm.$emit('click');
return wrapper.vm.$nextTick().then(() => {
expect(button.text()).toEqual('Restart Terminal');
expect(actions.restartSession).toHaveBeenCalled();
});
await nextTick();
expect(button.text()).toEqual('Restart Terminal');
expect(actions.restartSession).toHaveBeenCalled();
});
});
});
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import ScrollButton from '~/ide/components/jobs/detail/scroll_button.vue';
import TerminalControls from '~/ide/components/terminal/terminal_controls.vue';
......@@ -39,27 +40,25 @@ describe('IDE TerminalControls', () => {
);
});
it('emits "scroll-up" when click up button', () => {
it('emits "scroll-up" when click up button', async () => {
factory({ propsData: { canScrollUp: true } });
expect(wrapper.emitted()).toEqual({});
buttons.at(0).vm.$emit('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted('scroll-up')).toEqual([[]]);
});
await nextTick();
expect(wrapper.emitted('scroll-up')).toEqual([[]]);
});
it('emits "scroll-down" when click down button', () => {
it('emits "scroll-down" when click down button', async () => {
factory({ propsData: { canScrollDown: true } });
expect(wrapper.emitted()).toEqual({});
buttons.at(1).vm.$emit('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted('scroll-down')).toEqual([[]]);
});
await nextTick();
expect(wrapper.emitted('scroll-down')).toEqual([[]]);
});
});
import { GlAlert, GlLoadingIcon, GlTable, GlAvatar, GlEmptyState } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import IncidentsList from '~/incidents/components/incidents_list.vue';
import {
I18N,
......@@ -210,7 +211,7 @@ describe('Incidents List', () => {
it('sets button loading on click', async () => {
findCreateIncidentBtn().vm.$emit('click');
await wrapper.vm.$nextTick();
await nextTick();
expect(findCreateIncidentBtn().attributes('loading')).toBe('true');
});
......@@ -233,7 +234,7 @@ describe('Incidents List', () => {
it('should track create new incident button', async () => {
findCreateIncidentBtn().vm.$emit('click');
await wrapper.vm.$nextTick();
await nextTick();
expect(Tracking.event).toHaveBeenCalled();
});
});
......@@ -263,10 +264,10 @@ describe('Incidents List', () => {
const columnHeader = () => wrapper.find(`[${attr}="${value}"]`);
expect(columnHeader().attributes('aria-sort')).toBe(initialSort);
columnHeader().trigger('click');
await wrapper.vm.$nextTick();
await nextTick();
expect(columnHeader().attributes('aria-sort')).toBe(firstSort);
columnHeader().trigger('click');
await wrapper.vm.$nextTick();
await nextTick();
expect(columnHeader().attributes('aria-sort')).toBe(nextSort);
},
);
......@@ -287,7 +288,7 @@ describe('Incidents List', () => {
it('should track incident creation events', async () => {
findCreateIncidentBtn().vm.$emit('click');
await wrapper.vm.$nextTick();
await nextTick();
const { category, action } = trackIncidentCreateNewOptions;
expect(Tracking.event).toHaveBeenCalledWith(category, action);
});
......
import { GlFormCheckbox } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue';
import { createStore } from '~/integrations/edit/store';
......@@ -68,7 +69,7 @@ describe('ActiveCheckbox', () => {
it('switches the form value', async () => {
findInputInCheckbox().trigger('click');
await wrapper.vm.$nextTick();
await nextTick();
expect(findGlFormCheckbox().vm.$attrs.checked).toBe(false);
});
});
......
import { GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import ConfirmationModal from '~/integrations/edit/components/confirmation_modal.vue';
import { createStore } from '~/integrations/edit/store';
......@@ -40,7 +41,7 @@ describe('ConfirmationModal', () => {
findGlModal().vm.$emit('primary');
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.emitted().submit).toHaveLength(1);
});
......
import { GlFormCheckbox, GlFormInput } from '@gitlab/ui';
import { nextTick } from 'vue';
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
import JiraIssuesFields from '~/integrations/edit/components/jira_issues_fields.vue';
......@@ -193,7 +194,7 @@ describe('JiraIssuesFields', () => {
await setEnableCheckbox(true);
expect(findJiraForVulnerabilities().attributes('show-full-feature')).toBe('true');
wrapper.setProps({ showJiraVulnerabilitiesIntegration: false });
await wrapper.vm.$nextTick();
await nextTick();
expect(findJiraForVulnerabilities().attributes('show-full-feature')).toBeUndefined();
});
......
import { GlFormCheckbox } from '@gitlab/ui';
import { nextTick } from 'vue';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_fields.vue';
......@@ -71,12 +72,11 @@ describe('JiraTriggerFields', () => {
});
describe('on enable comments', () => {
it('shows comment detail', () => {
it('shows comment detail', async () => {
findCommentSettingsCheckbox().vm.$emit('input', true);
return wrapper.vm.$nextTick().then(() => {
expect(findCommentDetail().isVisible()).toBe(true);
});
await nextTick();
expect(findCommentDetail().isVisible()).toBe(true);
});
});
});
......@@ -107,7 +107,7 @@ describe('JiraTriggerFields', () => {
});
describe('initialJiraIssueTransitionAutomatic is false, initialJiraIssueTransitionId is not set', () => {
it('selects automatic transitions when enabling transitions', () => {
it('selects automatic transitions when enabling transitions', async () => {
createComponent({
initialTriggerCommit: true,
initialEnableComments: true,
......@@ -117,11 +117,10 @@ describe('JiraTriggerFields', () => {
expect(checkbox.element.checked).toBe(false);
checkbox.trigger('click');
return wrapper.vm.$nextTick().then(() => {
const [radio1, radio2] = findIssueTransitionModeRadios().wrappers;
expect(radio1.element.checked).toBe(true);
expect(radio2.element.checked).toBe(false);
});
await nextTick();
const [radio1, radio2] = findIssueTransitionModeRadios().wrappers;
expect(radio1.element.checked).toBe(true);
expect(radio2.element.checked).toBe(false);
});
});
......
import { GlFormGroup, GlSprintf, GlModal } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import { stubComponent } from 'helpers/stub_component';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
......@@ -91,7 +92,7 @@ describe('ImportAProjectModal', () => {
it('sets isLoading to true when the Invite button is clicked', async () => {
clickImportButton();
await wrapper.vm.$nextTick();
await nextTick();
expect(findImportButton().props('loading')).toBe(true);
});
......@@ -157,7 +158,7 @@ describe('ImportAProjectModal', () => {
clickCancelButton();
await wrapper.vm.$nextTick();
await nextTick();
expect(formGroupInvalidFeedback()).toBe('');
expect(formGroupErrorState()).not.toBe(false);
......
......@@ -8,6 +8,7 @@ import {
GlModal,
} from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import { stubComponent } from 'helpers/stub_component';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
......@@ -508,7 +509,7 @@ describe('InviteMembersModal', () => {
findMembersSelect().vm.$emit('clear');
await wrapper.vm.$nextTick();
await nextTick();
expect(membersFormGroupInvalidFeedback()).toBe('');
expect(findMembersFormGroup().props('state')).not.toBe(false);
......@@ -518,7 +519,7 @@ describe('InviteMembersModal', () => {
it('clears the error when the cancel button is clicked', async () => {
clickCancelButton();
await wrapper.vm.$nextTick();
await nextTick();
expect(membersFormGroupInvalidFeedback()).toBe('');
expect(findMembersFormGroup().props('state')).not.toBe(false);
......@@ -528,7 +529,7 @@ describe('InviteMembersModal', () => {
it('clears the error when the modal is hidden', async () => {
wrapper.findComponent(GlModal).vm.$emit('hide');
await wrapper.vm.$nextTick();
await nextTick();
expect(membersFormGroupInvalidFeedback()).toBe('');
expect(findMembersFormGroup().props('state')).not.toBe(false);
......
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import IssueDueDate from '~/boards/components/issue_due_date.vue';
import { formatDate } from '~/lib/utils/datetime_utility';
......@@ -105,7 +106,7 @@ describe('RelatedIssuableItem', () => {
state: 'closed',
closedAt: '2018-12-01T00:00:00.00Z',
});
await wrapper.vm.$nextTick();
await nextTick();
expect(tokenState().classes('issue-token-state-icon-closed')).toBe(true);
});
......@@ -140,7 +141,7 @@ describe('RelatedIssuableItem', () => {
closedAt: '2018-12-01T00:00:00.00Z',
},
});
await wrapper.vm.$nextTick();
await nextTick();
expect(wrapper.find(IssueDueDate).props('closed')).toBe(true);
});
......@@ -172,14 +173,14 @@ describe('RelatedIssuableItem', () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ removeDisabled: true });
await wrapper.vm.$nextTick();
await nextTick();
expect(findRemoveButton().attributes('disabled')).toEqual('disabled');
});
it('triggers onRemoveRequest when clicked', async () => {
findRemoveButton().trigger('click');
await wrapper.vm.$nextTick();
await nextTick();
const { relatedIssueRemoveRequest } = wrapper.emitted();
expect(relatedIssueRemoveRequest.length).toBe(1);
......
import { mount, shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import AddIssuableForm from '~/related_issues/components/add_issuable_form.vue';
import IssueToken from '~/related_issues/components/issue_token.vue';
import { issuableTypesMap, linkedIssueTypesMap, PathIdSeparator } from '~/related_issues/constants';
......@@ -194,63 +195,55 @@ describe('AddIssuableForm', () => {
});
describe('when the form is submitted', () => {
it('emits an event with a "relates_to" link type when the "relates to" radio input selected', (done) => {
it('emits an event with a "relates_to" link type when the "relates to" radio input selected', async () => {
jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {});
wrapper.vm.linkedIssueType = linkedIssueTypesMap.RELATES_TO;
wrapper.vm.onFormSubmit();
wrapper.vm.$nextTick(() => {
expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', {
pendingReferences: '',
linkedIssueType: linkedIssueTypesMap.RELATES_TO,
});
done();
await nextTick();
expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', {
pendingReferences: '',
linkedIssueType: linkedIssueTypesMap.RELATES_TO,
});
});
it('emits an event with a "blocks" link type when the "blocks" radio input selected', (done) => {
it('emits an event with a "blocks" link type when the "blocks" radio input selected', async () => {
jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {});
wrapper.vm.linkedIssueType = linkedIssueTypesMap.BLOCKS;
wrapper.vm.onFormSubmit();
wrapper.vm.$nextTick(() => {
expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', {
pendingReferences: '',
linkedIssueType: linkedIssueTypesMap.BLOCKS,
});
done();
await nextTick();
expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', {
pendingReferences: '',
linkedIssueType: linkedIssueTypesMap.BLOCKS,
});
});
it('emits an event with a "is_blocked_by" link type when the "is blocked by" radio input selected', (done) => {
it('emits an event with a "is_blocked_by" link type when the "is blocked by" radio input selected', async () => {
jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {});
wrapper.vm.linkedIssueType = linkedIssueTypesMap.IS_BLOCKED_BY;
wrapper.vm.onFormSubmit();
wrapper.vm.$nextTick(() => {
expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', {
pendingReferences: '',
linkedIssueType: linkedIssueTypesMap.IS_BLOCKED_BY,
});
done();
await nextTick();
expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', {
pendingReferences: '',
linkedIssueType: linkedIssueTypesMap.IS_BLOCKED_BY,
});
});
it('shows error message when error is present', (done) => {
it('shows error message when error is present', async () => {
const itemAddFailureMessage = 'Something went wrong while submitting.';
wrapper.setProps({
hasError: true,
itemAddFailureMessage,
});
wrapper.vm.$nextTick(() => {
expect(wrapper.find('.gl-field-error').exists()).toBe(true);
expect(wrapper.find('.gl-field-error').text()).toContain(itemAddFailureMessage);
done();
});
await nextTick();
expect(wrapper.find('.gl-field-error').exists()).toBe(true);
expect(wrapper.find('.gl-field-error').text()).toContain(itemAddFailureMessage);
});
});
});
......
import { mount, shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import {
defaultProps,
......@@ -210,40 +211,37 @@ describe('RelatedIssuesRoot', () => {
}),
);
it('when canceling and hiding add issuable form', () => {
it('when canceling and hiding add issuable form', async () => {
wrapper.vm.onPendingFormCancel();
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.vm.isFormVisible).toEqual(false);
expect(wrapper.vm.inputValue).toEqual('');
expect(wrapper.vm.state.pendingReferences).toHaveLength(0);
});
await nextTick();
expect(wrapper.vm.isFormVisible).toEqual(false);
expect(wrapper.vm.inputValue).toEqual('');
expect(wrapper.vm.state.pendingReferences).toHaveLength(0);
});
});
describe('fetchRelatedIssues', () => {
beforeEach(() => createComponent());
it('sets isFetching while fetching', () => {
it('sets isFetching while fetching', async () => {
wrapper.vm.fetchRelatedIssues();
expect(wrapper.vm.isFetching).toEqual(true);
return waitForPromises().then(() => {
expect(wrapper.vm.isFetching).toEqual(false);
});
await waitForPromises();
expect(wrapper.vm.isFetching).toEqual(false);
});
it('should fetch related issues', () => {
it('should fetch related issues', async () => {
mock.onGet(defaultProps.endpoint).reply(200, [issuable1, issuable2]);
wrapper.vm.fetchRelatedIssues();
return waitForPromises().then(() => {
expect(wrapper.vm.state.relatedIssues).toHaveLength(2);
expect(wrapper.vm.state.relatedIssues[0].id).toEqual(issuable1.id);
expect(wrapper.vm.state.relatedIssues[1].id).toEqual(issuable2.id);
});
await waitForPromises();
expect(wrapper.vm.state.relatedIssues).toHaveLength(2);
expect(wrapper.vm.state.relatedIssues[0].id).toEqual(issuable1.id);
expect(wrapper.vm.state.relatedIssues[1].id).toEqual(issuable2.id);
});
});
......
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import TitleSuggestions from '~/issues/new/components/title_suggestions.vue';
import TitleSuggestionsItem from '~/issues/new/components/title_suggestions_item.vue';
......@@ -22,12 +23,11 @@ describe('Issue title suggestions component', () => {
wrapper.destroy();
});
it('does not render with empty search', () => {
it('does not render with empty search', async () => {
wrapper.setProps({ search: '' });
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.isVisible()).toBe(false);
});
await nextTick();
expect(wrapper.isVisible()).toBe(false);
});
describe('with data', () => {
......@@ -37,28 +37,26 @@ describe('Issue title suggestions component', () => {
data = { issues: [{ id: 1 }, { id: 2 }] };
});
it('renders component', () => {
it('renders component', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData(data);
return wrapper.vm.$nextTick(() => {
expect(wrapper.findAll('li').length).toBe(data.issues.length);
});
await nextTick();
expect(wrapper.findAll('li').length).toBe(data.issues.length);
});
it('does not render with empty search', () => {
it('does not render with empty search', async () => {
wrapper.setProps({ search: '' });
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData(data);
return wrapper.vm.$nextTick(() => {
expect(wrapper.isVisible()).toBe(false);
});
await nextTick();
expect(wrapper.isVisible()).toBe(false);
});
it('does not render when loading', () => {
it('does not render when loading', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
......@@ -66,49 +64,44 @@ describe('Issue title suggestions component', () => {
loading: 1,
});
return wrapper.vm.$nextTick(() => {
expect(wrapper.isVisible()).toBe(false);
});
await nextTick();
expect(wrapper.isVisible()).toBe(false);
});
it('does not render with empty issues data', () => {
it('does not render with empty issues data', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ issues: [] });
return wrapper.vm.$nextTick(() => {
expect(wrapper.isVisible()).toBe(false);
});
await nextTick();
expect(wrapper.isVisible()).toBe(false);
});
it('renders list of issues', () => {
it('renders list of issues', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData(data);
return wrapper.vm.$nextTick(() => {
expect(wrapper.findAll(TitleSuggestionsItem).length).toBe(2);
});
await nextTick();
expect(wrapper.findAll(TitleSuggestionsItem).length).toBe(2);
});
it('adds margin class to first item', () => {
it('adds margin class to first item', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData(data);
return wrapper.vm.$nextTick(() => {
expect(wrapper.findAll('li').at(0).classes()).toContain('gl-mb-3');
});
await nextTick();
expect(wrapper.findAll('li').at(0).classes()).toContain('gl-mb-3');
});
it('does not add margin class to last item', () => {
it('does not add margin class to last item', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData(data);
return wrapper.vm.$nextTick(() => {
expect(wrapper.findAll('li').at(1).classes()).not.toContain('gl-mb-3');
});
await nextTick();
expect(wrapper.findAll('li').at(1).classes()).not.toContain('gl-mb-3');
});
});
});
......@@ -145,33 +145,30 @@ describe('Issuable output', () => {
});
});
it('shows actions if permissions are correct', () => {
it('shows actions if permissions are correct', async () => {
wrapper.vm.showForm = true;
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find('.markdown-selector').exists()).toBe(true);
});
await nextTick();
expect(wrapper.find('.markdown-selector').exists()).toBe(true);
});
it('does not show actions if permissions are incorrect', () => {
it('does not show actions if permissions are incorrect', async () => {
wrapper.vm.showForm = true;
wrapper.setProps({ canUpdate: false });
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find('.markdown-selector').exists()).toBe(false);
});
await nextTick();
expect(wrapper.find('.markdown-selector').exists()).toBe(false);
});
it('does not update formState if form is already open', () => {
it('does not update formState if form is already open', async () => {
wrapper.vm.updateAndShowForm();
wrapper.vm.state.titleText = 'testing 123';
wrapper.vm.updateAndShowForm();
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.vm.store.formState.title).not.toBe('testing 123');
});
await nextTick();
expect(wrapper.vm.store.formState.title).not.toBe('testing 123');
});
describe('Pinned links propagated', () => {
......@@ -186,31 +183,29 @@ describe('Issuable output', () => {
});
describe('updateIssuable', () => {
it('fetches new data after update', () => {
it('fetches new data after update', async () => {
const updateStoreSpy = jest.spyOn(wrapper.vm, 'updateStoreState');
const getDataSpy = jest.spyOn(wrapper.vm.service, 'getData');
jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({
data: { web_url: window.location.pathname },
});
return wrapper.vm.updateIssuable().then(() => {
expect(updateStoreSpy).toHaveBeenCalled();
expect(getDataSpy).toHaveBeenCalled();
});
await wrapper.vm.updateIssuable();
expect(updateStoreSpy).toHaveBeenCalled();
expect(getDataSpy).toHaveBeenCalled();
});
it('correctly updates issuable data', () => {
it('correctly updates issuable data', async () => {
const spy = jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({
data: { web_url: window.location.pathname },
});
return wrapper.vm.updateIssuable().then(() => {
expect(spy).toHaveBeenCalledWith(wrapper.vm.formState);
expect(eventHub.$emit).toHaveBeenCalledWith('close.form');
});
await wrapper.vm.updateIssuable();
expect(spy).toHaveBeenCalledWith(wrapper.vm.formState);
expect(eventHub.$emit).toHaveBeenCalledWith('close.form');
});
it('does not redirect if issue has not moved', () => {
it('does not redirect if issue has not moved', async () => {
jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({
data: {
web_url: window.location.pathname,
......@@ -218,12 +213,11 @@ describe('Issuable output', () => {
},
});
return wrapper.vm.updateIssuable().then(() => {
expect(visitUrl).not.toHaveBeenCalled();
});
await wrapper.vm.updateIssuable();
expect(visitUrl).not.toHaveBeenCalled();
});
it('does not redirect if issue has not moved and user has switched tabs', () => {
it('does not redirect if issue has not moved and user has switched tabs', async () => {
jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({
data: {
web_url: '',
......@@ -231,12 +225,11 @@ describe('Issuable output', () => {
},
});
return wrapper.vm.updateIssuable().then(() => {
expect(visitUrl).not.toHaveBeenCalled();
});
await wrapper.vm.updateIssuable();
expect(visitUrl).not.toHaveBeenCalled();
});
it('redirects if returned web_url has changed', () => {
it('redirects if returned web_url has changed', async () => {
jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({
data: {
web_url: '/testing-issue-move',
......@@ -246,108 +239,95 @@ describe('Issuable output', () => {
wrapper.vm.updateIssuable();
return wrapper.vm.updateIssuable().then(() => {
expect(visitUrl).toHaveBeenCalledWith('/testing-issue-move');
});
await wrapper.vm.updateIssuable();
expect(visitUrl).toHaveBeenCalledWith('/testing-issue-move');
});
describe('shows dialog when issue has unsaved changed', () => {
it('confirms on title change', () => {
it('confirms on title change', async () => {
wrapper.vm.showForm = true;
wrapper.vm.state.titleText = 'title has changed';
const e = { returnValue: null };
wrapper.vm.handleBeforeUnloadEvent(e);
return wrapper.vm.$nextTick().then(() => {
expect(e.returnValue).not.toBeNull();
});
await nextTick();
expect(e.returnValue).not.toBeNull();
});
it('confirms on description change', () => {
it('confirms on description change', async () => {
wrapper.vm.showForm = true;
wrapper.vm.state.descriptionText = 'description has changed';
const e = { returnValue: null };
wrapper.vm.handleBeforeUnloadEvent(e);
return wrapper.vm.$nextTick().then(() => {
expect(e.returnValue).not.toBeNull();
});
await nextTick();
expect(e.returnValue).not.toBeNull();
});
it('does nothing when nothing has changed', () => {
it('does nothing when nothing has changed', async () => {
const e = { returnValue: null };
wrapper.vm.handleBeforeUnloadEvent(e);
return wrapper.vm.$nextTick().then(() => {
expect(e.returnValue).toBeNull();
});
await nextTick();
expect(e.returnValue).toBeNull();
});
});
describe('error when updating', () => {
it('closes form on error', () => {
it('closes form on error', async () => {
jest.spyOn(wrapper.vm.service, 'updateIssuable').mockRejectedValue();
return wrapper.vm.updateIssuable().then(() => {
expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form');
expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
`Error updating issue`,
);
});
await wrapper.vm.updateIssuable();
expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form');
expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
`Error updating issue`,
);
});
it('returns the correct error message for issuableType', () => {
it('returns the correct error message for issuableType', async () => {
jest.spyOn(wrapper.vm.service, 'updateIssuable').mockRejectedValue();
wrapper.setProps({ issuableType: 'merge request' });
return wrapper.vm
.$nextTick()
.then(wrapper.vm.updateIssuable)
.then(() => {
expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form');
expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
`Error updating merge request`,
);
});
await nextTick();
await wrapper.vm.updateIssuable();
expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form');
expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
`Error updating merge request`,
);
});
it('shows error message from backend if exists', () => {
it('shows error message from backend if exists', async () => {
const msg = 'Custom error message from backend';
jest
.spyOn(wrapper.vm.service, 'updateIssuable')
.mockRejectedValue({ response: { data: { errors: [msg] } } });
return wrapper.vm.updateIssuable().then(() => {
expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
`${wrapper.vm.defaultErrorMessage}. ${msg}`,
);
});
await wrapper.vm.updateIssuable();
expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
`${wrapper.vm.defaultErrorMessage}. ${msg}`,
);
});
});
});
describe('updateAndShowForm', () => {
it('shows locked warning if form is open & data is different', () => {
return wrapper.vm
.$nextTick()
.then(() => {
wrapper.vm.updateAndShowForm();
wrapper.vm.poll.makeRequest();
return new Promise((resolve) => {
wrapper.vm.$watch('formState.lockedWarningVisible', (value) => {
if (value) {
resolve();
}
});
});
})
.then(() => {
expect(wrapper.vm.formState.lockedWarningVisible).toBe(true);
expect(wrapper.vm.formState.lock_version).toBe(1);
expect(findAlert().exists()).toBe(true);
it('shows locked warning if form is open & data is different', async () => {
await nextTick();
wrapper.vm.updateAndShowForm();
wrapper.vm.poll.makeRequest();
await new Promise((resolve) => {
wrapper.vm.$watch('formState.lockedWarningVisible', (value) => {
if (value) {
resolve();
}
});
});
expect(wrapper.vm.formState.lockedWarningVisible).toBe(true);
expect(wrapper.vm.formState.lock_version).toBe(1);
expect(findAlert().exists()).toBe(true);
});
});
......@@ -398,12 +378,11 @@ describe('Issuable output', () => {
expect(wrapper.find('.btn-edit').exists()).toBe(true);
});
it('should render if showInlineEditButton', () => {
it('should render if showInlineEditButton', async () => {
wrapper.setProps({ showInlineEditButton: true });
return wrapper.vm.$nextTick(() => {
expect(wrapper.find('.btn-edit').exists()).toBe(true);
});
await nextTick();
expect(wrapper.find('.btn-edit').exists()).toBe(true);
});
});
......
import { GlFormGroup, GlDropdown, GlDropdownItem, GlIcon } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import { nextTick } from 'vue';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import IssueTypeField, { i18n } from '~/issues/show/components/fields/type.vue';
......@@ -93,7 +94,7 @@ describe('Issue type field component', () => {
it('updates the `issue_type` in the apollo cache when the value is changed', async () => {
findTypeFromDropDownItems().at(1).vm.$emit('click', issuableTypes.incident);
await wrapper.vm.$nextTick();
await nextTick();
expect(findTypeFromDropDown().attributes('value')).toBe(issuableTypes.incident);
});
......
import { GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import Autosave from '~/autosave';
import DescriptionTemplate from '~/issues/show/components/fields/description_template.vue';
import IssueTypeField from '~/issues/show/components/fields/type.vue';
......@@ -148,7 +149,7 @@ describe('Inline edit form component', () => {
formState: { ...defaultProps.formState, lock_version: 'lock version from server' },
});
await wrapper.vm.$nextTick();
await nextTick();
expect(findAlert().exists()).toBe(true);
});
});
......
import { GlButton, GlDropdown, GlDropdownItem, GlLink, GlModal } from '@gitlab/ui';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
import { mockTracking } from 'helpers/tracking_helper';
......@@ -153,7 +153,7 @@ describe('HeaderActions component', () => {
it('dispatches a custom event to update the issue page', async () => {
findToggleIssueStateButton().vm.$emit('click');
await wrapper.vm.$nextTick();
await nextTick();
expect(dispatchEventSpy).toHaveBeenCalledTimes(1);
});
......
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