Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-08-19 12:08:42 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-08-19 12:08:42 +0300
commitb76ae638462ab0f673e5915986070518dd3f9ad3 (patch)
treebdab0533383b52873be0ec0eb4d3c66598ff8b91 /spec/frontend/__helpers__
parent434373eabe7b4be9593d18a585fb763f1e5f1a6f (diff)
Add latest changes from gitlab-org/gitlab@14-2-stable-eev14.2.0-rc42
Diffstat (limited to 'spec/frontend/__helpers__')
-rw-r--r--spec/frontend/__helpers__/mock_dom_observer.js22
-rw-r--r--spec/frontend/__helpers__/mock_window_location_helper.js2
-rw-r--r--spec/frontend/__helpers__/set_window_location_helper.js75
-rw-r--r--spec/frontend/__helpers__/set_window_location_helper_spec.js161
4 files changed, 182 insertions, 78 deletions
diff --git a/spec/frontend/__helpers__/mock_dom_observer.js b/spec/frontend/__helpers__/mock_dom_observer.js
index 1b93b81535d..dd26b594ad9 100644
--- a/spec/frontend/__helpers__/mock_dom_observer.js
+++ b/spec/frontend/__helpers__/mock_dom_observer.js
@@ -52,7 +52,7 @@ class MockIntersectionObserver extends MockObserver {
* const { trigger: triggerMutate } = useMockMutationObserver();
*
* it('test', () => {
- * trigger(el, { options: { childList: true }, entry: { } });
+ * triggerMutate(el, { options: { childList: true }, entry: { } });
* });
* })
* ```
@@ -60,33 +60,31 @@ class MockIntersectionObserver extends MockObserver {
* @param {String} key
*/
const useMockObserver = (key, createMock) => {
- let mockObserver;
+ let mockObservers = [];
let origObserver;
beforeEach(() => {
origObserver = global[key];
global[key] = jest.fn().mockImplementation((...args) => {
- mockObserver = createMock(...args);
+ const mockObserver = createMock(...args);
+ mockObservers.push(mockObserver);
return mockObserver;
});
});
afterEach(() => {
- mockObserver = null;
+ mockObservers.forEach((x) => x.disconnect());
+ mockObservers = [];
global[key] = origObserver;
});
const trigger = (...args) => {
- if (!mockObserver) {
- return;
- }
-
- mockObserver.$_triggerObserve(...args);
+ mockObservers.forEach((observer) => {
+ observer.$_triggerObserve(...args);
+ });
};
- const observersCount = () => mockObserver.$_observers.length;
-
- return { trigger, observersCount };
+ return { trigger };
};
export const useMockIntersectionObserver = () =>
diff --git a/spec/frontend/__helpers__/mock_window_location_helper.js b/spec/frontend/__helpers__/mock_window_location_helper.js
index 08a28fbbbd6..3755778e5c1 100644
--- a/spec/frontend/__helpers__/mock_window_location_helper.js
+++ b/spec/frontend/__helpers__/mock_window_location_helper.js
@@ -10,7 +10,7 @@
*/
const useMockLocation = (fn) => {
const origWindowLocation = window.location;
- let currentWindowLocation;
+ let currentWindowLocation = origWindowLocation;
Object.defineProperty(window, 'location', {
get: () => currentWindowLocation,
diff --git a/spec/frontend/__helpers__/set_window_location_helper.js b/spec/frontend/__helpers__/set_window_location_helper.js
index a94e73762c9..573a089f111 100644
--- a/spec/frontend/__helpers__/set_window_location_helper.js
+++ b/spec/frontend/__helpers__/set_window_location_helper.js
@@ -1,40 +1,53 @@
/**
- * setWindowLocation allows for setting `window.location`
- * (doing so directly is causing an error in jsdom)
+ * setWindowLocation allows for setting `window.location` within Jest.
*
- * Example usage:
- * assert(window.location.hash === undefined);
- * setWindowLocation('http://example.com#foo')
- * assert(window.location.hash === '#foo');
+ * The jsdom environment at the time of writing does not support changing the
+ * current location (see
+ * https://github.com/jsdom/jsdom/blob/16.4.0/lib/jsdom/living/window/navigation.js#L76),
+ * hence this helper.
*
- * More information:
- * https://github.com/facebook/jest/issues/890
+ * This helper mutates the current `window.location` very similarly to how
+ * a direct assignment to `window.location.href` would in a browser (but
+ * without the navigation/reload behaviour). For instance:
*
- * @param url
+ * - Set the full href by passing an absolute URL, e.g.:
+ *
+ * setWindowLocation('https://gdk.test');
+ * // window.location.href is now 'https://gdk.test'
+ *
+ * - Set the path, search and/or hash components by passing a relative URL:
+ *
+ * setWindowLocation('/foo/bar');
+ * // window.location.href is now 'http://test.host/foo/bar'
+ *
+ * setWindowLocation('?foo=bar');
+ * // window.location.href is now 'http://test.host/?foo=bar'
+ *
+ * setWindowLocation('#foo');
+ * // window.location.href is now 'http://test.host/#foo'
+ *
+ * setWindowLocation('/a/b/foo.html?bar=1#qux');
+ * // window.location.href is now 'http://test.host/a/b/foo.html?bar=1#qux
+ *
+ * Both approaches also automatically update the rest of the properties on
+ * `window.locaton`. For instance:
+ *
+ * setWindowLocation('http://test.host/a/b/foo.html?bar=1#qux');
+ * // window.location.origin is now 'http://test.host'
+ * // window.location.pathname is now '/a/b/foo.html'
+ * // window.location.search is now '?bar=1'
+ * // window.location.searchParams is now { bar: 1 }
+ * // window.location.hash is now '#qux'
+ *
+ * @param {string} url A string representing an absolute or relative URL.
+ * @returns {undefined}
*/
export default function setWindowLocation(url) {
- const parsedUrl = new URL(url);
+ if (typeof url !== 'string') {
+ throw new TypeError(`Expected string; got ${url} (${typeof url})`);
+ }
- const newLocationValue = [
- 'hash',
- 'host',
- 'hostname',
- 'href',
- 'origin',
- 'pathname',
- 'port',
- 'protocol',
- 'search',
- ].reduce(
- (location, prop) => ({
- ...location,
- [prop]: parsedUrl[prop],
- }),
- {},
- );
+ const newUrl = new URL(url, window.location.href);
- Object.defineProperty(window, 'location', {
- value: newLocationValue,
- writable: true,
- });
+ global.jsdom.reconfigure({ url: newUrl.href });
}
diff --git a/spec/frontend/__helpers__/set_window_location_helper_spec.js b/spec/frontend/__helpers__/set_window_location_helper_spec.js
index 98f26854822..c0f3debddbc 100644
--- a/spec/frontend/__helpers__/set_window_location_helper_spec.js
+++ b/spec/frontend/__helpers__/set_window_location_helper_spec.js
@@ -1,40 +1,133 @@
import setWindowLocation from './set_window_location_helper';
+import { TEST_HOST } from './test_constants';
-describe('setWindowLocation', () => {
- const originalLocation = window.location;
+describe('helpers/set_window_location_helper', () => {
+ const originalLocation = window.location.href;
- afterEach(() => {
- window.location = originalLocation;
+ beforeEach(() => {
+ setWindowLocation(originalLocation);
});
- it.each`
- url | property | value
- ${'https://gitlab.com#foo'} | ${'hash'} | ${'#foo'}
- ${'http://gitlab.com'} | ${'host'} | ${'gitlab.com'}
- ${'http://gitlab.org'} | ${'hostname'} | ${'gitlab.org'}
- ${'http://gitlab.org/foo#bar'} | ${'href'} | ${'http://gitlab.org/foo#bar'}
- ${'http://gitlab.com'} | ${'origin'} | ${'http://gitlab.com'}
- ${'http://gitlab.com/foo/bar/baz'} | ${'pathname'} | ${'/foo/bar/baz'}
- ${'https://gitlab.com'} | ${'protocol'} | ${'https:'}
- ${'http://gitlab.com#foo'} | ${'protocol'} | ${'http:'}
- ${'http://gitlab.com:8080'} | ${'port'} | ${'8080'}
- ${'http://gitlab.com?foo=bar&bar=foo'} | ${'search'} | ${'?foo=bar&bar=foo'}
- `(
- 'sets "window.location.$property" to be "$value" when called with: "$url"',
- ({ url, property, value }) => {
- expect(window.location).toBe(originalLocation);
-
- setWindowLocation(url);
-
- expect(window.location[property]).toBe(value);
- },
- );
-
- it.each([null, 1, undefined, false, '', 'gitlab.com'])(
- 'throws an error when called with an invalid url: "%s"',
- (invalidUrl) => {
- expect(() => setWindowLocation(invalidUrl)).toThrow(/Invalid URL/);
- expect(window.location).toBe(originalLocation);
- },
- );
+ describe('setWindowLocation', () => {
+ describe('given a complete URL', () => {
+ it.each`
+ url | property | value
+ ${'https://gitlab.com#foo'} | ${'hash'} | ${'#foo'}
+ ${'http://gitlab.com'} | ${'host'} | ${'gitlab.com'}
+ ${'http://gitlab.org'} | ${'hostname'} | ${'gitlab.org'}
+ ${'http://gitlab.org/foo#bar'} | ${'href'} | ${'http://gitlab.org/foo#bar'}
+ ${'http://gitlab.com'} | ${'origin'} | ${'http://gitlab.com'}
+ ${'http://gitlab.com/foo/bar/baz'} | ${'pathname'} | ${'/foo/bar/baz'}
+ ${'https://gitlab.com'} | ${'protocol'} | ${'https:'}
+ ${'ftp://gitlab.com#foo'} | ${'protocol'} | ${'ftp:'}
+ ${'http://gitlab.com:8080'} | ${'port'} | ${'8080'}
+ ${'http://gitlab.com?foo=bar&bar=foo'} | ${'search'} | ${'?foo=bar&bar=foo'}
+ `(
+ 'sets "window.location.$property" to be "$value" when called with: "$url"',
+ ({ url, property, value }) => {
+ expect(window.location.href).toBe(originalLocation);
+
+ setWindowLocation(url);
+
+ expect(window.location[property]).toBe(value);
+ },
+ );
+ });
+
+ describe('given a partial URL', () => {
+ it.each`
+ partialURL | href
+ ${'//foo.test:3000/'} | ${'http://foo.test:3000/'}
+ ${'/foo/bar'} | ${`${originalLocation}foo/bar`}
+ ${'foo/bar'} | ${`${originalLocation}foo/bar`}
+ ${'?foo=bar'} | ${`${originalLocation}?foo=bar`}
+ ${'#a-thing'} | ${`${originalLocation}#a-thing`}
+ `('$partialURL sets location.href to $href', ({ partialURL, href }) => {
+ expect(window.location.href).toBe(originalLocation);
+
+ setWindowLocation(partialURL);
+
+ expect(window.location.href).toBe(href);
+ });
+ });
+
+ describe('relative path', () => {
+ describe.each`
+ initialHref | path | newHref
+ ${'https://gdk.test/foo/bar'} | ${'/qux'} | ${'https://gdk.test/qux'}
+ ${'https://gdk.test/foo/bar/'} | ${'/qux'} | ${'https://gdk.test/qux'}
+ ${'https://gdk.test/foo/bar'} | ${'qux'} | ${'https://gdk.test/foo/qux'}
+ ${'https://gdk.test/foo/bar/'} | ${'qux'} | ${'https://gdk.test/foo/bar/qux'}
+ ${'https://gdk.test/foo/bar'} | ${'../qux'} | ${'https://gdk.test/qux'}
+ ${'https://gdk.test/foo/bar/'} | ${'../qux'} | ${'https://gdk.test/foo/qux'}
+ `('when location is $initialHref', ({ initialHref, path, newHref }) => {
+ beforeEach(() => {
+ setWindowLocation(initialHref);
+ });
+
+ it(`${path} sets window.location.href to ${newHref}`, () => {
+ expect(window.location.href).toBe(initialHref);
+
+ setWindowLocation(path);
+
+ expect(window.location.href).toBe(newHref);
+ });
+ });
+ });
+
+ it.each([null, 1, undefined, false, 'https://', 'https:', { foo: 1 }, []])(
+ 'throws an error when called with an invalid url: "%s"',
+ (invalidUrl) => {
+ expect(() => setWindowLocation(invalidUrl)).toThrow();
+ expect(window.location.href).toBe(originalLocation);
+ },
+ );
+
+ describe('affects links', () => {
+ it.each`
+ url | hrefAttr | expectedHref
+ ${'http://gitlab.com/'} | ${'foo'} | ${'http://gitlab.com/foo'}
+ ${'http://gitlab.com/bar/'} | ${'foo'} | ${'http://gitlab.com/bar/foo'}
+ ${'http://gitlab.com/bar/'} | ${'/foo'} | ${'http://gitlab.com/foo'}
+ ${'http://gdk.test:3000/?foo=bar'} | ${'?qux=1'} | ${'http://gdk.test:3000/?qux=1'}
+ ${'https://gdk.test:3000/?foo=bar'} | ${'//other.test'} | ${'https://other.test/'}
+ `(
+ 'given $url, <a href="$hrefAttr"> points to $expectedHref',
+ ({ url, hrefAttr, expectedHref }) => {
+ setWindowLocation(url);
+
+ const link = document.createElement('a');
+ link.setAttribute('href', hrefAttr);
+
+ expect(link.href).toBe(expectedHref);
+ },
+ );
+ });
+ });
+
+ // This set of tests relies on Jest executing tests in source order, which is
+ // at the time of writing the only order they will execute, by design.
+ // See https://github.com/facebook/jest/issues/4386 for more details.
+ describe('window.location resetting by global beforeEach', () => {
+ const overridden = 'https://gdk.test:1234/';
+ const initial = `${TEST_HOST}/`;
+
+ it('works before an override', () => {
+ expect(window.location.href).toBe(initial);
+ });
+
+ describe('overriding', () => {
+ beforeEach(() => {
+ setWindowLocation(overridden);
+ });
+
+ it('works', () => {
+ expect(window.location.href).toBe(overridden);
+ });
+ });
+
+ it('works after an override', () => {
+ expect(window.location.href).toBe(initial);
+ });
+ });
});