diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-09-16 00:11:56 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-09-16 00:11:56 +0300 |
commit | d30dfdfd05fedfa4b06f7905b5f193f3c6704284 (patch) | |
tree | 720a27bcaf375d8c02fbc267cde9620d443eeb30 /spec/frontend | |
parent | 7a15fb07cf363079c4c4683850ee131d80e75f75 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
7 files changed, 14 insertions, 1171 deletions
diff --git a/spec/frontend/lib/utils/datetime_range_spec.js b/spec/frontend/lib/utils/datetime_range_spec.js deleted file mode 100644 index 996a8e2e47b..00000000000 --- a/spec/frontend/lib/utils/datetime_range_spec.js +++ /dev/null @@ -1,382 +0,0 @@ -import _ from 'lodash'; -import { - getRangeType, - convertToFixedRange, - isEqualTimeRanges, - findTimeRange, - timeRangeToParams, - timeRangeFromParams, -} from '~/lib/utils/datetime_range'; - -const MOCK_NOW = Date.UTC(2020, 0, 23, 20); - -const MOCK_NOW_ISO_STRING = new Date(MOCK_NOW).toISOString(); - -const mockFixedRange = { - label: 'January 2020', - start: '2020-01-01T00:00:00.000Z', - end: '2020-01-31T23:59:00.000Z', -}; - -const mockAnchoredRange = { - label: 'First two minutes of 2020', - anchor: '2020-01-01T00:00:00.000Z', - direction: 'after', - duration: { - seconds: 60 * 2, - }, -}; - -const mockRollingRange = { - label: 'Next 2 minutes', - direction: 'after', - duration: { - seconds: 60 * 2, - }, -}; - -const mockOpenRange = { - label: '2020 so far', - anchor: '2020-01-01T00:00:00.000Z', - direction: 'after', -}; - -describe('Date time range utils', () => { - describe('getRangeType', () => { - it('infers correctly the range type from the input object', () => { - const rangeTypes = { - fixed: [{ start: MOCK_NOW_ISO_STRING, end: MOCK_NOW_ISO_STRING }], - anchored: [{ anchor: MOCK_NOW_ISO_STRING, duration: { seconds: 0 } }], - rolling: [{ duration: { seconds: 0 } }], - open: [{ anchor: MOCK_NOW_ISO_STRING }], - invalid: [ - {}, - { start: MOCK_NOW_ISO_STRING }, - { end: MOCK_NOW_ISO_STRING }, - { start: 'NOT_A_DATE', end: 'NOT_A_DATE' }, - { duration: { seconds: 'NOT_A_NUMBER' } }, - { duration: { seconds: Infinity } }, - { duration: { minutes: 20 } }, - { anchor: MOCK_NOW_ISO_STRING, duration: { seconds: 'NOT_A_NUMBER' } }, - { anchor: MOCK_NOW_ISO_STRING, duration: { seconds: Infinity } }, - { junk: 'exists' }, - ], - }; - - Object.entries(rangeTypes).forEach(([type, examples]) => { - examples.forEach((example) => expect(getRangeType(example)).toEqual(type)); - }); - }); - }); - - describe('convertToFixedRange', () => { - beforeEach(() => { - jest.spyOn(Date, 'now').mockImplementation(() => MOCK_NOW); - }); - - afterEach(() => { - Date.now.mockRestore(); - }); - - describe('When a fixed range is input', () => { - it('converts a fixed range to an equal fixed range', () => { - expect(convertToFixedRange(mockFixedRange)).toEqual({ - start: mockFixedRange.start, - end: mockFixedRange.end, - }); - }); - - it('throws an error when fixed range does not contain an end time', () => { - const aFixedRangeMissingEnd = _.omit(mockFixedRange, 'end'); - - expect(() => convertToFixedRange(aFixedRangeMissingEnd)).toThrow(); - }); - - it('throws an error when fixed range does not contain a start time', () => { - const aFixedRangeMissingStart = _.omit(mockFixedRange, 'start'); - - expect(() => convertToFixedRange(aFixedRangeMissingStart)).toThrow(); - }); - - it('throws an error when the dates cannot be parsed', () => { - const wrongStart = { ...mockFixedRange, start: 'I_CANNOT_BE_PARSED' }; - const wrongEnd = { ...mockFixedRange, end: 'I_CANNOT_BE_PARSED' }; - - expect(() => convertToFixedRange(wrongStart)).toThrow(); - expect(() => convertToFixedRange(wrongEnd)).toThrow(); - }); - }); - - describe('When an anchored range is input', () => { - it('converts to a fixed range', () => { - expect(convertToFixedRange(mockAnchoredRange)).toEqual({ - start: '2020-01-01T00:00:00.000Z', - end: '2020-01-01T00:02:00.000Z', - }); - }); - - it('converts to a fixed range with a `before` direction', () => { - expect(convertToFixedRange({ ...mockAnchoredRange, direction: 'before' })).toEqual({ - start: '2019-12-31T23:58:00.000Z', - end: '2020-01-01T00:00:00.000Z', - }); - }); - - it('converts to a fixed range without an explicit direction, defaulting to `before`', () => { - const defaultDirectionRange = _.omit(mockAnchoredRange, 'direction'); - - expect(convertToFixedRange(defaultDirectionRange)).toEqual({ - start: '2019-12-31T23:58:00.000Z', - end: '2020-01-01T00:00:00.000Z', - }); - }); - - it('throws an error when the anchor cannot be parsed', () => { - const wrongAnchor = { ...mockAnchoredRange, anchor: 'I_CANNOT_BE_PARSED' }; - - expect(() => convertToFixedRange(wrongAnchor)).toThrow(); - }); - }); - - describe('when a rolling range is input', () => { - it('converts to a fixed range', () => { - expect(convertToFixedRange(mockRollingRange)).toEqual({ - start: '2020-01-23T20:00:00.000Z', - end: '2020-01-23T20:02:00.000Z', - }); - }); - - it('converts to a fixed range with an implicit `before` direction', () => { - const noDirection = _.omit(mockRollingRange, 'direction'); - - expect(convertToFixedRange(noDirection)).toEqual({ - start: '2020-01-23T19:58:00.000Z', - end: '2020-01-23T20:00:00.000Z', - }); - }); - - it('throws an error when the duration is not in the right format', () => { - const wrongDuration = { ...mockRollingRange, duration: { minutes: 20 } }; - - expect(() => convertToFixedRange(wrongDuration)).toThrow(); - }); - - it('throws an error when the anchor is not valid', () => { - const wrongAnchor = { ...mockRollingRange, anchor: 'CAN_T_PARSE_THIS' }; - - expect(() => convertToFixedRange(wrongAnchor)).toThrow(); - }); - }); - - describe('when an open range is input', () => { - it('converts to a fixed range with an `after` direction', () => { - expect(convertToFixedRange(mockOpenRange)).toEqual({ - start: '2020-01-01T00:00:00.000Z', - end: '2020-01-23T20:00:00.000Z', - }); - }); - - it('converts to a fixed range with the explicit `before` direction', () => { - const beforeOpenRange = { ...mockOpenRange, direction: 'before' }; - - expect(convertToFixedRange(beforeOpenRange)).toEqual({ - start: '1970-01-01T00:00:00.000Z', - end: '2020-01-01T00:00:00.000Z', - }); - }); - - it('converts to a fixed range with the implicit `before` direction', () => { - const noDirectionOpenRange = _.omit(mockOpenRange, 'direction'); - - expect(convertToFixedRange(noDirectionOpenRange)).toEqual({ - start: '1970-01-01T00:00:00.000Z', - end: '2020-01-01T00:00:00.000Z', - }); - }); - - it('throws an error when the anchor cannot be parsed', () => { - const wrongAnchor = { ...mockOpenRange, anchor: 'CAN_T_PARSE_THIS' }; - - expect(() => convertToFixedRange(wrongAnchor)).toThrow(); - }); - }); - }); - - describe('isEqualTimeRanges', () => { - it('equal only compares relevant properies', () => { - expect( - isEqualTimeRanges( - { - ...mockFixedRange, - label: 'A label', - default: true, - }, - { - ...mockFixedRange, - label: 'Another label', - default: false, - anotherKey: 'anotherValue', - }, - ), - ).toBe(true); - - expect( - isEqualTimeRanges( - { - ...mockAnchoredRange, - label: 'A label', - default: true, - }, - { - ...mockAnchoredRange, - anotherKey: 'anotherValue', - }, - ), - ).toBe(true); - }); - }); - - describe('findTimeRange', () => { - const timeRanges = [ - { - label: 'Before 2020', - anchor: '2020-01-01T00:00:00.000Z', - }, - { - label: 'Last 30 minutes', - duration: { seconds: 60 * 30 }, - }, - { - label: 'In 2019', - start: '2019-01-01T00:00:00.000Z', - end: '2019-12-31T12:59:59.999Z', - }, - { - label: 'Next 2 minutes', - direction: 'after', - duration: { - seconds: 60 * 2, - }, - }, - ]; - - it('finds a time range', () => { - const tr0 = { - anchor: '2020-01-01T00:00:00.000Z', - }; - expect(findTimeRange(tr0, timeRanges)).toBe(timeRanges[0]); - - const tr1 = { - duration: { seconds: 60 * 30 }, - }; - expect(findTimeRange(tr1, timeRanges)).toBe(timeRanges[1]); - - const tr1Direction = { - direction: 'before', - duration: { - seconds: 60 * 30, - }, - }; - expect(findTimeRange(tr1Direction, timeRanges)).toBe(timeRanges[1]); - - const tr2 = { - someOtherLabel: 'Added arbitrarily', - start: '2019-01-01T00:00:00.000Z', - end: '2019-12-31T12:59:59.999Z', - }; - expect(findTimeRange(tr2, timeRanges)).toBe(timeRanges[2]); - - const tr3 = { - direction: 'after', - duration: { - seconds: 60 * 2, - }, - }; - expect(findTimeRange(tr3, timeRanges)).toBe(timeRanges[3]); - }); - - it('doesnot finds a missing time range', () => { - const nonExistant = { - direction: 'before', - duration: { - seconds: 200, - }, - }; - expect(findTimeRange(nonExistant, timeRanges)).toBeUndefined(); - }); - }); - - describe('conversion to/from params', () => { - const mockFixedParams = { - start: '2020-01-01T00:00:00.000Z', - end: '2020-01-31T23:59:00.000Z', - }; - - const mockAnchoredParams = { - anchor: '2020-01-01T00:00:00.000Z', - direction: 'after', - duration_seconds: '120', - }; - - const mockRollingParams = { - direction: 'after', - duration_seconds: '120', - }; - - describe('timeRangeToParams', () => { - it('converts fixed ranges to params', () => { - expect(timeRangeToParams(mockFixedRange)).toEqual(mockFixedParams); - }); - - it('converts anchored ranges to params', () => { - expect(timeRangeToParams(mockAnchoredRange)).toEqual(mockAnchoredParams); - }); - - it('converts rolling ranges to params', () => { - expect(timeRangeToParams(mockRollingRange)).toEqual(mockRollingParams); - }); - }); - - describe('timeRangeFromParams', () => { - it('converts fixed ranges from params', () => { - const params = { ...mockFixedParams, other_param: 'other_value' }; - const expectedRange = _.omit(mockFixedRange, 'label'); - - expect(timeRangeFromParams(params)).toEqual(expectedRange); - }); - - it('converts anchored ranges to params', () => { - const expectedRange = _.omit(mockRollingRange, 'label'); - - expect(timeRangeFromParams(mockRollingParams)).toEqual(expectedRange); - }); - - it('converts rolling ranges from params', () => { - const params = { ...mockRollingParams, other_param: 'other_value' }; - const expectedRange = _.omit(mockRollingRange, 'label'); - - expect(timeRangeFromParams(params)).toEqual(expectedRange); - }); - - it('converts rolling ranges from params with a default direction', () => { - const params = { - ...mockRollingParams, - direction: 'before', - other_param: 'other_value', - }; - const expectedRange = _.omit(mockRollingRange, 'label', 'direction'); - - expect(timeRangeFromParams(params)).toEqual(expectedRange); - }); - - it('converts to null when for no relevant params', () => { - const range = { - useless_param_1: 'value1', - useless_param_2: 'value2', - }; - - expect(timeRangeFromParams(range)).toBe(null); - }); - }); - }); -}); diff --git a/spec/frontend/super_sidebar/components/sidebar_menu_spec.js b/spec/frontend/super_sidebar/components/sidebar_menu_spec.js index dd780b172f5..c85a6609e6f 100644 --- a/spec/frontend/super_sidebar/components/sidebar_menu_spec.js +++ b/spec/frontend/super_sidebar/components/sidebar_menu_spec.js @@ -16,13 +16,8 @@ const menuItems = [ describe('Sidebar Menu', () => { let wrapper; - let flyoutFlag = false; - const createWrapper = (extraProps = {}) => { wrapper = shallowMountExtended(SidebarMenu, { - provide: { - glFeatures: { superSidebarFlyoutMenus: flyoutFlag }, - }, propsData: { items: sidebarData.current_menu_items, isLoggedIn: sidebarData.is_logged_in, @@ -125,8 +120,11 @@ describe('Sidebar Menu', () => { }); describe('flyout menus', () => { - describe('when feature is disabled', () => { + describe('when screen width is smaller than "md" breakpoint', () => { beforeEach(() => { + jest.spyOn(GlBreakpointInstance, 'windowWidth').mockImplementation(() => { + return 767; + }); createWrapper({ items: menuItems, }); @@ -140,45 +138,21 @@ describe('Sidebar Menu', () => { }); }); - describe('when feature is enabled', () => { + describe('when screen width is equal or larger than "md" breakpoint', () => { beforeEach(() => { - flyoutFlag = true; - }); - - describe('when screen width is smaller than "md" breakpoint', () => { - beforeEach(() => { - jest.spyOn(GlBreakpointInstance, 'windowWidth').mockImplementation(() => { - return 767; - }); - createWrapper({ - items: menuItems, - }); + jest.spyOn(GlBreakpointInstance, 'windowWidth').mockImplementation(() => { + return 768; }); - - it('does not add flyout menus to sections', () => { - expect(findNonStaticSectionItems().wrappers.map((w) => w.props('hasFlyout'))).toEqual([ - false, - false, - ]); + createWrapper({ + items: menuItems, }); }); - describe('when screen width is equal or larger than "md" breakpoint', () => { - beforeEach(() => { - jest.spyOn(GlBreakpointInstance, 'windowWidth').mockImplementation(() => { - return 768; - }); - createWrapper({ - items: menuItems, - }); - }); - - it('adds flyout menus to sections', () => { - expect(findNonStaticSectionItems().wrappers.map((w) => w.props('hasFlyout'))).toEqual([ - true, - true, - ]); - }); + it('adds flyout menus to sections', () => { + expect(findNonStaticSectionItems().wrappers.map((w) => w.props('hasFlyout'))).toEqual([ + true, + true, + ]); }); }); }); diff --git a/spec/frontend/vue_shared/components/__snapshots__/split_button_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/split_button_spec.js.snap deleted file mode 100644 index 98adcb5b178..00000000000 --- a/spec/frontend/vue_shared/components/__snapshots__/split_button_spec.js.snap +++ /dev/null @@ -1,54 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`SplitButton renders actionItems 1`] = ` -<gl-dropdown-stub - category="primary" - clearalltext="Clear all" - clearalltextclass="gl-px-5" - headertext="" - hideheaderborder="true" - highlighteditemstitle="Selected" - highlighteditemstitleclass="gl-px-5" - menu-class="" - size="medium" - split="true" - splithref="" - text="professor" - variant="default" -> - <gl-dropdown-item-stub - avatarurl="" - iconcolor="" - iconname="" - iconrightarialabel="" - iconrightname="" - ischecked="true" - ischeckitem="true" - secondarytext="" - > - <strong> - professor - </strong> - <div> - very symphonic - </div> - </gl-dropdown-item-stub> - <gl-dropdown-divider-stub /> - <gl-dropdown-item-stub - avatarurl="" - iconcolor="" - iconname="" - iconrightarialabel="" - iconrightname="" - ischeckitem="true" - secondarytext="" - > - <strong> - captain - </strong> - <div> - warp drive - </div> - </gl-dropdown-item-stub> -</gl-dropdown-stub> -`; diff --git a/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_input_spec.js b/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_input_spec.js deleted file mode 100644 index a3e5f187f9b..00000000000 --- a/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_input_spec.js +++ /dev/null @@ -1,62 +0,0 @@ -import { mount } from '@vue/test-utils'; -import DateTimePickerInput from '~/vue_shared/components/date_time_picker/date_time_picker_input.vue'; - -const inputLabel = 'This is a label'; -const inputValue = 'something'; - -describe('DateTimePickerInput', () => { - let wrapper; - - const createComponent = (propsData = {}) => { - wrapper = mount(DateTimePickerInput, { - propsData: { - state: null, - value: '', - label: '', - ...propsData, - }, - }); - }; - - it('renders label above the input', () => { - createComponent({ - label: inputLabel, - }); - - expect(wrapper.find('.gl-form-group label').text()).toBe(inputLabel); - }); - - it('renders the same `ID` for input and `for` for label', () => { - createComponent({ label: inputLabel }); - - expect(wrapper.find('.gl-form-group label').attributes('for')).toBe( - wrapper.find('input').attributes('id'), - ); - }); - - it('renders valid input in gray color instead of green', () => { - createComponent({ - state: true, - }); - - expect(wrapper.find('input').classes('is-valid')).toBe(false); - }); - - it('renders invalid input in red color', () => { - createComponent({ - state: false, - }); - - expect(wrapper.find('input').classes('is-invalid')).toBe(true); - }); - - it('input event is emitted when focus is lost', () => { - createComponent(); - - const input = wrapper.find('input'); - input.setValue(inputValue); - input.trigger('blur'); - - expect(wrapper.emitted('input')[0][0]).toEqual(inputValue); - }); -}); diff --git a/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_lib_spec.js b/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_lib_spec.js deleted file mode 100644 index 7a8f94b3746..00000000000 --- a/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_lib_spec.js +++ /dev/null @@ -1,190 +0,0 @@ -import timezoneMock from 'timezone-mock'; - -import { - isValidInputString, - inputStringToIsoDate, - isoDateToInputString, -} from '~/vue_shared/components/date_time_picker/date_time_picker_lib'; - -describe('date time picker lib', () => { - describe('isValidInputString', () => { - [ - { - input: '2019-09-09T00:00:00.000Z', - output: true, - }, - { - input: '2019-09-09T000:00.000Z', - output: false, - }, - { - input: 'a2019-09-09T000:00.000Z', - output: false, - }, - { - input: '2019-09-09T', - output: false, - }, - { - input: '2019-09-09', - output: true, - }, - { - input: '2019-9-9', - output: true, - }, - { - input: '2019-9-', - output: true, - }, - { - input: '2019--', - output: false, - }, - { - input: '2019', - output: true, - }, - { - input: '', - output: false, - }, - { - input: null, - output: false, - }, - ].forEach(({ input, output }) => { - it(`isValidInputString return ${output} for ${input}`, () => { - expect(isValidInputString(input)).toBe(output); - }); - }); - }); - - describe('inputStringToIsoDate', () => { - [ - '', - 'null', - undefined, - 'abc', - 'xxxx-xx-xx', - '9999-99-19', - '2019-19-23', - '2019-09-23 x', - '2019-09-29 24:24:24', - ].forEach((input) => { - it(`throws error for invalid input like ${input}`, () => { - expect(() => inputStringToIsoDate(input)).toThrow(); - }); - }); - - [ - { - input: '2019-09-08 01:01:01', - output: '2019-09-08T01:01:01Z', - }, - { - input: '2019-09-08 00:00:00', - output: '2019-09-08T00:00:00Z', - }, - { - input: '2019-09-08 23:59:59', - output: '2019-09-08T23:59:59Z', - }, - { - input: '2019-09-08', - output: '2019-09-08T00:00:00Z', - }, - { - input: '2019-09-08', - output: '2019-09-08T00:00:00Z', - }, - { - input: '2019-09-08 00:00:00', - output: '2019-09-08T00:00:00Z', - }, - { - input: '2019-09-08 23:24:24', - output: '2019-09-08T23:24:24Z', - }, - { - input: '2019-09-08 0:0:0', - output: '2019-09-08T00:00:00Z', - }, - ].forEach(({ input, output }) => { - it(`returns ${output} from ${input}`, () => { - expect(inputStringToIsoDate(input)).toBe(output); - }); - }); - - describe('timezone formatting', () => { - const value = '2019-09-08 01:01:01'; - const utcResult = '2019-09-08T01:01:01Z'; - const localResult = '2019-09-08T08:01:01Z'; - - it.each` - val | locatTimezone | utc | result - ${value} | ${'UTC'} | ${undefined} | ${utcResult} - ${value} | ${'UTC'} | ${false} | ${utcResult} - ${value} | ${'UTC'} | ${true} | ${utcResult} - ${value} | ${'US/Pacific'} | ${undefined} | ${localResult} - ${value} | ${'US/Pacific'} | ${false} | ${localResult} - ${value} | ${'US/Pacific'} | ${true} | ${utcResult} - `( - 'when timezone is $locatTimezone, formats $result for utc = $utc', - ({ val, locatTimezone, utc, result }) => { - timezoneMock.register(locatTimezone); - - expect(inputStringToIsoDate(val, utc)).toBe(result); - - timezoneMock.unregister(); - }, - ); - }); - }); - - describe('isoDateToInputString', () => { - [ - { - input: '2019-09-08T01:01:01Z', - output: '2019-09-08 01:01:01', - }, - { - input: '2019-09-08T01:01:01.999Z', - output: '2019-09-08 01:01:01', - }, - { - input: '2019-09-08T00:00:00Z', - output: '2019-09-08 00:00:00', - }, - ].forEach(({ input, output }) => { - it(`returns ${output} for ${input}`, () => { - expect(isoDateToInputString(input)).toBe(output); - }); - }); - - describe('timezone formatting', () => { - const value = '2019-09-08T08:01:01Z'; - const utcResult = '2019-09-08 08:01:01'; - const localResult = '2019-09-08 01:01:01'; - - it.each` - val | locatTimezone | utc | result - ${value} | ${'UTC'} | ${undefined} | ${utcResult} - ${value} | ${'UTC'} | ${false} | ${utcResult} - ${value} | ${'UTC'} | ${true} | ${utcResult} - ${value} | ${'US/Pacific'} | ${undefined} | ${localResult} - ${value} | ${'US/Pacific'} | ${false} | ${localResult} - ${value} | ${'US/Pacific'} | ${true} | ${utcResult} - `( - 'when timezone is $locatTimezone, formats $result for utc = $utc', - ({ val, locatTimezone, utc, result }) => { - timezoneMock.register(locatTimezone); - - expect(isoDateToInputString(val, utc)).toBe(result); - - timezoneMock.unregister(); - }, - ); - }); - }); -}); diff --git a/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_spec.js b/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_spec.js deleted file mode 100644 index 5620b569409..00000000000 --- a/spec/frontend/vue_shared/components/date_time_picker/date_time_picker_spec.js +++ /dev/null @@ -1,326 +0,0 @@ -import { mount } from '@vue/test-utils'; -import timezoneMock from 'timezone-mock'; -import { nextTick } from 'vue'; -import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue'; -import { - defaultTimeRanges, - defaultTimeRange, -} from '~/vue_shared/components/date_time_picker/date_time_picker_lib'; - -const optionsCount = defaultTimeRanges.length; - -describe('DateTimePicker', () => { - let wrapper; - - const dropdownToggle = () => wrapper.find('.dropdown-toggle'); - const dropdownMenu = () => wrapper.find('.dropdown-menu'); - const cancelButton = () => wrapper.find('[data-testid="cancelButton"]'); - const applyButtonElement = () => wrapper.find('button.btn-confirm').element; - const findQuickRangeItems = () => wrapper.findAll('.dropdown-item'); - - const createComponent = (props) => { - wrapper = mount(DateTimePicker, { - propsData: { - ...props, - }, - }); - }; - - it('renders dropdown toggle button with selected text', async () => { - createComponent(); - await nextTick(); - expect(dropdownToggle().text()).toBe(defaultTimeRange.label); - }); - - it('renders dropdown toggle button with selected text and utc label', async () => { - createComponent({ utc: true }); - await nextTick(); - expect(dropdownToggle().text()).toContain(defaultTimeRange.label); - expect(dropdownToggle().text()).toContain('UTC'); - }); - - it('renders dropdown with 2 custom time range inputs', async () => { - createComponent(); - await nextTick(); - expect(wrapper.findAll('input').length).toBe(2); - }); - - describe('renders label with h/m/s truncated if possible', () => { - [ - { - start: '2019-10-10T00:00:00.000Z', - end: '2019-10-10T00:00:00.000Z', - label: '2019-10-10 to 2019-10-10', - }, - { - start: '2019-10-10T00:00:00.000Z', - end: '2019-10-14T00:10:00.000Z', - label: '2019-10-10 to 2019-10-14 00:10:00', - }, - { - start: '2019-10-10T00:00:00.000Z', - end: '2019-10-10T00:00:01.000Z', - label: '2019-10-10 to 2019-10-10 00:00:01', - }, - { - start: '2019-10-10T00:00:01.000Z', - end: '2019-10-10T00:00:01.000Z', - label: '2019-10-10 00:00:01 to 2019-10-10 00:00:01', - }, - { - start: '2019-10-10T00:00:01.000Z', - end: '2019-10-10T00:00:01.000Z', - utc: true, - label: '2019-10-10 00:00:01 to 2019-10-10 00:00:01 UTC', - }, - ].forEach(({ start, end, utc, label }) => { - it(`for start ${start}, end ${end}, and utc ${utc}, label is ${label}`, async () => { - createComponent({ - value: { start, end }, - utc, - }); - await nextTick(); - expect(dropdownToggle().text()).toBe(label); - }); - }); - }); - - it(`renders dropdown with ${optionsCount} (default) items in quick range`, async () => { - createComponent(); - dropdownToggle().trigger('click'); - await nextTick(); - expect(findQuickRangeItems().length).toBe(optionsCount); - }); - - it('renders dropdown with a default quick range item selected', async () => { - createComponent(); - dropdownToggle().trigger('click'); - await nextTick(); - expect(wrapper.find('.dropdown-item.active').exists()).toBe(true); - expect(wrapper.find('.dropdown-item.active').text()).toBe(defaultTimeRange.label); - }); - - it('renders a disabled apply button on wrong input', () => { - createComponent({ - start: 'invalid-input-date', - }); - - expect(applyButtonElement().getAttribute('disabled')).toBe('disabled'); - }); - - describe('user input', () => { - const fillInputAndBlur = async (input, val) => { - wrapper.find(input).setValue(val); - await nextTick(); - wrapper.find(input).trigger('blur'); - await nextTick(); - }; - - beforeEach(async () => { - createComponent(); - await nextTick(); - }); - - it('displays inline error message if custom time range inputs are invalid', async () => { - await fillInputAndBlur('#custom-time-from', '2019-10-01abc'); - await fillInputAndBlur('#custom-time-to', '2019-10-10abc'); - expect(wrapper.findAll('.invalid-feedback').length).toBe(2); - }); - - it('keeps apply button disabled with invalid custom time range inputs', async () => { - await fillInputAndBlur('#custom-time-from', '2019-10-01abc'); - await fillInputAndBlur('#custom-time-to', '2019-09-19'); - expect(applyButtonElement().getAttribute('disabled')).toBe('disabled'); - }); - - it('enables apply button with valid custom time range inputs', async () => { - await fillInputAndBlur('#custom-time-from', '2019-10-01'); - await fillInputAndBlur('#custom-time-to', '2019-10-19'); - expect(applyButtonElement().getAttribute('disabled')).toBeNull(); - }); - - describe('when "apply" is clicked', () => { - it('emits iso dates', async () => { - await fillInputAndBlur('#custom-time-from', '2019-10-01 00:00:00'); - await fillInputAndBlur('#custom-time-to', '2019-10-19 00:00:00'); - applyButtonElement().click(); - - expect(wrapper.emitted().input).toHaveLength(1); - expect(wrapper.emitted().input[0]).toEqual([ - { - end: '2019-10-19T00:00:00Z', - start: '2019-10-01T00:00:00Z', - }, - ]); - }); - - it('emits iso dates, for dates without time of day', async () => { - await fillInputAndBlur('#custom-time-from', '2019-10-01'); - await fillInputAndBlur('#custom-time-to', '2019-10-19'); - applyButtonElement().click(); - - expect(wrapper.emitted().input).toHaveLength(1); - expect(wrapper.emitted().input[0]).toEqual([ - { - end: '2019-10-19T00:00:00Z', - start: '2019-10-01T00:00:00Z', - }, - ]); - }); - - describe('when timezone is different', () => { - beforeAll(() => { - timezoneMock.register('US/Pacific'); - }); - afterAll(() => { - timezoneMock.unregister(); - }); - - it('emits iso dates', async () => { - await fillInputAndBlur('#custom-time-from', '2019-10-01 00:00:00'); - await fillInputAndBlur('#custom-time-to', '2019-10-19 12:00:00'); - applyButtonElement().click(); - - expect(wrapper.emitted().input).toHaveLength(1); - expect(wrapper.emitted().input[0]).toEqual([ - { - start: '2019-10-01T07:00:00Z', - end: '2019-10-19T19:00:00Z', - }, - ]); - }); - - it('emits iso dates with utc format', async () => { - wrapper.setProps({ utc: true }); - await nextTick(); - await fillInputAndBlur('#custom-time-from', '2019-10-01 00:00:00'); - await fillInputAndBlur('#custom-time-to', '2019-10-19 12:00:00'); - applyButtonElement().click(); - - expect(wrapper.emitted().input).toHaveLength(1); - expect(wrapper.emitted().input[0]).toEqual([ - { - start: '2019-10-01T00:00:00Z', - end: '2019-10-19T12:00:00Z', - }, - ]); - }); - }); - }); - - it('unchecks quick range when text is input is clicked', async () => { - const findActiveItems = () => - findQuickRangeItems().filter((w) => w.classes().includes('active')); - - expect(findActiveItems().length).toBe(1); - - await fillInputAndBlur('#custom-time-from', '2019-10-01'); - expect(findActiveItems().length).toBe(0); - }); - - it('emits dates in an object when a is clicked', () => { - findQuickRangeItems() - .at(3) // any item - .trigger('click'); - - expect(wrapper.emitted().input).toHaveLength(1); - expect(wrapper.emitted().input[0][0]).toMatchObject({ - duration: { - seconds: expect.any(Number), - }, - }); - }); - - it('hides the popover with cancel button', async () => { - dropdownToggle().trigger('click'); - - await nextTick(); - cancelButton().trigger('click'); - - await nextTick(); - expect(dropdownMenu().classes('show')).toBe(false); - }); - }); - - describe('when using non-default time windows', () => { - const MOCK_NOW = Date.UTC(2020, 0, 23, 20); - - const otherTimeRanges = [ - { - label: '1 minute', - duration: { seconds: 60 }, - }, - { - label: '2 minutes', - duration: { seconds: 60 * 2 }, - default: true, - }, - { - label: '5 minutes', - duration: { seconds: 60 * 5 }, - }, - ]; - - beforeEach(() => { - jest.spyOn(Date, 'now').mockImplementation(() => MOCK_NOW); - }); - - it('renders dropdown with a label in the quick range', async () => { - createComponent({ - value: { - duration: { seconds: 60 * 5 }, - }, - options: otherTimeRanges, - }); - dropdownToggle().trigger('click'); - await nextTick(); - expect(dropdownToggle().text()).toBe('5 minutes'); - }); - - it('renders dropdown with a label in the quick range and utc label', async () => { - createComponent({ - value: { - duration: { seconds: 60 * 5 }, - }, - utc: true, - options: otherTimeRanges, - }); - dropdownToggle().trigger('click'); - await nextTick(); - expect(dropdownToggle().text()).toBe('5 minutes UTC'); - }); - - it('renders dropdown with quick range items', async () => { - createComponent({ - value: { - duration: { seconds: 60 * 2 }, - }, - options: otherTimeRanges, - }); - dropdownToggle().trigger('click'); - await nextTick(); - const items = findQuickRangeItems(); - - expect(items.length).toBe(Object.keys(otherTimeRanges).length); - expect(items.at(0).text()).toBe('1 minute'); - expect(items.at(0).classes()).not.toContain('active'); - - expect(items.at(1).text()).toBe('2 minutes'); - expect(items.at(1).classes()).toContain('active'); - - expect(items.at(2).text()).toBe('5 minutes'); - expect(items.at(2).classes()).not.toContain('active'); - }); - - it('renders dropdown with a label not in the quick range', async () => { - createComponent({ - value: { - duration: { seconds: 60 * 4 }, - }, - }); - dropdownToggle().trigger('click'); - await nextTick(); - expect(dropdownToggle().text()).toBe('2020-01-23 19:56:00 to 2020-01-23 20:00:00'); - }); - }); -}); diff --git a/spec/frontend/vue_shared/components/split_button_spec.js b/spec/frontend/vue_shared/components/split_button_spec.js deleted file mode 100644 index ffa25ae8448..00000000000 --- a/spec/frontend/vue_shared/components/split_button_spec.js +++ /dev/null @@ -1,117 +0,0 @@ -import { GlDropdown, GlDropdownItem } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; - -import { nextTick } from 'vue'; -import { assertProps } from 'helpers/assert_props'; -import SplitButton from '~/vue_shared/components/split_button.vue'; - -const mockActionItems = [ - { - eventName: 'concert', - title: 'professor', - description: 'very symphonic', - }, - { - eventName: 'apocalypse', - title: 'captain', - description: 'warp drive', - }, -]; - -describe('SplitButton', () => { - let wrapper; - - const createComponent = (propsData) => { - wrapper = shallowMount(SplitButton, { - propsData, - }); - }; - - const findDropdown = () => wrapper.findComponent(GlDropdown); - const findDropdownItem = (index = 0) => - findDropdown().findAllComponents(GlDropdownItem).at(index); - const selectItem = async (index) => { - findDropdownItem(index).vm.$emit('click'); - - await nextTick(); - }; - const clickToggleButton = async () => { - findDropdown().vm.$emit('click'); - - await nextTick(); - }; - - it('fails for empty actionItems', () => { - const actionItems = []; - expect(() => assertProps(SplitButton, { actionItems })).toThrow(); - }); - - it('fails for single actionItems', () => { - const actionItems = [mockActionItems[0]]; - expect(() => assertProps(SplitButton, { actionItems })).toThrow(); - }); - - it('renders actionItems', () => { - createComponent({ actionItems: mockActionItems }); - - expect(wrapper.element).toMatchSnapshot(); - }); - - describe('toggle button text', () => { - beforeEach(() => { - createComponent({ actionItems: mockActionItems }); - }); - - it('defaults to first actionItems title', () => { - expect(findDropdown().props().text).toBe(mockActionItems[0].title); - }); - - it('changes to selected actionItems title', () => - selectItem(1).then(() => { - expect(findDropdown().props().text).toBe(mockActionItems[1].title); - })); - }); - - describe('emitted event', () => { - let eventHandler; - let changeEventHandler; - - beforeEach(() => { - createComponent({ actionItems: mockActionItems }); - }); - - const addEventHandler = ({ eventName }) => { - eventHandler = jest.fn(); - wrapper.vm.$once(eventName, () => eventHandler()); - }; - - const addChangeEventHandler = () => { - changeEventHandler = jest.fn(); - wrapper.vm.$once('change', (item) => changeEventHandler(item)); - }; - - it('defaults to first actionItems event', () => { - addEventHandler(mockActionItems[0]); - - return clickToggleButton().then(() => { - expect(eventHandler).toHaveBeenCalled(); - }); - }); - - it('changes to selected actionItems event', () => - selectItem(1) - .then(() => addEventHandler(mockActionItems[1])) - .then(clickToggleButton) - .then(() => { - expect(eventHandler).toHaveBeenCalled(); - })); - - it('change to selected actionItem emits change event', () => { - addChangeEventHandler(); - - return selectItem(1).then(() => { - expect(changeEventHandler).toHaveBeenCalledWith(mockActionItems[1]); - }); - }); - }); -}); |