Commit 70abdb44 authored by Ezekiel Kigbo's avatar Ezekiel Kigbo

Added path navigation to project VSA

Adds the path navigation to project level
VSA and removes the existing horizontal
navigation. Update path navigation selectors.

Changelog: changed
EE: true
parent b4705bb2
......@@ -117,7 +117,6 @@ export default {
<div class="cycle-analytics">
<path-navigation
v-if="shouldDisplayPathNavigation"
:key="`path_navigation_key_${pathNavigationData.length}`"
class="js-path-navigation gl-w-full gl-pb-2"
:loading="isLoading"
:stages="pathNavigationData"
......
......@@ -167,7 +167,6 @@ export default {
<div v-if="!shouldRenderEmptyState" class="gl-max-w-full">
<path-navigation
v-if="selectedStageReady"
:key="`path_navigation_key_${pathNavigationData.length}`"
class="js-path-navigation gl-w-full gl-pb-2"
:loading="isLoading"
:stages="pathNavigationData"
......
import { mount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import Component from '~/cycle_analytics/components/path_navigation.vue';
import { OVERVIEW_STAGE_ID } from '~/cycle_analytics/constants';
import { transformedStagePathData, issueStage } from '../mock_data';
describe('Group PathNavigation', () => {
let wrapper = null;
const createComponent = (props) => {
return mount(Component, {
return extendedWrapper(
mount(Component, {
propsData: {
stages: transformedStagePathData,
selectedStage: issueStage,
loading: false,
...props,
},
});
}),
);
};
const pathNavigationItems = () => {
return wrapper.findAll('.gl-path-nav-list-item');
return wrapper.findByTestId('gl-path-nav').findAll('li');
};
const pathItemContent = () => pathNavigationItems().wrappers;
const stagesWithCounts = transformedStagePathData.filter(
(stage) => stage.id !== OVERVIEW_STAGE_ID,
);
beforeEach(() => {
wrapper = createComponent();
});
......@@ -35,8 +45,7 @@ describe('Group PathNavigation', () => {
});
it('renders popovers for all stages except for the overview stage', () => {
const pathItemContent = pathNavigationItems().wrappers;
const [overviewStage, ...popoverStages] = pathItemContent;
const [overviewStage, ...popoverStages] = pathItemContent();
expect(overviewStage.text()).toContain('Overview');
expect(overviewStage.find('[data-testid="stage-item-popover"]').exists()).toBe(false);
......@@ -63,5 +72,14 @@ describe('Group PathNavigation', () => {
const firstPopover = wrapper.findAll('[data-testid="stage-item-popover"]').at(0);
expect(firstPopover.text()).toContain('Stage time (median)');
});
it('renders each stage with its stage count', () => {
const popoverStages = pathItemContent().slice(1); // skip the first stage, the overview does not have a popover
popoverStages.forEach((stage, index) => {
const content = stage.find('[data-testid="stage-item-popover"]').html();
expect(content).toContain('Items in stage');
expect(content).toContain(`${stagesWithCounts[index].stageCount} items`);
});
});
});
});
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Project PathNavigation displays correctly loading is false matches the snapshot 1`] = `
<div
class="gl-path-nav"
data-testid="gl-path-nav"
style="--path-bg-color: white;"
>
<span
class="gl-path-fade gl-path-fade-left"
style="display: none;"
>
<button
aria-label="Scroll left"
class="gl-clear-icon-button"
>
<svg
aria-hidden="true"
class="gl-icon s32"
data-testid="chevron-left-icon"
role="img"
>
<use
href="#chevron-left"
/>
</svg>
</button>
</span>
<ul
class="gl-path-nav-list"
>
<li
class="gl-path-nav-list-item"
id="path-6-item-0"
>
<button
class="gl-path-button gl-path-active-item-indigo"
>
<!---->
Issue
<span
class="gl-font-weight-normal gl-pl-2"
>
172800
</span>
</button>
<div
class="gl-popover"
data-testid="stage-item-popover"
>
<div
class="gl-px-4"
>
<div
class="gl-display-flex gl-justify-content-space-between"
>
<div
class="gl-pr-4 gl-pb-4"
>
Stage time (median)
</div>
<div
class="gl-pb-4 gl-font-weight-bold"
>
172800
</div>
</div>
</div>
<div
class="gl-px-4"
>
<div
class="gl-display-flex gl-justify-content-space-between"
>
<div
class="gl-pr-4 gl-pb-4"
>
Items in stage
</div>
<div
class="gl-pb-4 gl-font-weight-bold"
>
-
</div>
</div>
</div>
<div
class="gl-px-4 gl-pt-4 gl-border-t-1 gl-border-t-solid gl-border-gray-50"
>
<!---->
<!---->
</div>
Issue
</div>
</li>
<li
class="gl-path-nav-list-item"
id="path-6-item-1"
>
<button
class="gl-path-button"
>
<!---->
Plan
<span
class="gl-font-weight-normal gl-pl-2"
>
86400
</span>
</button>
<div
class="gl-popover"
data-testid="stage-item-popover"
>
<div
class="gl-px-4"
>
<div
class="gl-display-flex gl-justify-content-space-between"
>
<div
class="gl-pr-4 gl-pb-4"
>
Stage time (median)
</div>
<div
class="gl-pb-4 gl-font-weight-bold"
>
86400
</div>
</div>
</div>
<div
class="gl-px-4"
>
<div
class="gl-display-flex gl-justify-content-space-between"
>
<div
class="gl-pr-4 gl-pb-4"
>
Items in stage
</div>
<div
class="gl-pb-4 gl-font-weight-bold"
>
-
</div>
</div>
</div>
<div
class="gl-px-4 gl-pt-4 gl-border-t-1 gl-border-t-solid gl-border-gray-50"
>
<!---->
<!---->
</div>
Plan
</div>
</li>
<li
class="gl-path-nav-list-item"
id="path-6-item-2"
>
<button
class="gl-path-button"
>
<!---->
Code
<span
class="gl-font-weight-normal gl-pl-2"
>
129600
</span>
</button>
<div
class="gl-popover"
data-testid="stage-item-popover"
>
<div
class="gl-px-4"
>
<div
class="gl-display-flex gl-justify-content-space-between"
>
<div
class="gl-pr-4 gl-pb-4"
>
Stage time (median)
</div>
<div
class="gl-pb-4 gl-font-weight-bold"
>
129600
</div>
</div>
</div>
<div
class="gl-px-4"
>
<div
class="gl-display-flex gl-justify-content-space-between"
>
<div
class="gl-pr-4 gl-pb-4"
>
Items in stage
</div>
<div
class="gl-pb-4 gl-font-weight-bold"
>
-
</div>
</div>
</div>
<div
class="gl-px-4 gl-pt-4 gl-border-t-1 gl-border-t-solid gl-border-gray-50"
>
<!---->
<!---->
</div>
Code
</div>
</li>
</ul>
<span
class="gl-path-fade gl-path-fade-right"
style="display: none;"
>
<button
aria-label="Scroll right"
class="gl-clear-icon-button"
>
<svg
aria-hidden="true"
class="gl-icon s32"
data-testid="chevron-right-icon"
role="img"
>
<use
href="#chevron-right"
/>
</svg>
</button>
</span>
</div>
`;
import { GlPath, GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import Component from '~/cycle_analytics/components/path_navigation.vue';
import { transformedProjectStagePathData, selectedStage } from './mock_data';
......@@ -7,26 +8,34 @@ describe('Project PathNavigation', () => {
let wrapper = null;
const createComponent = (props) => {
return mount(Component, {
return extendedWrapper(
mount(Component, {
propsData: {
stages: transformedProjectStagePathData,
selectedStage,
loading: false,
...props,
},
});
}),
);
};
const findPathNavigation = () => {
return wrapper.findByTestId('gl-path-nav');
};
const pathNavigationTitles = () => {
return wrapper.findAll('.gl-path-button');
const findPathNavigationItems = () => {
return findPathNavigation().findAll('li');
};
const pathNavigationItems = () => {
return wrapper.findAll('.gl-path-nav-list-item');
const findPathNavigationTitles = () => {
return findPathNavigation()
.findAll('li button')
.wrappers.map((w) => w.html());
};
const clickItemAt = (index) => {
pathNavigationTitles().at(index).trigger('click');
findPathNavigationItems().at(index).find('button').trigger('click');
};
beforeEach(() => {
......@@ -61,9 +70,17 @@ describe('Project PathNavigation', () => {
expect(wrapper.find(GlSkeletonLoading).exists()).toBe(false);
});
// TODO: make this test more granular
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
it('renders each stage', () => {
const result = findPathNavigationTitles();
expect(result.length).toBe(transformedProjectStagePathData.length);
});
it('renders each stage with its median', () => {
const result = findPathNavigationTitles();
transformedProjectStagePathData.forEach(({ title, metric }, index) => {
expect(result[index]).toContain(title);
expect(result[index]).toContain(metric);
});
});
describe('popovers', () => {
......@@ -72,7 +89,7 @@ describe('Project PathNavigation', () => {
});
it('renders popovers for all stages', () => {
const pathItemContent = pathNavigationItems().wrappers;
const pathItemContent = findPathNavigationItems().wrappers;
pathItemContent.forEach((stage) => {
expect(stage.find('[data-testid="stage-item-popover"]').exists()).toBe(true);
......
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