diff --git a/ee/app/assets/javascripts/roadmap/components/epics_list_section.vue b/ee/app/assets/javascripts/roadmap/components/epics_list_section.vue index 94fc284721c4ebbc0689d9bd69b706aa734d9bdd..bf306ec1265106c6058e977bb1a4f934d945c00e 100644 --- a/ee/app/assets/javascripts/roadmap/components/epics_list_section.vue +++ b/ee/app/assets/javascripts/roadmap/components/epics_list_section.vue @@ -84,7 +84,8 @@ export default { epicsWithAssociatedParents() { return this.epics.filter((epic) => { if (epic.hasParent) { - if (epic.parent.startDate && epic.parent.dueDate) { + // In case `epic.parent` is null, user doesn't have access to parent and in that case, we just show current epic as is. + if (epic.parent?.startDate && epic.parent?.dueDate) { return this.epicIds.indexOf(epic.parent.id) < 0; } return epic.ancestors.nodes.every((ancestor) => this.epicIds.indexOf(ancestor.id) < 0); @@ -142,9 +143,15 @@ export default { scrollToCurrentDay(this.$el); }); - if (!Object.keys(this.emptyRowContainerStyles).length) { - this.emptyRowContainerStyles = this.getEmptyRowContainerStyles(); - } + // Without setTimeout (or any form of deferred execution), when `getEmptyRowContainerStyles` function called, + // the props that the function relies on aren't available yet, so props like `bufferSize`, `displayedEpics` + // are still in process of initialization, and in that case, `emptyRowContainerStyles` is never initialised + // causing the element not to get the style definition it needs. Also, using `$nextTick` doesn't help here. + setTimeout(() => { + if (!Object.keys(this.emptyRowContainerStyles).length) { + this.emptyRowContainerStyles = this.getEmptyRowContainerStyles(); + } + }); }); this.syncClientWidth(); diff --git a/ee/spec/frontend/roadmap/components/epics_list_section_spec.js b/ee/spec/frontend/roadmap/components/epics_list_section_spec.js index a6de95534237c1fc5738170d0977f72670485ca9..57ca4d8607a9ccaa3895643aabbaf65c5f4c7e3b 100644 --- a/ee/spec/frontend/roadmap/components/epics_list_section_spec.js +++ b/ee/spec/frontend/roadmap/components/epics_list_section_spec.js @@ -107,13 +107,6 @@ describe('EpicsListSectionComponent', () => { expect(findEmptyRowEl().attributes('style')).not.toBeDefined(); }); - it('sets style attribute with `height` on empty row when there epics available to render', async () => { - createComponent(); - await nextTick(); - - expect(findEmptyRowEl().attributes('style')).toBe('height: calc(100vh - 1px);'); - }); - describe('epics with associated parents', () => { it('should return only epics where parent is not present on top level', async () => { createComponent({ epics: mockEpicsWithParents }); @@ -139,8 +132,11 @@ describe('EpicsListSectionComponent', () => { }); describe('when mounted', () => { - beforeEach(() => { + beforeEach(async () => { createComponent(); + + await nextTick(); + jest.runAllTimers(); }); it('calls `setBufferSize` mutation with value based on window.innerHeight and component element position', () => { diff --git a/ee/spec/frontend/roadmap/mock_data.js b/ee/spec/frontend/roadmap/mock_data.js index e95689b4de850bd89899118fdd0e663e8ed959ba..b482a5e26da3290f28fe7a0f0a1be5e6e27e7fa3 100644 --- a/ee/spec/frontend/roadmap/mock_data.js +++ b/ee/spec/frontend/roadmap/mock_data.js @@ -371,6 +371,28 @@ export const rawEpics = [ }, group: mockGroup2, }, + { + id: 'gid://gitlab/Epic/42', + iid: 18, + description: null, + title: 'Epic with inaccessible parent', + startDate: '2017-12-26', + endDate: '2018-03-10', + webUrl: '/groups/gitlab-org/marketing/-/epics/18', + descendantCounts: defaultDescendantCounts, + hasParent: true, + color: '#ff0000', + textColor: '#ffffff', + parent: null, + ancestors: { + nodes: [ + { + id: 'gid://gitlab/Epic/40', + }, + ], + }, + group: mockGroup2, + }, { id: 'gid://gitlab/Epic/40', iid: 1,