diff options
Diffstat (limited to 'spec/frontend/cycle_analytics/stage_table_spec.js')
-rw-r--r-- | spec/frontend/cycle_analytics/stage_table_spec.js | 371 |
1 files changed, 0 insertions, 371 deletions
diff --git a/spec/frontend/cycle_analytics/stage_table_spec.js b/spec/frontend/cycle_analytics/stage_table_spec.js deleted file mode 100644 index 473e1d5b664..00000000000 --- a/spec/frontend/cycle_analytics/stage_table_spec.js +++ /dev/null @@ -1,371 +0,0 @@ -import { GlEmptyState, GlLoadingIcon, GlTable } from '@gitlab/ui'; -import { shallowMount, mount } from '@vue/test-utils'; -import { nextTick } from 'vue'; -import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; -import { extendedWrapper } from 'helpers/vue_test_utils_helper'; -import StageTable from '~/cycle_analytics/components/stage_table.vue'; -import { PAGINATION_SORT_FIELD_DURATION } from '~/cycle_analytics/constants'; -import { issueEvents, issueStage, reviewStage, reviewEvents } from './mock_data'; - -let wrapper = null; -let trackingSpy = null; - -const noDataSvgPath = 'path/to/no/data'; -const emptyStateTitle = 'Too much data'; -const notEnoughDataError = "We don't have enough data to show this stage."; -const issueEventItems = issueEvents.events; -const reviewEventItems = reviewEvents.events; -const [firstIssueEvent] = issueEventItems; -const [firstReviewEvent] = reviewEventItems; -const pagination = { page: 1, hasNextPage: true }; - -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 findStageEventLink = (ev) => extendedWrapper(ev).findByTestId('vsa-stage-event-link'); -const findStageTime = () => wrapper.findByTestId('vsa-stage-event-time'); -const findStageLastEvent = () => wrapper.findByTestId('vsa-stage-last-event'); -const findIcon = (name) => wrapper.findByTestId(`${name}-icon`); - -function createComponent(props = {}, shallow = false) { - const func = shallow ? shallowMount : mount; - return extendedWrapper( - func(StageTable, { - propsData: { - isLoading: false, - stageEvents: issueEventItems, - noDataSvgPath, - selectedStage: issueStage, - pagination, - ...props, - }, - stubs: { - GlLoadingIcon, - GlEmptyState, - }, - }), - ); -} - -describe('StageTable', () => { - afterEach(() => { - wrapper.destroy(); - }); - - describe('is loaded with data', () => { - beforeEach(() => { - wrapper = createComponent(); - }); - - it('will render the correct events', () => { - const evs = findStageEvents(); - expect(evs).toHaveLength(issueEventItems.length); - - const titles = evs.wrappers.map((ev) => findStageEventTitle(ev).text()); - issueEventItems.forEach((ev, index) => { - expect(titles[index]).toBe(ev.title); - }); - }); - - it('will not display the default data message', () => { - expect(wrapper.html()).not.toContain(notEnoughDataError); - }); - }); - - describe('with minimal stage data', () => { - beforeEach(() => { - wrapper = createComponent({ currentStage: { title: 'New stage title' } }); - }); - - it('will render the correct events', () => { - const evs = findStageEvents(); - expect(evs).toHaveLength(issueEventItems.length); - - const titles = evs.wrappers.map((ev) => findStageEventTitle(ev).text()); - issueEventItems.forEach((ev, index) => { - expect(titles[index]).toBe(ev.title); - }); - }); - - it('will not display the project name in the record link', () => { - const evs = findStageEvents(); - - const links = evs.wrappers.map((ev) => findStageEventLink(ev).text()); - issueEventItems.forEach((ev, index) => { - expect(links[index]).toBe(`#${ev.iid}`); - }); - }); - }); - - describe('default event', () => { - beforeEach(() => { - wrapper = createComponent({ - stageEvents: [{ ...firstIssueEvent }], - selectedStage: { ...issueStage, custom: false }, - }); - }); - - it('will render the event title', () => { - expect(wrapper.findByTestId('vsa-stage-event-title').text()).toBe(firstIssueEvent.title); - }); - - it('will set the workflow title to "Issues"', () => { - expect(findTableHead().text()).toContain('Issues'); - }); - - it('does not render the fork icon', () => { - expect(findIcon('fork').exists()).toBe(false); - }); - - it('does not render the branch icon', () => { - expect(findIcon('commit').exists()).toBe(false); - }); - - it('will render the total time', () => { - const createdAt = firstIssueEvent.createdAt.replace(' ago', ''); - expect(findStageTime().text()).toBe(createdAt); - }); - - it('will render the end event', () => { - expect(findStageLastEvent().text()).toBe(firstIssueEvent.endEventTimestamp); - }); - - it('will render the author', () => { - expect(wrapper.findByTestId('vsa-stage-event-author').text()).toContain( - firstIssueEvent.author.name, - ); - }); - - it('will render the created at date', () => { - expect(wrapper.findByTestId('vsa-stage-event-date').text()).toContain( - firstIssueEvent.createdAt, - ); - }); - }); - - describe('merge request event', () => { - beforeEach(() => { - wrapper = createComponent({ - stageEvents: [{ ...firstReviewEvent }], - selectedStage: { ...reviewStage, custom: false }, - }); - }); - - it('will set the workflow title to "Merge requests"', () => { - expect(findTableHead().text()).toContain('Merge requests'); - expect(findTableHead().text()).not.toContain('Issues'); - }); - }); - - describe('isLoading = true', () => { - beforeEach(() => { - wrapper = createComponent({ isLoading: true }, true); - }); - - it('will display the loading icon', () => { - expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true); - }); - - it('will not display pagination', () => { - expect(findPagination().exists()).toBe(false); - }); - }); - - describe('with no stageEvents', () => { - beforeEach(() => { - wrapper = createComponent({ stageEvents: [] }); - }); - - it('will render the empty state', () => { - expect(wrapper.findComponent(GlEmptyState).exists()).toBe(true); - }); - - it('will display the default no data message', () => { - expect(wrapper.html()).toContain(notEnoughDataError); - }); - - it('will not display the pagination component', () => { - expect(findPagination().exists()).toBe(false); - }); - }); - - describe('emptyStateTitle set', () => { - beforeEach(() => { - wrapper = createComponent({ stageEvents: [], emptyStateTitle }); - }); - - it('will display the custom message', () => { - expect(wrapper.html()).not.toContain(notEnoughDataError); - expect(wrapper.html()).toContain(emptyStateTitle); - }); - }); - - describe('includeProjectName set', () => { - const fakenamespace = 'some/fake/path'; - beforeEach(() => { - wrapper = createComponent({ includeProjectName: true }); - }); - - it('will display the project name in the record link', () => { - const evs = findStageEvents(); - - const links = evs.wrappers.map((ev) => findStageEventLink(ev).text()); - issueEventItems.forEach((ev, index) => { - expect(links[index]).toBe(`${ev.projectPath}#${ev.iid}`); - }); - }); - - describe.each` - namespaceFullPath | hasFullPath - ${'fake'} | ${false} - ${fakenamespace} | ${true} - `('with a namespace', ({ namespaceFullPath, hasFullPath }) => { - let evs = null; - let links = null; - - beforeEach(() => { - wrapper = createComponent({ - includeProjectName: true, - stageEvents: issueEventItems.map((ie) => ({ ...ie, namespaceFullPath })), - }); - - evs = findStageEvents(); - links = evs.wrappers.map((ev) => findStageEventLink(ev).text()); - }); - - it(`with namespaceFullPath='${namespaceFullPath}' ${ - hasFullPath ? 'will' : 'does not' - } include the namespace`, () => { - issueEventItems.forEach((ev, index) => { - if (hasFullPath) { - expect(links[index]).toBe(`${namespaceFullPath}/${ev.projectPath}#${ev.iid}`); - } else { - expect(links[index]).toBe(`${ev.projectPath}#${ev.iid}`); - } - }); - }); - }); - }); - - describe('Pagination', () => { - beforeEach(() => { - wrapper = createComponent(); - trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn); - }); - - afterEach(() => { - unmockTracking(); - wrapper.destroy(); - }); - - it('will display the pagination component', () => { - expect(findPagination().exists()).toBe(true); - }); - - it('clicking prev or next will emit an event', async () => { - expect(wrapper.emitted('handleUpdatePagination')).toBeUndefined(); - - findPagination().vm.$emit('input', 2); - await nextTick(); - - expect(wrapper.emitted('handleUpdatePagination')[0]).toEqual([{ page: 2 }]); - }); - - it('clicking prev or next will send tracking information', () => { - findPagination().vm.$emit('input', 2); - - expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_button', { label: 'pagination' }); - }); - - describe('with `hasNextPage=false', () => { - beforeEach(() => { - wrapper = createComponent({ pagination: { page: 1, hasNextPage: false } }); - }); - - it('will not display the pagination component', () => { - expect(findPagination().exists()).toBe(false); - }); - }); - }); - - describe('Sorting', () => { - const triggerTableSort = (sortDesc = true) => - findTable().vm.$emit('sort-changed', { - sortBy: PAGINATION_SORT_FIELD_DURATION, - sortDesc, - }); - - beforeEach(() => { - wrapper = createComponent(); - trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn); - }); - - afterEach(() => { - unmockTracking(); - wrapper.destroy(); - }); - - it('can sort the end event or duration', () => { - findTableHeadColumns() - .wrappers.slice(1) - .forEach((w) => { - expect(w.attributes('aria-sort')).toBe('none'); - }); - }); - - it('cannot be sorted by title', () => { - findTableHeadColumns() - .wrappers.slice(0, 1) - .forEach((w) => { - expect(w.attributes('aria-sort')).toBeUndefined(); - }); - }); - - it('clicking a table column will send tracking information', () => { - triggerTableSort(); - - expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_button', { - label: 'sort_duration_desc', - }); - }); - - it('clicking a table column will update the sort field', () => { - expect(wrapper.emitted('handleUpdatePagination')).toBeUndefined(); - triggerTableSort(); - - expect(wrapper.emitted('handleUpdatePagination')[0]).toEqual([ - { - direction: 'desc', - sort: 'duration', - }, - ]); - }); - - it('with sortDesc=false will toggle the direction field', () => { - expect(wrapper.emitted('handleUpdatePagination')).toBeUndefined(); - triggerTableSort(false); - - expect(wrapper.emitted('handleUpdatePagination')[0]).toEqual([ - { - direction: 'asc', - sort: 'duration', - }, - ]); - }); - - describe('with sortable=false', () => { - beforeEach(() => { - wrapper = createComponent({ sortable: false }); - }); - - it('cannot sort the table', () => { - findTableHeadColumns().wrappers.forEach((w) => { - expect(w.attributes('aria-sort')).toBeUndefined(); - }); - }); - }); - }); -}); |