Commit ad1e207a authored by Kushal Pandya's avatar Kushal Pandya

Merge branch 'euko-small-roadmap-shell-clean-up' into 'master'

Remove unused skeleton loader, css and fix mock data for roadmap code

See merge request gitlab-org/gitlab!48654
parents 0c4d3ba4 f88b30aa
......@@ -165,7 +165,7 @@ export default {
<template>
<span class="epic-timeline-cell" data-qa-selector="epic_timeline_cell">
<current-day-indicator :preset-type="presetType" :timeframe-item="timeframeItem" />
<div class="epic-bar-wrapper">
<div class="gl-relative">
<a
v-if="hasStartDate"
:id="generateKey(epic)"
......
<script>
import { mapState } from 'vuex';
import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import { isInViewport } from '~/lib/utils/common_utils';
import { EXTEND_AS } from '../constants';
......@@ -12,7 +11,6 @@ import roadmapTimelineSection from './roadmap_timeline_section.vue';
export default {
components: {
GlSkeletonLoading,
epicsListSection,
milestonesListSection,
roadmapTimelineSection,
......@@ -92,7 +90,7 @@ export default {
<template>
<div
class="roadmap-shell js-roadmap-shell"
class="js-roadmap-shell gl-relative gl-h-full gl-w-full gl-overflow-x-auto"
data-qa-selector="roadmap_shell"
@scroll="handleScroll"
>
......@@ -109,13 +107,7 @@ export default {
:timeframe="timeframe"
:current-group-id="currentGroupId"
/>
<div v-if="!epics.length" class="skeleton-loader js-skeleton-loader">
<div v-for="n in 10" :key="n" class="mt-2">
<gl-skeleton-loading :lines="2" />
</div>
</div>
<epics-list-section
v-else
:preset-type="presetType"
:epics="epics"
:timeframe="timeframe"
......
......@@ -123,31 +123,6 @@ html.group-epics-roadmap-html {
}
}
.roadmap-shell {
position: relative;
height: 100%;
width: 100%;
overflow-x: auto;
.skeleton-loader {
position: absolute;
top: $header-item-height;
width: $details-cell-width;
height: 100%;
padding-top: $gl-padding-top;
padding-left: $gl-padding;
z-index: 4;
&::after {
height: 100%;
}
}
&.prevent-vertical-scroll {
overflow-y: hidden;
}
}
.roadmap-timeline-section .timeline-header-blank::after,
.epics-list-section .epic-details-cell::after,
.milestones-list-section .milestones-list-title::after,
......@@ -324,10 +299,6 @@ html.group-epics-roadmap-html {
}
}
.epic-bar-wrapper {
position: relative;
}
.epic-bar {
position: absolute;
top: 5px;
......
......@@ -67,9 +67,9 @@ RSpec.describe 'Epic show', :js do
it 'shows Roadmap timeline with child epics' do
page.within('.js-epic-tabs-content #roadmap') do
expect(page).to have_selector('.roadmap-container .roadmap-shell')
expect(page).to have_selector('.roadmap-container .js-roadmap-shell')
page.within('.roadmap-shell .epics-list-section') do
page.within('.js-roadmap-shell .epics-list-section') do
expect(page).not_to have_content(not_child.title)
expect(find('.epic-item-container:nth-child(1) .epics-list-item .epic-title')).to have_content('Child epic B')
expect(find('.epic-item-container:nth-child(2) .epics-list-item .epic-title')).to have_content('Child epic A')
......
......@@ -99,7 +99,7 @@ describe('EpicItemComponent', () => {
describe('timeframeString', () => {
it('returns timeframe string correctly when both start and end dates are defined', () => {
expect(wrapper.vm.timeframeString(mockEpic)).toBe('Jul 10, 2017 – Jun 2, 2018');
expect(wrapper.vm.timeframeString(mockEpic)).toBe('Nov 10, 2017 – Jun 2, 2018');
});
it('returns timeframe string correctly when no dates are defined', () => {
......@@ -113,7 +113,7 @@ describe('EpicItemComponent', () => {
const epic = { ...mockEpic, endDateUndefined: true };
wrapper = createComponent({ epic });
expect(wrapper.vm.timeframeString(epic)).toBe('Jul 10, 2017 – No end date');
expect(wrapper.vm.timeframeString(epic)).toBe('Nov 10, 2017 – No end date');
});
it('returns timeframe string correctly when only end date is defined', () => {
......
import Vue from 'vue';
import Vuex from 'vuex';
import { mount, createLocalVue } from '@vue/test-utils';
import roadmapShellComponent from 'ee/roadmap/components/roadmap_shell.vue';
import RoadmapShell from 'ee/roadmap/components/roadmap_shell.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import eventHub from 'ee/roadmap/event_hub';
import createStore from 'ee/roadmap/store';
......@@ -12,65 +13,71 @@ import {
mockGroupId,
mockMilestone,
} from 'ee_jest/roadmap/mock_data';
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const createComponent = (
{
epics = [mockEpic],
milestones = [mockMilestone],
timeframe = mockTimeframeMonths,
currentGroupId = mockGroupId,
defaultInnerHeight = 0,
hasFiltersApplied = false,
},
el,
) => {
const Component = Vue.extend(roadmapShellComponent);
const store = createStore();
store.dispatch('setInitialData', {
defaultInnerHeight,
childrenFlags: { '1': { itemExpanded: false } },
});
describe('RoadmapShell', () => {
const localVue = createLocalVue();
localVue.use(Vuex);
return mountComponentWithStore(Component, {
el,
store,
props: {
presetType: PRESET_TYPES.MONTHS,
epics,
milestones,
timeframe,
currentGroupId,
hasFiltersApplied,
},
});
};
let store;
let wrapper;
describe('RoadmapShellComponent', () => {
let vm;
const storeFactory = ({ defaultInnerHeight = 0 }) => {
store = createStore();
store.dispatch('setInitialData', {
defaultInnerHeight,
childrenFlags: { '1': { itemExpanded: false } },
});
};
const createComponent = (
{
epics = [mockEpic],
milestones = [mockMilestone],
timeframe = mockTimeframeMonths,
currentGroupId = mockGroupId,
hasFiltersApplied = false,
},
el,
) => {
wrapper = mount(RoadmapShell, {
localVue,
store,
attachTo: el,
propsData: {
presetType: PRESET_TYPES.MONTHS,
epics,
milestones,
timeframe,
currentGroupId,
hasFiltersApplied,
},
});
};
beforeEach(done => {
vm = createComponent({});
vm.$nextTick(done);
beforeEach(() => {
storeFactory({});
createComponent({});
});
afterEach(() => {
vm.$destroy();
wrapper.destroy();
wrapper = null;
store = null;
});
describe('data', () => {
it('returns default data props', () => {
expect(vm.timeframeStartOffset).toBe(0);
expect(wrapper.vm.timeframeStartOffset).toBe(0);
});
});
describe('methods', () => {
beforeEach(() => {
document.body.innerHTML +=
'<div class="roadmap-container"><div id="roadmap-shell"></div></div>';
'<div class="roadmap-container"><div data-testid="roadmap-shell"></div></div>';
createComponent({}, document.querySelector('[data-testid="roadmap-shell"]'));
});
afterEach(() => {
......@@ -78,38 +85,20 @@ describe('RoadmapShellComponent', () => {
});
describe('handleScroll', () => {
it('emits `epicsListScrolled` event via eventHub', done => {
const vmWithParentEl = createComponent({}, document.getElementById('roadmap-shell'));
it('emits `epicsListScrolled` event via eventHub', async () => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
Vue.nextTick()
.then(() => {
vmWithParentEl.handleScroll();
expect(eventHub.$emit).toHaveBeenCalledWith('epicsListScrolled', expect.any(Object));
await wrapper.vm.$nextTick();
wrapper.vm.handleScroll();
vmWithParentEl.$destroy();
})
.then(done)
.catch(done.fail);
expect(eventHub.$emit).toHaveBeenCalledWith('epicsListScrolled', expect.any(Object));
});
});
});
describe('template', () => {
it('renders component container element with class `roadmap-shell`', () => {
expect(vm.$el.classList.contains('roadmap-shell')).toBe(true);
});
it('renders skeleton loader element when Epics list is empty', done => {
vm.epics = [];
vm.$nextTick()
.then(() => {
expect(vm.$el.querySelector('.js-skeleton-loader')).not.toBeNull();
})
.then(done)
.catch(done.fail);
it('renders component container element with class `js-roadmap-shell`', () => {
expect(wrapper.find('.js-roadmap-shell').exists()).toBe(true);
});
});
});
......@@ -104,8 +104,8 @@ export const mockEpic = {
groupId: 2,
groupName: 'Gitlab Org',
groupFullName: 'Gitlab Org',
startDate: new Date('2017-07-10'),
originalStartDate: new Date('2017-07-10'),
startDate: new Date('2017-11-10'),
originalStartDate: new Date('2017-11-10'),
endDate: new Date('2018-06-02'),
webUrl: '/groups/gitlab-org/-/epics/1',
descendantCounts: {
......
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