diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-09-20 14:18:08 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-09-20 14:18:08 +0300 |
commit | 5afcbe03ead9ada87621888a31a62652b10a7e4f (patch) | |
tree | 9918b67a0d0f0bafa6542e839a8be37adf73102d /spec/frontend/lib | |
parent | c97c0201564848c1f53226fe19d71fdcc472f7d0 (diff) |
Add latest changes from gitlab-org/gitlab@16-4-stable-eev16.4.0-rc42
Diffstat (limited to 'spec/frontend/lib')
-rw-r--r-- | spec/frontend/lib/utils/array_utility_spec.js | 36 | ||||
-rw-r--r-- | spec/frontend/lib/utils/breadcrumbs_spec.js | 84 | ||||
-rw-r--r-- | spec/frontend/lib/utils/common_utils_spec.js | 39 | ||||
-rw-r--r-- | spec/frontend/lib/utils/datetime_range_spec.js | 382 | ||||
-rw-r--r-- | spec/frontend/lib/utils/secret_detection_spec.js | 1 | ||||
-rw-r--r-- | spec/frontend/lib/utils/text_utility_spec.js | 17 | ||||
-rw-r--r-- | spec/frontend/lib/utils/url_utility_spec.js | 10 |
7 files changed, 163 insertions, 406 deletions
diff --git a/spec/frontend/lib/utils/array_utility_spec.js b/spec/frontend/lib/utils/array_utility_spec.js index 64ddd400114..94461c72106 100644 --- a/spec/frontend/lib/utils/array_utility_spec.js +++ b/spec/frontend/lib/utils/array_utility_spec.js @@ -42,4 +42,40 @@ describe('array_utility', () => { expect(arrayUtils.getDuplicateItemsFromArray(array)).toEqual(result); }); }); + + describe('toggleArrayItem', () => { + it('adds an item to the array if it does not exist', () => { + expect(arrayUtils.toggleArrayItem([], 'item')).toStrictEqual(['item']); + }); + + it('removes an item from the array if it already exists', () => { + expect(arrayUtils.toggleArrayItem(['item'], 'item')).toStrictEqual([]); + }); + + describe('pass by value', () => { + it('does not toggle the array item when passed a new object', () => { + expect(arrayUtils.toggleArrayItem([{ a: 1 }], { a: 1 })).toStrictEqual([ + { a: 1 }, + { a: 1 }, + ]); + }); + + it('does not toggle the array item when passed a new array', () => { + expect(arrayUtils.toggleArrayItem([[1]], [1])).toStrictEqual([[1], [1]]); + }); + }); + + describe('pass by reference', () => { + const array = [1]; + const object = { a: 1 }; + + it('toggles the array item when passed a object reference', () => { + expect(arrayUtils.toggleArrayItem([object], object)).toStrictEqual([]); + }); + + it('toggles the array item when passed an array reference', () => { + expect(arrayUtils.toggleArrayItem([array], array)).toStrictEqual([]); + }); + }); + }); }); diff --git a/spec/frontend/lib/utils/breadcrumbs_spec.js b/spec/frontend/lib/utils/breadcrumbs_spec.js new file mode 100644 index 00000000000..3c29e3723d3 --- /dev/null +++ b/spec/frontend/lib/utils/breadcrumbs_spec.js @@ -0,0 +1,84 @@ +import { createWrapper } from '@vue/test-utils'; +import Vue from 'vue'; +import { injectVueAppBreadcrumbs } from '~/lib/utils/breadcrumbs'; +import { resetHTMLFixture, setHTMLFixture } from 'helpers/fixtures'; +import createMockApollo from 'helpers/mock_apollo_helper'; + +describe('Breadcrumbs utils', () => { + const breadcrumbsHTML = ` + <nav> + <ul class="js-breadcrumbs-list"> + <li> + <a href="/group-name" data-testid="existing-crumb">Group name</a> + </li> + <li> + <a href="/group-name/project-name/-/subpage" data-testid="last-crumb">Subpage</a> + </li> + </ul> + </nav> + `; + + const emptyBreadcrumbsHTML = ` + <nav> + <ul class="js-breadcrumbs-list" data-testid="breadcumbs-list"> + </ul> + </nav> + `; + + const mockRouter = jest.fn(); + let MockComponent; + let mockApolloProvider; + + beforeEach(() => { + MockComponent = Vue.component('MockComponent', { + render: (createElement) => + createElement('span', { + attrs: { + 'data-testid': 'mock-component', + }, + }), + }); + mockApolloProvider = createMockApollo(); + }); + + afterEach(() => { + resetHTMLFixture(); + MockComponent = null; + }); + + describe('injectVueAppBreadcrumbs', () => { + describe('without any breadcrumbs', () => { + beforeEach(() => { + setHTMLFixture(emptyBreadcrumbsHTML); + }); + + it('returns early and stops trying to inject', () => { + expect(injectVueAppBreadcrumbs(mockRouter, MockComponent)).toBe(false); + }); + }); + + describe('with breadcrumbs', () => { + beforeEach(() => { + setHTMLFixture(breadcrumbsHTML); + }); + + describe.each` + testLabel | apolloProvider + ${'set'} | ${mockApolloProvider} + ${'not set'} | ${null} + `('given the apollo provider is $testLabel', ({ apolloProvider }) => { + beforeEach(() => { + createWrapper(injectVueAppBreadcrumbs(mockRouter, MockComponent, apolloProvider)); + }); + + it('returns a new breadcrumbs component replacing the inject HTML', () => { + // Using `querySelectorAll` because we're not testing a full Vue app. + // We are testing a partial Vue app added into the pages HTML. + expect(document.querySelectorAll('[data-testid="existing-crumb"]')).toHaveLength(1); + expect(document.querySelectorAll('[data-testid="last-crumb"]')).toHaveLength(0); + expect(document.querySelectorAll('[data-testid="mock-component"]')).toHaveLength(1); + }); + }); + }); + }); +}); diff --git a/spec/frontend/lib/utils/common_utils_spec.js b/spec/frontend/lib/utils/common_utils_spec.js index 444d4a96f9c..8697249ebf5 100644 --- a/spec/frontend/lib/utils/common_utils_spec.js +++ b/spec/frontend/lib/utils/common_utils_spec.js @@ -1174,4 +1174,43 @@ describe('common_utils', () => { }); }); }); + + describe('cloneWithoutReferences', () => { + it('clones the provided object', () => { + const obj = { + foo: 'bar', + cool: 1337, + nested: { + peanut: 'butter', + }, + arrays: [0, 1, 2], + }; + + const cloned = commonUtils.cloneWithoutReferences(obj); + + expect(cloned).toMatchObject({ + foo: 'bar', + cool: 1337, + nested: { + peanut: 'butter', + }, + arrays: [0, 1, 2], + }); + }); + + it('does not persist object references after cloning', () => { + const ref = { + foo: 'bar', + }; + + const obj = { + ref, + }; + + const cloned = commonUtils.cloneWithoutReferences(obj); + + expect(cloned.ref).toMatchObject({ foo: 'bar' }); + expect(cloned.ref === ref).toBe(false); + }); + }); }); 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/lib/utils/secret_detection_spec.js b/spec/frontend/lib/utils/secret_detection_spec.js index 3213ecf3fe1..761062f0340 100644 --- a/spec/frontend/lib/utils/secret_detection_spec.js +++ b/spec/frontend/lib/utils/secret_detection_spec.js @@ -28,6 +28,7 @@ describe('containsSensitiveToken', () => { 'token: feed_token=ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'token: feed_token=glft-ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'token: feed_token=glft-a8cc74ccb0de004d09a968705ba49099229b288b3de43f26c473a9d8d7fb7693-1234', + 'token: gloas-a8cc74ccb0de004d09a968705ba49099229b288b3de43f26c473a9d8d7fb7693', 'https://example.com/feed?feed_token=123456789_abcdefghij', 'glpat-1234567890 and feed_token=ABCDEFGHIJKLMNOPQRSTUVWXYZ', ]; diff --git a/spec/frontend/lib/utils/text_utility_spec.js b/spec/frontend/lib/utils/text_utility_spec.js index b7d6bbd3991..6821ed56857 100644 --- a/spec/frontend/lib/utils/text_utility_spec.js +++ b/spec/frontend/lib/utils/text_utility_spec.js @@ -221,23 +221,6 @@ describe('text_utility', () => { }); }); - describe('getFirstCharacterCapitalized', () => { - it('returns the first character capitalized, if first character is alphabetic', () => { - expect(textUtils.getFirstCharacterCapitalized('loremIpsumDolar')).toEqual('L'); - expect(textUtils.getFirstCharacterCapitalized('Sit amit !')).toEqual('S'); - }); - - it('returns the first character, if first character is non-alphabetic', () => { - expect(textUtils.getFirstCharacterCapitalized(' lorem')).toEqual(' '); - expect(textUtils.getFirstCharacterCapitalized('%#!')).toEqual('%'); - }); - - it('returns an empty string, if string is falsey', () => { - expect(textUtils.getFirstCharacterCapitalized('')).toEqual(''); - expect(textUtils.getFirstCharacterCapitalized(null)).toEqual(''); - }); - }); - describe('slugifyWithUnderscore', () => { it('should replaces whitespaces with underscore and convert to lower case', () => { expect(textUtils.slugifyWithUnderscore('My Input String')).toEqual('my_input_string'); diff --git a/spec/frontend/lib/utils/url_utility_spec.js b/spec/frontend/lib/utils/url_utility_spec.js index 450eeefd898..ecd2d7f888d 100644 --- a/spec/frontend/lib/utils/url_utility_spec.js +++ b/spec/frontend/lib/utils/url_utility_spec.js @@ -1,11 +1,8 @@ -import * as Sentry from '@sentry/browser'; import setWindowLocation from 'helpers/set_window_location_helper'; import { TEST_HOST } from 'helpers/test_constants'; import * as urlUtils from '~/lib/utils/url_utility'; import { safeUrls, unsafeUrls } from './mock_data'; -jest.mock('@sentry/browser'); - const shas = { valid: [ 'ad9be38573f9ee4c4daec22673478c2dd1d81cd8', @@ -434,11 +431,10 @@ describe('URL utility', () => { it('does not navigate to unsafe urls', () => { // eslint-disable-next-line no-script-url const url = 'javascript:alert(document.domain)'; - urlUtils.visitUrl(url); - expect(Sentry.captureException).toHaveBeenCalledWith( - new RangeError(`Only http and https protocols are allowed: ${url}`), - ); + expect(() => { + urlUtils.visitUrl(url); + }).toThrow(new RangeError(`Only http and https protocols are allowed: ${url}`)); }); it('navigates to a page', () => { |