Commit 2c5dce71 authored by Andrew Fontaine's avatar Andrew Fontaine

Merge branch '215077-update-roadmap-app-spec-to-use-vue-test-utils' into 'master'

Update RoadmapApp spec to use vue-test-utils

See merge request gitlab-org/gitlab!31004
parents 92ccde67 9e24bc1a
import { mount, shallowMount, createLocalVue } from '@vue/test-utils';
import Vue from 'vue'; import Vue from 'vue';
import Vuex from 'vuex';
import appComponent from 'ee/roadmap/components/roadmap_app.vue'; import EpicsListEmpty from 'ee/roadmap/components/epics_list_empty.vue';
import createStore from 'ee/roadmap/store'; import RoadmapApp from 'ee/roadmap/components/roadmap_app.vue';
import RoadmapShell from 'ee/roadmap/components/roadmap_shell.vue';
import { PRESET_TYPES, EXTEND_AS } from 'ee/roadmap/constants';
import eventHub from 'ee/roadmap/event_hub'; import eventHub from 'ee/roadmap/event_hub';
import createStore from 'ee/roadmap/store';
import * as types from 'ee/roadmap/store/mutation_types';
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils'; import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { PRESET_TYPES, EXTEND_AS } from 'ee/roadmap/constants';
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import { import {
mockTimeframeInitialDate, basePath,
epicsPath,
mockFormattedEpic,
mockGroupId, mockGroupId,
mockNewEpicEndpoint, mockNewEpicEndpoint,
rawEpics,
mockSvgPath,
mockSortedBy, mockSortedBy,
basePath, mockSvgPath,
epicsPath, mockTimeframeInitialDate,
rawEpics,
} from 'ee_jest/roadmap/mock_data'; } from 'ee_jest/roadmap/mock_data';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate); describe('RoadmapApp', () => {
const localVue = createLocalVue();
const createComponent = () => { let store;
const Component = Vue.extend(appComponent); let wrapper;
localVue.use(Vuex);
const currentGroupId = mockGroupId;
const emptyStateIllustrationPath = mockSvgPath;
const epics = [mockFormattedEpic];
const hasFiltersApplied = true;
const newEpicEndpoint = mockNewEpicEndpoint;
const presetType = PRESET_TYPES.MONTHS;
const timeframe = getTimeframeForMonthsView(mockTimeframeInitialDate);
const createComponent = (mountFunction = shallowMount) => {
return mountFunction(RoadmapApp, {
localVue,
propsData: {
emptyStateIllustrationPath,
hasFiltersApplied,
newEpicEndpoint,
presetType,
},
store,
});
};
const store = createStore(); beforeEach(() => {
store.dispatch('setInitialData', { store = createStore();
currentGroupId: mockGroupId, store.dispatch('setInitialData', {
sortedBy: mockSortedBy, currentGroupId,
presetType: PRESET_TYPES.MONTHS, sortedBy: mockSortedBy,
timeframe: mockTimeframeMonths, presetType,
filterQueryString: '', timeframe,
initialEpicsPath: epicsPath, filterQueryString: '',
basePath, initialEpicsPath: epicsPath,
basePath,
});
}); });
return mountComponentWithStore(Component, { afterEach(() => {
store, wrapper.destroy();
props: { wrapper = null;
presetType: PRESET_TYPES.MONTHS,
hasFiltersApplied: true,
newEpicEndpoint: mockNewEpicEndpoint,
emptyStateIllustrationPath: mockSvgPath,
},
}); });
};
describe('Roadmap AppComponent', () => { describe('when the app contains epics', () => {
let vm; beforeEach(() => {
wrapper = createComponent();
store.commit(types.RECEIVE_EPICS_SUCCESS, epics);
});
beforeEach(() => { it('the roadmap is shown', () => {
vm = createComponent(); expect(wrapper.contains(RoadmapShell)).toBe(true);
}); });
afterEach(() => { it('the empty state view is not shown', () => {
vm.$destroy(); expect(wrapper.contains(EpicsListEmpty)).toBe(false);
});
}); });
describe('computed', () => { describe('when the app does not contain any epics', () => {
describe('timeframeStart', () => { beforeEach(() => {
it('returns first item of timeframe array', () => { wrapper = createComponent();
expect(vm.timeframeStart instanceof Date).toBe(true); store.commit(types.RECEIVE_EPICS_SUCCESS, []);
});
}); });
describe('timeframeEnd', () => { it('the roadmap is not shown', () => {
it('returns last item of timeframe array', () => { expect(wrapper.contains(RoadmapShell)).toBe(false);
expect(vm.timeframeEnd instanceof Date).toBe(true);
});
}); });
describe('showRoadmap', () => { it('the empty state view is shown', () => {
it('returns true if `windowResizeInProgress`, `epicsFetchInProgress`, `epicsFetchResultEmpty` and `epicsFetchFailure` are all `false`', () => { expect(wrapper.contains(EpicsListEmpty)).toBe(true);
vm.$store.state.windowResizeInProgress = false; });
vm.$store.state.epicsFetchInProgress = false; });
vm.$store.state.epicsFetchResultEmpty = false;
vm.$store.state.epicsFetchFailure = false;
expect(vm.showRoadmap).toBe(true);
});
it('returns false if either of `windowResizeInProgress`, `epicsFetchInProgress`, `epicsFetchResultEmpty` and `epicsFetchFailure` is `true`', () => { describe('empty state view', () => {
vm.$store.state.windowResizeInProgress = true; beforeEach(() => {
vm.$store.state.epicsFetchInProgress = false; wrapper = createComponent();
vm.$store.state.epicsFetchResultEmpty = false; store.commit(types.RECEIVE_EPICS_SUCCESS, []);
vm.$store.state.epicsFetchFailure = false; });
expect(vm.showRoadmap).toBe(false); it('contains path for the empty state illustration', () => {
expect(wrapper.find(EpicsListEmpty).props('emptyStateIllustrationPath')).toBe(
emptyStateIllustrationPath,
);
});
vm.$store.state.windowResizeInProgress = false; it('contains whether to apply filters', () => {
vm.$store.state.epicsFetchInProgress = true; expect(wrapper.find(EpicsListEmpty).props('hasFiltersApplied')).toBe(hasFiltersApplied);
vm.$store.state.epicsFetchResultEmpty = false; });
vm.$store.state.epicsFetchFailure = false;
expect(vm.showRoadmap).toBe(false); it('contains whether it is child epics', () => {
expect(wrapper.find(EpicsListEmpty).props('isChildEpics')).toBe(false);
});
vm.$store.state.windowResizeInProgress = false; it('contains endpoint to create a new epic', () => {
vm.$store.state.epicsFetchInProgress = false; expect(wrapper.find(EpicsListEmpty).props('newEpicEndpoint')).toBe(mockNewEpicEndpoint);
vm.$store.state.epicsFetchResultEmpty = true; });
vm.$store.state.epicsFetchFailure = false;
expect(vm.showRoadmap).toBe(false); it('contains the preset type', () => {
expect(wrapper.find(EpicsListEmpty).props('presetType')).toBe(presetType);
});
vm.$store.state.windowResizeInProgress = false; it('contains the start of the timeframe', () => {
vm.$store.state.epicsFetchInProgress = false; expect(wrapper.find(EpicsListEmpty).props('timeframeStart')).toStrictEqual(timeframe[0]);
vm.$store.state.epicsFetchResultEmpty = false; });
vm.$store.state.epicsFetchFailure = true;
expect(vm.showRoadmap).toBe(false); it('contains the end of the timeframe', () => {
}); expect(wrapper.find(EpicsListEmpty).props('timeframeEnd')).toStrictEqual(
timeframe[timeframe.length - 1],
);
}); });
}); });
describe('methods', () => { describe('roadmap view', () => {
describe('processExtendedTimeline', () => { beforeEach(() => {
it('updates timeline by extending timeframe from the start when called with extendType as `prepend`', () => { wrapper = createComponent();
vm.$store.dispatch('receiveEpicsSuccess', { rawEpics }); store.commit(types.RECEIVE_EPICS_SUCCESS, epics);
vm.$store.state.epicsFetchInProgress = false; });
return Vue.nextTick().then(() => {
const roadmapTimelineEl = vm.$el.querySelector('.roadmap-timeline-section');
jest.spyOn(eventHub, '$emit').mockImplementation(() => {}); it('contains the current group id', () => {
expect(wrapper.find(RoadmapShell).props('currentGroupId')).toBe(currentGroupId);
});
vm.processExtendedTimeline({ it('contains epics', () => {
extendType: EXTEND_AS.PREPEND, expect(wrapper.find(RoadmapShell).props('epics')).toEqual(epics);
roadmapTimelineEl, });
itemsCount: 0,
});
expect(eventHub.$emit).toHaveBeenCalledWith('refreshTimeline', expect.any(Object)); it('contains whether filters are applied', () => {
expect(roadmapTimelineEl.parentElement.scrollBy).toHaveBeenCalled(); expect(wrapper.find(RoadmapShell).props('hasFiltersApplied')).toBe(hasFiltersApplied);
}); });
});
it('updates timeline by extending timeframe from the end when called with extendType as `append`', () => { it('contains milestones', () => {
vm.$store.dispatch('receiveEpicsSuccess', { rawEpics }); expect(wrapper.find(RoadmapShell).props('milestones')).toEqual([]);
vm.$store.state.epicsFetchInProgress = false; });
return Vue.nextTick().then(() => { it('contains the preset type', () => {
const roadmapTimelineEl = vm.$el.querySelector('.roadmap-timeline-section'); expect(wrapper.find(RoadmapShell).props('presetType')).toBe(presetType);
});
jest.spyOn(eventHub, '$emit').mockImplementation(() => {}); it('contains timeframe', () => {
expect(wrapper.find(RoadmapShell).props('timeframe')).toEqual(timeframe);
});
});
vm.processExtendedTimeline({ describe('extending the roadmap timeline', () => {
extendType: EXTEND_AS.PREPEND, let roadmapTimelineEl;
roadmapTimelineEl,
itemsCount: 0,
});
expect(eventHub.$emit).toHaveBeenCalledWith('refreshTimeline', expect.any(Object)); beforeEach(() => {
}); wrapper = createComponent(mount);
}); store.dispatch('receiveEpicsSuccess', { rawEpics });
roadmapTimelineEl = wrapper.find('.roadmap-timeline-section').element;
}); });
describe('handleScrollToExtend', () => { it('updates timeline by extending timeframe from the start when called with extendType as `prepend`', () => {
let roadmapTimelineEl; jest.spyOn(eventHub, '$emit').mockImplementation();
beforeAll(() => { wrapper.vm.processExtendedTimeline({
vm.$store.dispatch('receiveEpicsSuccess', { rawEpics }); extendType: EXTEND_AS.PREPEND,
vm.$store.state.epicsFetchInProgress = false; roadmapTimelineEl,
roadmapTimelineEl = vm.$el.querySelector('.roadmap-timeline-section'); itemsCount: 0,
}); });
it('updates the store and refreshes roadmap with extended timeline based on provided extendType', () => { expect(eventHub.$emit).toHaveBeenCalledWith('refreshTimeline', expect.any(Object));
jest.spyOn(vm, 'extendTimeframe').mockImplementation(() => {}); expect(roadmapTimelineEl.parentElement.scrollBy).toHaveBeenCalled();
jest.spyOn(vm, 'refreshEpicDates').mockImplementation(() => {}); });
jest.spyOn(vm, 'refreshMilestoneDates').mockImplementation(() => {});
jest.spyOn(vm, 'fetchEpicsForTimeframe').mockResolvedValue();
const extendType = EXTEND_AS.PREPEND;
vm.handleScrollToExtend(roadmapTimelineEl, extendType); it('updates timeline by extending timeframe from the end when called with extendType as `append`', () => {
jest.spyOn(eventHub, '$emit').mockImplementation();
expect(vm.extendTimeframe).toHaveBeenCalledWith({ extendAs: extendType }); wrapper.vm.processExtendedTimeline({
expect(vm.refreshEpicDates).toHaveBeenCalled(); extendType: EXTEND_AS.APPEND,
expect(vm.refreshMilestoneDates).toHaveBeenCalled(); roadmapTimelineEl,
itemsCount: 0,
}); });
it('calls `fetchEpicsForTimeframe` with extended timeframe array', () => { expect(eventHub.$emit).toHaveBeenCalledWith('refreshTimeline', expect.any(Object));
jest.spyOn(vm, 'extendTimeframe').mockImplementation(() => {}); });
jest.spyOn(vm, 'refreshEpicDates').mockImplementation(() => {});
jest.spyOn(vm, 'refreshMilestoneDates').mockImplementation(() => {});
jest.spyOn(vm, 'fetchEpicsForTimeframe').mockResolvedValue();
const extendType = EXTEND_AS.PREPEND; it('updates the store and refreshes roadmap with extended timeline based on provided extendType', () => {
jest.spyOn(wrapper.vm, 'extendTimeframe').mockImplementation();
jest.spyOn(wrapper.vm, 'refreshEpicDates').mockImplementation();
jest.spyOn(wrapper.vm, 'refreshMilestoneDates').mockImplementation();
jest.spyOn(wrapper.vm, 'fetchEpicsForTimeframe').mockResolvedValue();
vm.handleScrollToExtend(roadmapTimelineEl, extendType); const extendType = EXTEND_AS.PREPEND;
return vm.$nextTick().then(() => { wrapper.vm.handleScrollToExtend(roadmapTimelineEl, extendType);
expect(vm.fetchEpicsForTimeframe).toHaveBeenCalledWith(
expect.objectContaining({
timeframe: vm.extendedTimeframe,
}),
);
});
});
});
});
describe('template', () => { expect(wrapper.vm.extendTimeframe).toHaveBeenCalledWith({ extendAs: extendType });
it('renders roadmap container with class `roadmap-container`', () => { expect(wrapper.vm.refreshEpicDates).toHaveBeenCalled();
expect(vm.$el.classList.contains('roadmap-container')).toBe(true); expect(wrapper.vm.refreshMilestoneDates).toHaveBeenCalled();
}); });
it('renders roadmap container with classes `roadmap-container overflow-reset` when isEpicsListEmpty prop is true', () => { it('calls `fetchEpicsForTimeframe` with extended timeframe array', () => {
vm.$store.state.epicsFetchResultEmpty = true; jest.spyOn(wrapper.vm, 'fetchEpicsForTimeframe').mockResolvedValue();
const extendType = EXTEND_AS.PREPEND;
wrapper.vm.handleScrollToExtend(roadmapTimelineEl, extendType);
return Vue.nextTick().then(() => { return Vue.nextTick(() => {
expect(vm.$el.classList.contains('roadmap-container')).toBe(true); expect(wrapper.vm.fetchEpicsForTimeframe).toHaveBeenCalledWith(
expect(vm.$el.classList.contains('overflow-reset')).toBe(true); expect.objectContaining({
timeframe: wrapper.vm.extendedTimeframe,
}),
);
}); });
}); });
}); });
......
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