diff options
Diffstat (limited to 'spec/frontend/cycle_analytics')
-rw-r--r-- | spec/frontend/cycle_analytics/banner_spec.js | 47 | ||||
-rw-r--r-- | spec/frontend/cycle_analytics/base_spec.js | 28 | ||||
-rw-r--r-- | spec/frontend/cycle_analytics/stage_table_spec.js | 19 | ||||
-rw-r--r-- | spec/frontend/cycle_analytics/store/actions_spec.js | 61 | ||||
-rw-r--r-- | spec/frontend/cycle_analytics/store/mutations_spec.js | 11 |
5 files changed, 95 insertions, 71 deletions
diff --git a/spec/frontend/cycle_analytics/banner_spec.js b/spec/frontend/cycle_analytics/banner_spec.js deleted file mode 100644 index ef7998c5ff5..00000000000 --- a/spec/frontend/cycle_analytics/banner_spec.js +++ /dev/null @@ -1,47 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import Banner from '~/cycle_analytics/components/banner.vue'; - -describe('Value Stream Analytics banner', () => { - let wrapper; - - const createComponent = () => { - wrapper = shallowMount(Banner, { - propsData: { - documentationLink: 'path', - }, - }); - }; - - beforeEach(() => { - createComponent(); - }); - - afterEach(() => { - wrapper.destroy(); - }); - - it('should render value stream analytics information', () => { - expect(wrapper.find('h4').text().trim()).toBe('Introducing Value Stream Analytics'); - - expect( - wrapper - .find('p') - .text() - .trim() - .replace(/[\r\n]+/g, ' '), - ).toContain( - 'Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project.', - ); - - expect(wrapper.find('a').text().trim()).toBe('Read more'); - expect(wrapper.find('a').attributes('href')).toBe('path'); - }); - - it('should emit an event when close button is clicked', async () => { - jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {}); - - await wrapper.find('.js-ca-dismiss-button').trigger('click'); - - expect(wrapper.vm.$emit).toHaveBeenCalled(); - }); -}); diff --git a/spec/frontend/cycle_analytics/base_spec.js b/spec/frontend/cycle_analytics/base_spec.js index 71830eed3ef..5d3361bfa35 100644 --- a/spec/frontend/cycle_analytics/base_spec.js +++ b/spec/frontend/cycle_analytics/base_spec.js @@ -6,6 +6,7 @@ import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import BaseComponent from '~/cycle_analytics/components/base.vue'; import PathNavigation from '~/cycle_analytics/components/path_navigation.vue'; import StageTable from '~/cycle_analytics/components/stage_table.vue'; +import ValueStreamFilters from '~/cycle_analytics/components/value_stream_filters.vue'; import ValueStreamMetrics from '~/cycle_analytics/components/value_stream_metrics.vue'; import { NOT_ENOUGH_DATA_ERROR } from '~/cycle_analytics/constants'; import initState from '~/cycle_analytics/store/state'; @@ -30,13 +31,14 @@ Vue.use(Vuex); let wrapper; +const { id: groupId, path: groupPath } = currentGroup; const defaultState = { permissions, currentGroup, createdBefore, createdAfter, stageCounts, - endpoints: { fullPath }, + endpoints: { fullPath, groupId, groupPath }, }; function createStore({ initialState = {}, initialGetters = {} }) { @@ -74,6 +76,7 @@ function createComponent({ initialState, initialGetters } = {}) { const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); const findPathNavigation = () => wrapper.findComponent(PathNavigation); +const findFilters = () => wrapper.findComponent(ValueStreamFilters); const findOverviewMetrics = () => wrapper.findComponent(ValueStreamMetrics); const findStageTable = () => wrapper.findComponent(StageTable); const findStageEvents = () => findStageTable().props('stageEvents'); @@ -123,6 +126,29 @@ describe('Value stream analytics component', () => { expect(findStageEvents()).toEqual(selectedStageEvents); }); + it('renders the filters', () => { + expect(findFilters().exists()).toBe(true); + }); + + it('displays the date range selector and hides the project selector', () => { + expect(findFilters().props()).toMatchObject({ + hasProjectFilter: false, + hasDateRangeFilter: true, + }); + }); + + it('passes the paths to the filter bar', () => { + expect(findFilters().props()).toEqual({ + groupId, + groupPath, + endDate: createdBefore, + hasDateRangeFilter: true, + hasProjectFilter: false, + selectedProjects: [], + startDate: createdAfter, + }); + }); + it('does not render the loading icon', () => { expect(findLoadingIcon().exists()).toBe(false); }); diff --git a/spec/frontend/cycle_analytics/stage_table_spec.js b/spec/frontend/cycle_analytics/stage_table_spec.js index 47a2ce4444b..3158446c37d 100644 --- a/spec/frontend/cycle_analytics/stage_table_spec.js +++ b/spec/frontend/cycle_analytics/stage_table_spec.js @@ -22,6 +22,7 @@ const findStageEvents = () => wrapper.findAllByTestId('vsa-stage-event'); const findPagination = () => wrapper.findByTestId('vsa-stage-pagination'); const findTable = () => wrapper.findComponent(GlTable); const findTableHead = () => wrapper.find('thead'); +const findTableHeadColumns = () => findTableHead().findAll('th'); const findStageEventTitle = (ev) => extendedWrapper(ev).findByTestId('vsa-stage-event-title'); const findStageTime = () => wrapper.findByTestId('vsa-stage-event-time'); const findIcon = (name) => wrapper.findByTestId(`${name}-icon`); @@ -244,6 +245,12 @@ describe('StageTable', () => { wrapper.destroy(); }); + it('can sort the table by each column', () => { + findTableHeadColumns().wrappers.forEach((w) => { + expect(w.attributes('aria-sort')).toBe('none'); + }); + }); + it('clicking a table column will send tracking information', () => { triggerTableSort(); @@ -275,5 +282,17 @@ describe('StageTable', () => { }, ]); }); + + describe('with sortable=false', () => { + beforeEach(() => { + wrapper = createComponent({ sortable: false }); + }); + + it('cannot sort the table', () => { + findTableHeadColumns().wrappers.forEach((w) => { + expect(w.attributes('aria-sort')).toBeUndefined(); + }); + }); + }); }); }); diff --git a/spec/frontend/cycle_analytics/store/actions_spec.js b/spec/frontend/cycle_analytics/store/actions_spec.js index 915a828ff19..97b5bd03e18 100644 --- a/spec/frontend/cycle_analytics/store/actions_spec.js +++ b/spec/frontend/cycle_analytics/store/actions_spec.js @@ -4,21 +4,41 @@ import testAction from 'helpers/vuex_action_helper'; import * as actions from '~/cycle_analytics/store/actions'; import * as getters from '~/cycle_analytics/store/getters'; import httpStatusCodes from '~/lib/utils/http_status'; -import { allowedStages, selectedStage, selectedValueStream } from '../mock_data'; - +import { + allowedStages, + selectedStage, + selectedValueStream, + currentGroup, + createdAfter, + createdBefore, +} from '../mock_data'; + +const { id: groupId, path: groupPath } = currentGroup; +const mockMilestonesPath = 'mock-milestones.json'; +const mockLabelsPath = 'mock-labels.json'; const mockRequestPath = 'some/cool/path'; const mockFullPath = '/namespace/-/analytics/value_stream_analytics/value_streams'; -const mockStartDate = 30; -const mockEndpoints = { fullPath: mockFullPath, requestPath: mockRequestPath }; -const mockSetDateActionCommit = { payload: { startDate: mockStartDate }, type: 'SET_DATE_RANGE' }; - -const defaultState = { ...getters, selectedValueStream }; +const mockEndpoints = { + fullPath: mockFullPath, + requestPath: mockRequestPath, + labelsPath: mockLabelsPath, + milestonesPath: mockMilestonesPath, + groupId, + groupPath, +}; +const mockSetDateActionCommit = { + payload: { createdAfter, createdBefore }, + type: 'SET_DATE_RANGE', +}; + +const defaultState = { ...getters, selectedValueStream, createdAfter, createdBefore }; describe('Project Value Stream Analytics actions', () => { let state; let mock; beforeEach(() => { + state = { ...defaultState }; mock = new MockAdapter(axios); }); @@ -34,16 +54,17 @@ describe('Project Value Stream Analytics actions', () => { { type: 'fetchCycleAnalyticsData' }, { type: 'fetchStageData' }, { type: 'fetchStageMedians' }, + { type: 'fetchStageCountValues' }, { type: 'setLoading', payload: false }, ]; describe.each` - action | payload | expectedActions | expectedMutations - ${'setLoading'} | ${true} | ${[]} | ${[{ type: 'SET_LOADING', payload: true }]} - ${'setDateRange'} | ${{ startDate: mockStartDate }} | ${mockFetchStageDataActions} | ${[mockSetDateActionCommit]} - ${'setFilters'} | ${[]} | ${mockFetchStageDataActions} | ${[]} - ${'setSelectedStage'} | ${{ selectedStage }} | ${[{ type: 'fetchStageData' }]} | ${[{ type: 'SET_SELECTED_STAGE', payload: { selectedStage } }]} - ${'setSelectedValueStream'} | ${{ selectedValueStream }} | ${[{ type: 'fetchValueStreamStages' }, { type: 'fetchCycleAnalyticsData' }]} | ${[{ type: 'SET_SELECTED_VALUE_STREAM', payload: { selectedValueStream } }]} + action | payload | expectedActions | expectedMutations + ${'setLoading'} | ${true} | ${[]} | ${[{ type: 'SET_LOADING', payload: true }]} + ${'setDateRange'} | ${{ createdAfter, createdBefore }} | ${mockFetchStageDataActions} | ${[mockSetDateActionCommit]} + ${'setFilters'} | ${[]} | ${mockFetchStageDataActions} | ${[]} + ${'setSelectedStage'} | ${{ selectedStage }} | ${[{ type: 'fetchStageData' }]} | ${[{ type: 'SET_SELECTED_STAGE', payload: { selectedStage } }]} + ${'setSelectedValueStream'} | ${{ selectedValueStream }} | ${[{ type: 'fetchValueStreamStages' }, { type: 'fetchCycleAnalyticsData' }]} | ${[{ type: 'SET_SELECTED_VALUE_STREAM', payload: { selectedValueStream } }]} `('$action', ({ action, payload, expectedActions, expectedMutations }) => { const types = mutationTypes(expectedMutations); it(`will dispatch ${expectedActions} and commit ${types}`, () => @@ -60,6 +81,12 @@ describe('Project Value Stream Analytics actions', () => { let mockDispatch; let mockCommit; const payload = { endpoints: mockEndpoints }; + const mockFilterEndpoints = { + groupEndpoint: 'foo', + labelsEndpoint: mockLabelsPath, + milestonesEndpoint: mockMilestonesPath, + projectEndpoint: '/namespace/-/analytics/value_stream_analytics/value_streams', + }; beforeEach(() => { mockDispatch = jest.fn(() => Promise.resolve()); @@ -76,6 +103,9 @@ describe('Project Value Stream Analytics actions', () => { payload, ); expect(mockCommit).toHaveBeenCalledWith('INITIALIZE_VSA', { endpoints: mockEndpoints }); + + expect(mockDispatch).toHaveBeenCalledTimes(4); + expect(mockDispatch).toHaveBeenCalledWith('filters/setEndpoints', mockFilterEndpoints); expect(mockDispatch).toHaveBeenCalledWith('setLoading', true); expect(mockDispatch).toHaveBeenCalledWith('fetchValueStreams'); expect(mockDispatch).toHaveBeenCalledWith('setLoading', false); @@ -84,7 +114,7 @@ describe('Project Value Stream Analytics actions', () => { describe('fetchCycleAnalyticsData', () => { beforeEach(() => { - state = { endpoints: mockEndpoints }; + state = { ...defaultState, endpoints: mockEndpoints }; mock = new MockAdapter(axios); mock.onGet(mockRequestPath).reply(httpStatusCodes.OK); }); @@ -129,7 +159,6 @@ describe('Project Value Stream Analytics actions', () => { state = { ...defaultState, endpoints: mockEndpoints, - startDate: mockStartDate, selectedStage, }; mock = new MockAdapter(axios); @@ -152,7 +181,6 @@ describe('Project Value Stream Analytics actions', () => { state = { ...defaultState, endpoints: mockEndpoints, - startDate: mockStartDate, selectedStage, }; mock = new MockAdapter(axios); @@ -177,7 +205,6 @@ describe('Project Value Stream Analytics actions', () => { state = { ...defaultState, endpoints: mockEndpoints, - startDate: mockStartDate, selectedStage, }; mock = new MockAdapter(axios); diff --git a/spec/frontend/cycle_analytics/store/mutations_spec.js b/spec/frontend/cycle_analytics/store/mutations_spec.js index 7fcfef98547..628e2a4e7ae 100644 --- a/spec/frontend/cycle_analytics/store/mutations_spec.js +++ b/spec/frontend/cycle_analytics/store/mutations_spec.js @@ -1,5 +1,4 @@ import { useFakeDate } from 'helpers/fake_date'; -import { DEFAULT_DAYS_TO_DISPLAY } from '~/cycle_analytics/constants'; import * as types from '~/cycle_analytics/store/mutation_types'; import mutations from '~/cycle_analytics/store/mutations'; import { @@ -65,15 +64,16 @@ describe('Project Value Stream Analytics mutations', () => { expect(state).toMatchObject({ [stateKey]: value }); }); + const mockSetDatePayload = { createdAfter: mockCreatedAfter, createdBefore: mockCreatedBefore }; const mockInitialPayload = { endpoints: { requestPath: mockRequestPath }, currentGroup: { title: 'cool-group' }, id: 1337, + ...mockSetDatePayload, }; const mockInitializedObj = { endpoints: { requestPath: mockRequestPath }, - createdAfter: mockCreatedAfter, - createdBefore: mockCreatedBefore, + ...mockSetDatePayload, }; it.each` @@ -89,9 +89,8 @@ describe('Project Value Stream Analytics mutations', () => { it.each` mutation | payload | stateKey | value - ${types.SET_DATE_RANGE} | ${DEFAULT_DAYS_TO_DISPLAY} | ${'daysInPast'} | ${DEFAULT_DAYS_TO_DISPLAY} - ${types.SET_DATE_RANGE} | ${DEFAULT_DAYS_TO_DISPLAY} | ${'createdAfter'} | ${mockCreatedAfter} - ${types.SET_DATE_RANGE} | ${DEFAULT_DAYS_TO_DISPLAY} | ${'createdBefore'} | ${mockCreatedBefore} + ${types.SET_DATE_RANGE} | ${mockSetDatePayload} | ${'createdAfter'} | ${mockCreatedAfter} + ${types.SET_DATE_RANGE} | ${mockSetDatePayload} | ${'createdBefore'} | ${mockCreatedBefore} ${types.SET_LOADING} | ${true} | ${'isLoading'} | ${true} ${types.SET_LOADING} | ${false} | ${'isLoading'} | ${false} ${types.SET_SELECTED_VALUE_STREAM} | ${selectedValueStream} | ${'selectedValueStream'} | ${selectedValueStream} |