diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-11-19 11:27:35 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-11-19 11:27:35 +0300 |
commit | 7e9c479f7de77702622631cff2628a9c8dcbc627 (patch) | |
tree | c8f718a08e110ad7e1894510980d2155a6549197 /spec/frontend/lib | |
parent | e852b0ae16db4052c1c567d9efa4facc81146e88 (diff) |
Add latest changes from gitlab-org/gitlab@13-6-stable-eev13.6.0-rc42
Diffstat (limited to 'spec/frontend/lib')
-rw-r--r-- | spec/frontend/lib/utils/apollo_startup_js_link_spec.js | 375 | ||||
-rw-r--r-- | spec/frontend/lib/utils/common_utils_spec.js | 19 | ||||
-rw-r--r-- | spec/frontend/lib/utils/datetime_utility_spec.js | 9 | ||||
-rw-r--r-- | spec/frontend/lib/utils/dom_utils_spec.js | 33 | ||||
-rw-r--r-- | spec/frontend/lib/utils/number_utility_spec.js | 11 | ||||
-rw-r--r-- | spec/frontend/lib/utils/text_utility_spec.js | 15 |
6 files changed, 446 insertions, 16 deletions
diff --git a/spec/frontend/lib/utils/apollo_startup_js_link_spec.js b/spec/frontend/lib/utils/apollo_startup_js_link_spec.js new file mode 100644 index 00000000000..faead3ff8fe --- /dev/null +++ b/spec/frontend/lib/utils/apollo_startup_js_link_spec.js @@ -0,0 +1,375 @@ +import { ApolloLink, Observable } from 'apollo-link'; +import { StartupJSLink } from '~/lib/utils/apollo_startup_js_link'; + +describe('StartupJSLink', () => { + const FORWARDED_RESPONSE = { data: 'FORWARDED_RESPONSE' }; + + const STARTUP_JS_RESPONSE = { data: 'STARTUP_JS_RESPONSE' }; + const OPERATION_NAME = 'startupJSQuery'; + const STARTUP_JS_QUERY = `query ${OPERATION_NAME}($id: Int = 3){ + name + id + }`; + + const STARTUP_JS_RESPONSE_TWO = { data: 'STARTUP_JS_RESPONSE_TWO' }; + const OPERATION_NAME_TWO = 'startupJSQueryTwo'; + const STARTUP_JS_QUERY_TWO = `query ${OPERATION_NAME_TWO}($id: Int = 3){ + id + name + }`; + + const ERROR_RESPONSE = { + data: { + user: null, + }, + errors: [ + { + path: ['user'], + locations: [{ line: 2, column: 3 }], + extensions: { + message: 'Object not found', + type: 2, + }, + }, + ], + }; + + let startupLink; + let link; + + function mockFetchCall(status = 200, response = STARTUP_JS_RESPONSE) { + const p = { + ok: status >= 200 && status < 300, + status, + headers: new Headers({ 'Content-Type': 'application/json' }), + statusText: `MOCK-FETCH ${status}`, + clone: () => p, + json: () => Promise.resolve(response), + }; + return Promise.resolve(p); + } + + function mockOperation({ operationName = OPERATION_NAME, variables = { id: 3 } } = {}) { + return { operationName, variables, setContext: () => {} }; + } + + const setupLink = () => { + startupLink = new StartupJSLink(); + link = ApolloLink.from([startupLink, new ApolloLink(() => Observable.of(FORWARDED_RESPONSE))]); + }; + + it('forwards requests if no calls are set up', done => { + setupLink(); + link.request(mockOperation()).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls).toBe(null); + expect(startupLink.request).toEqual(StartupJSLink.noopRequest); + done(); + }); + }); + + it('forwards requests if the operation is not pre-loaded', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { id: 3 }, + }, + ], + }; + setupLink(); + link.request(mockOperation({ operationName: 'notLoaded' })).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls.size).toBe(1); + done(); + }); + }); + + describe('variable match errors: ', () => { + it('forwards requests if the variables are not matching', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { id: 'NOT_MATCHING' }, + }, + ], + }; + setupLink(); + link.request(mockOperation()).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it('forwards requests if more variables are set in the operation', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + }, + ], + }; + setupLink(); + link.request(mockOperation()).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it('forwards requests if less variables are set in the operation', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { id: 3, name: 'tanuki' }, + }, + ], + }; + setupLink(); + link.request(mockOperation({ variables: { id: 3 } })).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it('forwards requests if different variables are set', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { name: 'tanuki' }, + }, + ], + }; + setupLink(); + link.request(mockOperation({ variables: { id: 3 } })).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it('forwards requests if array variables have a different order', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { id: [3, 4] }, + }, + ], + }; + setupLink(); + link.request(mockOperation({ variables: { id: [4, 3] } })).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + }); + + describe('error handling', () => { + it('forwards the call if the fetchCall is failing with a HTTP Error', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(404), + query: STARTUP_JS_QUERY, + variables: { id: 3 }, + }, + ], + }; + setupLink(); + link.request(mockOperation()).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it('forwards the call if it errors (e.g. failing JSON)', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: Promise.reject(new Error('Parsing failed')), + query: STARTUP_JS_QUERY, + variables: { id: 3 }, + }, + ], + }; + setupLink(); + link.request(mockOperation()).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it('forwards the call if the response contains an error', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(200, ERROR_RESPONSE), + query: STARTUP_JS_QUERY, + variables: { id: 3 }, + }, + ], + }; + setupLink(); + link.request(mockOperation()).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it("forwards the call if the response doesn't contain a data object", done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(200, { 'no-data': 'yay' }), + query: STARTUP_JS_QUERY, + variables: { id: 3 }, + }, + ], + }; + setupLink(); + link.request(mockOperation()).subscribe(result => { + expect(result).toEqual(FORWARDED_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + }); + + it('resolves the request if the operation is matching', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { id: 3 }, + }, + ], + }; + setupLink(); + link.request(mockOperation()).subscribe(result => { + expect(result).toEqual(STARTUP_JS_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it('resolves the request exactly once', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { id: 3 }, + }, + ], + }; + setupLink(); + link.request(mockOperation()).subscribe(result => { + expect(result).toEqual(STARTUP_JS_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + link.request(mockOperation()).subscribe(result2 => { + expect(result2).toEqual(FORWARDED_RESPONSE); + done(); + }); + }); + }); + + it('resolves the request if the variables have a different order', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { id: 3, name: 'foo' }, + }, + ], + }; + setupLink(); + link.request(mockOperation({ variables: { name: 'foo', id: 3 } })).subscribe(result => { + expect(result).toEqual(STARTUP_JS_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it('resolves the request if the variables have undefined values', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { name: 'foo' }, + }, + ], + }; + setupLink(); + link + .request(mockOperation({ variables: { name: 'foo', undef: undefined } })) + .subscribe(result => { + expect(result).toEqual(STARTUP_JS_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it('resolves the request if the variables are of an array format', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { id: [3, 4] }, + }, + ], + }; + setupLink(); + link.request(mockOperation({ variables: { id: [3, 4] } })).subscribe(result => { + expect(result).toEqual(STARTUP_JS_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + + it('resolves multiple requests correctly', done => { + window.gl = { + startup_graphql_calls: [ + { + fetchCall: mockFetchCall(), + query: STARTUP_JS_QUERY, + variables: { id: 3 }, + }, + { + fetchCall: mockFetchCall(200, STARTUP_JS_RESPONSE_TWO), + query: STARTUP_JS_QUERY_TWO, + variables: { id: 3 }, + }, + ], + }; + setupLink(); + link.request(mockOperation({ operationName: OPERATION_NAME_TWO })).subscribe(result => { + expect(result).toEqual(STARTUP_JS_RESPONSE_TWO); + expect(startupLink.startupCalls.size).toBe(1); + link.request(mockOperation({ operationName: OPERATION_NAME })).subscribe(result2 => { + expect(result2).toEqual(STARTUP_JS_RESPONSE); + expect(startupLink.startupCalls.size).toBe(0); + done(); + }); + }); + }); +}); diff --git a/spec/frontend/lib/utils/common_utils_spec.js b/spec/frontend/lib/utils/common_utils_spec.js index effc446d846..09eb362c77e 100644 --- a/spec/frontend/lib/utils/common_utils_spec.js +++ b/spec/frontend/lib/utils/common_utils_spec.js @@ -959,6 +959,25 @@ describe('common_utils', () => { }); }); + describe('roundDownFloat', () => { + it('Rounds down decimal places of a float number with provided precision', () => { + expect(commonUtils.roundDownFloat(3.141592, 3)).toBe(3.141); + }); + + it('Rounds down a float number to a whole number when provided precision is zero', () => { + expect(commonUtils.roundDownFloat(3.141592, 0)).toBe(3); + expect(commonUtils.roundDownFloat(3.9, 0)).toBe(3); + }); + + it('Rounds down float number to nearest 0, 10, 100, 1000 and so on when provided precision is below 0', () => { + expect(commonUtils.roundDownFloat(34567.14159, -1)).toBeCloseTo(34560); + expect(commonUtils.roundDownFloat(34567.14159, -2)).toBeCloseTo(34500); + expect(commonUtils.roundDownFloat(34567.14159, -3)).toBeCloseTo(34000); + expect(commonUtils.roundDownFloat(34567.14159, -4)).toBeCloseTo(30000); + expect(commonUtils.roundDownFloat(34567.14159, -5)).toBeCloseTo(0); + }); + }); + describe('searchBy', () => { const searchSpace = { iid: 1, diff --git a/spec/frontend/lib/utils/datetime_utility_spec.js b/spec/frontend/lib/utils/datetime_utility_spec.js index b0b0b028761..6092b44720f 100644 --- a/spec/frontend/lib/utils/datetime_utility_spec.js +++ b/spec/frontend/lib/utils/datetime_utility_spec.js @@ -643,16 +643,15 @@ describe('localTimeAgo', () => { }); it.each` - timeagoArg | title | dataOriginalTitle - ${false} | ${'some time'} | ${null} - ${true} | ${''} | ${'Feb 18, 2020 10:22pm GMT+0000'} - `('converts $seconds seconds to $approximation', ({ timeagoArg, title, dataOriginalTitle }) => { + timeagoArg | title + ${false} | ${'some time'} + ${true} | ${'Feb 18, 2020 10:22pm GMT+0000'} + `('converts $seconds seconds to $approximation', ({ timeagoArg, title }) => { const element = document.querySelector('time'); datetimeUtility.localTimeAgo($(element), timeagoArg); jest.runAllTimers(); - expect(element.getAttribute('data-original-title')).toBe(dataOriginalTitle); expect(element.getAttribute('title')).toBe(title); }); }); diff --git a/spec/frontend/lib/utils/dom_utils_spec.js b/spec/frontend/lib/utils/dom_utils_spec.js index d918016a5f4..f5c2a797df5 100644 --- a/spec/frontend/lib/utils/dom_utils_spec.js +++ b/spec/frontend/lib/utils/dom_utils_spec.js @@ -3,6 +3,8 @@ import { canScrollUp, canScrollDown, parseBooleanDataAttributes, + isElementVisible, + isElementHidden, } from '~/lib/utils/dom_utils'; const TEST_MARGIN = 5; @@ -160,4 +162,35 @@ describe('DOM Utils', () => { }); }); }); + + describe.each` + offsetWidth | offsetHeight | clientRectsLength | visible + ${0} | ${0} | ${0} | ${false} + ${1} | ${0} | ${0} | ${true} + ${0} | ${1} | ${0} | ${true} + ${0} | ${0} | ${1} | ${true} + `( + 'isElementVisible and isElementHidden', + ({ offsetWidth, offsetHeight, clientRectsLength, visible }) => { + const element = { + offsetWidth, + offsetHeight, + getClientRects: () => new Array(clientRectsLength), + }; + + const paramDescription = `offsetWidth=${offsetWidth}, offsetHeight=${offsetHeight}, and getClientRects().length=${clientRectsLength}`; + + describe('isElementVisible', () => { + it(`returns ${visible} when ${paramDescription}`, () => { + expect(isElementVisible(element)).toBe(visible); + }); + }); + + describe('isElementHidden', () => { + it(`returns ${!visible} when ${paramDescription}`, () => { + expect(isElementHidden(element)).toBe(!visible); + }); + }); + }, + ); }); diff --git a/spec/frontend/lib/utils/number_utility_spec.js b/spec/frontend/lib/utils/number_utility_spec.js index f600f2bcd55..2f8f1092612 100644 --- a/spec/frontend/lib/utils/number_utility_spec.js +++ b/spec/frontend/lib/utils/number_utility_spec.js @@ -1,6 +1,5 @@ import { formatRelevantDigits, - bytesToKB, bytesToKiB, bytesToMiB, bytesToGiB, @@ -55,16 +54,6 @@ describe('Number Utils', () => { }); }); - describe('bytesToKB', () => { - it.each` - input | output - ${1000} | ${1} - ${1024} | ${1.024} - `('returns $output KB for $input bytes', ({ input, output }) => { - expect(bytesToKB(input)).toBe(output); - }); - }); - describe('bytesToKiB', () => { it('calculates KiB for the given bytes', () => { expect(bytesToKiB(1024)).toEqual(1); diff --git a/spec/frontend/lib/utils/text_utility_spec.js b/spec/frontend/lib/utils/text_utility_spec.js index 6fef5f6b63c..d7cedb939d2 100644 --- a/spec/frontend/lib/utils/text_utility_spec.js +++ b/spec/frontend/lib/utils/text_utility_spec.js @@ -325,4 +325,19 @@ describe('text_utility', () => { expect(textUtils.hasContent(txt)).toEqual(result); }); }); + + describe('isValidSha1Hash', () => { + const validSha1Hash = '92d10c15'; + const stringOver40 = new Array(42).join('a'); + + it.each` + hash | valid + ${validSha1Hash} | ${true} + ${'__characters'} | ${false} + ${'abc'} | ${false} + ${stringOver40} | ${false} + `(`returns $valid for $hash`, ({ hash, valid }) => { + expect(textUtils.isValidSha1Hash(hash)).toBe(valid); + }); + }); }); |