Commit bbbc58a1 authored by Martin Wortschack's avatar Martin Wortschack

Merge branch 'xanf-vtu-30-mount' into 'master'

Fix shallowMount + stubs behavior change in `@vue/test-utils`

Closes #145615

See merge request gitlab-org/gitlab!22286
parents ebb9d17d 973e0e31
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`packages_list renders 1`] = `
<div
class="d-flex flex-column align-items-end"
>
<glsorting-stub
class="my-3"
isascending="true"
sortdirectiontooltip="Sort direction"
text="Name"
>
<div>
Name
</div>
<div>
Version
</div>
<div>
Type
</div>
<div>
Created
</div>
</glsorting-stub>
<table
aria-busy="false"
aria-colcount="5"
aria-describedby="__BVID__9__caption_"
class="table b-table gl-table b-table-stacked-md"
id="__BVID__9"
role="table"
>
<!---->
<!---->
<thead
class=""
role="rowgroup"
>
<!---->
<tr
role="row"
>
<th
aria-colindex="1"
class="text-left"
role="columnheader"
scope="col"
>
Name
</th>
<th
aria-colindex="2"
class="text-center"
role="columnheader"
scope="col"
>
Version
</th>
<th
aria-colindex="3"
class="text-center"
role="columnheader"
scope="col"
>
Type
</th>
<th
aria-colindex="4"
class="text-center"
role="columnheader"
scope="col"
>
Created
</th>
<th
aria-colindex="5"
aria-label="Actions"
class=""
role="columnheader"
scope="col"
>
</th>
</tr>
</thead>
<!---->
<tbody
class=""
role="rowgroup"
>
<!---->
<tr
class=""
role="row"
>
<td
aria-colindex="1"
class="text-left"
data-label="Name"
role="cell"
>
<div>
<div
class="flex-truncate-parent"
>
<a
class="flex-truncate-child"
data-qa-selector="package_link"
href="#"
>
Test package
</a>
</div>
</div>
</td>
<td
aria-colindex="2"
class="text-center"
data-label="Version"
role="cell"
>
<div>
1.0.0
</div>
</td>
<td
aria-colindex="3"
class="text-center"
data-label="Type"
role="cell"
>
<div>
maven
</div>
</td>
<td
aria-colindex="4"
class="text-center"
data-label="Created"
role="cell"
>
<div>
<timeagotooltip-stub
cssclass=""
time=""
tooltipplacement="top"
/>
</div>
</td>
<td
aria-colindex="5"
class="text-right"
data-label=""
role="cell"
>
<div>
<glbutton-stub
aria-label="Remove package"
title="Remove package"
variant="danger"
>
<icon-stub
name="remove"
size="16"
/>
</glbutton-stub>
</div>
</td>
</tr>
<tr
class=""
role="row"
>
<td
aria-colindex="1"
class="text-left"
data-label="Name"
role="cell"
>
<div>
<div
class="flex-truncate-parent"
>
<a
class="flex-truncate-child"
data-qa-selector="package_link"
href="#"
>
@Test/package
</a>
</div>
</div>
</td>
<td
aria-colindex="2"
class="text-center"
data-label="Version"
role="cell"
>
<div>
</div>
</td>
<td
aria-colindex="3"
class="text-center"
data-label="Type"
role="cell"
>
<div>
npm
</div>
</td>
<td
aria-colindex="4"
class="text-center"
data-label="Created"
role="cell"
>
<div>
<timeagotooltip-stub
cssclass=""
time=""
tooltipplacement="top"
/>
</div>
</td>
<td
aria-colindex="5"
class="text-right"
data-label=""
role="cell"
>
<div>
<glbutton-stub
aria-label="Remove package"
title="Remove package"
variant="danger"
>
<icon-stub
name="remove"
size="16"
/>
</glbutton-stub>
</div>
</td>
</tr>
<!---->
<!---->
</tbody>
</table>
<glpagination-stub
align="center"
class="w-100"
ellipsistext="…"
labelfirstpage="Go to first page"
labellastpage="Go to last page"
labelnextpage="Go to next page"
labelpage="function _default(page) {
return \\"Go to page \\".concat(page);
}"
labelprevpage="Go to previous page"
limits="[object Object]"
nexttext="Next ›"
perpage="1"
prevtext="‹ Prev"
totalitems="1"
value="1"
/>
<glmodal-stub
modalclass=""
modalid="confirm-delete-pacakge"
ok-variant="danger"
titletag="h4"
>
<p />
</glmodal-stub>
</div>
`;
import Vue from 'vue'; import Vue from 'vue';
import _ from 'underscore'; import _ from 'underscore';
import { shallowMount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import { GlTable } from '@gitlab/ui';
import PackagesList from 'ee/packages/list/components/packages_list.vue'; import PackagesList from 'ee/packages/list/components/packages_list.vue';
import stubChildren from 'helpers/stub_children';
import { packageList } from '../../mock_data'; import { packageList } from '../../mock_data';
describe('packages_list', () => { describe('packages_list', () => {
...@@ -16,9 +16,10 @@ describe('packages_list', () => { ...@@ -16,9 +16,10 @@ describe('packages_list', () => {
const findSortingItems = () => wrapper.findAll({ name: 'sorting-item-stub' }); const findSortingItems = () => wrapper.findAll({ name: 'sorting-item-stub' });
const findFirstProjectColumn = () => wrapper.find({ ref: 'col-project' }); const findFirstProjectColumn = () => wrapper.find({ ref: 'col-project' });
const defaultShallowMountOptions = { const mountOptions = {
stubs: { stubs: {
GlTable, ...stubChildren(PackagesList),
GlTable: false,
GlSortingItem: { name: 'sorting-item-stub', template: '<div><slot></slot></div>' }, GlSortingItem: { name: 'sorting-item-stub', template: '<div><slot></slot></div>' },
}, },
computed: { computed: {
...@@ -35,7 +36,7 @@ describe('packages_list', () => { ...@@ -35,7 +36,7 @@ describe('packages_list', () => {
// This is needed due to console.error called by vue to emit a warning that stop the tests // This is needed due to console.error called by vue to emit a warning that stop the tests
// see https://github.com/vuejs/vue-test-utils/issues/532 // see https://github.com/vuejs/vue-test-utils/issues/532
Vue.config.silent = true; Vue.config.silent = true;
wrapper = shallowMount(PackagesList, defaultShallowMountOptions); wrapper = mount(PackagesList, mountOptions);
}); });
afterEach(() => { afterEach(() => {
...@@ -43,16 +44,12 @@ describe('packages_list', () => { ...@@ -43,16 +44,12 @@ describe('packages_list', () => {
wrapper.destroy(); wrapper.destroy();
}); });
it('renders', () => {
expect(wrapper.element).toMatchSnapshot();
});
describe('when is isGroupPage', () => { describe('when is isGroupPage', () => {
beforeEach(() => { beforeEach(() => {
wrapper = shallowMount(PackagesList, { wrapper = mount(PackagesList, {
...defaultShallowMountOptions, ...mountOptions,
computed: { computed: {
...defaultShallowMountOptions.computed, ...mountOptions.computed,
canDestroyPackage: () => false, canDestroyPackage: () => false,
isGroupPage: () => true, isGroupPage: () => true,
}, },
...@@ -86,9 +83,9 @@ describe('packages_list', () => { ...@@ -86,9 +83,9 @@ describe('packages_list', () => {
describe('when user can not destroy the package', () => { describe('when user can not destroy the package', () => {
beforeEach(() => { beforeEach(() => {
wrapper = shallowMount(PackagesList, { wrapper = mount(PackagesList, {
...defaultShallowMountOptions, ...mountOptions,
computed: { ...defaultShallowMountOptions.computed, canDestroyPackage: () => false }, computed: { ...mountOptions.computed, canDestroyPackage: () => false },
}); });
}); });
...@@ -148,8 +145,8 @@ describe('packages_list', () => { ...@@ -148,8 +145,8 @@ describe('packages_list', () => {
const findEmptySlot = () => wrapper.find({ name: 'empty-slot-stub' }); const findEmptySlot = () => wrapper.find({ name: 'empty-slot-stub' });
beforeEach(() => { beforeEach(() => {
wrapper = shallowMount(PackagesList, { wrapper = mount(PackagesList, {
...defaultShallowMountOptions, ...mountOptions,
computed: { list: () => [] }, computed: { list: () => [] },
slots: { slots: {
'empty-state': { name: 'empty-slot-stub', template: '<div>bar</div>' }, 'empty-state': { name: 'empty-slot-stub', template: '<div>bar</div>' },
......
import Vuex from 'vuex'; import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils'; import { mount, createLocalVue } from '@vue/test-utils';
import { GlTable } from '@gitlab/ui';
import { GlSparklineChart } from '@gitlab/ui/dist/charts'; import { GlSparklineChart } from '@gitlab/ui/dist/charts';
import stubChildren from 'helpers/stub_children';
import SeverityBadge from 'ee/vue_shared/security_reports/components/severity_badge.vue'; import SeverityBadge from 'ee/vue_shared/security_reports/components/severity_badge.vue';
import Chart from 'ee/security_dashboard/components/vulnerability_chart.vue'; import Chart from 'ee/security_dashboard/components/vulnerability_chart.vue';
import ChartButtons from 'ee/security_dashboard/components/vulnerability_chart_buttons.vue'; import ChartButtons from 'ee/security_dashboard/components/vulnerability_chart_buttons.vue';
...@@ -27,7 +27,7 @@ describe('Vulnerability Chart component', () => { ...@@ -27,7 +27,7 @@ describe('Vulnerability Chart component', () => {
const findCurrentVulnerabilitiesCount = () => const findCurrentVulnerabilitiesCount = () =>
wrapper.find({ ref: 'currentVulnerabilitiesCount' }); wrapper.find({ ref: 'currentVulnerabilitiesCount' });
const factory = ({ vulnerabilitiesCount = [] } = {}) => { const factory = ({ vulnerabilitiesCount = [], stubs = {} } = {}) => {
actions = { actions = {
setVulnerabilitiesHistoryDayRange: jest.fn(), setVulnerabilitiesHistoryDayRange: jest.fn(),
}; };
...@@ -55,10 +55,13 @@ describe('Vulnerability Chart component', () => { ...@@ -55,10 +55,13 @@ describe('Vulnerability Chart component', () => {
}, },
}); });
wrapper = shallowMount(Chart, { wrapper = mount(Chart, {
localVue, localVue,
store, store,
stubs: { GlTable }, stubs: {
...stubChildren(Chart),
...stubs,
},
sync: false, sync: false,
}); });
}; };
...@@ -112,7 +115,9 @@ describe('Vulnerability Chart component', () => { ...@@ -112,7 +115,9 @@ describe('Vulnerability Chart component', () => {
describe.each(['Critical', 'Medium', 'High', 'Low'])( describe.each(['Critical', 'Medium', 'High', 'Low'])(
'for the given severity level "%s"', 'for the given severity level "%s"',
severityLevel => { severityLevel => {
beforeEach(factory); beforeEach(() => {
factory({ stubs: { GlTable: false } });
});
it('shows a severity badge', () => { it('shows a severity badge', () => {
expect(findSeverityBadgeForLevel(severityLevel).exists()).toBe(true); expect(findSeverityBadgeForLevel(severityLevel).exists()).toBe(true);
...@@ -135,6 +140,9 @@ describe('Vulnerability Chart component', () => { ...@@ -135,6 +140,9 @@ describe('Vulnerability Chart component', () => {
({ countPast, countCurrent, expectedOutput }) => { ({ countPast, countCurrent, expectedOutput }) => {
factory({ factory({
vulnerabilitiesCount: [countPast, countCurrent], vulnerabilitiesCount: [countPast, countCurrent],
stubs: {
GlTable: false,
},
}); });
expect(findChangeInPercent().text()).toBe(expectedOutput); expect(findChangeInPercent().text()).toBe(expectedOutput);
...@@ -145,7 +153,7 @@ describe('Vulnerability Chart component', () => { ...@@ -145,7 +153,7 @@ describe('Vulnerability Chart component', () => {
vulnerabilitiesCount | expectedOutput vulnerabilitiesCount | expectedOutput
${[1, 2, 3]} | ${'3'} ${[1, 2, 3]} | ${'3'}
`('shows the current vulnerabilities count', ({ vulnerabilitiesCount, expectedOutput }) => { `('shows the current vulnerabilities count', ({ vulnerabilitiesCount, expectedOutput }) => {
factory({ vulnerabilitiesCount }); factory({ vulnerabilitiesCount, stubs: { GlTable: false } });
expect(findCurrentVulnerabilitiesCount().text()).toBe(expectedOutput); expect(findCurrentVulnerabilitiesCount().text()).toBe(expectedOutput);
}); });
}); });
......
import { createLocalVue, shallowMount } from '@vue/test-utils'; import { createLocalVue, mount } from '@vue/test-utils';
import Vuex from 'vuex'; import Vuex from 'vuex';
import { import { GlEmptyState, GlLoadingIcon, GlFormInput, GlPagination } from '@gitlab/ui';
GlEmptyState, import stubChildren from 'helpers/stub_children';
GlLoadingIcon,
GlTable,
GlLink,
GlFormInput,
GlDropdown,
GlDropdownItem,
GlPagination,
} from '@gitlab/ui';
import ErrorTrackingList from '~/error_tracking/components/error_tracking_list.vue'; import ErrorTrackingList from '~/error_tracking/components/error_tracking_list.vue';
import errorsList from './list_mock.json'; import errorsList from './list_mock.json';
...@@ -32,19 +24,12 @@ describe('ErrorTrackingList', () => { ...@@ -32,19 +24,12 @@ describe('ErrorTrackingList', () => {
function mountComponent({ function mountComponent({
errorTrackingEnabled = true, errorTrackingEnabled = true,
userCanEnableErrorTracking = true, userCanEnableErrorTracking = true,
sync = true, stubs = {},
stubs = {
'gl-link': GlLink,
'gl-table': GlTable,
'gl-pagination': GlPagination,
'gl-dropdown': GlDropdown,
'gl-dropdown-item': GlDropdownItem,
},
} = {}) { } = {}) {
wrapper = shallowMount(ErrorTrackingList, { wrapper = mount(ErrorTrackingList, {
localVue, localVue,
store, store,
sync, sync: false,
propsData: { propsData: {
indexPath: '/path', indexPath: '/path',
enableErrorTrackingLink: '/link', enableErrorTrackingLink: '/link',
...@@ -52,7 +37,10 @@ describe('ErrorTrackingList', () => { ...@@ -52,7 +37,10 @@ describe('ErrorTrackingList', () => {
errorTrackingEnabled, errorTrackingEnabled,
illustrationPath: 'illustration/path', illustrationPath: 'illustration/path',
}, },
stubs, stubs: {
...stubChildren(ErrorTrackingList),
...stubs,
},
data() { data() {
return { errorSearchQuery: 'search' }; return { errorSearchQuery: 'search' };
}, },
...@@ -122,7 +110,14 @@ describe('ErrorTrackingList', () => { ...@@ -122,7 +110,14 @@ describe('ErrorTrackingList', () => {
beforeEach(() => { beforeEach(() => {
store.state.list.loading = false; store.state.list.loading = false;
store.state.list.errors = errorsList; store.state.list.errors = errorsList;
mountComponent(); mountComponent({
stubs: {
GlTable: false,
GlDropdown: false,
GlDropdownItem: false,
GlLink: false,
},
});
}); });
it('shows table', () => { it('shows table', () => {
...@@ -173,7 +168,13 @@ describe('ErrorTrackingList', () => { ...@@ -173,7 +168,13 @@ describe('ErrorTrackingList', () => {
store.state.list.loading = false; store.state.list.loading = false;
store.state.list.errors = []; store.state.list.errors = [];
mountComponent(); mountComponent({
stubs: {
GlTable: false,
GlDropdown: false,
GlDropdownItem: false,
},
});
}); });
it('shows empty table', () => { it('shows empty table', () => {
...@@ -187,7 +188,7 @@ describe('ErrorTrackingList', () => { ...@@ -187,7 +188,7 @@ describe('ErrorTrackingList', () => {
}); });
it('restarts polling', () => { it('restarts polling', () => {
findRefreshLink().trigger('click'); findRefreshLink().vm.$emit('click');
expect(actions.restartPolling).toHaveBeenCalled(); expect(actions.restartPolling).toHaveBeenCalled();
}); });
}); });
...@@ -211,8 +212,8 @@ describe('ErrorTrackingList', () => { ...@@ -211,8 +212,8 @@ describe('ErrorTrackingList', () => {
errorTrackingEnabled: false, errorTrackingEnabled: false,
userCanEnableErrorTracking: false, userCanEnableErrorTracking: false,
stubs: { stubs: {
'gl-link': GlLink, GlLink: false,
'gl-empty-state': GlEmptyState, GlEmptyState: false,
}, },
}); });
}); });
...@@ -226,7 +227,12 @@ describe('ErrorTrackingList', () => { ...@@ -226,7 +227,12 @@ describe('ErrorTrackingList', () => {
describe('recent searches', () => { describe('recent searches', () => {
beforeEach(() => { beforeEach(() => {
mountComponent(); mountComponent({
stubs: {
GlDropdown: false,
GlDropdownItem: false,
},
});
}); });
it('shows empty message', () => { it('shows empty message', () => {
...@@ -238,12 +244,13 @@ describe('ErrorTrackingList', () => { ...@@ -238,12 +244,13 @@ describe('ErrorTrackingList', () => {
it('shows items', () => { it('shows items', () => {
store.state.list.recentSearches = ['great', 'search']; store.state.list.recentSearches = ['great', 'search'];
return wrapper.vm.$nextTick().then(() => {
const dropdownItems = wrapper.findAll('.filtered-search-box li'); const dropdownItems = wrapper.findAll('.filtered-search-box li');
expect(dropdownItems.length).toBe(3); expect(dropdownItems.length).toBe(3);
expect(dropdownItems.at(0).text()).toBe('great'); expect(dropdownItems.at(0).text()).toBe('great');
expect(dropdownItems.at(1).text()).toBe('search'); expect(dropdownItems.at(1).text()).toBe('search');
}); });
});
describe('clear', () => { describe('clear', () => {
const clearRecentButton = () => wrapper.find({ ref: 'clearRecentSearches' }); const clearRecentButton = () => wrapper.find({ ref: 'clearRecentSearches' });
...@@ -257,19 +264,23 @@ describe('ErrorTrackingList', () => { ...@@ -257,19 +264,23 @@ describe('ErrorTrackingList', () => {
it('is visible when list has items', () => { it('is visible when list has items', () => {
store.state.list.recentSearches = ['some', 'searches']; store.state.list.recentSearches = ['some', 'searches'];
return wrapper.vm.$nextTick().then(() => {
expect(clearRecentButton().exists()).toBe(true); expect(clearRecentButton().exists()).toBe(true);
expect(clearRecentButton().text()).toBe('Clear recent searches'); expect(clearRecentButton().text()).toBe('Clear recent searches');
}); });
});
it('clears items on click', () => { it('clears items on click', () => {
store.state.list.recentSearches = ['some', 'searches']; store.state.list.recentSearches = ['some', 'searches'];
return wrapper.vm.$nextTick().then(() => {
clearRecentButton().vm.$emit('click'); clearRecentButton().vm.$emit('click');
expect(actions.clearRecentSearches).toHaveBeenCalledTimes(1); expect(actions.clearRecentSearches).toHaveBeenCalledTimes(1);
}); });
}); });
}); });
});
describe('When pagination is not required', () => { describe('When pagination is not required', () => {
beforeEach(() => { beforeEach(() => {
...@@ -287,7 +298,11 @@ describe('ErrorTrackingList', () => { ...@@ -287,7 +298,11 @@ describe('ErrorTrackingList', () => {
describe('and the user is on the first page', () => { describe('and the user is on the first page', () => {
beforeEach(() => { beforeEach(() => {
store.state.list.loading = false; store.state.list.loading = false;
mountComponent({ sync: false }); mountComponent({
stubs: {
GlPagination: false,
},
});
}); });
it('shows a disabled Prev button', () => { it('shows a disabled Prev button', () => {
...@@ -299,8 +314,14 @@ describe('ErrorTrackingList', () => { ...@@ -299,8 +314,14 @@ describe('ErrorTrackingList', () => {
describe('and the previous button is clicked', () => { describe('and the previous button is clicked', () => {
beforeEach(() => { beforeEach(() => {
store.state.list.loading = false; store.state.list.loading = false;
mountComponent({ sync: false }); mountComponent({
stubs: {
GlTable: false,
GlPagination: false,
},
});
wrapper.setData({ pageValue: 2 }); wrapper.setData({ pageValue: 2 });
return wrapper.vm.$nextTick();
}); });
it('fetches the previous page of results', () => { it('fetches the previous page of results', () => {
...@@ -318,7 +339,7 @@ describe('ErrorTrackingList', () => { ...@@ -318,7 +339,7 @@ describe('ErrorTrackingList', () => {
describe('and the next page button is clicked', () => { describe('and the next page button is clicked', () => {
beforeEach(() => { beforeEach(() => {
store.state.list.loading = false; store.state.list.loading = false;
mountComponent({ sync: false }); mountComponent();
}); });
it('fetches the next page of results', () => { it('fetches the next page of results', () => {
......
export default function stubChildren(Component) {
return Object.fromEntries(Object.keys(Component.components).map(c => [c, true]));
}
import { shallowMount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import UserModalManager from '~/pages/admin/users/components/user_modal_manager.vue'; import UserModalManager from '~/pages/admin/users/components/user_modal_manager.vue';
import ModalStub from './stubs/modal_stub'; import ModalStub from './stubs/modal_stub';
...@@ -22,17 +22,13 @@ describe('Users admin page Modal Manager', () => { ...@@ -22,17 +22,13 @@ describe('Users admin page Modal Manager', () => {
let wrapper; let wrapper;
const createComponent = (props = {}) => { const createComponent = (props = {}) => {
wrapper = shallowMount(UserModalManager, { wrapper = mount(UserModalManager, {
propsData: { propsData: {
actionModals, actionModals,
modalConfiguration, modalConfiguration,
csrfToken: 'dummyCSRF', csrfToken: 'dummyCSRF',
...props, ...props,
}, },
stubs: {
dummyComponent1: true,
dummyComponent2: true,
},
sync: false, sync: false,
}); });
}; };
......
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