Commit e7d4816c authored by Vitaly Slobodin's avatar Vitaly Slobodin

Migrate ee/roadmap to Jest

Closes https://gitlab.com/gitlab-org/gitlab/issues/194303
parent 4c84caaa
......@@ -8,7 +8,7 @@ import {
} from 'ee/roadmap/utils/roadmap_utils';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { mockTimeframeInitialDate } from '../mock_data';
import { mockTimeframeInitialDate } from 'ee_jest/roadmap/mock_data';
const mockTimeframeQuarters = getTimeframeForQuartersView(mockTimeframeInitialDate);
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
......@@ -46,7 +46,7 @@ describe('CurrentDayIndicator', () => {
describe('computed', () => {
describe('hasToday', () => {
it('returns true when presetType is QUARTERS and currentDate is within current quarter', done => {
it('returns true when presetType is QUARTERS and currentDate is within current quarter', () => {
wrapper.setData({
currentDate: mockTimeframeQuarters[0].range[1],
});
......@@ -56,13 +56,12 @@ describe('CurrentDayIndicator', () => {
timeframeItem: mockTimeframeQuarters[0],
});
wrapper.vm.$nextTick(() => {
return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.hasToday).toBe(true);
done();
});
});
it('returns true when presetType is MONTHS and currentDate is within current month', done => {
it('returns true when presetType is MONTHS and currentDate is within current month', () => {
wrapper.setData({
currentDate: new Date(2020, 0, 15),
});
......@@ -72,13 +71,12 @@ describe('CurrentDayIndicator', () => {
timeframeItem: new Date(2020, 0, 1),
});
wrapper.vm.$nextTick(() => {
return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.hasToday).toBe(true);
done();
});
});
it('returns true when presetType is WEEKS and currentDate is within current week', done => {
it('returns true when presetType is WEEKS and currentDate is within current week', () => {
wrapper.setData({
currentDate: mockTimeframeWeeks[0],
});
......@@ -88,9 +86,8 @@ describe('CurrentDayIndicator', () => {
timeframeItem: mockTimeframeWeeks[0],
});
wrapper.vm.$nextTick(() => {
return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.hasToday).toBe(true);
done();
});
});
});
......@@ -98,7 +95,7 @@ describe('CurrentDayIndicator', () => {
describe('methods', () => {
describe('getIndicatorStyles', () => {
it('returns object containing `left` with value `34%` when presetType is QUARTERS', done => {
it('returns object containing `left` with value `34%` when presetType is QUARTERS', () => {
wrapper.setData({
currentDate: mockTimeframeQuarters[0].range[1],
});
......@@ -108,17 +105,16 @@ describe('CurrentDayIndicator', () => {
timeframeItem: mockTimeframeQuarters[0],
});
wrapper.vm.$nextTick(() => {
return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.getIndicatorStyles()).toEqual(
jasmine.objectContaining({
expect.objectContaining({
left: '34%',
}),
);
done();
});
});
it('returns object containing `left` with value `48%` when presetType is MONTHS', done => {
it('returns object containing `left` with value `48%` when presetType is MONTHS', () => {
wrapper.setData({
currentDate: new Date(2020, 0, 15),
});
......@@ -128,17 +124,16 @@ describe('CurrentDayIndicator', () => {
timeframeItem: new Date(2020, 0, 1),
});
wrapper.vm.$nextTick(() => {
return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.getIndicatorStyles()).toEqual(
jasmine.objectContaining({
expect.objectContaining({
left: '48%',
}),
);
done();
});
});
it('returns object containing `left` with value `7%` when presetType is WEEKS', done => {
it('returns object containing `left` with value `7%` when presetType is WEEKS', () => {
wrapper.setData({
currentDate: mockTimeframeWeeks[0],
});
......@@ -148,34 +143,33 @@ describe('CurrentDayIndicator', () => {
timeframeItem: mockTimeframeWeeks[0],
});
wrapper.vm.$nextTick(() => {
return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.getIndicatorStyles()).toEqual(
jasmine.objectContaining({
expect.objectContaining({
left: '7%',
}),
);
done();
});
});
});
});
describe('template', () => {
beforeEach(done => {
beforeEach(() => {
wrapper = createComponent();
wrapper.setData({
currentDate: mockTimeframeMonths[0],
});
wrapper.vm.$nextTick(() => {
done();
});
return wrapper.vm.$nextTick();
});
it('renders span element containing class `current-day-indicator`', () => {
expect(wrapper.element.classList.contains('current-day-indicator')).toBe(true);
expect(wrapper.classes('current-day-indicator')).toBe(true);
});
it('renders span element with style attribute containing `left: 3%;`', () => {
expect(wrapper.element.getAttribute('style')).toBe('left: 3%;');
expect(wrapper.attributes('style')).toBe('left: 3%;');
});
});
});
......@@ -7,7 +7,7 @@ import {
mockFormattedEpic,
mockFormattedChildEpic2,
mockFormattedChildEpic1,
} from '../mock_data';
} from 'ee_jest/roadmap/mock_data';
const createComponent = (
epic = mockFormattedEpic,
......@@ -159,7 +159,7 @@ describe('EpicItemDetails', () => {
});
it('emits toggleIsEpicExpanded event when clicked', () => {
spyOn(eventHub, '$emit');
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
const id = 42;
const epic = {
......
......@@ -8,8 +8,8 @@ import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate, mockEpic, mockGroupId } from '../mock_data';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate, mockEpic, mockGroupId } from 'ee_jest/roadmap/mock_data';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
......@@ -111,7 +111,7 @@ describe('EpicItemComponent', () => {
describe('methods', () => {
describe('removeHighlight', () => {
it('should call _.delay after 3 seconds with a callback function which would set `epic.newEpic` to false when it is true already', done => {
spyOn(_, 'delay');
jest.spyOn(_, 'delay').mockImplementation(() => {});
vm.epic.newEpic = true;
......@@ -119,7 +119,7 @@ describe('EpicItemComponent', () => {
vm.$nextTick()
.then(() => {
expect(_.delay).toHaveBeenCalledWith(jasmine.any(Function), 3000);
expect(_.delay).toHaveBeenCalledWith(expect.any(Function), 3000);
})
.then(done)
.catch(done.fail);
......
......@@ -4,7 +4,7 @@ import CurrentDayIndicator from 'ee/roadmap/components/current_day_indicator.vue
import EpicItemTimeline from 'ee/roadmap/components/epic_item_timeline.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { mockTimeframeInitialDate, mockFormattedEpic } from '../mock_data';
import { mockTimeframeInitialDate, mockFormattedEpic } from 'ee_jest/roadmap/mock_data';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
......
......@@ -10,8 +10,12 @@ import {
import { PRESET_TYPES } from 'ee/roadmap/constants';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate, mockSvgPath, mockNewEpicEndpoint } from '../mock_data';
import mountComponent from 'helpers/vue_mount_component_helper';
import {
mockTimeframeInitialDate,
mockSvgPath,
mockNewEpicEndpoint,
} from 'ee_jest/roadmap/mock_data';
const mockTimeframeQuarters = getTimeframeForQuartersView(mockTimeframeInitialDate);
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
......
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VirtualList from 'vue-virtual-scroll-list';
import epicsListSectionComponent from 'ee/roadmap/components/epics_list_section.vue';
import EpicsListSection from 'ee/roadmap/components/epics_list_section.vue';
import EpicItem from 'ee/roadmap/components/epic_item.vue';
import createStore from 'ee/roadmap/store';
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
......@@ -18,7 +18,7 @@ import {
mockSortedBy,
basePath,
epicsPath,
} from '../mock_data';
} from 'ee_jest/roadmap/mock_data';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const store = createStore();
......@@ -39,6 +39,7 @@ const mockEpics = store.state.epics;
store.state.epics[0].children = {
edges: [mockFormattedChildEpic1, mockFormattedChildEpic2],
};
const localVue = createLocalVue();
const createComponent = ({
epics = mockEpics,
......@@ -47,9 +48,7 @@ const createComponent = ({
presetType = PRESET_TYPES.MONTHS,
roadmapBufferedRendering = true,
} = {}) => {
const localVue = createLocalVue();
return shallowMount(epicsListSectionComponent, {
return shallowMount(EpicsListSection, {
localVue,
store,
stubs: {
......@@ -82,6 +81,13 @@ describe('EpicsListSectionComponent', () => {
describe('data', () => {
it('returns default data props', () => {
// Destroy the existing wrapper, and create a new one. This works around
// a race condition between how Jest runs tests and the $nextTick call in
// EpicsListSectionComponent's mounted hook.
// https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27992#note_319213990
wrapper.destroy();
wrapper = createComponent();
expect(wrapper.vm.offsetLeft).toBe(0);
expect(wrapper.vm.emptyRowContainerStyles).toEqual({});
expect(wrapper.vm.showBottomShadow).toBe(false);
......@@ -115,63 +121,69 @@ describe('EpicsListSectionComponent', () => {
describe('methods', () => {
describe('initMounted', () => {
beforeEach(() => {
// Destroy the existing wrapper, and create a new one. This works
// around a race condition between how Jest runs tests and the
// $nextTick call in EpicsListSectionComponent's mounted hook.
// https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27992#note_319213990
wrapper.destroy();
wrapper = createComponent();
jest.spyOn(wrapper.vm, 'scrollToTodayIndicator').mockImplementation(() => {});
});
it('sets value of `roadmapShellEl` with root component element', () => {
expect(wrapper.vm.roadmapShellEl instanceof HTMLElement).toBe(true);
});
it('calls action `setBufferSize` with value based on window.innerHeight and component element position', () => {
expect(wrapper.vm.bufferSize).toBe(12);
expect(wrapper.vm.bufferSize).toBe(16);
});
it('sets value of `offsetLeft` with parentElement.offsetLeft', done => {
wrapper.vm.$nextTick(() => {
it('sets value of `offsetLeft` with parentElement.offsetLeft', () => {
return wrapper.vm.$nextTick(() => {
// During tests, there's no `$el.parentElement` present
// hence offsetLeft is 0.
expect(wrapper.vm.offsetLeft).toBe(0);
done();
});
});
it('calls `scrollToTodayIndicator` following the component render', done => {
spyOn(wrapper.vm, 'scrollToTodayIndicator');
it('calls `scrollToTodayIndicator` following the component render', () => {
// Original method implementation waits for render cycle
// to complete at 2 levels before scrolling.
wrapper.vm.$nextTick(() => {
wrapper.vm.$nextTick(() => {
return wrapper.vm
.$nextTick()
.then(() => wrapper.vm.$nextTick())
.then(() => {
expect(wrapper.vm.scrollToTodayIndicator).toHaveBeenCalled();
done();
});
});
});
it('sets style object to `emptyRowContainerStyles`', done => {
wrapper.vm.$nextTick(() => {
it('sets style object to `emptyRowContainerStyles`', () => {
return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.emptyRowContainerStyles).toEqual(
jasmine.objectContaining({
expect.objectContaining({
height: '0px',
}),
);
done();
});
});
});
describe('getEmptyRowContainerStyles', () => {
it('returns empty object when there are no epics available to render', done => {
it('returns empty object when there are no epics available to render', () => {
wrapper.setProps({
epics: [],
});
wrapper.vm.$nextTick(() => {
return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.getEmptyRowContainerStyles()).toEqual({});
done();
});
});
it('returns object containing `height` when there epics available to render', () => {
expect(wrapper.vm.getEmptyRowContainerStyles()).toEqual(
jasmine.objectContaining({
expect.objectContaining({
height: '0px',
}),
);
......@@ -203,7 +215,7 @@ describe('EpicsListSectionComponent', () => {
describe('getEpicItemProps', () => {
it('returns an object containing props for EpicItem component', () => {
expect(wrapper.vm.getEpicItemProps(1)).toEqual(
jasmine.objectContaining({
expect.objectContaining({
key: 1,
props: {
epic: wrapper.vm.epics[1],
......@@ -219,15 +231,14 @@ describe('EpicsListSectionComponent', () => {
describe('template', () => {
it('renders component container element with class `epics-list-section`', () => {
expect(wrapper.vm.$el.classList.contains('epics-list-section')).toBe(true);
expect(wrapper.classes('epics-list-section')).toBe(true);
});
it('renders virtual-list when roadmapBufferedRendering is `true` and `epics.length` is more than `bufferSize`', done => {
it('renders virtual-list when roadmapBufferedRendering is `true` and `epics.length` is more than `bufferSize`', () => {
wrapper.vm.setBufferSize(5);
wrapper.vm.$nextTick(() => {
return wrapper.vm.$nextTick(() => {
expect(wrapper.find(VirtualList).exists()).toBe(true);
done();
});
});
......@@ -267,7 +278,6 @@ describe('EpicsListSectionComponent', () => {
it('expands to show child epics when epic is toggled', done => {
const epic = mockEpics[0];
wrapper = createComponent();
expect(wrapper.findAll(EpicItem).length).toBe(mockEpics.length);
......
......@@ -7,7 +7,7 @@ import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { mount } from '@vue/test-utils';
import { mockTimeframeInitialDate, mockMilestone2 } from '../../../javascripts/roadmap/mock_data';
import { mockTimeframeInitialDate, mockMilestone2 } from 'ee_jest/roadmap/mock_data';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
......@@ -45,29 +45,25 @@ describe('MilestoneItemComponent', () => {
describe('computed', () => {
describe('startDateValues', () => {
it('returns object containing date parts from milestone.startDate', () => {
expect(wrapper.vm.startDateValues).toEqual(
jasmine.objectContaining({
expect(wrapper.vm.startDateValues).toMatchObject({
day: mockMilestone2.startDate.getDay(),
date: mockMilestone2.startDate.getDate(),
month: mockMilestone2.startDate.getMonth(),
year: mockMilestone2.startDate.getFullYear(),
time: mockMilestone2.startDate.getTime(),
}),
);
});
});
});
describe('endDateValues', () => {
it('returns object containing date parts from milestone.endDate', () => {
expect(wrapper.vm.endDateValues).toEqual(
jasmine.objectContaining({
expect(wrapper.vm.endDateValues).toMatchObject({
day: mockMilestone2.endDate.getDay(),
date: mockMilestone2.endDate.getDate(),
month: mockMilestone2.endDate.getMonth(),
year: mockMilestone2.endDate.getFullYear(),
time: mockMilestone2.endDate.getTime(),
}),
);
});
});
});
......
......@@ -7,11 +7,7 @@ import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import {
mockTimeframeInitialDate,
mockMilestone2,
mockGroupId,
} from '../../../javascripts/roadmap/mock_data';
import { mockTimeframeInitialDate, mockMilestone2, mockGroupId } from 'ee_jest/roadmap/mock_data';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
......
......@@ -8,11 +8,7 @@ import {
EPIC_DETAILS_CELL_WIDTH,
TIMELINE_CELL_MIN_WIDTH,
} from 'ee/roadmap/constants';
import {
mockTimeframeInitialDate,
mockGroupId,
rawMilestones,
} from '../../../javascripts/roadmap/mock_data';
import { mockTimeframeInitialDate, mockGroupId, rawMilestones } from 'ee_jest/roadmap/mock_data';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const store = createStore();
......
......@@ -3,8 +3,8 @@ import Vue from 'vue';
import MonthsHeaderItemComponent from 'ee/roadmap/components/preset_months/months_header_item.vue';
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate } from 'ee_spec/roadmap/mock_data';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate } from '../../mock_data';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const mockTimeframeIndex = 0;
......
......@@ -4,8 +4,8 @@ import MonthsHeaderSubItemComponent from 'ee/roadmap/components/preset_months/mo
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate } from 'ee_spec/roadmap/mock_data';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate } from '../../mock_data';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
......
......@@ -3,8 +3,8 @@ import Vue from 'vue';
import QuartersHeaderItemComponent from 'ee/roadmap/components/preset_quarters/quarters_header_item.vue';
import { getTimeframeForQuartersView } from 'ee/roadmap/utils/roadmap_utils';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate } from 'ee_spec/roadmap/mock_data';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate } from '../../mock_data';
const mockTimeframeIndex = 0;
const mockTimeframeQuarters = getTimeframeForQuartersView(mockTimeframeInitialDate);
......
......@@ -4,8 +4,8 @@ import QuartersHeaderSubItemComponent from 'ee/roadmap/components/preset_quarter
import { getTimeframeForQuartersView } from 'ee/roadmap/utils/roadmap_utils';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate } from 'ee_spec/roadmap/mock_data';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate } from '../../mock_data';
const mockTimeframeQuarters = getTimeframeForQuartersView(mockTimeframeInitialDate);
......
......@@ -3,8 +3,8 @@ import Vue from 'vue';
import WeeksHeaderItemComponent from 'ee/roadmap/components/preset_weeks/weeks_header_item.vue';
import { getTimeframeForWeeksView } from 'ee/roadmap/utils/roadmap_utils';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate } from 'ee_spec/roadmap/mock_data';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate } from '../../mock_data';
const mockTimeframeIndex = 0;
const mockTimeframeWeeks = getTimeframeForWeeksView(mockTimeframeInitialDate);
......
......@@ -4,8 +4,8 @@ import WeeksHeaderSubItemComponent from 'ee/roadmap/components/preset_weeks/week
import { getTimeframeForWeeksView } from 'ee/roadmap/utils/roadmap_utils';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate } from 'ee_spec/roadmap/mock_data';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate } from '../../mock_data';
const mockTimeframeWeeks = getTimeframeForWeeksView(mockTimeframeInitialDate);
......
......@@ -8,7 +8,7 @@ import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { PRESET_TYPES, EXTEND_AS } from 'ee/roadmap/constants';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import {
mockTimeframeInitialDate,
mockGroupId,
......@@ -18,7 +18,7 @@ import {
mockSortedBy,
basePath,
epicsPath,
} from '../mock_data';
} from 'ee_jest/roadmap/mock_data';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
......@@ -115,16 +115,14 @@ describe('Roadmap AppComponent', () => {
describe('methods', () => {
describe('processExtendedTimeline', () => {
it('updates timeline by extending timeframe from the start when called with extendType as `prepend`', done => {
it('updates timeline by extending timeframe from the start when called with extendType as `prepend`', () => {
vm.$store.dispatch('receiveEpicsSuccess', { rawEpics });
vm.$store.state.epicsFetchInProgress = false;
Vue.nextTick()
.then(() => {
return Vue.nextTick().then(() => {
const roadmapTimelineEl = vm.$el.querySelector('.roadmap-timeline-section');
spyOn(eventHub, '$emit');
spyOn(roadmapTimelineEl.parentElement, 'scrollBy');
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
vm.processExtendedTimeline({
extendType: EXTEND_AS.PREPEND,
......@@ -132,22 +130,19 @@ describe('Roadmap AppComponent', () => {
itemsCount: 0,
});
expect(eventHub.$emit).toHaveBeenCalledWith('refreshTimeline', jasmine.any(Object));
expect(eventHub.$emit).toHaveBeenCalledWith('refreshTimeline', expect.any(Object));
expect(roadmapTimelineEl.parentElement.scrollBy).toHaveBeenCalled();
})
.then(done)
.catch(done.fail);
});
});
it('updates timeline by extending timeframe from the end when called with extendType as `append`', done => {
it('updates timeline by extending timeframe from the end when called with extendType as `append`', () => {
vm.$store.dispatch('receiveEpicsSuccess', { rawEpics });
vm.$store.state.epicsFetchInProgress = false;
Vue.nextTick()
.then(() => {
return Vue.nextTick().then(() => {
const roadmapTimelineEl = vm.$el.querySelector('.roadmap-timeline-section');
spyOn(eventHub, '$emit');
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
vm.processExtendedTimeline({
extendType: EXTEND_AS.PREPEND,
......@@ -155,10 +150,8 @@ describe('Roadmap AppComponent', () => {
itemsCount: 0,
});
expect(eventHub.$emit).toHaveBeenCalledWith('refreshTimeline', jasmine.any(Object));
})
.then(done)
.catch(done.fail);
expect(eventHub.$emit).toHaveBeenCalledWith('refreshTimeline', expect.any(Object));
});
});
});
......@@ -172,10 +165,10 @@ describe('Roadmap AppComponent', () => {
});
it('updates the store and refreshes roadmap with extended timeline based on provided extendType', () => {
spyOn(vm, 'extendTimeframe');
spyOn(vm, 'refreshEpicDates');
spyOn(vm, 'refreshMilestoneDates');
spyOn(vm, 'fetchEpicsForTimeframe').and.callFake(() => new Promise(() => {}));
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;
......@@ -186,26 +179,23 @@ describe('Roadmap AppComponent', () => {
expect(vm.refreshMilestoneDates).toHaveBeenCalled();
});
it('calls `fetchEpicsForTimeframe` with extended timeframe array', done => {
spyOn(vm, 'extendTimeframe').and.stub();
spyOn(vm, 'refreshEpicDates').and.stub();
spyOn(vm, 'refreshMilestoneDates').and.stub();
spyOn(vm, 'fetchEpicsForTimeframe').and.callFake(() => new Promise(() => {}));
it('calls `fetchEpicsForTimeframe` with extended timeframe array', () => {
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;
vm.handleScrollToExtend(roadmapTimelineEl, extendType);
vm.$nextTick()
.then(() => {
return vm.$nextTick().then(() => {
expect(vm.fetchEpicsForTimeframe).toHaveBeenCalledWith(
jasmine.objectContaining({
expect.objectContaining({
timeframe: vm.extendedTimeframe,
}),
);
})
.then(done)
.catch(done.fail);
});
});
});
});
......@@ -215,15 +205,13 @@ describe('Roadmap AppComponent', () => {
expect(vm.$el.classList.contains('roadmap-container')).toBe(true);
});
it('renders roadmap container with classes `roadmap-container overflow-reset` when isEpicsListEmpty prop is true', done => {
it('renders roadmap container with classes `roadmap-container overflow-reset` when isEpicsListEmpty prop is true', () => {
vm.$store.state.epicsFetchResultEmpty = true;
Vue.nextTick()
.then(() => {
return Vue.nextTick().then(() => {
expect(vm.$el.classList.contains('roadmap-container')).toBe(true);
expect(vm.$el.classList.contains('overflow-reset')).toBe(true);
})
.then(done)
.catch(done.fail);
});
});
});
});
......@@ -7,8 +7,13 @@ import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { mockEpic, mockTimeframeInitialDate, mockGroupId, mockMilestone } from '../mock_data';
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import {
mockEpic,
mockTimeframeInitialDate,
mockGroupId,
mockMilestone,
} from 'ee_jest/roadmap/mock_data';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
......@@ -73,13 +78,13 @@ describe('RoadmapShellComponent', () => {
describe('handleScroll', () => {
it('emits `epicsListScrolled` event via eventHub', done => {
const vmWithParentEl = createComponent({}, document.getElementById('roadmap-shell'));
spyOn(eventHub, '$emit');
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
Vue.nextTick()
.then(() => {
vmWithParentEl.handleScroll();
expect(eventHub.$emit).toHaveBeenCalledWith('epicsListScrolled', jasmine.any(Object));
expect(eventHub.$emit).toHaveBeenCalledWith('epicsListScrolled', expect.any(Object));
vmWithParentEl.$destroy();
})
......
......@@ -6,8 +6,8 @@ import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockEpic, mockTimeframeInitialDate } from '../mock_data';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockEpic, mockTimeframeInitialDate } from 'ee_jest/roadmap/mock_data';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
......@@ -46,7 +46,7 @@ describe('RoadmapTimelineSectionComponent', () => {
describe('sectionContainerStyles', () => {
it('returns object containing `width` with value based on epic details cell width, timeline cell width and timeframe length', () => {
expect(vm.sectionContainerStyles).toEqual(
jasmine.objectContaining({
expect.objectContaining({
width: '1760px',
}),
);
......@@ -73,21 +73,21 @@ describe('RoadmapTimelineSectionComponent', () => {
describe('mounted', () => {
it('binds `epicsListScrolled` event listener via eventHub', () => {
spyOn(eventHub, '$on');
jest.spyOn(eventHub, '$on').mockImplementation(() => {});
const vmX = createComponent({});
expect(eventHub.$on).toHaveBeenCalledWith('epicsListScrolled', jasmine.any(Function));
expect(eventHub.$on).toHaveBeenCalledWith('epicsListScrolled', expect.any(Function));
vmX.$destroy();
});
});
describe('beforeDestroy', () => {
it('unbinds `epicsListScrolled` event listener via eventHub', () => {
spyOn(eventHub, '$off');
jest.spyOn(eventHub, '$off').mockImplementation(() => {});
const vmX = createComponent({});
vmX.$destroy();
expect(eventHub.$off).toHaveBeenCalledWith('epicsListScrolled', jasmine.any(Function));
expect(eventHub.$off).toHaveBeenCalledWith('epicsListScrolled', expect.any(Function));
});
});
......
......@@ -5,8 +5,8 @@ import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate, mockEpic } from '../mock_data';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate, mockEpic } from 'ee_jest/roadmap/mock_data';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
......
......@@ -5,8 +5,8 @@ import { getTimeframeForQuartersView } from 'ee/roadmap/utils/roadmap_utils';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate, mockEpic } from '../mock_data';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate, mockEpic } from 'ee_jest/roadmap/mock_data';
const mockTimeframeQuarters = getTimeframeForQuartersView(mockTimeframeInitialDate);
......
......@@ -5,8 +5,8 @@ import { getTimeframeForWeeksView } from 'ee/roadmap/utils/roadmap_utils';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate, mockEpic } from '../mock_data';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockTimeframeInitialDate, mockEpic } from 'ee_jest/roadmap/mock_data';
const mockTimeframeWeeks = getTimeframeForWeeksView(mockTimeframeInitialDate);
......
......@@ -12,8 +12,9 @@ import groupEpics from 'ee/roadmap/queries/groupEpics.query.graphql';
import groupMilestones from 'ee/roadmap/queries/groupMilestones.query.graphql';
import epicChildEpics from 'ee/roadmap/queries/epicChildEpics.query.graphql';
import testAction from 'spec/helpers/vuex_action_helper';
import testAction from 'helpers/vuex_action_helper';
import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
import {
mockGroupId,
......@@ -35,6 +36,8 @@ import {
mockFormattedMilestone,
} from '../mock_data';
jest.mock('~/flash');
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
describe('Roadmap Vuex Actions', () => {
......@@ -57,32 +60,30 @@ describe('Roadmap Vuex Actions', () => {
});
describe('setInitialData', () => {
it('should set initial roadmap props', done => {
it('should set initial roadmap props', () => {
const mockRoadmap = {
foo: 'bar',
bar: 'baz',
};
testAction(
return testAction(
actions.setInitialData,
mockRoadmap,
{},
[{ type: types.SET_INITIAL_DATA, payload: mockRoadmap }],
[],
done,
);
});
});
describe('setWindowResizeInProgress', () => {
it('should set value of `state.windowResizeInProgress` based on provided value', done => {
testAction(
it('should set value of `state.windowResizeInProgress` based on provided value', () => {
return testAction(
actions.setWindowResizeInProgress,
true,
state,
[{ type: types.SET_WINDOW_RESIZE_IN_PROGRESS, payload: true }],
[],
done,
);
});
});
......@@ -110,27 +111,23 @@ describe('Roadmap Vuex Actions', () => {
};
});
it('should fetch Group Epics using GraphQL client when epicIid is not present in state', done => {
spyOn(epicUtils.gqClient, 'query').and.returnValue(
it('should fetch Group Epics using GraphQL client when epicIid is not present in state', () => {
jest.spyOn(epicUtils.gqClient, 'query').mockReturnValue(
Promise.resolve({
data: mockGroupEpicsQueryResponse.data,
}),
);
actions
.fetchGroupEpics(mockState)
.then(() => {
return actions.fetchGroupEpics(mockState).then(() => {
expect(epicUtils.gqClient.query).toHaveBeenCalledWith({
query: groupEpics,
variables: expectedVariables,
});
})
.then(done)
.catch(done.fail);
});
});
it('should fetch child Epics of an Epic using GraphQL client when epicIid is present in state', done => {
spyOn(epicUtils.gqClient, 'query').and.returnValue(
it('should fetch child Epics of an Epic using GraphQL client when epicIid is present in state', () => {
jest.spyOn(epicUtils.gqClient, 'query').mockReturnValue(
Promise.resolve({
data: mockEpicChildEpicsQueryResponse.data,
}),
......@@ -138,9 +135,7 @@ describe('Roadmap Vuex Actions', () => {
mockState.epicIid = '1';
actions
.fetchGroupEpics(mockState)
.then(() => {
return actions.fetchGroupEpics(mockState).then(() => {
expect(epicUtils.gqClient.query).toHaveBeenCalledWith({
query: epicChildEpics,
variables: {
......@@ -148,34 +143,31 @@ describe('Roadmap Vuex Actions', () => {
...expectedVariables,
},
});
})
.then(done)
.catch(done.fail);
});
});
});
describe('requestEpics', () => {
it('should set `epicsFetchInProgress` to true', done => {
testAction(actions.requestEpics, {}, state, [{ type: 'REQUEST_EPICS' }], [], done);
it('should set `epicsFetchInProgress` to true', () => {
return testAction(actions.requestEpics, {}, state, [{ type: 'REQUEST_EPICS' }], []);
});
});
describe('requestEpicsForTimeframe', () => {
it('should set `epicsFetchForTimeframeInProgress` to true', done => {
testAction(
it('should set `epicsFetchForTimeframeInProgress` to true', () => {
return testAction(
actions.requestEpicsForTimeframe,
{},
state,
[{ type: types.REQUEST_EPICS_FOR_TIMEFRAME }],
[],
done,
);
});
});
describe('receiveEpicsSuccess', () => {
it('should set formatted epics array and epicId to IDs array in state based on provided epics list', done => {
testAction(
it('should set formatted epics array and epicId to IDs array in state based on provided epics list', () => {
return testAction(
actions.receiveEpicsSuccess,
{
rawEpics: [
......@@ -207,12 +199,11 @@ describe('Roadmap Vuex Actions', () => {
},
],
[],
done,
);
});
it('should set formatted epics array and epicId to IDs array in state based on provided epics list when timeframe was extended', done => {
testAction(
it('should set formatted epics array and epicId to IDs array in state based on provided epics list when timeframe was extended', () => {
return testAction(
actions.receiveEpicsSuccess,
{
rawEpics: [
......@@ -236,33 +227,25 @@ describe('Roadmap Vuex Actions', () => {
},
],
[],
done,
);
});
});
describe('receiveEpicsFailure', () => {
beforeEach(() => {
setFixtures('<div class="flash-container"></div>');
});
it('should set epicsFetchInProgress, epicsFetchForTimeframeInProgress to false and epicsFetchFailure to true', done => {
testAction(
it('should set epicsFetchInProgress, epicsFetchForTimeframeInProgress to false and epicsFetchFailure to true', () => {
return testAction(
actions.receiveEpicsFailure,
{},
state,
[{ type: types.RECEIVE_EPICS_FAILURE }],
[],
done,
);
});
it('should show flash error', () => {
actions.receiveEpicsFailure({ commit: () => {} });
expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
'Something went wrong while fetching epics',
);
expect(createFlash).toHaveBeenCalledWith('Something went wrong while fetching epics');
});
});
......@@ -278,14 +261,14 @@ describe('Roadmap Vuex Actions', () => {
});
describe('success', () => {
it('should dispatch requestEpics and receiveEpicsSuccess when request is successful', done => {
spyOn(epicUtils.gqClient, 'query').and.returnValue(
it('should dispatch requestEpics and receiveEpicsSuccess when request is successful', () => {
jest.spyOn(epicUtils.gqClient, 'query').mockReturnValue(
Promise.resolve({
data: mockGroupEpicsQueryResponse.data,
}),
);
testAction(
return testAction(
actions.fetchEpics,
null,
state,
......@@ -299,18 +282,15 @@ describe('Roadmap Vuex Actions', () => {
payload: { rawEpics: mockGroupEpicsQueryResponseFormatted },
},
],
done,
);
});
});
describe('failure', () => {
it('should dispatch requestEpics and receiveEpicsFailure when request fails', done => {
spyOn(epicUtils.gqClient, 'query').and.returnValue(
Promise.reject(new Error('error message')),
);
it('should dispatch requestEpics and receiveEpicsFailure when request fails', () => {
jest.spyOn(epicUtils.gqClient, 'query').mockRejectedValue(new Error('error message'));
testAction(
return testAction(
actions.fetchEpics,
null,
state,
......@@ -323,34 +303,21 @@ describe('Roadmap Vuex Actions', () => {
type: 'receiveEpicsFailure',
},
],
done,
);
});
});
});
describe('fetchEpicsForTimeframe', () => {
const mockEpicsPath =
'/groups/gitlab-org/-/epics.json?state=&start_date=2017-11-1&end_date=2018-6-30';
let mock;
beforeEach(() => {
mock = new MockAdapter(axios);
});
afterEach(() => {
mock.restore();
});
describe('success', () => {
it('should dispatch requestEpicsForTimeframe and receiveEpicsSuccess when request is successful', done => {
spyOn(epicUtils.gqClient, 'query').and.returnValue(
it('should dispatch requestEpicsForTimeframe and receiveEpicsSuccess when request is successful', () => {
jest.spyOn(epicUtils.gqClient, 'query').mockReturnValue(
Promise.resolve({
data: mockGroupEpicsQueryResponse.data,
}),
);
testAction(
return testAction(
actions.fetchEpicsForTimeframe,
{ timeframe: mockTimeframeMonths },
state,
......@@ -368,16 +335,15 @@ describe('Roadmap Vuex Actions', () => {
},
},
],
done,
);
});
});
describe('failure', () => {
it('should dispatch requestEpicsForTimeframe and requestEpicsFailure when request fails', done => {
mock.onGet(mockEpicsPath).replyOnce(500, {});
it('should dispatch requestEpicsForTimeframe and requestEpicsFailure when request fails', () => {
jest.spyOn(epicUtils.gqClient, 'query').mockRejectedValue();
testAction(
return testAction(
actions.fetchEpicsForTimeframe,
{ timeframe: mockTimeframeMonths },
state,
......@@ -390,38 +356,35 @@ describe('Roadmap Vuex Actions', () => {
type: 'receiveEpicsFailure',
},
],
done,
);
});
});
});
describe('extendTimeframe', () => {
it('should prepend to timeframe when called with extend type prepend', done => {
testAction(
it('should prepend to timeframe when called with extend type prepend', () => {
return testAction(
actions.extendTimeframe,
{ extendAs: EXTEND_AS.PREPEND },
state,
[{ type: types.PREPEND_TIMEFRAME, payload: mockTimeframeMonthsPrepend }],
[],
done,
);
});
it('should append to timeframe when called with extend type append', done => {
testAction(
it('should append to timeframe when called with extend type append', () => {
return testAction(
actions.extendTimeframe,
{ extendAs: EXTEND_AS.APPEND },
state,
[{ type: types.APPEND_TIMEFRAME, payload: mockTimeframeMonthsAppend }],
[],
done,
);
});
});
describe('refreshEpicDates', () => {
it('should update epics after refreshing epic dates to match with updated timeframe', done => {
it('should update epics after refreshing epic dates to match with updated timeframe', () => {
const epics = rawEpics.map(epic =>
roadmapItemUtils.formatRoadmapItemDetails(
epic,
......@@ -430,26 +393,24 @@ describe('Roadmap Vuex Actions', () => {
),
);
testAction(
return testAction(
actions.refreshEpicDates,
{},
{ ...state, timeframe: mockTimeframeMonths.concat(mockTimeframeMonthsAppend), epics },
[{ type: types.SET_EPICS, payload: epics }],
[],
done,
);
});
});
describe('setBufferSize', () => {
it('should set bufferSize in store state', done => {
testAction(
it('should set bufferSize in store state', () => {
return testAction(
actions.setBufferSize,
10,
state,
[{ type: types.SET_BUFFER_SIZE, payload: 10 }],
[],
done,
);
});
});
......@@ -474,42 +435,38 @@ describe('Roadmap Vuex Actions', () => {
};
});
it('should fetch Group Milestones using GraphQL client when milestoneIid is not present in state', done => {
spyOn(epicUtils.gqClient, 'query').and.returnValue(
it('should fetch Group Milestones using GraphQL client when milestoneIid is not present in state', () => {
jest.spyOn(epicUtils.gqClient, 'query').mockReturnValue(
Promise.resolve({
data: mockGroupMilestonesQueryResponse.data,
}),
);
actions
.fetchGroupMilestones(mockState)
.then(() => {
return actions.fetchGroupMilestones(mockState).then(() => {
expect(epicUtils.gqClient.query).toHaveBeenCalledWith({
query: groupMilestones,
variables: expectedVariables,
});
})
.then(done)
.catch(done.fail);
});
});
});
describe('requestMilestones', () => {
it('should set `milestonesFetchInProgress` to true', done => {
testAction(actions.requestMilestones, {}, state, [{ type: 'REQUEST_MILESTONES' }], [], done);
it('should set `milestonesFetchInProgress` to true', () => {
return testAction(actions.requestMilestones, {}, state, [{ type: 'REQUEST_MILESTONES' }], []);
});
});
describe('fetchMilestones', () => {
describe('success', () => {
it('should dispatch requestMilestones and receiveMilestonesSuccess when request is successful', done => {
spyOn(epicUtils.gqClient, 'query').and.returnValue(
it('should dispatch requestMilestones and receiveMilestonesSuccess when request is successful', () => {
jest.spyOn(epicUtils.gqClient, 'query').mockReturnValue(
Promise.resolve({
data: mockGroupMilestonesQueryResponse.data,
}),
);
testAction(
return testAction(
actions.fetchMilestones,
null,
state,
......@@ -523,14 +480,15 @@ describe('Roadmap Vuex Actions', () => {
payload: { rawMilestones },
},
],
done,
);
});
});
describe('failure', () => {
it('should dispatch requestMilestones and receiveMilestonesFailure when request fails', done => {
testAction(
it('should dispatch requestMilestones and receiveMilestonesFailure when request fails', () => {
jest.spyOn(epicUtils.gqClient, 'query').mockReturnValue(Promise.reject());
return testAction(
actions.fetchMilestones,
null,
state,
......@@ -543,15 +501,14 @@ describe('Roadmap Vuex Actions', () => {
type: 'receiveMilestonesFailure',
},
],
done,
);
});
});
});
describe('receiveMilestonesSuccess', () => {
it('should set formatted milestones array and milestoneId to IDs array in state based on provided milestones list', done => {
testAction(
it('should set formatted milestones array and milestoneId to IDs array in state based on provided milestones list', () => {
return testAction(
actions.receiveMilestonesSuccess,
{
rawMilestones: [
......@@ -579,38 +536,30 @@ describe('Roadmap Vuex Actions', () => {
},
],
[],
done,
);
});
});
describe('receiveMilestonesFailure', () => {
beforeEach(() => {
setFixtures('<div class="flash-container"></div>');
});
it('should set milestonesFetchInProgress to false and milestonesFetchFailure to true', done => {
testAction(
it('should set milestonesFetchInProgress to false and milestonesFetchFailure to true', () => {
return testAction(
actions.receiveMilestonesFailure,
{},
state,
[{ type: types.RECEIVE_MILESTONES_FAILURE }],
[],
done,
);
});
it('should show flash error', () => {
actions.receiveMilestonesFailure({ commit: () => {} });
expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
'Something went wrong while fetching milestones',
);
expect(createFlash).toHaveBeenCalledWith('Something went wrong while fetching milestones');
});
});
describe('refreshMilestoneDates', () => {
it('should update milestones after refreshing milestone dates to match with updated timeframe', done => {
it('should update milestones after refreshing milestone dates to match with updated timeframe', () => {
const milestones = rawMilestones.map(milestone =>
roadmapItemUtils.formatRoadmapItemDetails(
milestone,
......@@ -619,13 +568,12 @@ describe('Roadmap Vuex Actions', () => {
),
);
testAction(
return testAction(
actions.refreshMilestoneDates,
{},
{ ...state, timeframe: mockTimeframeMonths.concat(mockTimeframeMonthsAppend), milestones },
[{ type: types.SET_MILESTONES, payload: milestones }],
[],
done,
);
});
});
......
......@@ -3,7 +3,7 @@ import * as types from 'ee/roadmap/store/mutation_types';
import defaultState from 'ee/roadmap/store/state';
import { mockGroupId, basePath, epicsPath, mockSortedBy } from '../mock_data';
import { mockGroupId, basePath, epicsPath, mockSortedBy } from 'ee_jest/roadmap/mock_data';
const getEpic = (epicId, epics) => epics.find(e => e.id === epicId);
......@@ -36,7 +36,7 @@ describe('Roadmap Store Mutations', () => {
mutations[types.SET_INITIAL_DATA](state, initialData);
expect(state).toEqual(jasmine.objectContaining(initialData));
expect(state).toEqual(expect.objectContaining(initialData));
});
});
......
......@@ -9,7 +9,7 @@ describe('extractGroupEpics', () => {
expect(extractedEpics.length).toBe(edges.length);
expect(extractedEpics[0]).toEqual(
jasmine.objectContaining({
expect.objectContaining({
...edges[0].node,
groupName: edges[0].node.group.name,
groupFullName: edges[0].node.group.fullName,
......
......@@ -43,8 +43,8 @@ describe('getTimeframeForQuartersView', () => {
it('each timeframe item has `quarterSequence`, `year` and `range` present', () => {
const timeframeItem = timeframe[0];
expect(timeframeItem.quarterSequence).toEqual(jasmine.any(Number));
expect(timeframeItem.year).toEqual(jasmine.any(Number));
expect(timeframeItem.quarterSequence).toEqual(expect.any(Number));
expect(timeframeItem.year).toEqual(expect.any(Number));
expect(Array.isArray(timeframeItem.range)).toBe(true);
});
......@@ -307,7 +307,7 @@ describe('getEpicsTimeframeRange', () => {
});
expect(range).toEqual(
jasmine.objectContaining({
expect.objectContaining({
startDate: '2017-7-1',
dueDate: '2019-3-31',
}),
......@@ -322,7 +322,7 @@ describe('getEpicsTimeframeRange', () => {
});
expect(range).toEqual(
jasmine.objectContaining({
expect.objectContaining({
startDate: '2017-11-1',
dueDate: '2018-6-30',
}),
......@@ -337,7 +337,7 @@ describe('getEpicsTimeframeRange', () => {
});
expect(range).toEqual(
jasmine.objectContaining({
expect.objectContaining({
startDate: '2017-12-17',
dueDate: '2018-2-3',
}),
......
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