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>2023-01-24 21:11:44 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-01-24 21:11:44 +0300
commitfd247970cfe1e98276c780fbdcca026b7960e42a (patch)
treeab7963eb9b30fd73283c526cb6ae4ca1ef61c06f /spec/frontend
parentdf9890e9a702e2f12bbc8f022b916ca72820a292 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
-rw-r--r--spec/frontend/authentication/u2f/register_spec.js3
-rw-r--r--spec/frontend/authentication/webauthn/register_spec.js3
-rw-r--r--spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap47
-rw-r--r--spec/frontend/contributors/component/contributors_spec.js63
-rw-r--r--spec/frontend/projects/settings/components/default_branch_selector_spec.js1
-rw-r--r--spec/frontend/ref/components/ref_selector_spec.js2
-rw-r--r--spec/frontend/usage_quotas/components/usage_quotas_app_spec.js39
-rw-r--r--spec/frontend/usage_quotas/mock_data.js3
-rw-r--r--spec/frontend/vue_shared/components/entity_select/group_select_spec.js8
-rw-r--r--spec/frontend/vue_shared/components/entity_select/project_select_spec.js152
10 files changed, 302 insertions, 19 deletions
diff --git a/spec/frontend/authentication/u2f/register_spec.js b/spec/frontend/authentication/u2f/register_spec.js
index 7ae3a2734cb..23d1e5c7dee 100644
--- a/spec/frontend/authentication/u2f/register_spec.js
+++ b/spec/frontend/authentication/u2f/register_spec.js
@@ -1,5 +1,6 @@
import $ from 'jquery';
import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
+import { trimText } from 'helpers/text_helper';
import U2FRegister from '~/authentication/u2f/register';
import 'vendor/u2f';
import MockU2FDevice from './mock_u2f_device';
@@ -24,7 +25,7 @@ describe('U2FRegister', () => {
it('allows registering a U2F device', () => {
const setupButton = container.find('#js-setup-token-2fa-device');
- expect(setupButton.text()).toBe('Set up new device');
+ expect(trimText(setupButton.text())).toBe('Set up new device');
setupButton.trigger('click');
const inProgressMessage = container.children('p');
diff --git a/spec/frontend/authentication/webauthn/register_spec.js b/spec/frontend/authentication/webauthn/register_spec.js
index 95cb993fc70..773481346fc 100644
--- a/spec/frontend/authentication/webauthn/register_spec.js
+++ b/spec/frontend/authentication/webauthn/register_spec.js
@@ -1,5 +1,6 @@
import $ from 'jquery';
import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
+import { trimText } from 'helpers/text_helper';
import setWindowLocation from 'helpers/set_window_location_helper';
import waitForPromises from 'helpers/wait_for_promises';
import WebAuthnRegister from '~/authentication/webauthn/register';
@@ -52,7 +53,7 @@ describe('WebAuthnRegister', () => {
const findRetryButton = () => container.find('#js-token-2fa-try-again');
it('shows setup button', () => {
- expect(findSetupButton().text()).toBe('Set up new device');
+ expect(trimText(findSetupButton().text())).toBe('Set up new device');
});
describe('when unsupported', () => {
diff --git a/spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap b/spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap
index 3f812d3cf4e..50cbef21fd5 100644
--- a/spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap
+++ b/spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap
@@ -1,9 +1,48 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Contributors charts should render charts when loading completed and there is chart data 1`] = `
+exports[`Contributors charts should render charts and a RefSelector when loading completed and there is chart data 1`] = `
<div>
<div
- class="contributors-charts"
+ class="gl-border-b gl-border-gray-100 gl-mb-6 gl-bg-gray-10 gl-p-5"
+ >
+ <div
+ class="gl-display-flex"
+ >
+ <div
+ class="gl-mr-3"
+ >
+ <refselector-stub
+ enabledreftypes="REF_TYPE_BRANCHES,REF_TYPE_TAGS"
+ name=""
+ projectid="23"
+ state="true"
+ togglebuttonclass="gl-max-w-26"
+ translations="[object Object]"
+ value="main"
+ />
+ </div>
+
+ <a
+ class="btn btn-default btn-md gl-button"
+ data-testid="history-button"
+ href="some/path"
+ >
+ <!---->
+
+ <!---->
+
+ <span
+ class="gl-button-text"
+ >
+ History
+
+ </span>
+ </a>
+ </div>
+ </div>
+
+ <div
+ data-testid="contributors-charts"
>
<h4
class="gl-mb-2 gl-mt-5"
@@ -49,8 +88,8 @@ exports[`Contributors charts should render charts when loading completed and the
class="gl-mb-3"
>
- 2 commits (jawnnypoo@gmail.com)
-
+ 2 commits (jawnnypoo@gmail.com)
+
</p>
<div>
diff --git a/spec/frontend/contributors/component/contributors_spec.js b/spec/frontend/contributors/component/contributors_spec.js
index 2f0b5719326..c14bbc2f9f9 100644
--- a/spec/frontend/contributors/component/contributors_spec.js
+++ b/spec/frontend/contributors/component/contributors_spec.js
@@ -1,21 +1,29 @@
-import { mount } from '@vue/test-utils';
-import { GlLoadingIcon } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import Vue, { nextTick } from 'vue';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
import ContributorsCharts from '~/contributors/components/contributors.vue';
import { createStore } from '~/contributors/stores';
import axios from '~/lib/utils/axios_utils';
+import { visitUrl } from '~/lib/utils/url_utility';
+import RefSelector from '~/ref/components/ref_selector.vue';
+import { REF_TYPE_BRANCHES, REF_TYPE_TAGS } from '~/ref/constants';
+
+jest.mock('~/lib/utils/url_utility', () => ({
+ visitUrl: jest.fn(),
+}));
let wrapper;
let mock;
let store;
const Component = Vue.extend(ContributorsCharts);
-const endpoint = 'contributors';
+const endpoint = 'contributors/-/graphs';
const branch = 'main';
const chartData = [
{ author_name: 'John', author_email: 'jawnnypoo@gmail.com', date: '2019-05-05' },
{ author_name: 'John', author_email: 'jawnnypoo@gmail.com', date: '2019-03-03' },
];
+const projectId = '23';
+const commitsPath = 'some/path';
function factory() {
mock = new MockAdapter(axios);
@@ -23,19 +31,27 @@ function factory() {
mock.onGet().reply(200, chartData);
store = createStore();
- wrapper = mount(Component, {
+ wrapper = mountExtended(Component, {
propsData: {
endpoint,
branch,
+ projectId,
+ commitsPath,
},
stubs: {
GlLoadingIcon: true,
GlAreaChart: true,
+ RefSelector: true,
},
store,
});
}
+const findLoadingIcon = () => wrapper.findByTestId('loading-app-icon');
+const findRefSelector = () => wrapper.findComponent(RefSelector);
+const findHistoryButton = () => wrapper.findByTestId('history-button');
+const findContributorsCharts = () => wrapper.findByTestId('contributors-charts');
+
describe('Contributors charts', () => {
beforeEach(() => {
factory();
@@ -53,15 +69,46 @@ describe('Contributors charts', () => {
it('should display loader whiled loading data', async () => {
wrapper.vm.$store.state.loading = true;
await nextTick();
- expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
+ expect(findLoadingIcon().exists()).toBe(true);
});
- it('should render charts when loading completed and there is chart data', async () => {
+ it('should render charts and a RefSelector when loading completed and there is chart data', async () => {
wrapper.vm.$store.state.loading = false;
wrapper.vm.$store.state.chartData = chartData;
await nextTick();
- expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
- expect(wrapper.find('.contributors-charts').exists()).toBe(true);
+
+ expect(findLoadingIcon().exists()).toBe(false);
+ expect(findRefSelector().exists()).toBe(true);
+ expect(findRefSelector().props()).toMatchObject({
+ enabledRefTypes: [REF_TYPE_BRANCHES, REF_TYPE_TAGS],
+ value: branch,
+ projectId,
+ translations: { dropdownHeader: 'Switch branch/tag' },
+ useSymbolicRefNames: false,
+ state: true,
+ name: '',
+ });
+ expect(findContributorsCharts().exists()).toBe(true);
expect(wrapper.element).toMatchSnapshot();
});
+
+ it('should have a history button with a set href attribute', async () => {
+ wrapper.vm.$store.state.loading = false;
+ wrapper.vm.$store.state.chartData = chartData;
+ await nextTick();
+
+ const historyButton = findHistoryButton();
+ expect(historyButton.exists()).toBe(true);
+ expect(historyButton.attributes('href')).toBe(commitsPath);
+ });
+
+ it('visits a URL when clicking on a branch/tag', async () => {
+ wrapper.vm.$store.state.loading = false;
+ wrapper.vm.$store.state.chartData = chartData;
+ await nextTick();
+
+ findRefSelector().vm.$emit('input', branch);
+
+ expect(visitUrl).toHaveBeenCalledWith(`${endpoint}/${branch}`);
+ });
});
diff --git a/spec/frontend/projects/settings/components/default_branch_selector_spec.js b/spec/frontend/projects/settings/components/default_branch_selector_spec.js
index bfbf3e234f4..ca9a72663d2 100644
--- a/spec/frontend/projects/settings/components/default_branch_selector_spec.js
+++ b/spec/frontend/projects/settings/components/default_branch_selector_spec.js
@@ -34,6 +34,7 @@ describe('projects/settings/components/default_branch_selector', () => {
projectId,
refType: null,
state: true,
+ toggleButtonClass: null,
translations: {
dropdownHeader: expect.any(String),
searchPlaceholder: expect.any(String),
diff --git a/spec/frontend/ref/components/ref_selector_spec.js b/spec/frontend/ref/components/ref_selector_spec.js
index e12659a0eff..ec14d8bacb2 100644
--- a/spec/frontend/ref/components/ref_selector_spec.js
+++ b/spec/frontend/ref/components/ref_selector_spec.js
@@ -715,7 +715,7 @@ describe('Ref selector component', () => {
describe('validation state', () => {
const invalidClass = 'gl-inset-border-1-red-500!';
const isInvalidClassApplied = () =>
- wrapper.findComponent(GlDropdown).props('toggleClass')[invalidClass];
+ wrapper.findComponent(GlDropdown).props('toggleClass')[0][invalidClass];
describe('valid state', () => {
describe('when the state prop is not provided', () => {
diff --git a/spec/frontend/usage_quotas/components/usage_quotas_app_spec.js b/spec/frontend/usage_quotas/components/usage_quotas_app_spec.js
new file mode 100644
index 00000000000..cb70ea4e72d
--- /dev/null
+++ b/spec/frontend/usage_quotas/components/usage_quotas_app_spec.js
@@ -0,0 +1,39 @@
+import { GlSprintf } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import UsageQuotasApp from '~/usage_quotas/components/usage_quotas_app.vue';
+import { USAGE_QUOTAS_TITLE } from '~/usage_quotas/constants';
+import { defaultProvide } from '../mock_data';
+
+describe('UsageQuotasApp', () => {
+ let wrapper;
+
+ const createComponent = ({ provide = {} } = {}) => {
+ wrapper = shallowMountExtended(UsageQuotasApp, {
+ provide: {
+ ...defaultProvide,
+ ...provide,
+ },
+ stubs: {
+ GlSprintf,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findSubTitle = () => wrapper.findByTestId('usage-quotas-page-subtitle');
+
+ it('renders the view title', () => {
+ expect(wrapper.text()).toContain(USAGE_QUOTAS_TITLE);
+ });
+
+ it('renders the view subtitle', () => {
+ expect(findSubTitle().text()).toContain(defaultProvide.namespaceName);
+ });
+});
diff --git a/spec/frontend/usage_quotas/mock_data.js b/spec/frontend/usage_quotas/mock_data.js
new file mode 100644
index 00000000000..a9d2a7ad1db
--- /dev/null
+++ b/spec/frontend/usage_quotas/mock_data.js
@@ -0,0 +1,3 @@
+export const defaultProvide = {
+ namespaceName: 'Group 1',
+};
diff --git a/spec/frontend/vue_shared/components/entity_select/group_select_spec.js b/spec/frontend/vue_shared/components/entity_select/group_select_spec.js
index 2c94b34971d..b9479b0d51d 100644
--- a/spec/frontend/vue_shared/components/entity_select/group_select_spec.js
+++ b/spec/frontend/vue_shared/components/entity_select/group_select_spec.js
@@ -6,8 +6,8 @@ import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status';
import GroupSelect from '~/vue_shared/components/entity_select/group_select.vue';
import EntitySelect from '~/vue_shared/components/entity_select/entity_select.vue';
import {
- TOGGLE_TEXT,
- HEADER_TEXT,
+ GROUP_TOGGLE_TEXT,
+ GROUP_HEADER_TEXT,
FETCH_GROUPS_ERROR,
FETCH_GROUP_ERROR,
} from '~/vue_shared/components/entity_select/constants';
@@ -74,8 +74,8 @@ describe('GroupSelect', () => {
${'label'} | ${label}
${'inputName'} | ${inputName}
${'inputId'} | ${inputId}
- ${'defaultToggleText'} | ${TOGGLE_TEXT}
- ${'headerText'} | ${HEADER_TEXT}
+ ${'defaultToggleText'} | ${GROUP_TOGGLE_TEXT}
+ ${'headerText'} | ${GROUP_HEADER_TEXT}
`('passes the $prop prop to entity-select', ({ prop, expectedValue }) => {
expect(findEntitySelect().props(prop)).toBe(expectedValue);
});
diff --git a/spec/frontend/vue_shared/components/entity_select/project_select_spec.js b/spec/frontend/vue_shared/components/entity_select/project_select_spec.js
new file mode 100644
index 00000000000..ef5fa78f5cc
--- /dev/null
+++ b/spec/frontend/vue_shared/components/entity_select/project_select_spec.js
@@ -0,0 +1,152 @@
+import { GlCollapsibleListbox } from '@gitlab/ui';
+import MockAdapter from 'axios-mock-adapter';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import axios from '~/lib/utils/axios_utils';
+import { HTTP_STATUS_OK, HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status';
+import ProjectSelect from '~/vue_shared/components/entity_select/project_select.vue';
+import EntitySelect from '~/vue_shared/components/entity_select/entity_select.vue';
+import {
+ PROJECT_TOGGLE_TEXT,
+ PROJECT_HEADER_TEXT,
+ FETCH_PROJECTS_ERROR,
+ FETCH_PROJECT_ERROR,
+} from '~/vue_shared/components/entity_select/constants';
+import waitForPromises from 'helpers/wait_for_promises';
+
+describe('ProjectSelect', () => {
+ let wrapper;
+ let mock;
+
+ // Stubs
+ const GlAlert = {
+ template: '<div><slot /></div>',
+ };
+
+ // Props
+ const label = 'label';
+ const inputName = 'inputName';
+ const inputId = 'inputId';
+ const groupId = '22';
+
+ // Mocks
+ const apiVersion = 'v4';
+ const projectMock = {
+ name_with_namespace: 'selectedProject',
+ id: '1',
+ };
+ const groupProjectEndpoint = `/api/${apiVersion}/groups/${groupId}/projects.json`;
+ const projectEndpoint = `/api/${apiVersion}/projects/${projectMock.id}`;
+
+ // Finders
+ const findListbox = () => wrapper.findComponent(GlCollapsibleListbox);
+ const findEntitySelect = () => wrapper.findComponent(EntitySelect);
+ const findAlert = () => wrapper.findComponent(GlAlert);
+
+ // Helpers
+ const createComponent = ({ props = {} } = {}) => {
+ wrapper = mountExtended(ProjectSelect, {
+ propsData: {
+ label,
+ inputName,
+ inputId,
+ groupId,
+ ...props,
+ },
+ stubs: {
+ GlAlert,
+ EntitySelect,
+ },
+ });
+ };
+ const openListbox = () => findListbox().vm.$emit('shown');
+
+ beforeAll(() => {
+ gon.api_version = apiVersion;
+ });
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ describe('entity_select props', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it.each`
+ prop | expectedValue
+ ${'label'} | ${label}
+ ${'inputName'} | ${inputName}
+ ${'inputId'} | ${inputId}
+ ${'defaultToggleText'} | ${PROJECT_TOGGLE_TEXT}
+ ${'headerText'} | ${PROJECT_HEADER_TEXT}
+ `('passes the $prop prop to entity-select', ({ prop, expectedValue }) => {
+ expect(findEntitySelect().props(prop)).toBe(expectedValue);
+ });
+ });
+
+ describe('on mount', () => {
+ it('fetches projects when the listbox is opened', async () => {
+ createComponent();
+ await waitForPromises();
+
+ expect(mock.history.get).toHaveLength(0);
+
+ openListbox();
+ await waitForPromises();
+
+ expect(mock.history.get).toHaveLength(1);
+ expect(mock.history.get[0].url).toBe(groupProjectEndpoint);
+ expect(mock.history.get[0].params).toEqual({
+ include_subgroups: false,
+ order_by: 'similarity',
+ per_page: 20,
+ search: '',
+ simple: true,
+ with_shared: true,
+ });
+ });
+
+ describe('with an initial selection', () => {
+ it("fetches the initially selected value's name", async () => {
+ mock.onGet(projectEndpoint).reply(HTTP_STATUS_OK, projectMock);
+ createComponent({ props: { initialSelection: projectMock.id } });
+ await waitForPromises();
+
+ expect(mock.history.get).toHaveLength(1);
+ expect(findListbox().props('toggleText')).toBe(projectMock.name_with_namespace);
+ });
+
+ it('show an error if fetching the individual project fails', async () => {
+ mock
+ .onGet(groupProjectEndpoint)
+ .reply(200, [{ full_name: 'notTheSelectedProject', id: '2' }]);
+ mock.onGet(projectEndpoint).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR);
+ createComponent({ props: { initialSelection: projectMock.id } });
+
+ expect(findAlert().exists()).toBe(false);
+
+ await waitForPromises();
+
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlert().text()).toBe(FETCH_PROJECT_ERROR);
+ });
+ });
+ });
+
+ it('shows an error when fetching projects fails', async () => {
+ mock.onGet(groupProjectEndpoint).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR);
+ createComponent();
+ openListbox();
+ expect(findAlert().exists()).toBe(false);
+
+ await waitForPromises();
+
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlert().text()).toBe(FETCH_PROJECTS_ERROR);
+ });
+});