diff options
Diffstat (limited to 'spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js')
-rw-r--r-- | spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js | 357 |
1 files changed, 153 insertions, 204 deletions
diff --git a/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js b/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js index 5307be0bf58..bcd2c14f2fa 100644 --- a/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js +++ b/spec/frontend/sidebar/components/time_tracking/time_tracker_spec.js @@ -1,277 +1,226 @@ -import Vue from 'vue'; - -import mountComponent from 'helpers/vue_mount_component_helper'; +import { createMockDirective } from 'helpers/vue_mock_directive'; +import { mount } from '@vue/test-utils'; import TimeTracker from '~/sidebar/components/time_tracking/time_tracker.vue'; describe('Issuable Time Tracker', () => { - let initialData; - let vm; - - const initTimeTrackingComponent = ({ - timeEstimate, - timeSpent, - timeEstimateHumanReadable, - timeSpentHumanReadable, - limitToHours, - }) => { - setFixtures(` - <div> - <div id="mock-container"></div> - </div> - `); - - initialData = { - timeEstimate, - timeSpent, - humanTimeEstimate: timeEstimateHumanReadable, - humanTimeSpent: timeSpentHumanReadable, - limitToHours: Boolean(limitToHours), - rootPath: '/', - }; - - const TimeTrackingComponent = Vue.extend({ - ...TimeTracker, - components: { - ...TimeTracker.components, - transition: { - // disable animations - render(h) { - return h('div', this.$slots.default); - }, - }, - }, - }); - vm = mountComponent(TimeTrackingComponent, initialData, '#mock-container'); + let wrapper; + + const findByTestId = testId => wrapper.find(`[data-testid=${testId}]`); + const findComparisonMeter = () => findByTestId('compareMeter').attributes('title'); + const findCollapsedState = () => findByTestId('collapsedState'); + const findTimeRemainingProgress = () => findByTestId('timeRemainingProgress'); + + const defaultProps = { + timeEstimate: 10_000, // 2h 46m + timeSpent: 5_000, // 1h 23m + humanTimeEstimate: '2h 46m', + humanTimeSpent: '1h 23m', + limitToHours: false, }; + const mountComponent = ({ props = {} } = {}) => + mount(TimeTracker, { + propsData: { ...defaultProps, ...props }, + directives: { GlTooltip: createMockDirective() }, + }); + afterEach(() => { - vm.$destroy(); + wrapper.destroy(); }); describe('Initialization', () => { beforeEach(() => { - initTimeTrackingComponent({ - timeEstimate: 10000, // 2h 46m - timeSpent: 5000, // 1h 23m - timeEstimateHumanReadable: '2h 46m', - timeSpentHumanReadable: '1h 23m', - }); + wrapper = mountComponent(); }); it('should return something defined', () => { - expect(vm).toBeDefined(); + expect(wrapper).toBeDefined(); }); - it('should correctly set timeEstimate', done => { - Vue.nextTick(() => { - expect(vm.timeEstimate).toBe(initialData.timeEstimate); - done(); - }); + it('should correctly render timeEstimate', () => { + expect(findByTestId('timeTrackingComparisonPane').html()).toContain( + defaultProps.humanTimeEstimate, + ); }); - it('should correctly set time_spent', done => { - Vue.nextTick(() => { - expect(vm.timeSpent).toBe(initialData.timeSpent); - done(); - }); + it('should correctly render time_spent', () => { + expect(findByTestId('timeTrackingComparisonPane').html()).toContain( + defaultProps.humanTimeSpent, + ); }); }); - describe('Content Display', () => { - describe('Panes', () => { - describe('Comparison pane', () => { - beforeEach(() => { - initTimeTrackingComponent({ - timeEstimate: 100000, // 1d 3h - timeSpent: 5000, // 1h 23m - timeEstimateHumanReadable: '1d 3h', - timeSpentHumanReadable: '1h 23m', - }); + describe('Content panes', () => { + describe('Collapsed state', () => { + it('should render "time-tracking-collapsed-state" by default when "showCollapsed" prop is not specified', () => { + wrapper = mountComponent(); + + expect(findCollapsedState().exists()).toBe(true); + }); + + it('should not render "time-tracking-collapsed-state" when "showCollapsed" is false', () => { + wrapper = mountComponent({ + props: { + showCollapsed: false, + }, }); - it('should show the "Comparison" pane when timeEstimate and time_spent are truthy', done => { - Vue.nextTick(() => { - expect(vm.showComparisonState).toBe(true); - const $comparisonPane = vm.$el.querySelector('.time-tracking-comparison-pane'); + expect(findCollapsedState().exists()).toBe(false); + }); + }); - expect($comparisonPane).toBeVisible(); - done(); - }); + describe('Comparison pane', () => { + beforeEach(() => { + wrapper = mountComponent({ + props: { + timeEstimate: 100_000, // 1d 3h + timeSpent: 5_000, // 1h 23m + humanTimeEstimate: '1d 3h', + humanTimeSpent: '1h 23m', + }, }); + }); - it('should show full times when the sidebar is collapsed', done => { - Vue.nextTick(() => { - const timeTrackingText = vm.$el.querySelector('.time-tracking-collapsed-summary span') - .textContent; + it('should show the "Comparison" pane when timeEstimate and time_spent are truthy', () => { + const pane = findByTestId('timeTrackingComparisonPane'); + expect(pane.exists()).toBe(true); + expect(pane.isVisible()).toBe(true); + }); - expect(timeTrackingText.trim()).toBe('1h 23m / 1d 3h'); - done(); - }); + it('should show full times when the sidebar is collapsed', () => { + expect(findCollapsedState().text()).toBe('1h 23m / 1d 3h'); + }); + + describe('Remaining meter', () => { + it('should display the remaining meter with the correct width', () => { + expect(findTimeRemainingProgress().attributes('value')).toBe('5'); }); - describe('Remaining meter', () => { - it('should display the remaining meter with the correct width', done => { - Vue.nextTick(() => { - expect( - vm.$el.querySelector('.time-tracking-comparison-pane .progress[value="5"]'), - ).not.toBeNull(); - done(); - }); - }); + it('should display the remaining meter with the correct background color when within estimate', () => { + expect(findTimeRemainingProgress().attributes('variant')).toBe('primary'); + }); - it('should display the remaining meter with the correct background color when within estimate', done => { - Vue.nextTick(() => { - expect( - vm.$el.querySelector('.time-tracking-comparison-pane .progress[variant="primary"]'), - ).not.toBeNull(); - done(); - }); + it('should display the remaining meter with the correct background color when over estimate', () => { + wrapper = mountComponent({ + props: { + timeEstimate: 10_000, // 2h 46m + timeSpent: 20_000_000, // 231 days + }, }); - it('should display the remaining meter with the correct background color when over estimate', done => { - vm.timeEstimate = 10000; // 2h 46m - vm.timeSpent = 20000000; // 231 days - Vue.nextTick(() => { - expect( - vm.$el.querySelector('.time-tracking-comparison-pane .progress[variant="danger"]'), - ).not.toBeNull(); - done(); - }); - }); + expect(findTimeRemainingProgress().attributes('variant')).toBe('danger'); }); }); + }); - describe('Comparison pane when limitToHours is true', () => { - beforeEach(() => { - initTimeTrackingComponent({ - timeEstimate: 100000, // 1d 3h - timeSpent: 5000, // 1h 23m - timeEstimateHumanReadable: '', - timeSpentHumanReadable: '', + describe('Comparison pane when limitToHours is true', () => { + beforeEach(async () => { + wrapper = mountComponent({ + props: { + timeEstimate: 100_000, // 1d 3h limitToHours: true, - }); + }, }); + }); - it('should show the correct tooltip text', done => { - Vue.nextTick(() => { - expect(vm.showComparisonState).toBe(true); - const $title = vm.$el.querySelector('.time-tracking-content .compare-meter').title; + it('should show the correct tooltip text', async () => { + expect(findByTestId('timeTrackingComparisonPane').exists()).toBe(true); + await wrapper.vm.$nextTick(); - expect($title).toBe('Time remaining: 26h 23m'); - done(); - }); - }); + expect(findComparisonMeter()).toBe('Time remaining: 26h 23m'); }); + }); - describe('Estimate only pane', () => { - beforeEach(() => { - initTimeTrackingComponent({ - timeEstimate: 10000, // 2h 46m + describe('Estimate only pane', () => { + beforeEach(async () => { + wrapper = mountComponent({ + props: { + timeEstimate: 10_000, // 2h 46m timeSpent: 0, timeEstimateHumanReadable: '2h 46m', timeSpentHumanReadable: '', - }); + }, }); + await wrapper.vm.$nextTick(); + }); - it('should display the human readable version of time estimated', done => { - Vue.nextTick(() => { - const estimateText = vm.$el.querySelector('.time-tracking-estimate-only-pane') - .textContent; - const correctText = 'Estimated: 2h 46m'; - - expect(estimateText.trim()).toBe(correctText); - done(); - }); - }); + it('should display the human readable version of time estimated', () => { + const estimateText = findByTestId('estimateOnlyPane').text(); + expect(estimateText.trim()).toBe('Estimated: 2h 46m'); }); + }); - describe('Spent only pane', () => { - beforeEach(() => { - initTimeTrackingComponent({ + describe('Spent only pane', () => { + beforeEach(() => { + wrapper = mountComponent({ + props: { timeEstimate: 0, - timeSpent: 5000, // 1h 23m + timeSpent: 5_000, // 1h 23m timeEstimateHumanReadable: '2h 46m', timeSpentHumanReadable: '1h 23m', - }); + }, }); + }); - it('should display the human readable version of time spent', done => { - Vue.nextTick(() => { - const spentText = vm.$el.querySelector('.time-tracking-spend-only-pane').textContent; - const correctText = 'Spent: 1h 23m'; - - expect(spentText).toBe(correctText); - done(); - }); - }); + it('should display the human readable version of time spent', () => { + const spentText = findByTestId('spentOnlyPane').text(); + expect(spentText.trim()).toBe('Spent: 1h 23m'); }); + }); - describe('No time tracking pane', () => { - beforeEach(() => { - initTimeTrackingComponent({ + describe('No time tracking pane', () => { + beforeEach(() => { + wrapper = mountComponent({ + props: { timeEstimate: 0, timeSpent: 0, timeEstimateHumanReadable: '', timeSpentHumanReadable: '', - }); + }, }); + }); - it('should only show the "No time tracking" pane when both timeEstimate and time_spent are falsey', done => { - Vue.nextTick(() => { - const $noTrackingPane = vm.$el.querySelector('.time-tracking-no-tracking-pane'); - const noTrackingText = $noTrackingPane.textContent; - const correctText = 'No estimate or time spent'; - - expect(vm.showNoTimeTrackingState).toBe(true); - expect($noTrackingPane).toBeVisible(); - expect(noTrackingText.trim()).toBe(correctText); - done(); - }); - }); + it('should only show the "No time tracking" pane when both timeEstimate and time_spent are falsey', () => { + const pane = findByTestId('noTrackingPane'); + const correctText = 'No estimate or time spent'; + expect(pane.exists()).toBe(true); + expect(pane.text().trim()).toBe(correctText); }); + }); + + describe('Help pane', () => { + const findHelpButton = () => findByTestId('helpButton'); + const findCloseHelpButton = () => findByTestId('closeHelpButton'); - describe('Help pane', () => { - const helpButton = () => vm.$el.querySelector('.help-button'); - const closeHelpButton = () => vm.$el.querySelector('.close-help-button'); - const helpPane = () => vm.$el.querySelector('.time-tracking-help-state'); + beforeEach(async () => { + wrapper = mountComponent({ props: { timeEstimate: 0, timeSpent: 0 } }); + await wrapper.vm.$nextTick(); + }); - beforeEach(() => { - initTimeTrackingComponent({ timeEstimate: 0, timeSpent: 0 }); + it('should not show the "Help" pane by default', () => { + expect(findByTestId('helpPane').exists()).toBe(false); + }); - return vm.$nextTick(); - }); + it('should show the "Help" pane when help button is clicked', async () => { + findHelpButton().trigger('click'); - it('should not show the "Help" pane by default', () => { - expect(vm.showHelpState).toBe(false); - expect(helpPane()).toBeNull(); - }); + await wrapper.vm.$nextTick(); - it('should show the "Help" pane when help button is clicked', () => { - helpButton().click(); + expect(findByTestId('helpPane').exists()).toBe(true); + }); - return vm.$nextTick().then(() => { - expect(vm.showHelpState).toBe(true); + it('should not show the "Help" pane when help button is clicked and then closed', async () => { + findHelpButton().trigger('click'); + await wrapper.vm.$nextTick(); - // let animations run - jest.advanceTimersByTime(500); + expect(findByTestId('helpPane').classes('help-state-toggle-enter')).toBe(true); + expect(findByTestId('helpPane').classes('help-state-toggle-leave')).toBe(false); - expect(helpPane()).toBeVisible(); - }); - }); + findCloseHelpButton().trigger('click'); + await wrapper.vm.$nextTick(); - it('should not show the "Help" pane when help button is clicked and then closed', done => { - helpButton().click(); - - Vue.nextTick() - .then(() => closeHelpButton().click()) - .then(() => Vue.nextTick()) - .then(() => { - expect(vm.showHelpState).toBe(false); - expect(helpPane()).toBeNull(); - }) - .then(done) - .catch(done.fail); - }); + expect(findByTestId('helpPane').classes('help-state-toggle-leave')).toBe(true); + expect(findByTestId('helpPane').classes('help-state-toggle-enter')).toBe(false); }); }); }); |