summaryrefslogtreecommitdiff
path: root/spec/frontend/__helpers__
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-02-18 10:34:06 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-02-18 10:34:06 +0000
commit859a6fb938bb9ee2a317c46dfa4fcc1af49608f0 (patch)
treed7f2700abe6b4ffcb2dcfc80631b2d87d0609239 /spec/frontend/__helpers__
parent446d496a6d000c73a304be52587cd9bbc7493136 (diff)
downloadgitlab-ce-859a6fb938bb9ee2a317c46dfa4fcc1af49608f0.tar.gz
Add latest changes from gitlab-org/gitlab@13-9-stable-eev13.9.0-rc42
Diffstat (limited to 'spec/frontend/__helpers__')
-rw-r--r--spec/frontend/__helpers__/emoji.js36
-rw-r--r--spec/frontend/__helpers__/fake_date/fake_date.js (renamed from spec/frontend/__helpers__/fake_date.js)21
-rw-r--r--spec/frontend/__helpers__/fake_date/fake_date_spec.js (renamed from spec/frontend/__helpers__/fake_date_spec.js)8
-rw-r--r--spec/frontend/__helpers__/fake_date/index.js2
-rw-r--r--spec/frontend/__helpers__/fake_date/jest.js41
-rw-r--r--spec/frontend/__helpers__/graphql_helpers.js14
-rw-r--r--spec/frontend/__helpers__/graphql_helpers_spec.js23
-rw-r--r--spec/frontend/__helpers__/init_vue_mr_page_helper.js4
-rw-r--r--spec/frontend/__helpers__/jest_execution_watcher.js12
-rw-r--r--spec/frontend/__helpers__/stub_component.js25
10 files changed, 145 insertions, 41 deletions
diff --git a/spec/frontend/__helpers__/emoji.js b/spec/frontend/__helpers__/emoji.js
index ea6613b53c9..9f9134f6f63 100644
--- a/spec/frontend/__helpers__/emoji.js
+++ b/spec/frontend/__helpers__/emoji.js
@@ -1,6 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
import { initEmojiMap, EMOJI_VERSION } from '~/emoji';
+import axios from '~/lib/utils/axios_utils';
export const emojiFixtureMap = {
atom: {
@@ -29,10 +29,6 @@ export const emojiFixtureMap = {
unicodeVersion: '6.0',
description: 'white question mark ornament',
},
-
- // used for regression tests
- // black_heart MUST come before heart
- // custard MUST come before star
black_heart: {
moji: '🖤',
unicodeVersion: '1.1',
@@ -55,34 +51,18 @@ export const emojiFixtureMap = {
},
};
-Object.keys(emojiFixtureMap).forEach((k) => {
- emojiFixtureMap[k].name = k;
- if (!emojiFixtureMap[k].aliases) {
- emojiFixtureMap[k].aliases = [];
- }
-});
+export const mockEmojiData = Object.keys(emojiFixtureMap).reduce((acc, k) => {
+ const { moji: e, unicodeVersion: u, category: c, description: d } = emojiFixtureMap[k];
+ acc[k] = { name: k, e, u, c, d };
-export async function initEmojiMock() {
- const emojiData = Object.fromEntries(
- Object.values(emojiFixtureMap).map((m) => {
- const { name: n, moji: e, unicodeVersion: u, category: c, description: d } = m;
- return [n, { c, e, d, u }];
- }),
- );
+ return acc;
+}, {});
+export async function initEmojiMock(mockData = mockEmojiData) {
const mock = new MockAdapter(axios);
- mock.onGet(`/-/emojis/${EMOJI_VERSION}/emojis.json`).reply(200, JSON.stringify(emojiData));
+ mock.onGet(`/-/emojis/${EMOJI_VERSION}/emojis.json`).reply(200, JSON.stringify(mockData));
await initEmojiMap();
return mock;
}
-
-export function describeEmojiFields(label, tests) {
- describe.each`
- field | accessor
- ${'name'} | ${(e) => e.name}
- ${'alias'} | ${(e) => e.aliases[0]}
- ${'description'} | ${(e) => e.description}
- `(label, tests);
-}
diff --git a/spec/frontend/__helpers__/fake_date.js b/spec/frontend/__helpers__/fake_date/fake_date.js
index 5391ae04797..bc088ad96b6 100644
--- a/spec/frontend/__helpers__/fake_date.js
+++ b/spec/frontend/__helpers__/fake_date/fake_date.js
@@ -1,11 +1,13 @@
// Frida Kahlo's birthday (6 = July)
-export const DEFAULT_ARGS = [2020, 6, 6];
+const DEFAULT_ARGS = [2020, 6, 6];
const RealDate = Date;
const isMocked = (val) => Boolean(val.mock);
-export const createFakeDateClass = (ctorDefault) => {
+const createFakeDateClass = (ctorDefaultParam = []) => {
+ const ctorDefault = ctorDefaultParam.length ? ctorDefaultParam : DEFAULT_ARGS;
+
const FakeDate = new Proxy(RealDate, {
construct: (target, argArray) => {
const ctorArgs = argArray.length ? argArray : ctorDefault;
@@ -39,11 +41,20 @@ export const createFakeDateClass = (ctorDefault) => {
return FakeDate;
};
-export const useFakeDate = (...args) => {
- const FakeDate = createFakeDateClass(args.length ? args : DEFAULT_ARGS);
+const setGlobalDateToFakeDate = (...args) => {
+ const FakeDate = createFakeDateClass(args);
global.Date = FakeDate;
};
-export const useRealDate = () => {
+const setGlobalDateToRealDate = () => {
global.Date = RealDate;
};
+
+// We use commonjs so that the test environment module can pick this up
+// eslint-disable-next-line import/no-commonjs
+module.exports = {
+ setGlobalDateToFakeDate,
+ setGlobalDateToRealDate,
+ createFakeDateClass,
+ RealDate,
+};
diff --git a/spec/frontend/__helpers__/fake_date_spec.js b/spec/frontend/__helpers__/fake_date/fake_date_spec.js
index b3ed13e238a..730765e52d2 100644
--- a/spec/frontend/__helpers__/fake_date_spec.js
+++ b/spec/frontend/__helpers__/fake_date/fake_date_spec.js
@@ -1,15 +1,11 @@
-import { createFakeDateClass, DEFAULT_ARGS, useRealDate } from './fake_date';
+import { createFakeDateClass } from './fake_date';
describe('spec/helpers/fake_date', () => {
describe('createFakeDateClass', () => {
let FakeDate;
- beforeAll(() => {
- useRealDate();
- });
-
beforeEach(() => {
- FakeDate = createFakeDateClass(DEFAULT_ARGS);
+ FakeDate = createFakeDateClass();
});
it('should use default args', () => {
diff --git a/spec/frontend/__helpers__/fake_date/index.js b/spec/frontend/__helpers__/fake_date/index.js
new file mode 100644
index 00000000000..3d1b124ce79
--- /dev/null
+++ b/spec/frontend/__helpers__/fake_date/index.js
@@ -0,0 +1,2 @@
+export * from './fake_date';
+export * from './jest';
diff --git a/spec/frontend/__helpers__/fake_date/jest.js b/spec/frontend/__helpers__/fake_date/jest.js
new file mode 100644
index 00000000000..65e45619049
--- /dev/null
+++ b/spec/frontend/__helpers__/fake_date/jest.js
@@ -0,0 +1,41 @@
+import { createJestExecutionWatcher } from '../jest_execution_watcher';
+import { RealDate, createFakeDateClass } from './fake_date';
+
+const throwInsideExecutionError = (fnName) => {
+ throw new Error(`Cannot call "${fnName}" during test execution (i.e. within "it", "beforeEach", "beforeAll", etc.).
+
+Instead, please move the call to "${fnName}" inside the "describe" block itself.
+
+ describe('', () => {
+ + ${fnName}();
+
+ it('', () => {
+ - ${fnName}();
+ })
+ })
+`);
+};
+
+const isExecutingTest = createJestExecutionWatcher();
+
+export const useDateInScope = (fnName, factory) => {
+ if (isExecutingTest()) {
+ throwInsideExecutionError(fnName);
+ }
+
+ let origDate;
+
+ beforeAll(() => {
+ origDate = global.Date;
+ global.Date = factory();
+ });
+
+ afterAll(() => {
+ global.Date = origDate;
+ });
+};
+
+export const useFakeDate = (...args) =>
+ useDateInScope('useFakeDate', () => createFakeDateClass(args));
+
+export const useRealDate = () => useDateInScope('useRealDate', () => RealDate);
diff --git a/spec/frontend/__helpers__/graphql_helpers.js b/spec/frontend/__helpers__/graphql_helpers.js
new file mode 100644
index 00000000000..63123aa046f
--- /dev/null
+++ b/spec/frontend/__helpers__/graphql_helpers.js
@@ -0,0 +1,14 @@
+/**
+ * Returns a clone of the given object with all __typename keys omitted,
+ * including deeply nested ones.
+ *
+ * Only works with JSON-serializable objects.
+ *
+ * @param {object} An object with __typename keys (e.g., a GraphQL response)
+ * @returns {object} A new object with no __typename keys
+ */
+export const stripTypenames = (object) => {
+ return JSON.parse(
+ JSON.stringify(object, (key, value) => (key === '__typename' ? undefined : value)),
+ );
+};
diff --git a/spec/frontend/__helpers__/graphql_helpers_spec.js b/spec/frontend/__helpers__/graphql_helpers_spec.js
new file mode 100644
index 00000000000..dd23fbbf4e9
--- /dev/null
+++ b/spec/frontend/__helpers__/graphql_helpers_spec.js
@@ -0,0 +1,23 @@
+import { stripTypenames } from './graphql_helpers';
+
+describe('stripTypenames', () => {
+ it.each`
+ input | expected
+ ${{}} | ${{}}
+ ${{ __typename: 'Foo' }} | ${{}}
+ ${{ bar: 'bar', __typename: 'Foo' }} | ${{ bar: 'bar' }}
+ ${{ bar: { __typename: 'Bar' }, __typename: 'Foo' }} | ${{ bar: {} }}
+ ${{ bar: [{ __typename: 'Bar' }], __typename: 'Foo' }} | ${{ bar: [{}] }}
+ ${[]} | ${[]}
+ ${[{ __typename: 'Foo' }]} | ${[{}]}
+ ${[{ bar: [{ a: 1, __typename: 'Bar' }] }]} | ${[{ bar: [{ a: 1 }] }]}
+ `('given $input returns $expected, with all __typename keys removed', ({ input, expected }) => {
+ const actual = stripTypenames(input);
+ expect(actual).toEqual(expected);
+ expect(input).not.toBe(actual);
+ });
+
+ it('given null returns null', () => {
+ expect(stripTypenames(null)).toEqual(null);
+ });
+});
diff --git a/spec/frontend/__helpers__/init_vue_mr_page_helper.js b/spec/frontend/__helpers__/init_vue_mr_page_helper.js
index b9aed63d0f6..ee01e9e6268 100644
--- a/spec/frontend/__helpers__/init_vue_mr_page_helper.js
+++ b/spec/frontend/__helpers__/init_vue_mr_page_helper.js
@@ -1,8 +1,8 @@
import MockAdapter from 'axios-mock-adapter';
-import initMRPage from '~/mr_notes';
import axios from '~/lib/utils/axios_utils';
-import { userDataMock, notesDataMock, noteableDataMock } from '../notes/mock_data';
+import initMRPage from '~/mr_notes';
import diffFileMockData from '../diffs/mock_data/diff_file';
+import { userDataMock, notesDataMock, noteableDataMock } from '../notes/mock_data';
export default function initVueMRPage() {
const mrTestEl = document.createElement('div');
diff --git a/spec/frontend/__helpers__/jest_execution_watcher.js b/spec/frontend/__helpers__/jest_execution_watcher.js
new file mode 100644
index 00000000000..0fc3d330ec3
--- /dev/null
+++ b/spec/frontend/__helpers__/jest_execution_watcher.js
@@ -0,0 +1,12 @@
+export const createJestExecutionWatcher = () => {
+ let isExecuting = false;
+
+ beforeAll(() => {
+ isExecuting = true;
+ });
+ afterAll(() => {
+ isExecuting = false;
+ });
+
+ return () => isExecuting;
+};
diff --git a/spec/frontend/__helpers__/stub_component.js b/spec/frontend/__helpers__/stub_component.js
index 45550450517..96fe3a8bc45 100644
--- a/spec/frontend/__helpers__/stub_component.js
+++ b/spec/frontend/__helpers__/stub_component.js
@@ -1,7 +1,32 @@
+/**
+ * Returns a new object with keys pointing to stubbed methods
+ *
+ * This is helpful for stubbing components like GlModal where it's supported
+ * in the API to call `.show()` and `.hide()` ([Bootstrap Vue docs][1]).
+ *
+ * [1]: https://bootstrap-vue.org/docs/components/modal#using-show-hide-and-toggle-component-methods
+ *
+ * @param {Object} methods - Object whose keys will be in the returned object.
+ */
+const createStubbedMethods = (methods = {}) => {
+ if (!methods) {
+ return {};
+ }
+
+ return Object.keys(methods).reduce(
+ (acc, key) =>
+ Object.assign(acc, {
+ [key]: () => {},
+ }),
+ {},
+ );
+};
+
export function stubComponent(Component, options = {}) {
return {
props: Component.props,
model: Component.model,
+ methods: createStubbedMethods(Component.methods),
// Do not render any slots/scoped slots except default
// This differs from VTU behavior which renders all slots
template: '<div><slot></slot></div>',