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:
Diffstat (limited to 'spec/frontend')
-rw-r--r--spec/frontend/fixtures/issues.rb2
-rw-r--r--spec/frontend/fixtures/snippet.rb2
-rw-r--r--spec/frontend/header_spec.js9
-rw-r--r--spec/frontend/ide/components/repo_editor_spec.js9
-rw-r--r--spec/frontend/issues/issue_spec.js12
-rw-r--r--spec/frontend/lib/utils/common_utils_spec.js24
-rw-r--r--spec/frontend/shortcuts_spec.js40
-rw-r--r--spec/frontend/vue_shared/components/list_selector/index_spec.js134
-rw-r--r--spec/frontend/vue_shared/components/list_selector/mock_data.js25
-rw-r--r--spec/frontend/vue_shared/components/list_selector/user_spec.js55
10 files changed, 284 insertions, 28 deletions
diff --git a/spec/frontend/fixtures/issues.rb b/spec/frontend/fixtures/issues.rb
index 90aa0544526..6d81d9ca1d2 100644
--- a/spec/frontend/fixtures/issues.rb
+++ b/spec/frontend/fixtures/issues.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::IssuesController, '(JavaScript fixtures)', :with_license, type: :controller do
include JavaScriptFixturesHelpers
- let(:user) { create(:user, :no_super_sidebar, feed_token: 'feedtoken:coldfeed') }
+ let(:user) { create(:user, feed_token: 'feedtoken:coldfeed') }
let(:namespace) { create(:namespace, name: 'frontend-fixtures') }
let(:project) { create(:project_empty_repo, namespace: namespace, path: 'issues-project') }
diff --git a/spec/frontend/fixtures/snippet.rb b/spec/frontend/fixtures/snippet.rb
index 23df89a244c..a96b7a57106 100644
--- a/spec/frontend/fixtures/snippet.rb
+++ b/spec/frontend/fixtures/snippet.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe SnippetsController, '(JavaScript fixtures)', type: :controller do
include JavaScriptFixturesHelpers
- let(:user) { create(:user, :no_super_sidebar) }
+ let(:user) { create(:user) }
let(:namespace) { create(:namespace, name: 'frontend-fixtures', owner: user) }
let(:project) { create(:project, :repository, namespace: namespace, path: 'branches-project') }
let(:snippet) { create(:personal_snippet, :public, title: 'snippet.md', content: '# snippet', file_name: 'snippet.md', author: user) }
diff --git a/spec/frontend/header_spec.js b/spec/frontend/header_spec.js
index 4907dc09a3c..13c11863443 100644
--- a/spec/frontend/header_spec.js
+++ b/spec/frontend/header_spec.js
@@ -3,7 +3,14 @@ import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import initTodoToggle, { initNavUserDropdownTracking } from '~/header';
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
-describe('Header', () => {
+// TODO: Remove this with the removal of the old navigation.
+// See https://gitlab.com/groups/gitlab-org/-/epics/11875.
+//
+// This and ~/header will be removed. These tests no longer work due to the
+// corresponding fixtures changing for
+// https://gitlab.com/gitlab-org/gitlab/-/issues/420121.
+// eslint-disable-next-line jest/no-disabled-tests
+describe.skip('Header', () => {
describe('Todos notification', () => {
const todosPendingCount = '.js-todos-count';
diff --git a/spec/frontend/ide/components/repo_editor_spec.js b/spec/frontend/ide/components/repo_editor_spec.js
index 33fa5bc799f..6f53aaed655 100644
--- a/spec/frontend/ide/components/repo_editor_spec.js
+++ b/spec/frontend/ide/components/repo_editor_spec.js
@@ -8,17 +8,14 @@ import { shallowMount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
import { stubPerformanceWebAPI } from 'helpers/performance';
import { exampleConfigs, exampleFiles } from 'jest/ide/lib/editorconfig/mock_data';
-import {
- EDITOR_CODE_INSTANCE_FN,
- EDITOR_DIFF_INSTANCE_FN,
- EXTENSION_CI_SCHEMA_FILE_NAME_MATCH,
-} from '~/editor/constants';
+import { EDITOR_CODE_INSTANCE_FN, EDITOR_DIFF_INSTANCE_FN } from '~/editor/constants';
import { EditorMarkdownExtension } from '~/editor/extensions/source_editor_markdown_ext';
import { EditorMarkdownPreviewExtension } from '~/editor/extensions/source_editor_markdown_livepreview_ext';
import { CiSchemaExtension } from '~/editor/extensions/source_editor_ci_schema_ext';
import SourceEditor from '~/editor/source_editor';
import RepoEditor from '~/ide/components/repo_editor.vue';
import { leftSidebarViews, FILE_VIEW_MODE_PREVIEW, viewerTypes } from '~/ide/constants';
+import { DEFAULT_CI_CONFIG_PATH } from '~/lib/utils/constants';
import ModelManager from '~/ide/lib/common/model_manager';
import service from '~/ide/services';
import { createStoreOptions } from '~/ide/stores';
@@ -56,7 +53,7 @@ const dummyFile = {
active: true,
},
ciConfig: {
- ...file(EXTENSION_CI_SCHEMA_FILE_NAME_MATCH),
+ ...file(DEFAULT_CI_CONFIG_PATH),
content: '',
tempFile: true,
active: true,
diff --git a/spec/frontend/issues/issue_spec.js b/spec/frontend/issues/issue_spec.js
index bf2ca42f71f..b976a051f7a 100644
--- a/spec/frontend/issues/issue_spec.js
+++ b/spec/frontend/issues/issue_spec.js
@@ -58,7 +58,17 @@ describe('Issue', () => {
);
});
- it('updates issueCounter text', () => {
+ // TODO: Remove this with the removal of the old navigation.
+ // See https://gitlab.com/groups/gitlab-org/-/epics/11875.
+ // See also https://gitlab.com/gitlab-org/gitlab/-/issues/429678 about
+ // reimplementing this in the new navigation.
+ //
+ // Since this entire suite only tests the issue count updating, removing
+ // this test would mean removing the entire suite. But, ~/issues/issue.js
+ // does more than just that. Tests should be written to cover those other
+ // features. So we're just skipping this for now.
+ // eslint-disable-next-line jest/no-disabled-tests
+ it.skip('updates issueCounter text', () => {
expect(testContext.issueCounter).toBeVisible();
expect(testContext.issueCounter).toHaveText(expectedCounterText);
});
diff --git a/spec/frontend/lib/utils/common_utils_spec.js b/spec/frontend/lib/utils/common_utils_spec.js
index 8697249ebf5..6295914b127 100644
--- a/spec/frontend/lib/utils/common_utils_spec.js
+++ b/spec/frontend/lib/utils/common_utils_spec.js
@@ -1213,4 +1213,28 @@ describe('common_utils', () => {
expect(cloned.ref === ref).toBe(false);
});
});
+
+ describe('isDefaultCiConfig', () => {
+ it('returns true when the path is the default CI config path', () => {
+ expect(commonUtils.isDefaultCiConfig('.gitlab-ci.yml')).toBe(true);
+ });
+
+ it('returns false when the path is not the default CI config path', () => {
+ expect(commonUtils.isDefaultCiConfig('some/other/path.yml')).toBe(false);
+ });
+ });
+
+ describe('hasCiConfigExtension', () => {
+ it('returns true when the path is the default CI config path', () => {
+ expect(commonUtils.hasCiConfigExtension('.gitlab-ci.yml')).toBe(true);
+ });
+
+ it('returns true when the path has a CI config extension', () => {
+ expect(commonUtils.hasCiConfigExtension('some/path.gitlab-ci.yml')).toBe(true);
+ });
+
+ it('returns false when the path does not have a CI config extension', () => {
+ expect(commonUtils.hasCiConfigExtension('some/other/path.yml')).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/shortcuts_spec.js b/spec/frontend/shortcuts_spec.js
index 88ad9204d08..ca72426cb44 100644
--- a/spec/frontend/shortcuts_spec.js
+++ b/spec/frontend/shortcuts_spec.js
@@ -7,23 +7,26 @@ import Shortcuts, { LOCAL_MOUSETRAP_DATA_KEY } from '~/behaviors/shortcuts/short
import MarkdownPreview from '~/behaviors/preview_markdown';
describe('Shortcuts', () => {
- const createEvent = (type, target) =>
- $.Event(type, {
- target,
- });
let shortcuts;
beforeAll(() => {
shortcuts = new Shortcuts();
});
+ const mockSuperSidebarSearchButton = () => {
+ const button = document.createElement('button');
+ button.id = 'super-sidebar-search';
+ return button;
+ };
+
beforeEach(() => {
setHTMLFixture(htmlSnippetsShow);
+ document.body.appendChild(mockSuperSidebarSearchButton());
new Shortcuts(); // eslint-disable-line no-new
new MarkdownPreview(); // eslint-disable-line no-new
- jest.spyOn(document.querySelector('#search'), 'focus');
+ jest.spyOn(HTMLElement.prototype, 'click');
jest.spyOn(Mousetrap.prototype, 'stopCallback');
jest.spyOn(Mousetrap.prototype, 'bind').mockImplementation();
@@ -100,21 +103,22 @@ describe('Shortcuts', () => {
});
describe('focusSearch', () => {
- describe('when super sidebar is NOT enabled', () => {
- let originalGon;
- beforeEach(() => {
- originalGon = window.gon;
- window.gon = { use_new_navigation: false };
- });
+ let event;
- afterEach(() => {
- window.gon = originalGon;
- });
+ beforeEach(() => {
+ window.gon.use_new_navigation = true;
+ event = new KeyboardEvent('keydown', { cancelable: true });
+ Shortcuts.focusSearch(event);
+ });
- it('focuses the search bar', () => {
- Shortcuts.focusSearch(createEvent('KeyboardEvent'));
- expect(document.querySelector('#search').focus).toHaveBeenCalled();
- });
+ it('clicks the super sidebar search button', () => {
+ expect(HTMLElement.prototype.click).toHaveBeenCalled();
+ const thisArg = HTMLElement.prototype.click.mock.contexts[0];
+ expect(thisArg.id).toBe('super-sidebar-search');
+ });
+
+ it('cancels the default behaviour of the event', () => {
+ expect(event.defaultPrevented).toBe(true);
});
});
diff --git a/spec/frontend/vue_shared/components/list_selector/index_spec.js b/spec/frontend/vue_shared/components/list_selector/index_spec.js
new file mode 100644
index 00000000000..96074519857
--- /dev/null
+++ b/spec/frontend/vue_shared/components/list_selector/index_spec.js
@@ -0,0 +1,134 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { GlCard, GlIcon, GlCollapsibleListbox, GlSearchBoxByType } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import ListSelector from '~/vue_shared/components/list_selector/index.vue';
+import User from '~/vue_shared/components/list_selector/user.vue';
+import usersAutocompleteQuery from '~/graphql_shared/queries/users_autocomplete.query.graphql';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import { USERS_RESPONSE_MOCK } from './mock_data';
+
+Vue.use(VueApollo);
+
+describe('List Selector spec', () => {
+ let wrapper;
+ let fakeApollo;
+
+ const MOCK_PROPS = {
+ title: 'Users',
+ projectPath: 'some/project/path',
+ type: 'users',
+ };
+
+ const usersAutocompleteQuerySuccess = jest.fn().mockResolvedValue(USERS_RESPONSE_MOCK);
+
+ const createComponent = async (props) => {
+ fakeApollo = createMockApollo([[usersAutocompleteQuery, usersAutocompleteQuerySuccess]]);
+
+ wrapper = mountExtended(ListSelector, {
+ apolloProvider: fakeApollo,
+ propsData: {
+ ...MOCK_PROPS,
+ ...props,
+ },
+ });
+
+ await waitForPromises();
+ };
+
+ const findCard = () => wrapper.findComponent(GlCard);
+ const findTitle = () => wrapper.findByText(MOCK_PROPS.title);
+ const findIcon = () => wrapper.findComponent(GlIcon);
+ const findListBox = () => wrapper.findComponent(GlCollapsibleListbox);
+ const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
+ const findAllUserComponents = () => wrapper.findAllComponents(User);
+
+ describe('Users type', () => {
+ beforeEach(() => createComponent({ type: 'users' }));
+
+ it('renders a Card component', () => {
+ expect(findCard().exists()).toBe(true);
+ });
+
+ it('renders a title', () => {
+ expect(findTitle().exists()).toBe(true);
+ });
+
+ it('renders the correct icon', () => {
+ expect(findIcon().props('name')).toBe('user');
+ });
+
+ it('renders a Search box component', () => {
+ expect(findSearchBox().exists()).toBe(true);
+ });
+
+ it('does not call query when search box has not received an input', () => {
+ expect(usersAutocompleteQuerySuccess).not.toHaveBeenCalled();
+ expect(findAllUserComponents().length).toBe(0);
+ });
+
+ describe('searching', () => {
+ const searchResponse = USERS_RESPONSE_MOCK.data.project.autocompleteUsers;
+ const search = 'foo';
+
+ const emitSearchInput = async () => {
+ findSearchBox().vm.$emit('input', search);
+ await waitForPromises();
+ };
+
+ beforeEach(() => emitSearchInput());
+
+ it('calls query with correct variables when Search box receives an input', () => {
+ expect(usersAutocompleteQuerySuccess).toHaveBeenCalledWith({
+ fullPath: MOCK_PROPS.projectPath,
+ isProject: true,
+ search,
+ });
+ });
+
+ it('renders a List box component with the correct props', () => {
+ expect(findListBox().props()).toMatchObject({ multiple: true, items: searchResponse });
+ });
+
+ it('renders a user component for each search result', () => {
+ expect(findAllUserComponents().length).toBe(searchResponse.length);
+ });
+
+ it('emits an event when a search result is selected', () => {
+ const firstSearchResult = searchResponse[0];
+ findAllUserComponents().at(0).vm.$emit('select', firstSearchResult.username);
+
+ expect(wrapper.emitted('select')).toEqual([
+ [{ ...firstSearchResult, text: 'Administrator', value: 'root' }],
+ ]);
+ });
+ });
+
+ describe('selected items', () => {
+ const selectedUser = { username: 'root' };
+ const selectedItems = [selectedUser];
+ beforeEach(() => createComponent({ selectedItems }));
+
+ it('renders a heading with the total selected items', () => {
+ expect(findCard().text()).toContain('Users');
+ expect(findCard().text()).toContain('1');
+ });
+
+ it('renders a user component for each selected item', () => {
+ expect(findAllUserComponents().length).toBe(selectedItems.length);
+ expect(findAllUserComponents().at(0).props()).toMatchObject({
+ data: selectedUser,
+ canDelete: true,
+ });
+ });
+
+ it('emits a delete event when a delete event is emitted from the user component', () => {
+ const username = 'root';
+ findAllUserComponents().at(0).vm.$emit('delete', username);
+
+ expect(wrapper.emitted('delete')).toEqual([[username]]);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/list_selector/mock_data.js b/spec/frontend/vue_shared/components/list_selector/mock_data.js
new file mode 100644
index 00000000000..ce5d209a938
--- /dev/null
+++ b/spec/frontend/vue_shared/components/list_selector/mock_data.js
@@ -0,0 +1,25 @@
+export const USERS_RESPONSE_MOCK = {
+ data: {
+ project: {
+ id: 'gid://gitlab/Project/20',
+ autocompleteUsers: [
+ {
+ id: 'gid://gitlab/User/1',
+ avatarUrl: '/uploads/-/system/user/avatar/1/avatar.png',
+ name: 'Administrator',
+ username: 'root',
+ __typename: 'AutocompletedUser',
+ },
+ {
+ id: 'gid://gitlab/User/15',
+ avatarUrl:
+ 'https://www.gravatar.com/avatar/c4ab964b90c3049c47882b319d3c5cc0?s=80\u0026d=identicon',
+ name: 'Corrine Rath',
+ username: 'laronda.graham',
+ __typename: 'AutocompletedUser',
+ },
+ ],
+ __typename: 'Project',
+ },
+ },
+};
diff --git a/spec/frontend/vue_shared/components/list_selector/user_spec.js b/spec/frontend/vue_shared/components/list_selector/user_spec.js
new file mode 100644
index 00000000000..5ce21f6672b
--- /dev/null
+++ b/spec/frontend/vue_shared/components/list_selector/user_spec.js
@@ -0,0 +1,55 @@
+import { GlAvatar } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import User from '~/vue_shared/components/list_selector/user.vue';
+
+describe('User spec', () => {
+ let wrapper;
+
+ const MOCK_USER = { name: 'Admin', username: 'root', avatarUrl: 'some/avatar.jpg' };
+
+ const createComponent = (props) => {
+ wrapper = mountExtended(User, {
+ propsData: {
+ data: MOCK_USER,
+ ...props,
+ },
+ });
+ };
+
+ const findAvatar = () => wrapper.findComponent(GlAvatar);
+ const findDeleteButton = () => wrapper.findByRole('button', { name: 'Delete Admin' });
+
+ beforeEach(() => createComponent());
+
+ it('renders an Avatar component', () => {
+ expect(findAvatar().props('size')).toBe(32);
+ expect(findAvatar().attributes()).toMatchObject({
+ src: MOCK_USER.avatarUrl,
+ alt: MOCK_USER.name,
+ });
+ });
+
+ it('renders a name and username', () => {
+ expect(wrapper.text()).toContain('Admin');
+ expect(wrapper.text()).toContain('@root');
+ });
+
+ it('does not render a delete button by default', () => {
+ expect(findDeleteButton().exists()).toBe(false);
+ });
+
+ describe('Delete button', () => {
+ beforeEach(() => createComponent({ canDelete: true }));
+
+ it('renders a delete button', () => {
+ expect(findDeleteButton().exists()).toBe(true);
+ expect(findDeleteButton().props('icon')).toBe('remove');
+ });
+
+ it('emits a delete event if the delete button is clicked', () => {
+ findDeleteButton().trigger('click');
+
+ expect(wrapper.emitted('delete')).toEqual([[MOCK_USER.username]]);
+ });
+ });
+});