Commit b8618652 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 79f66000
import { GlButton, GlIcon, GlBadge, GlProgressBar, GlLink } from '@gitlab/ui';
import { nextTick } from 'vue';
import DevopsAdoptionDeleteModal from 'ee/analytics/devops_reports/devops_adoption/components/devops_adoption_delete_modal.vue';
import DevopsAdoptionOverviewTable from 'ee/analytics/devops_reports/devops_adoption/components/devops_adoption_overview_table.vue';
import { DEVOPS_ADOPTION_TABLE_CONFIGURATION } from 'ee/analytics/devops_reports/devops_adoption/constants';
......@@ -186,7 +187,7 @@ describe('DevopsAdoptionOverviewTable', () => {
const deleteButton = findColSubComponent(TABLE_TEST_IDS_ACTIONS, GlButton);
deleteButton.vm.$emit('click');
await deleteButton.vm.$nextTick();
await nextTick();
});
it('renders delete modal', () => {
......
......@@ -2,6 +2,7 @@ import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import { GlSingleStat } from '@gitlab/ui/dist/charts';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import GroupActivityCard from 'ee/analytics/group_analytics/components/group_activity_card.vue';
import Api from 'ee/api';
import waitForPromises from 'helpers/wait_for_promises';
......@@ -48,40 +49,32 @@ describe('GroupActivity component', () => {
const findAllSkeletonLoaders = () => wrapper.findAllComponents(GlSkeletonLoading);
const findAllSingleStats = () => wrapper.findAllComponents(GlSingleStat);
it('fetches the metrics and updates isLoading properly', () => {
it('fetches the metrics and updates isLoading properly', async () => {
createComponent();
expect(wrapper.vm.isLoading).toBe(true);
return wrapper.vm
.$nextTick()
.then(() => {
await nextTick();
expect(Api.groupActivityMergeRequestsCount).toHaveBeenCalledWith(TEST_GROUP_ID);
expect(Api.groupActivityIssuesCount).toHaveBeenCalledWith(TEST_GROUP_ID);
expect(Api.groupActivityNewMembersCount).toHaveBeenCalledWith(TEST_GROUP_ID);
waitForPromises();
})
.then(() => {
await waitForPromises();
expect(wrapper.vm.isLoading).toBe(false);
expect(wrapper.vm.metrics.mergeRequests.value).toBe(10);
expect(wrapper.vm.metrics.issues.value).toBe(20);
expect(wrapper.vm.metrics.newMembers.value).toBe(30);
});
});
it('updates the loading state properly', () => {
it('updates the loading state properly', async () => {
createComponent();
expect(findAllSkeletonLoaders()).toHaveLength(3);
return wrapper.vm
.$nextTick()
.then(waitForPromises)
.then(() => {
await nextTick();
await waitForPromises();
expect(findAllSkeletonLoaders()).toHaveLength(0);
});
});
describe('metrics', () => {
beforeEach(() => {
......@@ -93,16 +86,13 @@ describe('GroupActivity component', () => {
${0} | ${10} | ${'Merge Requests opened'}
${1} | ${20} | ${'Issues opened'}
${2} | ${30} | ${'Members added'}
`('renders a GlSingleStat for "$title"', ({ index, value, title }) => {
`('renders a GlSingleStat for "$title"', async ({ index, value, title }) => {
const singleStat = findAllSingleStats().at(index);
return wrapper.vm
.$nextTick()
.then(waitForPromises)
.then(() => {
await nextTick();
await waitForPromises();
expect(singleStat.props('value')).toBe(`${value}`);
expect(singleStat.props('title')).toBe(title);
});
});
});
});
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import SidebarTodo from 'ee/epic/components/sidebar_items/sidebar_todo.vue';
import createStore from 'ee/epic/store';
......@@ -31,16 +31,12 @@ describe('SidebarTodoComponent', () => {
});
describe('template', () => {
it('renders component container element with classes `block` & `todo` when `isUserSignedIn` & `sidebarCollapsed` is `true`', (done) => {
it('renders component container element with classes `block` & `todo` when `isUserSignedIn` & `sidebarCollapsed` is `true`', async () => {
vm.sidebarCollapsed = true;
vm.$nextTick()
.then(() => {
await nextTick();
expect(vm.$el.classList.contains('block')).toBe(true);
expect(vm.$el.classList.contains('todo')).toBe(true);
})
.then(done)
.catch(done.fail);
});
it('renders Todo toggle button element', () => {
......
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import AppComponent from 'ee/group_member_contributions/components/app.vue';
import GroupMemberStore from 'ee/group_member_contributions/store/group_member_store';
......@@ -48,10 +48,10 @@ describe('AppComponent', () => {
expect(vm.$el.querySelector('h3').innerText.trim()).toBe('Contributions per group member');
});
it('shows loading icon when isLoading prop is true', () => {
it('shows loading icon when isLoading prop is true', async () => {
vm.store.state.isLoading = true;
return vm.$nextTick().then(() => {
await nextTick();
const loadingEl = vm.$el.querySelector('.loading-animation');
expect(loadingEl).not.toBeNull();
......@@ -59,14 +59,12 @@ describe('AppComponent', () => {
'Loading contribution stats for group members',
);
});
});
it('renders table container element', () => {
it('renders table container element', async () => {
vm.store.state.isLoading = false;
return vm.$nextTick().then(() => {
await nextTick();
expect(vm.$el.querySelector('table.table.gl-sortable')).not.toBeNull();
});
});
});
});
......@@ -9,6 +9,7 @@ import {
GlTable,
} from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import IterationReportIssues from 'ee/iterations/components/iteration_report_issues.vue';
import { Namespace } from 'ee/iterations/constants';
......@@ -183,9 +184,9 @@ describe('Iterations report issues', () => {
});
const findPagination = () => wrapper.findComponent(GlPagination);
const setPage = (page) => {
const setPage = async (page) => {
findPagination().vm.$emit('input', page);
return findPagination().vm.$nextTick();
await nextTick();
};
it('passes prev, next, and current page props', () => {
......
import { GlEmptyState } 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 Dashboard from 'ee/operations/components/dashboard/dashboard.vue';
......@@ -67,28 +67,21 @@ describe('dashboard component', () => {
});
describe('when a project is added', () => {
it('immediately requests the project list again', () => {
it('immediately requests the project list again', async () => {
mockAxios.reset();
mockAxios.onGet(mockListEndpoint).replyOnce(200, { projects: mockProjectData(2) });
mockAxios.onPost(mockAddEndpoint).replyOnce(200, { added: [1], invalid: [] });
return wrapper.vm
.$nextTick()
.then(() => {
await nextTick();
wrapper.vm.projectClicked({ id: 1 });
})
.then(waitForPromises)
.then(() => {
await waitForPromises();
wrapper.vm.onOk();
})
.then(waitForPromises)
.then(() => {
await waitForPromises();
expect(store.state.projects.length).toEqual(2);
expect(wrapper.findAllComponents(Project).length).toEqual(2);
});
});
});
});
describe('wrapped components', () => {
describe('dashboard project component', () => {
......@@ -144,66 +137,46 @@ describe('dashboard component', () => {
store.state.selectedProjects = mockProjectData(1);
});
it('clears state when adding a valid project', () => {
it('clears state when adding a valid project', async () => {
mockAxios.onPost(mockAddEndpoint).replyOnce(200, { added: [1], invalid: [] });
return wrapper.vm
.$nextTick()
.then(() => {
await nextTick();
wrapper.vm.onOk();
})
.then(waitForPromises)
.then(() => {
await waitForPromises();
expect(store.state.projectSearchResults).toHaveLength(0);
expect(store.state.selectedProjects).toHaveLength(0);
});
});
it('clears state when adding an invalid project', () => {
it('clears state when adding an invalid project', async () => {
mockAxios.onPost(mockAddEndpoint).replyOnce(200, { added: [], invalid: [1] });
return wrapper.vm
.$nextTick()
.then(() => {
await nextTick();
wrapper.vm.onOk();
})
.then(waitForPromises)
.then(() => {
await waitForPromises();
expect(store.state.projectSearchResults).toHaveLength(0);
expect(store.state.selectedProjects).toHaveLength(0);
});
});
it('clears state when canceled', () => {
return wrapper.vm
.$nextTick()
.then(() => {
it('clears state when canceled', async () => {
await nextTick();
wrapper.vm.onCancel();
})
.then(waitForPromises)
.then(() => {
await waitForPromises();
expect(store.state.projectSearchResults).toHaveLength(0);
expect(store.state.selectedProjects).toHaveLength(0);
});
});
it('clears state on error', () => {
it('clears state on error', async () => {
mockAxios.onPost(mockAddEndpoint).replyOnce(500, {});
return wrapper.vm
.$nextTick()
.then(() => {
await nextTick();
expect(store.state.projectSearchResults.length).not.toBe(0);
expect(store.state.selectedProjects.length).not.toBe(0);
wrapper.vm.onOk();
})
.then(waitForPromises)
.then(() => {
await waitForPromises();
expect(store.state.projectSearchResults).toHaveLength(0);
expect(store.state.selectedProjects).toHaveLength(0);
});
});
});
describe('when no projects have been added', () => {
beforeEach(() => {
......
import { merge } from 'lodash';
import { GlLoadingIcon, GlKeysetPagination } from '@gitlab/ui';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import { shallowMount } from '@vue/test-utils';
......@@ -51,14 +51,14 @@ describe('EE - CorpusManagement', () => {
const findPagination = () => wrapper.findComponent(GlKeysetPagination);
const nextPage = (cursor) => {
const nextPage = async (cursor) => {
findPagination().vm.$emit('next', cursor);
return findPagination().vm.$nextTick();
await nextTick();
};
const prevPage = (cursor) => {
const prevPage = async (cursor) => {
findPagination().vm.$emit('prev', cursor);
return findPagination().vm.$nextTick();
await nextTick();
};
const createComponentFactory = (mountFn = shallowMount) => (options = {}) => {
......
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import createStore from '~/notes/stores';
......@@ -76,16 +77,14 @@ describe('system note component', () => {
expect(findDescriptionVersion().exists()).toBe(false);
});
it('click on button to toggle description diff displays description diff with delete icon button', (done) => {
it('click on button to toggle description diff displays description diff with delete icon button', async () => {
mockFetchDiff();
expect(findDescriptionVersion().exists()).toBe(false);
const button = findBlankBtn();
button.trigger('click');
return wrapper.vm
.$nextTick()
.then(() => waitForPromises())
.then(() => {
await nextTick();
await waitForPromises();
expect(findDescriptionVersion().exists()).toBe(true);
expect(findDescriptionVersion().html()).toContain(diffData);
expect(
......@@ -95,8 +94,6 @@ describe('system note component', () => {
)
.exists(),
).toBe(true);
done();
});
});
describe('click on delete icon button', () => {
......
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import DraftsCount from '~/batch_comments/components/drafts_count.vue';
import { createStore } from '~/batch_comments/stores';
......@@ -27,17 +27,14 @@ describe('Batch comments drafts count component', () => {
expect(vm.$el.textContent).toContain('1');
});
it('renders screen reader text', (done) => {
it('renders screen reader text', async () => {
const el = vm.$el.querySelector('.sr-only');
expect(el.textContent).toContain('draft');
vm.$store.state.batchComments.drafts.push('comment 2');
vm.$nextTick(() => {
await nextTick();
expect(el.textContent).toContain('drafts');
done();
});
});
});
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import PublishButton from '~/batch_comments/components/publish_button.vue';
import { createStore } from '~/batch_comments/stores';
......@@ -29,13 +29,10 @@ describe('Batch comments publish button component', () => {
expect(vm.$store.dispatch).toHaveBeenCalledWith('batchComments/publishReview', undefined);
});
it('sets loading when isPublishing is true', (done) => {
it('sets loading when isPublishing is true', async () => {
vm.$store.state.batchComments.isPublishing = true;
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.getAttribute('disabled')).toBe('disabled');
done();
});
});
});
import { GlToggle, GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import IntegrationForm from '~/clusters/forms/components/integration_form.vue';
import { createStore } from '~/clusters/forms/stores/index';
......@@ -75,32 +75,22 @@ describe('ClusterIntegrationForm', () => {
describe('reactivity', () => {
beforeEach(() => createWrapper());
it('enables the submit button on changing toggle to different value', () => {
return wrapper.vm
.$nextTick()
.then(() => {
it('enables the submit button on changing toggle to different value', async () => {
await nextTick();
// setData is a bad approach because it changes the internal implementation which we should not touch
// but our GlFormInput lacks the ability to set a new value.
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ toggleEnabled: !defaultStoreValues.enabled });
})
.then(() => {
await wrapper.setData({ toggleEnabled: !defaultStoreValues.enabled });
expect(findSubmitButton().props('disabled')).toBe(false);
});
});
it('enables the submit button on changing input values', () => {
return wrapper.vm
.$nextTick()
.then(() => {
it('enables the submit button on changing input values', async () => {
await nextTick();
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ envScope: `${defaultStoreValues.environmentScope}1` });
})
.then(() => {
await wrapper.setData({ envScope: `${defaultStoreValues.environmentScope}1` });
expect(findSubmitButton().props('disabled')).toBe(false);
});
});
});
});
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 ServiceCredentialsForm from '~/create_cluster/eks_cluster/components/service_credentials_form.vue';
import eksClusterState from '~/create_cluster/eks_cluster/store/state';
......@@ -65,15 +65,14 @@ describe('ServiceCredentialsForm', () => {
expect(findSubmitButton().attributes('disabled')).toBeTruthy();
});
it('enables submit button when role ARN is not provided', () => {
it('enables submit button when role ARN is not provided', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
vm.setData({ roleArn: '123' });
return vm.vm.$nextTick().then(() => {
await nextTick();
expect(findSubmitButton().attributes('disabled')).toBeFalsy();
});
});
it('dispatches createRole action when submit button is clicked', () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
......@@ -86,14 +85,14 @@ describe('ServiceCredentialsForm', () => {
});
describe('when is creating role', () => {
beforeEach(() => {
beforeEach(async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
vm.setData({ roleArn: '123' }); // set role ARN to enable button
state.isCreatingRole = true;
return vm.vm.$nextTick();
await nextTick();
});
it('disables submit button', () => {
......
......@@ -74,7 +74,7 @@ describe('Design management design presentation component', () => {
.mockReturnValue((childDimensions.height - viewportDimensions.height) * scrollTopPerc);
}
function clickDragExplore(startCoords, endCoords, { useTouchEvents, mouseup } = {}) {
async function clickDragExplore(startCoords, endCoords, { useTouchEvents, mouseup } = {}) {
const event = useTouchEvents
? {
mousedown: 'touchstart',
......@@ -96,24 +96,17 @@ describe('Design management design presentation component', () => {
clientX: startCoords.clientX,
clientY: startCoords.clientY,
});
return wrapper.vm
.$nextTick()
.then(() => {
await nextTick();
addCommentOverlay.trigger(event.mousemove, {
clientX: endCoords.clientX,
clientY: endCoords.clientY,
});
return nextTick();
})
.then(() => {
await nextTick();
if (mouseup) {
addCommentOverlay.trigger(event.mouseup);
return nextTick();
await nextTick();
}
return undefined;
});
}
beforeEach(() => {
......@@ -125,7 +118,7 @@ describe('Design management design presentation component', () => {
window.gon = originalGon;
});
it('renders image and overlay when image provided', () => {
it('renders image and overlay when image provided', async () => {
createComponent(
{
image: 'test.jpg',
......@@ -134,20 +127,18 @@ describe('Design management design presentation component', () => {
mockOverlayData,
);
return nextTick().then(() => {
await nextTick();
expect(wrapper.element).toMatchSnapshot();
});
});
it('renders empty state when no image provided', () => {
it('renders empty state when no image provided', async () => {
createComponent();
return nextTick().then(() => {
await nextTick();
expect(wrapper.element).toMatchSnapshot();
});
});
it('openCommentForm event emits correct data', () => {
it('openCommentForm event emits correct data', async () => {
createComponent(
{
image: 'test.jpg',
......@@ -158,15 +149,14 @@ describe('Design management design presentation component', () => {
wrapper.vm.openCommentForm({ x: 1, y: 1 });
return nextTick().then(() => {
await nextTick();
expect(wrapper.emitted('openCommentForm')).toEqual([
[{ ...mockOverlayData.overlayDimensions, x: 1, y: 1 }],
]);
});
});
describe('currentCommentForm', () => {
it('is null when isAnnotating is false', () => {
it('is null when isAnnotating is false', async () => {
createComponent(
{
image: 'test.jpg',
......@@ -175,13 +165,12 @@ describe('Design management design presentation component', () => {
mockOverlayData,
);
return nextTick().then(() => {
await nextTick();
expect(wrapper.vm.currentCommentForm).toBeNull();
expect(wrapper.element).toMatchSnapshot();
});
});
it('is null when isAnnotating is true but annotation position is falsey', () => {
it('is null when isAnnotating is true but annotation position is falsey', async () => {
createComponent(
{
image: 'test.jpg',
......@@ -191,13 +180,12 @@ describe('Design management design presentation component', () => {
mockOverlayData,
);
return nextTick().then(() => {
await nextTick();
expect(wrapper.vm.currentCommentForm).toBeNull();
expect(wrapper.element).toMatchSnapshot();
});
});
it('is equal to current annotation position when isAnnotating is true', () => {
it('is equal to current annotation position when isAnnotating is true', async () => {
createComponent(
{
image: 'test.jpg',
......@@ -215,7 +203,7 @@ describe('Design management design presentation component', () => {
},
);
return nextTick().then(() => {
await nextTick();
expect(wrapper.vm.currentCommentForm).toEqual({
x: 1,
y: 1,
......@@ -225,7 +213,6 @@ describe('Design management design presentation component', () => {
expect(wrapper.element).toMatchSnapshot();
});
});
});
describe('setOverlayPosition', () => {
beforeEach(() => {
......@@ -388,7 +375,7 @@ describe('Design management design presentation component', () => {
});
describe('onImageResize', () => {
beforeEach(() => {
beforeEach(async () => {
createComponent(
{
image: 'test.jpg',
......@@ -401,7 +388,7 @@ describe('Design management design presentation component', () => {
jest.spyOn(wrapper.vm, 'scaleZoomFocalPoint');
jest.spyOn(wrapper.vm, 'scrollToFocalPoint');
wrapper.vm.onImageResize({ width: 10, height: 10 });
return nextTick();
await nextTick();
});
it('sets zoom focal point on initial load', () => {
......@@ -409,14 +396,13 @@ describe('Design management design presentation component', () => {
expect(wrapper.vm.initialLoad).toBe(false);
});
it('calls scaleZoomFocalPoint and scrollToFocalPoint after initial load', () => {
it('calls scaleZoomFocalPoint and scrollToFocalPoint after initial load', async () => {
wrapper.vm.onImageResize({ width: 10, height: 10 });
return nextTick().then(() => {
await nextTick();
expect(wrapper.vm.scaleZoomFocalPoint).toHaveBeenCalled();
expect(wrapper.vm.scrollToFocalPoint).toHaveBeenCalled();
});
});
});
describe('onPresentationMousedown', () => {
it.each`
......@@ -498,7 +484,7 @@ describe('Design management design presentation component', () => {
);
});
it('opens a comment form if design was not dragged', () => {
it('opens a comment form if design was not dragged', async () => {
const addCommentOverlay = findOverlayCommentButton();
const startCoords = {
clientX: 1,
......@@ -510,16 +496,11 @@ describe('Design management design presentation component', () => {
clientY: startCoords.clientY,
});
return wrapper.vm
.$nextTick()
.then(() => {
await nextTick();
addCommentOverlay.trigger('mouseup');
return nextTick();
})
.then(() => {
await nextTick();
expect(wrapper.emitted('openCommentForm')).toBeDefined();
});
});
describe('when clicking and dragging', () => {
it.each`
......
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import SettingsDropdown from '~/diffs/components/settings_dropdown.vue';
......@@ -10,7 +11,6 @@ import createDiffsStore from '../create_diffs_store';
describe('Diff settings dropdown component', () => {
let wrapper;
let vm;
let store;
function createComponent(extendStore = () => {}) {
......@@ -23,7 +23,6 @@ describe('Diff settings dropdown component', () => {
store,
}),
);
vm = wrapper.vm;
}
function getFileByFileCheckbox(vueWrapper) {
......@@ -142,7 +141,7 @@ describe('Diff settings dropdown component', () => {
checkbox.trigger('click');
await vm.$nextTick();
await nextTick();
expect(store.dispatch).toHaveBeenCalledWith('diffs/setShowWhitespace', {
showWhitespace: !checked,
......@@ -185,7 +184,7 @@ describe('Diff settings dropdown component', () => {
getFileByFileCheckbox(wrapper).trigger('click');
await vm.$nextTick();
await nextTick();
expect(store.dispatch).toHaveBeenCalledWith('diffs/setFileByFile', {
fileByFile: setting,
......
import { nextTick } from 'vue';
import { setHTMLFixture } from 'helpers/fixtures';
import RecentSearchesRoot from '~/filtered_search/recent_searches_root';
......@@ -10,7 +11,7 @@ describe('RecentSearchesRoot', () => {
let vm;
let containerEl;
beforeEach(() => {
beforeEach(async () => {
setHTMLFixture(`
<div id="${containerId}">
<div id="${dropdownElementId}"></div>
......@@ -33,7 +34,7 @@ describe('RecentSearchesRoot', () => {
RecentSearchesRoot.prototype.render.call(recentSearchesRootMockInstance);
vm = recentSearchesRootMockInstance.vm;
return vm.$nextTick();
await nextTick();
});
afterEach(() => {
......
import { GlModal, GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
import appComponent from '~/groups/components/app.vue';
......@@ -58,7 +58,7 @@ describe('AppComponent', () => {
wrapper = null;
});
beforeEach(() => {
beforeEach(async () => {
mock = new AxiosMockAdapter(axios);
mock.onGet('/dashboard/groups.json').reply(200, mockGroups);
Vue.component('GroupFolder', groupFolderComponent);
......@@ -66,7 +66,7 @@ describe('AppComponent', () => {
createShallowComponent();
getGroupsSpy = jest.spyOn(vm.service, 'getGroups');
return vm.$nextTick();
await nextTick();
});
describe('computed', () => {
......@@ -397,43 +397,40 @@ describe('AppComponent', () => {
});
describe('created', () => {
it('should bind event listeners on eventHub', () => {
it('should bind event listeners on eventHub', async () => {
jest.spyOn(eventHub, '$on').mockImplementation(() => {});
createShallowComponent();
return vm.$nextTick().then(() => {
await nextTick();
expect(eventHub.$on).toHaveBeenCalledWith('fetchPage', expect.any(Function));
expect(eventHub.$on).toHaveBeenCalledWith('toggleChildren', expect.any(Function));
expect(eventHub.$on).toHaveBeenCalledWith('showLeaveGroupModal', expect.any(Function));
expect(eventHub.$on).toHaveBeenCalledWith('updatePagination', expect.any(Function));
expect(eventHub.$on).toHaveBeenCalledWith('updateGroups', expect.any(Function));
});
});
it('should initialize `searchEmptyMessage` prop with correct string when `hideProjects` is `false`', () => {
it('should initialize `searchEmptyMessage` prop with correct string when `hideProjects` is `false`', async () => {
createShallowComponent();
return vm.$nextTick().then(() => {
await nextTick();
expect(vm.searchEmptyMessage).toBe('No groups or projects matched your search');
});
});
it('should initialize `searchEmptyMessage` prop with correct string when `hideProjects` is `true`', () => {
it('should initialize `searchEmptyMessage` prop with correct string when `hideProjects` is `true`', async () => {
createShallowComponent(true);
return vm.$nextTick().then(() => {
await nextTick();
expect(vm.searchEmptyMessage).toBe('No groups matched your search');
});
});
});
describe('beforeDestroy', () => {
it('should unbind event listeners on eventHub', () => {
it('should unbind event listeners on eventHub', async () => {
jest.spyOn(eventHub, '$off').mockImplementation(() => {});
createShallowComponent();
wrapper.destroy();
return vm.$nextTick().then(() => {
await nextTick();
expect(eventHub.$off).toHaveBeenCalledWith('fetchPage', expect.any(Function));
expect(eventHub.$off).toHaveBeenCalledWith('toggleChildren', expect.any(Function));
expect(eventHub.$off).toHaveBeenCalledWith('showLeaveGroupModal', expect.any(Function));
......@@ -441,23 +438,20 @@ describe('AppComponent', () => {
expect(eventHub.$off).toHaveBeenCalledWith('updateGroups', expect.any(Function));
});
});
});
describe('template', () => {
it('should render loading icon', () => {
it('should render loading icon', async () => {
vm.isLoading = true;
return vm.$nextTick().then(() => {
await nextTick();
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
});
it('should render groups tree', () => {
it('should render groups tree', async () => {
vm.store.state.groups = [mockParentGroupItem];
vm.isLoading = false;
return vm.$nextTick().then(() => {
await nextTick();
expect(vm.$el.querySelector('.groups-list-tree-container')).toBeDefined();
});
});
it('renders modal confirmation dialog', () => {
createShallowComponent();
......
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import groupFolderComponent from '~/groups/components/group_folder.vue';
......@@ -21,13 +21,13 @@ const createComponent = (searchEmpty = false) => {
describe('GroupsComponent', () => {
let vm;
beforeEach(() => {
beforeEach(async () => {
Vue.component('GroupFolder', groupFolderComponent);
Vue.component('GroupItem', groupItemComponent);
vm = createComponent();
return vm.$nextTick();
await nextTick();
});
afterEach(() => {
......@@ -52,20 +52,18 @@ describe('GroupsComponent', () => {
});
describe('template', () => {
it('should render component template correctly', () => {
return vm.$nextTick().then(() => {
it('should render component template correctly', async () => {
await nextTick();
expect(vm.$el.querySelector('.groups-list-tree-container')).toBeDefined();
expect(vm.$el.querySelector('.group-list-tree')).toBeDefined();
expect(vm.$el.querySelector('.gl-pagination')).toBeDefined();
expect(vm.$el.querySelectorAll('.has-no-search-results').length).toBe(0);
});
});
it('should render empty search message when `searchEmpty` is `true`', () => {
it('should render empty search message when `searchEmpty` is `true`', async () => {
vm.searchEmpty = true;
return vm.$nextTick().then(() => {
await nextTick();
expect(vm.$el.querySelector('.has-no-search-results')).toBeDefined();
});
});
});
});
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import ActivityBar from '~/ide/components/activity_bar.vue';
import { leftSidebarViews } from '~/ide/constants';
......@@ -61,14 +61,11 @@ describe('IDE activity bar', () => {
expect(vm.$el.querySelector('.js-ide-edit-mode').classList).toContain('active');
});
it('sets commit item active', (done) => {
it('sets commit item active', async () => {
vm.$store.state.currentActivityView = leftSidebarViews.commit.name;
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('.js-ide-commit-mode').classList).toContain('active');
done();
});
});
});
......
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import { projectData, branches } from 'jest/ide/mock_data';
import commitActions from '~/ide/components/commit_sidebar/actions.vue';
......@@ -71,15 +71,12 @@ describe('IDE commit sidebar actions', () => {
expect(findText()).toContain('Commit to main branch');
});
it('hides merge request option when project merge requests are disabled', (done) => {
it('hides merge request option when project merge requests are disabled', async () => {
createComponent({ hasMR: false });
vm.$nextTick(() => {
await nextTick();
expect(findRadios().length).toBe(2);
expect(findText()).not.toContain('Create a new branch and merge request');
done();
});
});
describe('currentBranchText', () => {
......@@ -105,22 +102,18 @@ describe('IDE commit sidebar actions', () => {
expect(vm.$store.dispatch).not.toHaveBeenCalled();
});
it('calls again after staged changes', (done) => {
it('calls again after staged changes', async () => {
createComponent({ currentBranchId: null });
vm.$store.state.currentBranchId = 'main';
vm.$store.state.changedFiles.push({});
vm.$store.state.stagedFiles.push({});
vm.$nextTick()
.then(() => {
await nextTick();
expect(vm.$store.dispatch).toHaveBeenCalledWith(
ACTION_UPDATE_COMMIT_ACTION,
expect.anything(),
);
})
.then(done)
.catch(done.fail);
});
it.each`
......
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import { trimText } from 'helpers/text_helper';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import listItem from '~/ide/components/commit_sidebar/list_item.vue';
......@@ -41,26 +41,18 @@ describe('Multi-file editor commit sidebar list item', () => {
expect(findPathText()).toContain(f.path);
});
it('correctly renders renamed entries', (done) => {
it('correctly renders renamed entries', async () => {
Vue.set(vm.file, 'prevName', 'Old name');
vm.$nextTick()
.then(() => {
await nextTick();
expect(findPathText()).toEqual(`Old name → ${f.name}`);
})
.then(done)
.catch(done.fail);
});
it('correctly renders entry, the name of which did not change after rename (as within a folder)', (done) => {
it('correctly renders entry, the name of which did not change after rename (as within a folder)', async () => {
Vue.set(vm.file, 'prevName', f.name);
vm.$nextTick()
.then(() => {
await nextTick();
expect(findPathText()).toEqual(f.name);
})
.then(done)
.catch(done.fail);
});
it('opens a closed file in the editor when clicking the file path', (done) => {
......@@ -134,14 +126,11 @@ describe('Multi-file editor commit sidebar list item', () => {
expect(vm.$el.querySelector('.is-active')).toBe(null);
});
it('adds active class when keys match', (done) => {
it('adds active class when keys match', async () => {
vm.keyPrefix = 'staged';
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('.is-active')).not.toBe(null);
done();
});
});
});
});
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import createComponent from 'helpers/vue_mount_component_helper';
import CommitMessageField from '~/ide/components/commit_sidebar/message_field.vue';
......@@ -23,34 +23,23 @@ describe('IDE commit message field', () => {
vm.$destroy();
});
it('adds is-focused class on focus', (done) => {
it('adds is-focused class on focus', async () => {
vm.$el.querySelector('textarea').focus();
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('.is-focused')).not.toBeNull();
done();
});
});
it('removed is-focused class on blur', (done) => {
it('removed is-focused class on blur', async () => {
vm.$el.querySelector('textarea').focus();
vm.$nextTick()
.then(() => {
await nextTick();
expect(vm.$el.querySelector('.is-focused')).not.toBeNull();
vm.$el.querySelector('textarea').blur();
return vm.$nextTick();
})
.then(() => {
await nextTick();
expect(vm.$el.querySelector('.is-focused')).toBeNull();
done();
})
.then(done)
.catch(done.fail);
});
it('emits input event on input', () => {
......@@ -66,27 +55,22 @@ describe('IDE commit message field', () => {
describe('highlights', () => {
describe('subject line', () => {
it('does not highlight less than 50 characters', (done) => {
it('does not highlight less than 50 characters', async () => {
vm.text = 'text less than 50 chars';
vm.$nextTick()
.then(() => {
await nextTick();
expect(vm.$el.querySelector('.highlights span').textContent).toContain(
'text less than 50 chars',
);
expect(vm.$el.querySelector('mark').style.display).toBe('none');
})
.then(done)
.catch(done.fail);
});
it('highlights characters over 50 length', (done) => {
it('highlights characters over 50 length', async () => {
vm.text =
'text less than 50 chars that should not highlighted. text more than 50 should be highlighted';
vm.$nextTick()
.then(() => {
await nextTick();
expect(vm.$el.querySelector('.highlights span').textContent).toContain(
'text less than 50 chars that should not highlighte',
);
......@@ -95,76 +79,54 @@ describe('IDE commit message field', () => {
expect(vm.$el.querySelector('mark').textContent).toBe(
'd. text more than 50 should be highlighted',
);
})
.then(done)
.catch(done.fail);
});
});
describe('body text', () => {
it('does not highlight body text less tan 72 characters', (done) => {
it('does not highlight body text less tan 72 characters', async () => {
vm.text = 'subject line\nbody content';
vm.$nextTick()
.then(() => {
await nextTick();
expect(vm.$el.querySelectorAll('.highlights span').length).toBe(2);
expect(vm.$el.querySelectorAll('mark')[1].style.display).toBe('none');
})
.then(done)
.catch(done.fail);
});
it('highlights body text more than 72 characters', (done) => {
it('highlights body text more than 72 characters', async () => {
vm.text =
'subject line\nbody content that will be highlighted when it is more than 72 characters in length';
vm.$nextTick()
.then(() => {
await nextTick();
expect(vm.$el.querySelectorAll('.highlights span').length).toBe(2);
expect(vm.$el.querySelectorAll('mark')[1].style.display).not.toBe('none');
expect(vm.$el.querySelectorAll('mark')[1].textContent).toBe(' in length');
})
.then(done)
.catch(done.fail);
});
it('highlights body text & subject line', (done) => {
it('highlights body text & subject line', async () => {
vm.text =
'text less than 50 chars that should not highlighted\nbody content that will be highlighted when it is more than 72 characters in length';
vm.$nextTick()
.then(() => {
await nextTick();
expect(vm.$el.querySelectorAll('.highlights span').length).toBe(2);
expect(vm.$el.querySelectorAll('mark').length).toBe(2);
expect(vm.$el.querySelectorAll('mark')[0].textContent).toContain('d');
expect(vm.$el.querySelectorAll('mark')[1].textContent).toBe(' in length');
})
.then(done)
.catch(done.fail);
});
});
});
describe('scrolling textarea', () => {
it('updates transform of highlights', (done) => {
it('updates transform of highlights', async () => {
vm.text = 'subject line\n\n\n\n\n\n\n\n\n\n\nbody content';
vm.$nextTick()
.then(() => {
await nextTick();
vm.$el.querySelector('textarea').scrollTo(0, 50);
vm.handleScroll();
})
.then(vm.$nextTick)
.then(() => {
await nextTick();
expect(vm.scrollTop).toBe(50);
expect(vm.$el.querySelector('.highlights').style.transform).toBe(
'translate3d(0, -50px, 0)',
);
})
.then(done)
.catch(done.fail);
expect(vm.$el.querySelector('.highlights').style.transform).toBe('translate3d(0, -50px, 0)');
});
});
});
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import { projectData, branches } from 'jest/ide/mock_data';
import NewMergeRequestOption from '~/ide/components/commit_sidebar/new_merge_request_option.vue';
......@@ -72,15 +72,11 @@ describe('create new MR checkbox', () => {
expect(vm.$el.textContent).not.toBe('');
});
it('has new MR', (done) => {
it('has new MR', async () => {
setMR();
vm.$nextTick()
.then(() => {
await nextTick();
expect(vm.$el.textContent).not.toBe('');
})
.then(done)
.catch(done.fail);
});
});
......@@ -96,15 +92,11 @@ describe('create new MR checkbox', () => {
expect(vm.$el.textContent).toBe('');
});
it('has new MR', (done) => {
it('has new MR', async () => {
setMR();
vm.$nextTick()
.then(() => {
await nextTick();
expect(vm.$el.textContent).toBe('');
})
.then(done)
.catch(done.fail);
});
});
});
......@@ -121,15 +113,11 @@ describe('create new MR checkbox', () => {
expect(vm.$el.textContent).not.toBe('');
});
it('is rendered if MR exists', (done) => {
it('is rendered if MR exists', async () => {
setMR();
vm.$nextTick()
.then(() => {
await nextTick();
expect(vm.$el.textContent).not.toBe('');
})
.then(done)
.catch(done.fail);
});
});
......@@ -144,15 +132,11 @@ describe('create new MR checkbox', () => {
expect(vm.$el.textContent).not.toBe('');
});
it('is hidden if MR exists', (done) => {
it('is hidden if MR exists', async () => {
setMR();
vm.$nextTick()
.then(() => {
await nextTick();
expect(vm.$el.textContent).toBe('');
})
.then(done)
.catch(done.fail);
});
});
});
......@@ -168,15 +152,11 @@ describe('create new MR checkbox', () => {
expect(vm.$el.textContent).not.toBe('');
});
it('is hidden if MR exists', (done) => {
it('is hidden if MR exists', async () => {
setMR();
vm.$nextTick()
.then(() => {
await nextTick();
expect(vm.$el.textContent).toBe('');
})
.then(done)
.catch(done.fail);
});
it('shows enablded checkbox', () => {
......
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import FileRowExtra from '~/ide/components/file_row_extra.vue';
import { createStore } from '~/ide/stores';
......@@ -70,28 +70,22 @@ describe('IDE extra file row component', () => {
expect(vm.$el.querySelector('.ide-tree-changes')).toBe(null);
});
it('does not show when tree is open', (done) => {
it('does not show when tree is open', async () => {
vm.file.type = 'tree';
vm.file.opened = true;
changesCount = 1;
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('.ide-tree-changes')).toBe(null);
done();
});
});
it('shows for trees with changes', (done) => {
it('shows for trees with changes', async () => {
vm.file.type = 'tree';
vm.file.opened = false;
changesCount = 1;
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('.ide-tree-changes')).not.toBe(null);
done();
});
});
});
......@@ -100,55 +94,40 @@ describe('IDE extra file row component', () => {
expect(vm.$el.querySelector('.file-changed-icon')).toBe(null);
});
it('shows when file is changed', (done) => {
it('shows when file is changed', async () => {
vm.file.changed = true;
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
done();
});
});
it('shows when file is staged', (done) => {
it('shows when file is staged', async () => {
vm.file.staged = true;
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
done();
});
});
it('shows when file is a tempFile', (done) => {
it('shows when file is a tempFile', async () => {
vm.file.tempFile = true;
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
done();
});
});
it('shows when file is renamed', (done) => {
it('shows when file is renamed', async () => {
vm.file.prevPath = 'original-file';
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
done();
});
});
it('hides when file is renamed', (done) => {
it('hides when file is renamed', async () => {
vm.file.prevPath = 'original-file';
vm.file.type = 'tree';
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('.file-changed-icon')).toBe(null);
done();
});
});
});
......@@ -157,14 +136,11 @@ describe('IDE extra file row component', () => {
expect(vm.$el.querySelector('[data-testid="git-merge-icon"]')).toBe(null);
});
it('shows when a merge request change', (done) => {
it('shows when a merge request change', async () => {
vm.file.mrChange = true;
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('[data-testid="git-merge-icon"]')).not.toBe(null);
done();
});
});
});
});
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import Bar from '~/ide/components/file_templates/bar.vue';
import { createStore } from '~/ide/stores';
......@@ -46,7 +46,7 @@ describe('IDE file templates bar component', () => {
});
describe('template dropdown', () => {
beforeEach((done) => {
beforeEach(async () => {
vm.$store.state.fileTemplates.templates = [
{
name: 'test',
......@@ -57,7 +57,7 @@ describe('IDE file templates bar component', () => {
key: 'gitlab_ci_ymls',
};
vm.$nextTick(done);
await nextTick();
});
it('renders dropdown component', () => {
......@@ -75,14 +75,11 @@ describe('IDE file templates bar component', () => {
});
});
it('shows undo button if updateSuccess is true', (done) => {
it('shows undo button if updateSuccess is true', async () => {
vm.$store.state.fileTemplates.updateSuccess = true;
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('.btn-default').style.display).not.toBe('none');
done();
});
});
it('calls undoFileTemplate when clicking undo button', () => {
......@@ -93,7 +90,7 @@ describe('IDE file templates bar component', () => {
expect(vm.undoFileTemplate).toHaveBeenCalled();
});
it('calls setSelectedTemplateType if activeFile name matches a template', (done) => {
it('calls setSelectedTemplateType if activeFile name matches a template', async () => {
const fileName = '.gitlab-ci.yml';
jest.spyOn(vm, 'setSelectedTemplateType').mockImplementation(() => {});
......@@ -101,13 +98,10 @@ describe('IDE file templates bar component', () => {
vm.setInitialType();
vm.$nextTick(() => {
await nextTick();
expect(vm.setSelectedTemplateType).toHaveBeenCalledWith({
name: fileName,
key: 'gitlab_ci_ymls',
});
done();
});
});
});
import _ from 'lodash';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import IdeStatusBar from '~/ide/components/ide_status_bar.vue';
......@@ -73,7 +73,7 @@ describe('ideStatusBar', () => {
});
describe('pipeline status', () => {
it('opens right sidebar on clicking icon', (done) => {
it('opens right sidebar on clicking icon', async () => {
jest.spyOn(vm, 'openRightPane').mockImplementation(() => {});
Vue.set(vm.$store.state.pipelines, 'latestPipeline', {
details: {
......@@ -88,14 +88,10 @@ describe('ideStatusBar', () => {
},
});
vm.$nextTick()
.then(() => {
await nextTick();
vm.$el.querySelector('.ide-status-pipeline button').click();
expect(vm.openRightPane).toHaveBeenCalledWith(rightSidebarViews.pipelines);
})
.then(done)
.catch(done.fail);
});
});
......
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import IdeTreeList from '~/ide/components/ide_tree_list.vue';
import { createStore } from '~/ide/stores';
......@@ -48,15 +48,12 @@ describe('IDE tree list', () => {
expect(vm.$emit).toHaveBeenCalledWith('tree-ready');
});
it('renders loading indicator', (done) => {
it('renders loading indicator', async () => {
store.state.trees['abcproject/main'].loading = true;
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('.multi-file-loading-container')).not.toBeNull();
expect(vm.$el.querySelectorAll('.multi-file-loading-container').length).toBe(3);
done();
});
});
it('renders list of files', () => {
......
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import JobDetail from '~/ide/components/jobs/detail.vue';
......@@ -48,14 +48,11 @@ describe('IDE jobs detail view', () => {
expect(vm.$el.querySelector('.bash').textContent).toContain('testing');
});
it('renders empty message output', (done) => {
it('renders empty message output', async () => {
vm.$store.state.pipelines.detailJob.output = '';
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('.bash').textContent).toContain('No messages were logged');
done();
});
});
it('renders loading icon', () => {
......@@ -68,14 +65,11 @@ describe('IDE jobs detail view', () => {
expect(vm.$el.querySelector('.bash').style.display).toBe('none');
});
it('hide loading icon when isLoading is false', (done) => {
it('hide loading icon when isLoading is false', async () => {
vm.$store.state.pipelines.detailJob.isLoading = false;
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('.build-loader-animation').style.display).toBe('none');
done();
});
});
it('resets detailJob when clicking header button', () => {
......@@ -107,19 +101,18 @@ describe('IDE jobs detail view', () => {
fnName | btnName | scrollPos
${'scrollDown'} | ${'down'} | ${0}
${'scrollUp'} | ${'up'} | ${1}
`('triggers $fnName when clicking $btnName button', ({ fnName, scrollPos }) => {
`('triggers $fnName when clicking $btnName button', async ({ fnName, scrollPos }) => {
jest.spyOn(vm, fnName).mockImplementation();
vm = vm.$mount();
vm.scrollPos = scrollPos;
return vm.$nextTick().then(() => {
await nextTick();
vm.$el.querySelector('.btn-scroll:not([disabled])').click();
expect(vm[fnName]).toHaveBeenCalled();
});
});
});
describe('scrollDown', () => {
beforeEach(() => {
......
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import JobItem from '~/ide/components/jobs/item.vue';
import { jobs } from '../../mock_data';
......@@ -27,13 +27,10 @@ describe('IDE jobs item', () => {
expect(vm.$el.querySelector('[data-testid="status_success_borderless-icon"]')).not.toBe(null);
});
it('does not render view logs button if not started', (done) => {
it('does not render view logs button if not started', async () => {
vm.job.started = false;
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('.btn')).toBe(null);
done();
});
});
});
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import { trimText } from 'helpers/text_helper';
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import NavDropdownButton from '~/ide/components/nav_dropdown_button.vue';
......@@ -36,38 +36,26 @@ describe('NavDropdown', () => {
expect(trimText(vm.$el.textContent)).toEqual('- -');
});
it('renders branch name, if state has currentBranchId', (done) => {
it('renders branch name, if state has currentBranchId', async () => {
vm.$store.state.currentBranchId = TEST_BRANCH_ID;
vm.$nextTick()
.then(() => {
await nextTick();
expect(trimText(vm.$el.textContent)).toEqual(`${TEST_BRANCH_ID} -`);
})
.then(done)
.catch(done.fail);
});
it('renders mr id, if state has currentMergeRequestId', (done) => {
it('renders mr id, if state has currentMergeRequestId', async () => {
vm.$store.state.currentMergeRequestId = TEST_MR_ID;
vm.$nextTick()
.then(() => {
await nextTick();
expect(trimText(vm.$el.textContent)).toEqual(`- !${TEST_MR_ID}`);
})
.then(done)
.catch(done.fail);
});
it('renders branch and mr, if state has both', (done) => {
it('renders branch and mr, if state has both', async () => {
vm.$store.state.currentBranchId = TEST_BRANCH_ID;
vm.$store.state.currentMergeRequestId = TEST_MR_ID;
vm.$nextTick()
.then(() => {
await nextTick();
expect(trimText(vm.$el.textContent)).toEqual(`${TEST_BRANCH_ID} !${TEST_MR_ID}`);
})
.then(done)
.catch(done.fail);
});
it('shows icons', () => {
......
import { mount } from '@vue/test-utils';
import $ from 'jquery';
import { nextTick } from 'vue';
import NavDropdown from '~/ide/components/nav_dropdown.vue';
import { PERMISSION_READ_MR } from '~/ide/constants';
import { createStore } from '~/ide/stores';
......@@ -58,29 +59,19 @@ describe('IDE NavDropdown', () => {
expect(findNavForm().exists()).toBe(false);
});
it('renders nav form when show.bs.dropdown', (done) => {
it('renders nav form when show.bs.dropdown', async () => {
showDropdown();
wrapper.vm
.$nextTick()
.then(() => {
await nextTick();
expect(findNavForm().exists()).toBe(true);
})
.then(done)
.catch(done.fail);
});
it('destroys nav form when closed', (done) => {
it('destroys nav form when closed', async () => {
showDropdown();
hideDropdown();
wrapper.vm
.$nextTick()
.then(() => {
await nextTick();
expect(findNavForm().exists()).toBe(false);
})
.then(done)
.catch(done.fail);
});
it('renders merge request icon', () => {
......
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import Button from '~/ide/components/new_dropdown/button.vue';
......@@ -37,14 +37,11 @@ describe('IDE new entry dropdown button component', () => {
expect(vm.$emit).toHaveBeenCalledWith('click');
});
it('hides label if showLabel is false', (done) => {
it('hides label if showLabel is false', async () => {
vm.showLabel = false;
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.textContent).not.toContain('Testing');
done();
});
});
describe('tooltipTitle', () => {
......@@ -52,14 +49,11 @@ describe('IDE new entry dropdown button component', () => {
expect(vm.tooltipTitle).toBe('');
});
it('returns label', (done) => {
it('returns label', async () => {
vm.showLabel = false;
vm.$nextTick(() => {
await nextTick();
expect(vm.tooltipTitle).toBe('Testing');
done();
});
});
});
});
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import createFlash from '~/flash';
import modal from '~/ide/components/new_dropdown/modal.vue';
......@@ -19,14 +19,14 @@ describe('new file modal component', () => {
${'tree'} | ${'Create new directory'} | ${'Create directory'} | ${false}
${'blob'} | ${'Create new file'} | ${'Create file'} | ${true}
`('$entryType', ({ entryType, modalTitle, btnTitle, showsFileTemplates }) => {
beforeEach((done) => {
beforeEach(async () => {
const store = createStore();
vm = createComponentWithStore(Component, store).$mount();
vm.open(entryType);
vm.name = 'testing';
vm.$nextTick(done);
await nextTick();
});
afterEach(() => {
......@@ -71,16 +71,13 @@ describe('new file modal component', () => {
${'blob'} | ${'Rename file'} | ${'Rename file'}
`(
'renders title and button for renaming $entryType',
({ entryType, modalTitle, btnTitle }, done) => {
async ({ entryType, modalTitle, btnTitle }) => {
vm.$store.state.entries['test-path'].type = entryType;
vm.open('rename', 'test-path');
vm.$nextTick(() => {
await nextTick();
expect(document.querySelector('.modal-title').textContent.trim()).toBe(modalTitle);
expect(document.querySelector('.btn-success').textContent.trim()).toBe(btnTitle);
done();
});
},
);
......
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { editor as monacoEditor, Range } from 'monaco-editor';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import '~/behaviors/markdown/render_gfm';
import waitForPromises from 'helpers/wait_for_promises';
......@@ -367,17 +367,17 @@ describe('RepoEditor', () => {
expect(vm.$store.state.panelResizing).toBe(false); // default value
vm.$store.state.panelResizing = true;
await vm.$nextTick();
await nextTick();
expect(updateDimensionsSpy).not.toHaveBeenCalled();
vm.$store.state.panelResizing = false;
await vm.$nextTick();
await nextTick();
expect(updateDimensionsSpy).toHaveBeenCalledTimes(1);
vm.$store.state.panelResizing = true;
await vm.$nextTick();
await nextTick();
expect(updateDimensionsSpy).toHaveBeenCalledTimes(1);
});
......@@ -387,12 +387,12 @@ describe('RepoEditor', () => {
expect(vm.$store.state.rightPane.isOpen).toBe(false); // default value
vm.$store.state.rightPane.isOpen = true;
await vm.$nextTick();
await nextTick();
expect(updateDimensionsSpy).toHaveBeenCalledTimes(1);
vm.$store.state.rightPane.isOpen = false;
await vm.$nextTick();
await nextTick();
expect(updateDimensionsSpy).toHaveBeenCalledTimes(2);
});
......@@ -411,7 +411,7 @@ describe('RepoEditor', () => {
`('tabs in $mode are $isVisible', async ({ mode, isVisible } = {}) => {
vm.$store.state.currentActivityView = leftSidebarViews[mode].name;
await vm.$nextTick();
await nextTick();
expect(wrapper.find('.nav-links').exists()).toBe(isVisible);
});
});
......@@ -436,7 +436,7 @@ describe('RepoEditor', () => {
});
changeViewMode(FILE_VIEW_MODE_PREVIEW);
await vm.$nextTick();
await nextTick();
});
it('do not show the editor', () => {
......@@ -448,7 +448,7 @@ describe('RepoEditor', () => {
expect(updateDimensionsSpy).not.toHaveBeenCalled();
changeViewMode(FILE_VIEW_MODE_EDITOR);
await vm.$nextTick();
await nextTick();
expect(updateDimensionsSpy).toHaveBeenCalled();
});
......@@ -460,7 +460,7 @@ describe('RepoEditor', () => {
jest.spyOn(vm, 'shouldHideEditor', 'get').mockReturnValue(true);
vm.initEditor();
await vm.$nextTick();
await nextTick();
};
it('does not fetch file information for temp entries', async () => {
......@@ -511,20 +511,20 @@ describe('RepoEditor', () => {
const origFile = vm.file;
vm.file.pending = true;
await vm.$nextTick();
await nextTick();
wrapper.setProps({
file: file('testing'),
});
vm.file.content = 'foo'; // need to prevent full cycle of initEditor
await vm.$nextTick();
await nextTick();
expect(vm.removePendingTab).toHaveBeenCalledWith(origFile);
});
it('does not call initEditor if the file did not change', async () => {
Vue.set(vm, 'file', vm.file);
await vm.$nextTick();
await nextTick();
expect(vm.initEditor).not.toHaveBeenCalled();
});
......@@ -538,7 +538,7 @@ describe('RepoEditor', () => {
key: 'new',
},
});
await vm.$nextTick();
await nextTick();
expect(vm.initEditor).toHaveBeenCalled();
});
......
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import TokenedInput from '~/ide/components/shared/tokened_input.vue';
......@@ -54,15 +54,11 @@ describe('IDE shared/TokenedInput', () => {
expect(vm.$refs.input).toHaveValue(TEST_VALUE);
});
it('renders placeholder, when tokens are empty', (done) => {
it('renders placeholder, when tokens are empty', async () => {
vm.tokens = [];
vm.$nextTick()
.then(() => {
await nextTick();
expect(vm.$refs.input).toHaveAttr('placeholder', TEST_PLACEHOLDER);
})
.then(done)
.catch(done.fail);
});
it('triggers "removeToken" on token click', () => {
......
import $ from 'jquery';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import '~/behaviors/markdown/render_gfm';
import { TEST_HOST } from 'helpers/test_constants';
import mountComponent from 'helpers/vue_mount_component_helper';
......@@ -36,52 +36,38 @@ describe('Description component', () => {
$('.issuable-meta .flash-container').remove();
});
it('doesnt animate first description changes', () => {
it('doesnt animate first description changes', async () => {
vm.descriptionHtml = 'changed';
return vm.$nextTick().then(() => {
expect(
vm.$el.querySelector('.md').classList.contains('issue-realtime-pre-pulse'),
).toBeFalsy();
await nextTick();
expect(vm.$el.querySelector('.md').classList.contains('issue-realtime-pre-pulse')).toBeFalsy();
jest.runAllTimers();
return vm.$nextTick();
});
});
it('animates description changes on live update', () => {
it('animates description changes on live update', async () => {
vm.descriptionHtml = 'changed';
return vm
.$nextTick()
.then(() => {
await nextTick();
vm.descriptionHtml = 'changed second time';
return vm.$nextTick();
})
.then(() => {
expect(
vm.$el.querySelector('.md').classList.contains('issue-realtime-pre-pulse'),
).toBeTruthy();
await nextTick();
expect(vm.$el.querySelector('.md').classList.contains('issue-realtime-pre-pulse')).toBeTruthy();
jest.runAllTimers();
return vm.$nextTick();
})
.then(() => {
await nextTick();
expect(
vm.$el.querySelector('.md').classList.contains('issue-realtime-trigger-pulse'),
).toBeTruthy();
});
});
it('applies syntax highlighting and math when description changed', () => {
it('applies syntax highlighting and math when description changed', async () => {
const vmSpy = jest.spyOn(vm, 'renderGFM');
const prototypeSpy = jest.spyOn($.prototype, 'renderGFM');
vm.descriptionHtml = 'changed';
return vm.$nextTick().then(() => {
await nextTick();
expect(vm.$refs['gfm-content']).toBeDefined();
expect(vmSpy).toHaveBeenCalled();
expect(prototypeSpy).toHaveBeenCalled();
expect($.prototype.renderGFM).toHaveBeenCalled();
});
});
it('sets data-update-url', () => {
expect(vm.$el.querySelector('textarea').dataset.updateUrl).toEqual(TEST_HOST);
......@@ -123,34 +109,31 @@ describe('Description component', () => {
});
describe('taskStatus', () => {
it('adds full taskStatus', () => {
it('adds full taskStatus', async () => {
vm.taskStatus = '1 of 1';
return vm.$nextTick().then(() => {
await nextTick();
expect(document.querySelector('.issuable-meta #task_status').textContent.trim()).toBe(
'1 of 1',
);
});
});
it('adds short taskStatus', () => {
it('adds short taskStatus', async () => {
vm.taskStatus = '1 of 1';
return vm.$nextTick().then(() => {
await nextTick();
expect(document.querySelector('.issuable-meta #task_status_short').textContent.trim()).toBe(
'1/1 task',
);
});
});
it('clears task status text when no tasks are present', () => {
it('clears task status text when no tasks are present', async () => {
vm.taskStatus = '0 of 0';
return vm.$nextTick().then(() => {
await nextTick();
expect(document.querySelector('.issuable-meta #task_status').textContent.trim()).toBe('');
});
});
});
describe('taskListUpdateStarted', () => {
it('emits event to parent', () => {
......
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import fixture from 'test_fixtures/blob/notebook/basic.json';
import CodeComponent from '~/notebook/cells/code.vue';
......@@ -58,12 +58,12 @@ describe('Code component', () => {
describe('with string for output', () => {
// NBFormat Version 4.1 allows outputs.text to be a string
beforeEach(() => {
beforeEach(async () => {
const cell = json.cells[2];
cell.outputs[0].text = cell.outputs[0].text.join('');
vm = setupComponent(cell);
return vm.$nextTick();
await nextTick();
});
it('does not render output prompt', () => {
......@@ -76,12 +76,12 @@ describe('Code component', () => {
});
describe('with string for cell.source', () => {
beforeEach(() => {
beforeEach(async () => {
const cell = json.cells[0];
cell.source = cell.source.join('');
vm = setupComponent(cell);
return vm.$nextTick();
await nextTick();
});
it('renders the same input as when cell.source is an array', () => {
......
import { mount } from '@vue/test-utils';
import katex from 'katex';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import markdownTableJson from 'test_fixtures/blob/notebook/markdown-table.json';
import basicJson from 'test_fixtures/blob/notebook/basic.json';
import mathJson from 'test_fixtures/blob/notebook/math.json';
......@@ -37,7 +37,7 @@ describe('Markdown component', () => {
let cell;
let json;
beforeEach(() => {
beforeEach(async () => {
json = basicJson;
// eslint-disable-next-line prefer-destructuring
......@@ -45,7 +45,7 @@ describe('Markdown component', () => {
vm = buildCellComponent(cell);
return vm.$nextTick();
await nextTick();
});
it('does not render prompt', () => {
......@@ -67,7 +67,7 @@ describe('Markdown component', () => {
],
});
await vm.$nextTick();
await nextTick();
expect(vm.$el.querySelector('a').getAttribute('href')).toBeNull();
});
......@@ -77,7 +77,7 @@ describe('Markdown component', () => {
source: ['<a href="test.js" data-remote=true data-type="script" class="xss-link">XSS</a>\n'],
});
await vm.$nextTick();
await nextTick();
expect(findLink().getAttribute('data-remote')).toBe(null);
expect(findLink().getAttribute('data-type')).toBe(null);
});
......@@ -99,7 +99,7 @@ describe('Markdown component', () => {
])('%s', async ([testMd, mustContain]) => {
vm = buildMarkdownComponent([testMd], '/raw/');
await vm.$nextTick();
await nextTick();
expect(vm.$el.innerHTML).toContain(mustContain);
});
......@@ -110,10 +110,10 @@ describe('Markdown component', () => {
json = markdownTableJson;
});
it('renders images and text', () => {
it('renders images and text', async () => {
vm = buildCellComponent(json.cells[0]);
return vm.$nextTick().then(() => {
await nextTick();
const images = vm.$el.querySelectorAll('img');
expect(images.length).toBe(5);
......@@ -134,7 +134,6 @@ describe('Markdown component', () => {
expect(columns[4].innerHTML).toContain('<img src="https://www.google.com/');
});
});
});
describe('katex', () => {
beforeEach(() => {
......@@ -144,28 +143,28 @@ describe('Markdown component', () => {
it('renders multi-line katex', async () => {
vm = buildCellComponent(json.cells[0]);
await vm.$nextTick();
await nextTick();
expect(vm.$el.querySelector('.katex')).not.toBeNull();
});
it('renders inline katex', async () => {
vm = buildCellComponent(json.cells[1]);
await vm.$nextTick();
await nextTick();
expect(vm.$el.querySelector('p:first-child .katex')).not.toBeNull();
});
it('renders multiple inline katex', async () => {
vm = buildCellComponent(json.cells[1]);
await vm.$nextTick();
await nextTick();
expect(vm.$el.querySelectorAll('p:nth-child(2) .katex')).toHaveLength(4);
});
it('output cell in case of katex error', async () => {
vm = buildMarkdownComponent(['Some invalid $a & b$ inline formula $b & c$\n', '\n']);
await vm.$nextTick();
await nextTick();
// expect one paragraph with no katex formula in it
expect(vm.$el.querySelectorAll('p')).toHaveLength(1);
expect(vm.$el.querySelectorAll('p .katex')).toHaveLength(0);
......@@ -177,7 +176,7 @@ describe('Markdown component', () => {
'\n',
]);
await vm.$nextTick();
await nextTick();
// expect one paragraph with no katex formula in it
expect(vm.$el.querySelectorAll('p')).toHaveLength(1);
expect(vm.$el.querySelectorAll('p .katex')).toHaveLength(1);
......@@ -186,7 +185,7 @@ describe('Markdown component', () => {
it('renders math formula in list object', async () => {
vm = buildMarkdownComponent(["- list with inline $a=2$ inline formula $a' + b = c$\n", '\n']);
await vm.$nextTick();
await nextTick();
// expect one list with a katex formula in it
expect(vm.$el.querySelectorAll('li')).toHaveLength(1);
expect(vm.$el.querySelectorAll('li .katex')).toHaveLength(2);
......@@ -195,7 +194,7 @@ describe('Markdown component', () => {
it("renders math formula with tick ' in it", async () => {
vm = buildMarkdownComponent(["- list with inline $a=2$ inline formula $a' + b = c$\n", '\n']);
await vm.$nextTick();
await nextTick();
// expect one list with a katex formula in it
expect(vm.$el.querySelectorAll('li')).toHaveLength(1);
expect(vm.$el.querySelectorAll('li .katex')).toHaveLength(2);
......@@ -204,7 +203,7 @@ describe('Markdown component', () => {
it('renders math formula with less-than-operator < in it', async () => {
vm = buildMarkdownComponent(['- list with inline $a=2$ inline formula $a + b < c$\n', '\n']);
await vm.$nextTick();
await nextTick();
// expect one list with a katex formula in it
expect(vm.$el.querySelectorAll('li')).toHaveLength(1);
expect(vm.$el.querySelectorAll('li .katex')).toHaveLength(2);
......@@ -213,7 +212,7 @@ describe('Markdown component', () => {
it('renders math formula with greater-than-operator > in it', async () => {
vm = buildMarkdownComponent(['- list with inline $a=2$ inline formula $a + b > c$\n', '\n']);
await vm.$nextTick();
await nextTick();
// expect one list with a katex formula in it
expect(vm.$el.querySelectorAll('li')).toHaveLength(1);
expect(vm.$el.querySelectorAll('li .katex')).toHaveLength(2);
......
import { nextTick } from 'vue';
import { initPopovers, dispose, destroy } from '~/popovers';
describe('popovers/index.js', () => {
let popoversApp;
const createPopoverTarget = (trigger = 'hover') => {
const target = document.createElement('button');
const dataset = {
......@@ -22,7 +21,7 @@ describe('popovers/index.js', () => {
};
const buildPopoversApp = () => {
popoversApp = initPopovers('[data-toggle="popover"]');
initPopovers('[data-toggle="popover"]');
};
const triggerEvent = (target, eventName = 'mouseenter') => {
......@@ -44,7 +43,7 @@ describe('popovers/index.js', () => {
triggerEvent(target);
await popoversApp.$nextTick();
await nextTick();
const html = document.querySelector('.gl-popover').innerHTML;
expect(document.querySelector('.gl-popover')).not.toBe(null);
......@@ -59,7 +58,7 @@ describe('popovers/index.js', () => {
buildPopoversApp();
triggerEvent(target, trigger);
await popoversApp.$nextTick();
await nextTick();
expect(document.querySelector('.gl-popover')).not.toBe(null);
expect(document.querySelector('.gl-popover').innerHTML).toContain('default title');
......@@ -73,7 +72,7 @@ describe('popovers/index.js', () => {
const trigger = 'click';
const target = createPopoverTarget(trigger);
triggerEvent(target, trigger);
await popoversApp.$nextTick();
await nextTick();
expect(document.querySelector('.gl-popover')).not.toBe(null);
});
......@@ -86,17 +85,17 @@ describe('popovers/index.js', () => {
buildPopoversApp();
triggerEvent(target);
triggerEvent(createPopoverTarget());
await popoversApp.$nextTick();
await nextTick();
expect(document.querySelectorAll('.gl-popover')).toHaveLength(2);
dispose([fakeTarget]);
await popoversApp.$nextTick();
await nextTick();
expect(document.querySelectorAll('.gl-popover')).toHaveLength(2);
dispose([target]);
await popoversApp.$nextTick();
await nextTick();
expect(document.querySelectorAll('.gl-popover')).toHaveLength(1);
});
......
import { GlModal } 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 axios from '~/lib/utils/axios_utils';
import ResetKey from '~/prometheus_alerts/components/reset_key.vue';
......@@ -45,29 +46,24 @@ describe('ResetKey', () => {
expect(vm.find('.js-reset-auth-key').text()).toEqual('Reset key');
});
it('reset updates key', () => {
it('reset updates key', async () => {
mock.onPost(propsData.changeKeyUrl).replyOnce(200, { token: 'newToken' });
vm.find(GlModal).vm.$emit('ok');
return vm.vm
.$nextTick()
.then(waitForPromises)
.then(() => {
await nextTick();
await waitForPromises();
expect(vm.vm.authorizationKey).toEqual('newToken');
expect(vm.find('#authorization-key').attributes('value')).toEqual('newToken');
});
});
it('reset key failure shows error', () => {
it('reset key failure shows error', async () => {
mock.onPost(propsData.changeKeyUrl).replyOnce(500);
vm.find(GlModal).vm.$emit('ok');
return vm.vm
.$nextTick()
.then(waitForPromises)
.then(() => {
await nextTick();
await waitForPromises();
expect(vm.find('#authorization-key').attributes('value')).toEqual(
propsData.initialAuthorizationKey,
);
......@@ -77,7 +73,6 @@ describe('ResetKey', () => {
);
});
});
});
describe('authorization key has not been set', () => {
beforeEach(() => {
......@@ -92,14 +87,13 @@ describe('ResetKey', () => {
expect(vm.find('#authorization-key').attributes('value')).toEqual('');
});
it('Generate key button triggers key change', () => {
it('Generate key button triggers key change', async () => {
mock.onPost(propsData.changeKeyUrl).replyOnce(200, { token: 'newToken' });
vm.find('.js-reset-auth-key').vm.$emit('click');
return waitForPromises().then(() => {
await waitForPromises();
expect(vm.find('#authorization-key').attributes('value')).toEqual('newToken');
});
});
});
});
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import LastCommit from '~/repository/components/last_commit.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
......@@ -63,7 +64,7 @@ describe('Repository last commit component', () => {
`('$label when loading icon $loading is true', async ({ loading }) => {
factory(createCommitData(), loading);
await vm.vm.$nextTick();
await nextTick();
expect(vm.find(GlLoadingIcon).exists()).toBe(loading);
});
......@@ -71,7 +72,7 @@ describe('Repository last commit component', () => {
it('renders commit widget', async () => {
factory();
await vm.vm.$nextTick();
await nextTick();
expect(vm.element).toMatchSnapshot();
});
......@@ -79,7 +80,7 @@ describe('Repository last commit component', () => {
it('renders short commit ID', async () => {
factory();
await vm.vm.$nextTick();
await nextTick();
expect(vm.find('[data-testid="last-commit-id-label"]').text()).toEqual('12345678');
});
......@@ -87,7 +88,7 @@ describe('Repository last commit component', () => {
it('hides pipeline components when pipeline does not exist', async () => {
factory(createCommitData({ pipeline: null }));
await vm.vm.$nextTick();
await nextTick();
expect(vm.find('.js-commit-pipeline').exists()).toBe(false);
});
......@@ -95,7 +96,7 @@ describe('Repository last commit component', () => {
it('renders pipeline components', async () => {
factory();
await vm.vm.$nextTick();
await nextTick();
expect(vm.find('.js-commit-pipeline').exists()).toBe(true);
});
......@@ -103,7 +104,7 @@ describe('Repository last commit component', () => {
it('hides author component when author does not exist', async () => {
factory(createCommitData({ author: null }));
await vm.vm.$nextTick();
await nextTick();
expect(vm.find('.js-user-link').exists()).toBe(false);
expect(vm.find(UserAvatarLink).exists()).toBe(false);
......@@ -112,7 +113,7 @@ describe('Repository last commit component', () => {
it('does not render description expander when description is null', async () => {
factory(createCommitData({ descriptionHtml: null }));
await vm.vm.$nextTick();
await nextTick();
expect(vm.find('.text-expander').exists()).toBe(false);
expect(vm.find('.commit-row-description').exists()).toBe(false);
......@@ -121,11 +122,11 @@ describe('Repository last commit component', () => {
it('expands commit description when clicking expander', async () => {
factory(createCommitData({ descriptionHtml: 'Test description' }));
await vm.vm.$nextTick();
await nextTick();
vm.find('.text-expander').vm.$emit('click');
await vm.vm.$nextTick();
await nextTick();
expect(vm.find('.commit-row-description').isVisible()).toBe(true);
expect(vm.find('.text-expander').classes('open')).toBe(true);
......@@ -134,7 +135,7 @@ describe('Repository last commit component', () => {
it('strips the first newline of the description', async () => {
factory(createCommitData({ descriptionHtml: '&#x000A;Update ADOPTERS.md' }));
await vm.vm.$nextTick();
await nextTick();
expect(vm.find('.commit-row-description').html()).toBe(
'<pre class="commit-row-description gl-mb-3">Update ADOPTERS.md</pre>',
......@@ -144,7 +145,7 @@ describe('Repository last commit component', () => {
it('renders the signature HTML as returned by the backend', async () => {
factory(createCommitData({ signatureHtml: '<button>Verified</button>' }));
await vm.vm.$nextTick();
await nextTick();
expect(vm.element).toMatchSnapshot();
});
......@@ -152,7 +153,7 @@ describe('Repository last commit component', () => {
it('sets correct CSS class if the commit message is empty', async () => {
factory(createCommitData({ message: '' }));
await vm.vm.$nextTick();
await nextTick();
expect(vm.find('.item-title').classes()).toContain(emptyMessageClass);
});
......
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { handleLocationHash } from '~/lib/utils/common_utils';
import Preview from '~/repository/components/preview/index.vue';
......@@ -28,7 +29,7 @@ describe('Repository file preview component', () => {
vm.destroy();
});
it('renders file HTML', () => {
it('renders file HTML', async () => {
factory({
webPath: 'http://test.com',
name: 'README.md',
......@@ -38,12 +39,11 @@ describe('Repository file preview component', () => {
// eslint-disable-next-line no-restricted-syntax
vm.setData({ readme: { html: '<div class="blob">test</div>' } });
return vm.vm.$nextTick(() => {
await nextTick();
expect(vm.element).toMatchSnapshot();
});
});
it('handles hash after render', () => {
it('handles hash after render', async () => {
factory({
webPath: 'http://test.com',
name: 'README.md',
......@@ -53,15 +53,11 @@ describe('Repository file preview component', () => {
// eslint-disable-next-line no-restricted-syntax
vm.setData({ readme: { html: '<div class="blob">test</div>' } });
return vm.vm
.$nextTick()
.then(vm.vm.$nextTick())
.then(() => {
await nextTick();
expect(handleLocationHash).toHaveBeenCalled();
});
});
it('renders loading icon', () => {
it('renders loading icon', async () => {
factory({
webPath: 'http://test.com',
name: 'README.md',
......@@ -71,8 +67,7 @@ describe('Repository file preview component', () => {
// eslint-disable-next-line no-restricted-syntax
vm.setData({ loading: 1 });
return vm.vm.$nextTick(() => {
await nextTick();
expect(vm.find(GlLoadingIcon).exists()).toBe(true);
});
});
});
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading, GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import Table from '~/repository/components/table/index.vue';
import TableRow from '~/repository/components/table/row.vue';
......@@ -86,19 +87,18 @@ describe('Repository table component', () => {
${'/'} | ${'main'}
${'app/assets'} | ${'main'}
${'/'} | ${'test'}
`('renders table caption for $ref in $path', ({ path, ref }) => {
`('renders table caption for $ref in $path', async ({ path, ref }) => {
factory({ path });
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
vm.setData({ ref });
return vm.vm.$nextTick(() => {
await nextTick();
expect(vm.find('.table').attributes('aria-label')).toEqual(
`Files, directories, and submodules in the path ${path} for commit reference ${ref}`,
);
});
});
it('shows loading icon', () => {
factory({ path: '/', isLoading: true });
......@@ -140,7 +140,7 @@ describe('Repository table component', () => {
showMoreButton().vm.$emit('click');
await vm.vm.$nextTick();
await nextTick();
expect(vm.emitted('showMore')).toHaveLength(1);
});
......
import { GlBadge, GlLink, GlIcon, GlIntersectionObserver } from '@gitlab/ui';
import { shallowMount, RouterLinkStub } from '@vue/test-utils';
import { nextTick } from 'vue';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import TableRow from '~/repository/components/table/row.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
......@@ -53,7 +54,7 @@ describe('Repository table row component', () => {
vm.destroy();
});
it('renders table row', () => {
it('renders table row', async () => {
factory({
id: '1',
sha: '123',
......@@ -62,12 +63,11 @@ describe('Repository table row component', () => {
currentPath: '/',
});
return vm.vm.$nextTick().then(() => {
await nextTick();
expect(vm.element).toMatchSnapshot();
});
});
it('renders a symlink table row', () => {
it('renders a symlink table row', async () => {
factory({
id: '1',
sha: '123',
......@@ -77,12 +77,11 @@ describe('Repository table row component', () => {
mode: FILE_SYMLINK_MODE,
});
return vm.vm.$nextTick().then(() => {
await nextTick();
expect(vm.element).toMatchSnapshot();
});
});
it('renders table row for path with special character', () => {
it('renders table row for path with special character', async () => {
factory({
id: '1',
sha: '123',
......@@ -91,10 +90,9 @@ describe('Repository table row component', () => {
currentPath: 'test$',
});
return vm.vm.$nextTick().then(() => {
await nextTick();
expect(vm.element).toMatchSnapshot();
});
});
it('renders a gl-hover-load directive', () => {
factory({
......@@ -116,7 +114,7 @@ describe('Repository table row component', () => {
${'tree'} | ${RouterLinkStub} | ${'RouterLink'}
${'blob'} | ${RouterLinkStub} | ${'RouterLink'}
${'commit'} | ${'a'} | ${'hyperlink'}
`('renders a $componentName for type $type', ({ type, component }) => {
`('renders a $componentName for type $type', async ({ type, component }) => {
factory({
id: '1',
sha: '123',
......@@ -125,16 +123,15 @@ describe('Repository table row component', () => {
currentPath: '/',
});
return vm.vm.$nextTick().then(() => {
await nextTick();
expect(vm.find(component).exists()).toBe(true);
});
});
it.each`
path
${'test#'}
${'Änderungen'}
`('renders link for $path', ({ path }) => {
`('renders link for $path', async ({ path }) => {
factory({
id: '1',
sha: '123',
......@@ -143,14 +140,13 @@ describe('Repository table row component', () => {
currentPath: '/',
});
return vm.vm.$nextTick().then(() => {
await nextTick();
expect(vm.find({ ref: 'link' }).props('to')).toEqual({
path: `/-/tree/main/${encodeURIComponent(path)}`,
});
});
});
it('renders link for directory with hash', () => {
it('renders link for directory with hash', async () => {
factory({
id: '1',
sha: '123',
......@@ -159,12 +155,11 @@ describe('Repository table row component', () => {
currentPath: '/',
});
return vm.vm.$nextTick().then(() => {
await nextTick();
expect(vm.find('.tree-item-link').props('to')).toEqual({ path: '/-/tree/main/test%23' });
});
});
it('renders commit ID for submodule', () => {
it('renders commit ID for submodule', async () => {
factory({
id: '1',
sha: '123',
......@@ -173,12 +168,11 @@ describe('Repository table row component', () => {
currentPath: '/',
});
return vm.vm.$nextTick().then(() => {
await nextTick();
expect(vm.find('.commit-sha').text()).toContain('1');
});
});
it('renders link with href', () => {
it('renders link with href', async () => {
factory({
id: '1',
sha: '123',
......@@ -188,12 +182,11 @@ describe('Repository table row component', () => {
currentPath: '/',
});
return vm.vm.$nextTick().then(() => {
await nextTick();
expect(vm.find('a').attributes('href')).toEqual('https://test.com');
});
});
it('renders LFS badge', () => {
it('renders LFS badge', async () => {
factory({
id: '1',
sha: '123',
......@@ -203,12 +196,11 @@ describe('Repository table row component', () => {
lfsOid: '1',
});
return vm.vm.$nextTick().then(() => {
await nextTick();
expect(vm.find(GlBadge).exists()).toBe(true);
});
});
it('renders commit and web links with href for submodule', () => {
it('renders commit and web links with href for submodule', async () => {
factory({
id: '1',
sha: '123',
......@@ -219,13 +211,12 @@ describe('Repository table row component', () => {
currentPath: '/',
});
return vm.vm.$nextTick().then(() => {
await nextTick();
expect(vm.find('a').attributes('href')).toEqual('https://test.com');
expect(vm.find(GlLink).attributes('href')).toEqual('https://test.com/commit');
});
});
it('renders lock icon', () => {
it('renders lock icon', async () => {
factory({
id: '1',
sha: '123',
......@@ -234,11 +225,10 @@ describe('Repository table row component', () => {
currentPath: '/',
});
return vm.vm.$nextTick().then(() => {
await nextTick();
expect(vm.find(GlIcon).exists()).toBe(true);
expect(vm.find(GlIcon).props('name')).toBe('lock');
});
});
it('renders loading icon when path is loading', () => {
factory({
......
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import paginatedTreeQuery from 'shared_queries/repository/paginated_tree.query.graphql';
import FilePreview from '~/repository/components/preview/index.vue';
import FileTable from '~/repository/components/table/index.vue';
......@@ -50,7 +51,7 @@ describe('Repository table component', () => {
// eslint-disable-next-line no-restricted-syntax
vm.setData({ entries: { blobs: [{ name: 'README.md' }] } });
await vm.vm.$nextTick();
await nextTick();
expect(vm.find(FilePreview).exists()).toBe(true);
});
......@@ -60,7 +61,7 @@ describe('Repository table component', () => {
jest.spyOn(vm.vm, 'fetchFiles').mockImplementation(() => {});
await vm.vm.$nextTick();
await nextTick();
expect(vm.vm.fetchFiles).toHaveBeenCalled();
expect(resetRequestedCommits).toHaveBeenCalled();
......@@ -111,7 +112,7 @@ describe('Repository table component', () => {
it('is changes hasShowMore to false when "showMore" event is emitted', async () => {
findFileTable().vm.$emit('showMore');
await vm.vm.$nextTick();
await nextTick();
expect(vm.vm.hasShowMore).toBe(false);
});
......@@ -119,7 +120,7 @@ describe('Repository table component', () => {
it('changes clickedShowMore when "showMore" event is emitted', async () => {
findFileTable().vm.$emit('showMore');
await vm.vm.$nextTick();
await nextTick();
expect(vm.vm.clickedShowMore).toBe(true);
});
......@@ -140,7 +141,7 @@ describe('Repository table component', () => {
// eslint-disable-next-line no-restricted-syntax
vm.setData({ fetchCounter: 5, clickedShowMore: false });
await vm.vm.$nextTick();
await nextTick();
expect(vm.vm.hasShowMore).toBe(false);
});
......@@ -161,7 +162,7 @@ describe('Repository table component', () => {
// eslint-disable-next-line no-restricted-syntax
vm.setData({ entries: { blobs }, pagesLoaded });
await vm.vm.$nextTick();
await nextTick();
expect(findFileTable().props('hasMore')).toBe(limitReached);
});
......
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import AxiosMockAdapter from 'axios-mock-adapter';
import Vuex from 'vuex';
import { TEST_HOST } from 'helpers/test_constants';
......@@ -73,15 +73,14 @@ describe('functionsComponent', () => {
expect(component.find('.js-functions-loader').exists()).toBe(true);
});
it('should render the functions list', () => {
it('should render the functions list', async () => {
store = createStore({ clustersPath: 'clustersPath', helpPath: 'helpPath', statusPath });
component = shallowMount(functionsComponent, { store });
component.vm.$store.dispatch('receiveFunctionsSuccess', mockServerlessFunctions);
await component.vm.$store.dispatch('receiveFunctionsSuccess', mockServerlessFunctions);
return component.vm.$nextTick().then(() => {
await nextTick();
expect(component.find(EnvironmentRow).exists()).toBe(true);
});
});
});
......@@ -86,22 +86,18 @@ describe('Blob Embeddable', () => {
expect(wrapper.find(RichViewer).exists()).toBe(true);
});
it('correctly switches viewer type', () => {
it('correctly switches viewer type', async () => {
createComponent();
expect(wrapper.find(SimpleViewer).exists()).toBe(true);
wrapper.vm.switchViewer(RichViewerMock.type);
return wrapper.vm
.$nextTick()
.then(() => {
await nextTick();
expect(wrapper.find(RichViewer).exists()).toBe(true);
wrapper.vm.switchViewer(SimpleViewerMock.type);
})
.then(() => {
await wrapper.vm.switchViewer(SimpleViewerMock.type);
expect(wrapper.find(SimpleViewer).exists()).toBe(true);
});
});
it('passes information about render error down to blob header', () => {
createComponent({
......@@ -191,26 +187,22 @@ describe('Blob Embeddable', () => {
});
describe('switchViewer()', () => {
it('switches to the passed viewer', () => {
it('switches to the passed viewer', async () => {
createComponent();
wrapper.vm.switchViewer(RichViewerMock.type);
return wrapper.vm
.$nextTick()
.then(() => {
await nextTick();
expect(wrapper.vm.activeViewerType).toBe(RichViewerMock.type);
expect(wrapper.find(RichViewer).exists()).toBe(true);
wrapper.vm.switchViewer(SimpleViewerMock.type);
})
.then(() => {
await wrapper.vm.switchViewer(SimpleViewerMock.type);
expect(wrapper.vm.activeViewerType).toBe(SimpleViewerMock.type);
expect(wrapper.find(SimpleViewer).exists()).toBe(true);
});
});
});
});
});
describe('functionality', () => {
describe('render error', () => {
......
import { nextTick } from 'vue';
import {
add,
initTooltips,
......@@ -57,7 +58,7 @@ describe('tooltips/index.js', () => {
triggerEvent(target);
await tooltipsApp.$nextTick();
await nextTick();
expect(document.querySelector('.gl-tooltip')).not.toBe(null);
expect(document.querySelector('.gl-tooltip').innerHTML).toContain('default title');
......@@ -69,7 +70,7 @@ describe('tooltips/index.js', () => {
buildTooltipsApp();
triggerEvent(target, 'click');
await tooltipsApp.$nextTick();
await nextTick();
expect(document.querySelector('.gl-tooltip')).not.toBe(null);
expect(document.querySelector('.gl-tooltip').innerHTML).toContain('default title');
......@@ -83,7 +84,7 @@ describe('tooltips/index.js', () => {
buildTooltipsApp();
add([target], { title: 'custom title' });
await tooltipsApp.$nextTick();
await nextTick();
expect(document.querySelector('.gl-tooltip')).not.toBe(null);
expect(document.querySelector('.gl-tooltip').innerHTML).toContain('custom title');
......@@ -97,13 +98,13 @@ describe('tooltips/index.js', () => {
buildTooltipsApp();
triggerEvent(target);
await tooltipsApp.$nextTick();
await nextTick();
expect(document.querySelector('.gl-tooltip')).not.toBe(null);
dispose([target]);
await tooltipsApp.$nextTick();
await nextTick();
expect(document.querySelector('.gl-tooltip')).toBe(null);
});
......@@ -122,7 +123,7 @@ describe('tooltips/index.js', () => {
buildTooltipsApp();
await tooltipsApp.$nextTick();
await nextTick();
jest.spyOn(tooltipsApp, 'triggerEvent');
......@@ -137,7 +138,7 @@ describe('tooltips/index.js', () => {
buildTooltipsApp();
await tooltipsApp.$nextTick();
await nextTick();
jest.spyOn(tooltipsApp, 'fixTitle');
......
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import { compileToFunctions } from 'vue-template-compiler';
import { GREEN_BOX_IMAGE_URL, RED_BOX_IMAGE_URL } from 'spec/test_constants';
......@@ -51,10 +51,10 @@ describe('ImageDiffViewer', () => {
wrapper.destroy();
});
it('renders image diff for replaced', (done) => {
it('renders image diff for replaced', async () => {
createComponent({ ...allProps });
vm.$nextTick(() => {
await nextTick();
const metaInfoElements = vm.$el.querySelectorAll('.image-info');
expect(vm.$el.querySelector('.added img').getAttribute('src')).toBe(GREEN_BOX_IMAGE_URL);
......@@ -73,9 +73,6 @@ describe('ImageDiffViewer', () => {
expect(metaInfoElements.length).toBe(2);
expect(metaInfoElements[0]).toHaveText('2.00 KiB');
expect(metaInfoElements[1]).toHaveText('1.00 KiB');
done();
});
});
it('renders image diff for new', (done) => {
......@@ -151,13 +148,11 @@ describe('ImageDiffViewer', () => {
});
});
it('switches to Swipe Mode', (done) => {
it('switches to Swipe Mode', async () => {
vm.$el.querySelector('.view-modes-menu li:nth-child(2)').click();
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('.view-modes-menu li.active').textContent.trim()).toBe('Swipe');
done();
});
});
});
......@@ -170,29 +165,24 @@ describe('ImageDiffViewer', () => {
});
});
it('switches to Onion Skin Mode', (done) => {
it('switches to Onion Skin Mode', async () => {
vm.$el.querySelector('.view-modes-menu li:nth-child(3)').click();
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('.view-modes-menu li.active').textContent.trim()).toBe(
'Onion skin',
);
done();
});
});
it('has working drag handler', (done) => {
it('has working drag handler', async () => {
vm.$el.querySelector('.view-modes-menu li:nth-child(3)').click();
vm.$nextTick(() => {
await nextTick();
dragSlider(vm.$el.querySelector('.dragger'), document, 20);
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('.dragger').style.left).toBe('20px');
expect(vm.$el.querySelector('.added.frame').style.opacity).toBe('0.2');
done();
});
});
});
});
});
import Mousetrap from 'mousetrap';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import { file } from 'jest/ide/helpers';
import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes';
......@@ -310,34 +310,26 @@ describe('File finder item spec', () => {
});
describe('keyboard shortcuts', () => {
beforeEach((done) => {
beforeEach(async () => {
createComponent();
jest.spyOn(vm, 'toggle').mockImplementation(() => {});
vm.$nextTick(done);
await nextTick();
});
it('calls toggle on `t` key press', (done) => {
it('calls toggle on `t` key press', async () => {
Mousetrap.trigger('t');
vm.$nextTick()
.then(() => {
await nextTick();
expect(vm.toggle).toHaveBeenCalled();
})
.then(done)
.catch(done.fail);
});
it('calls toggle on `mod+p` key press', (done) => {
it('calls toggle on `mod+p` key press', async () => {
Mousetrap.trigger('mod+p');
vm.$nextTick()
.then(() => {
await nextTick();
expect(vm.toggle).toHaveBeenCalled();
})
.then(done)
.catch(done.fail);
});
it('always allows `mod+p` to trigger toggle', () => {
......
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import createComponent from 'helpers/vue_mount_component_helper';
import { file } from 'jest/ide/helpers';
import ItemComponent from '~/vue_shared/components/file_finder/item.vue';
......@@ -37,14 +37,11 @@ describe('File finder item spec', () => {
expect(vm.$el.classList).toContain('is-focused');
});
it('does not have is-focused class when not focused', (done) => {
it('does not have is-focused class when not focused', async () => {
vm.focused = false;
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.classList).not.toContain('is-focused');
done();
});
});
});
......@@ -53,24 +50,18 @@ describe('File finder item spec', () => {
expect(vm.$el.querySelector('.diff-changed-stats')).toBe(null);
});
it('renders when a changed file', (done) => {
it('renders when a changed file', async () => {
vm.file.changed = true;
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('.diff-changed-stats')).not.toBe(null);
done();
});
});
it('renders when a temp file', (done) => {
it('renders when a temp file', async () => {
vm.file.tempFile = true;
vm.$nextTick(() => {
await nextTick();
expect(vm.$el.querySelector('.diff-changed-stats')).not.toBe(null);
done();
});
});
});
......@@ -85,56 +76,52 @@ describe('File finder item spec', () => {
describe('path', () => {
let el;
beforeEach((done) => {
beforeEach(async () => {
vm.searchText = 'file';
el = vm.$el.querySelector('.diff-changed-file-path');
vm.$nextTick(done);
nextTick();
});
it('highlights text', () => {
expect(el.querySelectorAll('.highlighted').length).toBe(4);
});
it('adds ellipsis to long text', (done) => {
it('adds ellipsis to long text', async () => {
vm.file.path = new Array(70)
.fill()
.map((_, i) => `${i}-`)
.join('');
vm.$nextTick(() => {
await nextTick();
expect(el.textContent).toBe(`...${vm.file.path.substr(vm.file.path.length - 60)}`);
done();
});
});
});
describe('name', () => {
let el;
beforeEach((done) => {
beforeEach(async () => {
vm.searchText = 'file';
el = vm.$el.querySelector('.diff-changed-file-name');
vm.$nextTick(done);
await nextTick();
});
it('highlights text', () => {
expect(el.querySelectorAll('.highlighted').length).toBe(4);
});
it('does not add ellipsis to long text', (done) => {
it('does not add ellipsis to long text', async () => {
vm.file.name = new Array(70)
.fill()
.map((_, i) => `${i}-`)
.join('');
vm.$nextTick(() => {
await nextTick();
expect(el.textContent).not.toBe(`...${vm.file.name.substr(vm.file.name.length - 60)}`);
done();
});
});
});
});
import { GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
import GlModalVuex from '~/vue_shared/components/gl_modal_vuex.vue';
......@@ -118,7 +118,7 @@ describe('GlModalVuex', () => {
expect(actions.hide).toHaveBeenCalledTimes(1);
});
it('calls bootstrap show when isVisible changes', (done) => {
it('calls bootstrap show when isVisible changes', async () => {
state.isVisible = false;
factory();
......@@ -126,16 +126,11 @@ describe('GlModalVuex', () => {
state.isVisible = true;
wrapper.vm
.$nextTick()
.then(() => {
await nextTick();
expect(rootEmit).toHaveBeenCalledWith(BV_SHOW_MODAL, TEST_MODAL_ID);
})
.then(done)
.catch(done.fail);
});
it('calls bootstrap hide when isVisible changes', (done) => {
it('calls bootstrap hide when isVisible changes', async () => {
state.isVisible = true;
factory();
......@@ -143,13 +138,8 @@ describe('GlModalVuex', () => {
state.isVisible = false;
wrapper.vm
.$nextTick()
.then(() => {
await nextTick();
expect(rootEmit).toHaveBeenCalledWith(BV_HIDE_MODAL, TEST_MODAL_ID);
})
.then(done)
.catch(done.fail);
});
it.each(['ok', 'cancel'])(
......
......@@ -100,117 +100,102 @@ describe('Markdown field component', () => {
axiosMock.onPost(markdownPreviewPath).reply(200, { body: previewHTML });
});
it('sets preview link as active', () => {
it('sets preview link as active', async () => {
previewLink = getPreviewLink();
previewLink.trigger('click');
return subject.vm.$nextTick().then(() => {
await nextTick();
expect(previewLink.element.parentNode.classList.contains('active')).toBeTruthy();
});
});
it('shows preview loading text', () => {
it('shows preview loading text', async () => {
previewLink = getPreviewLink();
previewLink.trigger('click');
return subject.vm.$nextTick(() => {
expect(subject.find('.md-preview-holder').element.textContent.trim()).toContain(
'Loading…',
);
});
await nextTick();
expect(subject.find('.md-preview-holder').element.textContent.trim()).toContain('Loading…');
});
it('renders markdown preview and GFM', () => {
it('renders markdown preview and GFM', async () => {
const renderGFMSpy = jest.spyOn($.fn, 'renderGFM');
previewLink = getPreviewLink();
previewLink.trigger('click');
return axios.waitFor(markdownPreviewPath).then(() => {
await axios.waitFor(markdownPreviewPath);
expect(subject.find('.md-preview-holder').element.innerHTML).toContain(previewHTML);
expect(renderGFMSpy).toHaveBeenCalled();
});
});
it('calls video.pause() on comment input when isSubmitting is changed to true', () => {
it('calls video.pause() on comment input when isSubmitting is changed to true', async () => {
previewLink = getPreviewLink();
previewLink.trigger('click');
let callPause;
return axios
.waitFor(markdownPreviewPath)
.then(() => {
await axios.waitFor(markdownPreviewPath);
const video = getVideo();
callPause = jest.spyOn(video.element, 'pause').mockImplementation(() => true);
const callPause = jest.spyOn(video.element, 'pause').mockImplementation(() => true);
subject.setProps({ isSubmitting: true });
return subject.vm.$nextTick();
})
.then(() => {
await nextTick();
expect(callPause).toHaveBeenCalled();
});
});
it('clicking already active write or preview link does nothing', async () => {
writeLink = getWriteLink();
previewLink = getPreviewLink();
writeLink.trigger('click');
await subject.vm.$nextTick();
await nextTick();
assertMarkdownTabs(true, writeLink, previewLink, subject);
writeLink.trigger('click');
await subject.vm.$nextTick();
await nextTick();
assertMarkdownTabs(true, writeLink, previewLink, subject);
previewLink.trigger('click');
await subject.vm.$nextTick();
await nextTick();
assertMarkdownTabs(false, writeLink, previewLink, subject);
previewLink.trigger('click');
await subject.vm.$nextTick();
await nextTick();
assertMarkdownTabs(false, writeLink, previewLink, subject);
});
});
describe('markdown buttons', () => {
it('converts single words', () => {
it('converts single words', async () => {
const textarea = subject.find('textarea').element;
textarea.setSelectionRange(0, 7);
const markdownButton = getMarkdownButton();
markdownButton.trigger('click');
return subject.vm.$nextTick(() => {
await nextTick();
expect(textarea.value).toContain('**testing**');
});
});
it('converts a line', () => {
it('converts a line', async () => {
const textarea = subject.find('textarea').element;
textarea.setSelectionRange(0, 0);
const markdownButton = getAllMarkdownButtons().wrappers[5];
markdownButton.trigger('click');
return subject.vm.$nextTick(() => {
await nextTick();
expect(textarea.value).toContain('- testing');
});
});
it('converts multiple lines', () => {
it('converts multiple lines', async () => {
const textarea = subject.find('textarea').element;
textarea.setSelectionRange(0, 50);
const markdownButton = getAllMarkdownButtons().wrappers[5];
markdownButton.trigger('click');
return subject.vm.$nextTick(() => {
await nextTick();
expect(textarea.value).toContain('- testing\n- 123');
});
});
});
it('should render attach a file button', () => {
expect(getAttachButton().text()).toBe('Attach a file');
......@@ -229,7 +214,7 @@ describe('Markdown field component', () => {
// Do something to trigger rerendering the class
subject.setProps({ wrapperClasses: 'foo' });
await subject.vm.$nextTick();
await nextTick();
});
it('should have rerendered classes and kept gfm-form', () => {
......
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import { projectData } from 'jest/ide/mock_data';
import { TEST_HOST } from 'spec/test_constants';
......@@ -19,7 +19,7 @@ describe('ProjectAvatarDefault component', () => {
vm.$destroy();
});
it('renders identicon if project has no avatar_url', (done) => {
it('renders identicon if project has no avatar_url', async () => {
const expectedText = getFirstCharacterCapitalized(projectData.name);
vm.project = {
......@@ -27,18 +27,14 @@ describe('ProjectAvatarDefault component', () => {
avatar_url: null,
};
vm.$nextTick()
.then(() => {
await nextTick();
const identiconEl = vm.$el.querySelector('.identicon');
expect(identiconEl).not.toBe(null);
expect(identiconEl.textContent.trim()).toEqual(expectedText);
})
.then(done)
.catch(done.fail);
});
it('renders avatar image if project has avatar_url', (done) => {
it('renders avatar image if project has avatar_url', async () => {
const avatarUrl = `${TEST_HOST}/images/home/nasa.svg`;
vm.project = {
......@@ -46,13 +42,9 @@ describe('ProjectAvatarDefault component', () => {
avatar_url: avatarUrl,
};
vm.$nextTick()
.then(() => {
await nextTick();
expect(vm.$el.querySelector('.avatar')).not.toBeNull();
expect(vm.$el.querySelector('.identicon')).toBeNull();
expect(vm.$el.querySelector('img')).toHaveAttr('src', avatarUrl);
})
.then(done)
.catch(done.fail);
});
});
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import IssuableBulkEditSidebar from '~/vue_shared/issuable/list/components/issuable_bulk_edit_sidebar.vue';
const createComponent = ({ expanded = true } = {}) =>
......@@ -48,7 +49,7 @@ describe('IssuableBulkEditSidebar', () => {
expanded,
});
await wrappeCustom.vm.$nextTick();
await nextTick();
expect(document.querySelector('.layout-page').classList.contains(layoutPageClass)).toBe(
true,
......@@ -78,7 +79,7 @@ describe('IssuableBulkEditSidebar', () => {
expanded,
});
await wrappeCustom.vm.$nextTick();
await nextTick();
expect(wrappeCustom.classes()).toContain(layoutPageClass);
......
import { nextTick } from 'vue';
import { setTestTimeout } from 'helpers/timeout';
import waitForPromises from 'helpers/wait_for_promises';
import { waitForText } from 'helpers/wait_for_text';
......@@ -134,7 +135,7 @@ describe('WebIDE', () => {
describe('when editor position changes', () => {
beforeEach(async () => {
editor.setPosition({ lineNumber: 4, column: 10 });
await vm.$nextTick();
await nextTick();
});
it('shows new line position', () => {
......@@ -145,7 +146,7 @@ describe('WebIDE', () => {
it('updates after rename', async () => {
await ideHelper.renameFile('README.md', 'READMEZ.txt');
await ideHelper.waitForEditorModelChange(editor);
await vm.$nextTick();
await nextTick();
expect(statusBar).toHaveText('1:1');
expect(statusBar).toHaveText('plaintext');
......@@ -166,7 +167,7 @@ describe('WebIDE', () => {
await ideHelper.closeFile('README.md');
await ideHelper.openFile('README.md');
await ideHelper.waitForMonacoEditor();
await vm.$nextTick();
await nextTick();
expect(statusBar).toHaveText('4:10');
expect(statusBar).toHaveText('markdown');
......
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