Commit 047f4c6a authored by Zack Cuddy's avatar Zack Cuddy

Refactor some Geo Node tests with vue-test-utils

This MR is split off from:
https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27033

In the above MR we implement GlPopover.  However,
in doing so there are problems with fully mounting it.

Using shallowMount and stubbing it fixes the problem,
however, the affected tests were written without
vue-test-utils and thus cannot shallowMount.

This MR simply rewrites the impacted tests with
vue-test-utils and shallowMounts the components.
parent 1438907f
import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
import Icon from '~/vue_shared/components/icon.vue';
import StackedProgressBar from '~/vue_shared/components/stacked_progress_bar.vue';
import GeoNodeDetailItemComponent from 'ee/geo_nodes/components/geo_node_detail_item.vue';
import GeoNodeSyncSettings from 'ee/geo_nodes/components/geo_node_sync_settings.vue';
import GeoNodeEventStatus from 'ee/geo_nodes/components/geo_node_event_status.vue';
import geoNodeDetailItemComponent from 'ee/geo_nodes/components/geo_node_detail_item.vue';
import { VALUE_TYPE, CUSTOM_TYPE } from 'ee/geo_nodes/constants';
import mountComponent from 'helpers/vue_mount_component_helper';
import { rawMockNodeDetails } from '../mock_data';
const createComponent = config => {
const Component = Vue.extend(geoNodeDetailItemComponent);
const defaultConfig = Object.assign(
{
itemTitle: 'GitLab version',
cssClass: 'node-version',
itemValue: '10.4.0-pre',
successLabel: 'Synced',
failureLabel: 'Failed',
neutralLabel: 'Out of sync',
itemValueType: VALUE_TYPE.PLAIN,
},
config,
);
return mountComponent(Component, defaultConfig);
};
describe('GeoNodeDetailItemComponent', () => {
describe('template', () => {
it('renders container elements correctly', () => {
const vm = createComponent();
expect(vm.$el.classList.contains('node-detail-item')).toBeTruthy();
expect(vm.$el.querySelectorAll('.node-detail-title').length).not.toBe(0);
expect(vm.$el.querySelector('.node-detail-title').innerText.trim()).toBe('GitLab version');
vm.$destroy();
let wrapper;
const defaultProps = {
itemTitle: 'GitLab version',
cssClass: 'node-version',
itemValue: '10.4.0-pre',
successLabel: 'Synced',
failureLabel: 'Failed',
neutralLabel: 'Out of sync',
itemValueType: VALUE_TYPE.PLAIN,
};
const createComponent = (props = {}) => {
wrapper = shallowMount(GeoNodeDetailItemComponent, {
propsData: {
...defaultProps,
...props,
},
});
};
it('renders plain item value', () => {
const vm = createComponent();
afterEach(() => {
wrapper.destroy();
});
expect(vm.$el.querySelectorAll('.node-detail-value').length).not.toBe(0);
expect(vm.$el.querySelector('.node-detail-value').innerText.trim()).toBe('10.4.0-pre');
vm.$destroy();
describe('template', () => {
beforeEach(() => {
createComponent();
});
it('renders item title help info icon and popover with help info', () => {
const helpInfo = {
title: 'Foo title tooltip',
url: 'https://docs.gitlab.com',
urlText: 'Help',
};
const vm = createComponent({ helpInfo });
const helpTextIconEl = vm.$el.querySelector('.node-detail-help-text');
expect(helpTextIconEl).not.toBeNull();
expect(helpTextIconEl.querySelector('use').getAttribute('xlink:href')).toContain('question');
vm.$destroy();
it('renders container elements correctly', () => {
expect(wrapper.vm.$el.classList.contains('node-detail-item')).toBeTruthy();
expect(wrapper.vm.$el.querySelectorAll('.node-detail-title').length).not.toBe(0);
expect(wrapper.vm.$el.querySelector('.node-detail-title').innerText.trim()).toBe(
'GitLab version',
);
});
it('renders graph item value', () => {
const vm = createComponent({
itemValueType: VALUE_TYPE.GRAPH,
itemValue: { successCount: 5, failureCount: 3, totalCount: 10 },
it('renders plain item value', () => {
expect(wrapper.vm.$el.querySelectorAll('.node-detail-value').length).not.toBe(0);
expect(wrapper.vm.$el.querySelector('.node-detail-value').innerText.trim()).toBe(
'10.4.0-pre',
);
});
describe('with help info', () => {
beforeEach(() => {
createComponent({
helpInfo: {
title: 'Foo title tooltip',
url: 'https://docs.gitlab.com',
urlText: 'Help',
},
});
});
expect(vm.$el.querySelectorAll('.stacked-progress-bar').length).not.toBe(0);
vm.$destroy();
it('renders item title help info icon', () => {
const helpTextIconEl = wrapper.find(Icon);
expect(helpTextIconEl.exists()).toBeTruthy();
expect(helpTextIconEl.attributes('name')).toBe('question');
});
});
it('renders stale information status icon when `itemValueStale` prop is true', () => {
const itemValueStaleTooltip = 'Data is out of date from 8 hours ago';
const vm = createComponent({
itemValueType: VALUE_TYPE.GRAPH,
itemValue: { successCount: 5, failureCount: 3, totalCount: 10 },
itemValueStale: true,
itemValueStaleTooltip,
describe('when graph item value', () => {
beforeEach(() => {
createComponent({
itemValueType: VALUE_TYPE.GRAPH,
itemValue: { successCount: 5, failureCount: 3, totalCount: 10 },
});
});
const iconEl = vm.$el.querySelector('.text-warning-500');
it('renders progress bar', () => {
expect(wrapper.find(StackedProgressBar).exists()).toBeTruthy();
});
expect(iconEl).not.toBeNull();
expect(iconEl.dataset.originalTitle).toBe(itemValueStaleTooltip);
expect(iconEl.querySelector('use').getAttribute('xlink:href')).toContain('time-out');
vm.$destroy();
describe('with itemValueStale prop', () => {
const itemValueStaleTooltip = 'Data is out of date from 8 hours ago';
beforeEach(() => {
createComponent({
itemValueType: VALUE_TYPE.GRAPH,
itemValue: { successCount: 5, failureCount: 3, totalCount: 10 },
itemValueStale: true,
itemValueStaleTooltip,
});
});
it('renders stale information icon', () => {
const iconEl = wrapper.find('.text-warning-500');
expect(iconEl).not.toBeNull();
expect(iconEl.attributes('data-original-title')).toBe(itemValueStaleTooltip);
expect(iconEl.attributes('name')).toBe('time-out');
});
});
});
it('renders sync settings item value', () => {
const vm = createComponent({
itemValueType: VALUE_TYPE.CUSTOM,
customType: CUSTOM_TYPE.SYNC,
itemValue: {
namespaces: rawMockNodeDetails.namespaces,
lastEvent: {
id: rawMockNodeDetails.last_event_id,
timeStamp: rawMockNodeDetails.last_event_timestamp,
describe('when custom type is sync', () => {
beforeEach(() => {
createComponent({
itemValueType: VALUE_TYPE.CUSTOM,
customType: CUSTOM_TYPE.SYNC,
itemValue: {
namespaces: rawMockNodeDetails.namespaces,
lastEvent: {
id: rawMockNodeDetails.last_event_id,
timeStamp: rawMockNodeDetails.last_event_timestamp,
},
cursorLastEvent: {
id: rawMockNodeDetails.cursor_last_event_id,
timeStamp: rawMockNodeDetails.cursor_last_event_timestamp,
},
},
cursorLastEvent: {
id: rawMockNodeDetails.cursor_last_event_id,
timeStamp: rawMockNodeDetails.cursor_last_event_timestamp,
},
},
});
});
expect(vm.$el.querySelectorAll('.node-sync-settings').length).not.toBe(0);
vm.$destroy();
it('renders sync settings item value', () => {
expect(wrapper.find(GeoNodeSyncSettings).exists()).toBeTruthy();
});
});
it('renders event status item value', () => {
const vm = createComponent({
itemValueType: VALUE_TYPE.CUSTOM,
customType: CUSTOM_TYPE.EVENT,
itemValue: {
eventId: rawMockNodeDetails.last_event_id,
eventTimeStamp: rawMockNodeDetails.last_event_timestamp,
},
describe('when custom type is event', () => {
beforeEach(() => {
createComponent({
itemValueType: VALUE_TYPE.CUSTOM,
customType: CUSTOM_TYPE.EVENT,
itemValue: {
eventId: rawMockNodeDetails.last_event_id,
eventTimeStamp: rawMockNodeDetails.last_event_timestamp,
},
});
});
expect(vm.$el.querySelectorAll('.event-status-timestamp').length).not.toBe(0);
vm.$destroy();
it('renders event status item value', () => {
expect(wrapper.find(GeoNodeEventStatus).exists()).toBeTruthy();
});
});
it('does not render if featureDisabled is true', () => {
const vm = createComponent({
featureDisabled: true,
describe('when featureDisabled is true', () => {
beforeEach(() => {
createComponent({
featureDisabled: true,
});
});
expect(vm.$el.innerHTML).toBeUndefined();
vm.$destroy();
it('does not render', () => {
expect(wrapper.vm.$el.innerHTML).toBeUndefined();
});
});
});
});
import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
import NodeDetailsSectionSyncComponent from 'ee/geo_nodes/components/node_detail_sections/node_details_section_sync.vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockNodeDetails } from '../../mock_data';
import SectionRevealButton from 'ee/geo_nodes/components/node_detail_sections/section_reveal_button.vue';
const createComponent = (nodeDetails = Object.assign({}, mockNodeDetails)) => {
const Component = Vue.extend(NodeDetailsSectionSyncComponent);
return mountComponent(Component, {
nodeDetails,
});
};
import { mockNode, mockNodeDetails } from '../../mock_data';
describe('NodeDetailsSectionSync', () => {
let vm;
let wrapper;
const propsData = {
node: mockNode,
nodeDetails: mockNodeDetails,
};
const createComponent = () => {
wrapper = shallowMount(NodeDetailsSectionSyncComponent, {
stubs: {
geoNodeSyncProgress: true,
},
propsData,
});
};
beforeEach(() => {
gon.features = gon.features || {};
vm = createComponent();
createComponent();
});
afterEach(() => {
vm.$destroy();
wrapper.destroy();
});
describe('data', () => {
it('returns default data props', () => {
expect(vm.showSectionItems).toBe(false);
expect(Array.isArray(vm.nodeDetailItems)).toBe(true);
expect(vm.nodeDetailItems.length).toBeGreaterThan(0);
expect(wrapper.vm.showSectionItems).toBe(false);
expect(Array.isArray(wrapper.vm.nodeDetailItems)).toBe(true);
expect(wrapper.vm.nodeDetailItems.length).toBeGreaterThan(0);
});
});
describe('methods', () => {
describe('syncSettings', () => {
it('returns sync settings object', done => {
vm.nodeDetails.syncStatusUnavailable = true;
Vue.nextTick()
.then(() => {
const syncSettings = vm.syncSettings();
expect(syncSettings.syncStatusUnavailable).toBe(true);
expect(syncSettings.namespaces).toBe(mockNodeDetails.namespaces);
expect(syncSettings.lastEvent).toBe(mockNodeDetails.lastEvent);
expect(syncSettings.cursorLastEvent).toBe(mockNodeDetails.cursorLastEvent);
})
.then(done)
.catch(done.fail);
it('returns sync settings object', () => {
wrapper.vm.nodeDetails.syncStatusUnavailable = true;
return wrapper.vm.$nextTick(() => {
const syncSettings = wrapper.vm.syncSettings();
expect(syncSettings.syncStatusUnavailable).toBe(true);
expect(syncSettings.namespaces).toBe(mockNodeDetails.namespaces);
expect(syncSettings.lastEvent).toBe(mockNodeDetails.lastEvent);
expect(syncSettings.cursorLastEvent).toBe(mockNodeDetails.cursorLastEvent);
});
});
});
describe('dbReplicationLag', () => {
it('returns DB replication lag time duration', () => {
expect(vm.dbReplicationLag()).toBe('0m');
expect(wrapper.vm.dbReplicationLag()).toBe('0m');
});
it('returns `Unknown` when `dbReplicationLag` is null', done => {
vm.nodeDetails.dbReplicationLag = null;
Vue.nextTick()
.then(() => {
expect(vm.dbReplicationLag()).toBe('Unknown');
})
.then(done)
.catch(done.fail);
it('returns `Unknown` when `dbReplicationLag` is null', () => {
wrapper.vm.nodeDetails.dbReplicationLag = null;
return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.dbReplicationLag()).toBe('Unknown');
});
});
});
describe('lastEventStatus', () => {
it('returns event status object', () => {
expect(vm.lastEventStatus().eventId).toBe(mockNodeDetails.lastEvent.id);
expect(vm.lastEventStatus().eventTimeStamp).toBe(mockNodeDetails.lastEvent.timeStamp);
expect(wrapper.vm.lastEventStatus().eventId).toBe(mockNodeDetails.lastEvent.id);
expect(wrapper.vm.lastEventStatus().eventTimeStamp).toBe(
mockNodeDetails.lastEvent.timeStamp,
);
});
});
describe('cursorLastEventStatus', () => {
it('returns event status object', () => {
expect(vm.cursorLastEventStatus().eventId).toBe(mockNodeDetails.cursorLastEvent.id);
expect(vm.cursorLastEventStatus().eventTimeStamp).toBe(
expect(wrapper.vm.cursorLastEventStatus().eventId).toBe(mockNodeDetails.cursorLastEvent.id);
expect(wrapper.vm.cursorLastEventStatus().eventTimeStamp).toBe(
mockNodeDetails.cursorLastEvent.timeStamp,
);
});
......@@ -85,19 +87,18 @@ describe('NodeDetailsSectionSync', () => {
describe('template', () => {
it('renders component container element', () => {
expect(vm.$el.classList.contains('sync-section')).toBe(true);
expect(wrapper.vm.$el.classList.contains('sync-section')).toBe(true);
});
it('renders show section button element', () => {
expect(vm.$el.querySelector('.btn-link')).not.toBeNull();
expect(vm.$el.querySelector('.btn-link > span').innerText.trim()).toBe('Sync information');
expect(wrapper.find(SectionRevealButton).exists()).toBeTruthy();
expect(wrapper.find(SectionRevealButton).attributes('buttontitle')).toBe('Sync information');
});
it('renders section items container element', done => {
vm.showSectionItems = true;
Vue.nextTick(() => {
expect(vm.$el.querySelector('.section-items-container')).not.toBeNull();
done();
it('renders section items container element', () => {
wrapper.vm.showSectionItems = true;
return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.$el.querySelector('.section-items-container')).not.toBeNull();
});
});
});
......
import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
import NodeDetailsSectionVerificationComponent from 'ee/geo_nodes/components/node_detail_sections/node_details_section_verification.vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import SectionRevealButton from 'ee/geo_nodes/components/node_detail_sections/section_reveal_button.vue';
import { mockNodeDetails } from '../../mock_data';
const createComponent = ({ nodeDetails = mockNodeDetails, nodeTypePrimary = false }) => {
const Component = Vue.extend(NodeDetailsSectionVerificationComponent);
describe('NodeDetailsSectionVerification', () => {
let wrapper;
return mountComponent(Component, {
nodeDetails,
nodeTypePrimary,
});
};
const propsData = {
nodeDetails: mockNodeDetails,
nodeTypePrimary: false,
};
describe('NodeDetailsSectionVerification', () => {
let vm;
const createComponent = () => {
wrapper = shallowMount(NodeDetailsSectionVerificationComponent, {
propsData,
});
};
beforeEach(() => {
vm = createComponent({});
createComponent();
});
afterEach(() => {
vm.$destroy();
wrapper.destroy();
});
describe('data', () => {
it('returns default data props', () => {
expect(vm.showSectionItems).toBe(false);
expect(Array.isArray(vm.primaryNodeDetailItems)).toBe(true);
expect(Array.isArray(vm.secondaryNodeDetailItems)).toBe(true);
expect(vm.primaryNodeDetailItems.length).toBeGreaterThan(0);
expect(vm.secondaryNodeDetailItems.length).toBeGreaterThan(0);
expect(wrapper.vm.showSectionItems).toBe(false);
expect(Array.isArray(wrapper.vm.primaryNodeDetailItems)).toBe(true);
expect(Array.isArray(wrapper.vm.secondaryNodeDetailItems)).toBe(true);
expect(wrapper.vm.primaryNodeDetailItems.length).toBeGreaterThan(0);
expect(wrapper.vm.secondaryNodeDetailItems.length).toBeGreaterThan(0);
});
});
......@@ -48,7 +51,7 @@ describe('NodeDetailsSectionVerification', () => {
];
it('returns array containing items to show under primary node', () => {
const actualPrimaryItems = vm.getPrimaryNodeDetailItems();
const actualPrimaryItems = wrapper.vm.getPrimaryNodeDetailItems();
primaryItems.forEach((item, index) => {
expect(actualPrimaryItems[index].itemTitle).toBe(item.title);
expect(actualPrimaryItems[index].itemValue).toBe(mockNodeDetails[item.valueProp]);
......@@ -69,7 +72,7 @@ describe('NodeDetailsSectionVerification', () => {
];
it('returns array containing items to show under secondary node', () => {
const actualSecondaryItems = vm.getSecondaryNodeDetailItems();
const actualSecondaryItems = wrapper.vm.getSecondaryNodeDetailItems();
secondaryItems.forEach((item, index) => {
expect(actualSecondaryItems[index].itemTitle).toBe(item.title);
expect(actualSecondaryItems[index].itemValue).toBe(mockNodeDetails[item.valueProp]);
......@@ -80,21 +83,20 @@ describe('NodeDetailsSectionVerification', () => {
describe('template', () => {
it('renders component container element', () => {
expect(vm.$el.classList.contains('verification-section')).toBe(true);
expect(wrapper.vm.$el.classList.contains('verification-section')).toBe(true);
});
it('renders show section button element', () => {
expect(vm.$el.querySelector('.btn-link')).not.toBeNull();
expect(vm.$el.querySelector('.btn-link > span').innerText.trim()).toBe(
expect(wrapper.find(SectionRevealButton).exists()).toBeTruthy();
expect(wrapper.find(SectionRevealButton).attributes('buttontitle')).toBe(
'Verification information',
);
});
it('renders section items container element', done => {
vm.showSectionItems = true;
Vue.nextTick(() => {
expect(vm.$el.querySelector('.section-items-container')).not.toBeNull();
done();
it('renders section items container element', () => {
wrapper.vm.showSectionItems = true;
return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.$el.querySelector('.section-items-container')).not.toBeNull();
});
});
});
......
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