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-09-12 15:11:33 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-09-12 15:11:33 +0300
commit0127158127cb4f21b06ea39cc243d8ac17fc3e41 (patch)
treefa430e57fd398272df6fda9bbf9a8dd19af063f9 /spec/frontend
parentfab43fda656e091104f79668db65f7c5e2a2e68c (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
-rw-r--r--spec/frontend/ci/job_details/components/sidebar/external_links_block_spec.js49
-rw-r--r--spec/frontend/ci/job_details/components/sidebar/sidebar_spec.js38
-rw-r--r--spec/frontend/ci/job_details/utils_spec.js45
-rw-r--r--spec/frontend/ci/jobs_mock_data.js1
-rw-r--r--spec/frontend/protected_branches/protected_branch_edit_spec.js2
-rw-r--r--spec/frontend/search/mock_data.js2
-rw-r--r--spec/frontend/search/sidebar/components/app_spec.js26
-rw-r--r--spec/frontend/search/sidebar/components/issues_filters_spec.js96
-rw-r--r--spec/frontend/search/sidebar/components/small_screen_drawer_navigation_spec.js68
-rw-r--r--spec/frontend/search/store/actions_spec.js16
10 files changed, 328 insertions, 15 deletions
diff --git a/spec/frontend/ci/job_details/components/sidebar/external_links_block_spec.js b/spec/frontend/ci/job_details/components/sidebar/external_links_block_spec.js
new file mode 100644
index 00000000000..1f2c448f1c6
--- /dev/null
+++ b/spec/frontend/ci/job_details/components/sidebar/external_links_block_spec.js
@@ -0,0 +1,49 @@
+import { GlLink } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import ExternalLinksBlock from '~/ci/job_details/components/sidebar/external_links_block.vue';
+
+describe('External links block', () => {
+ let wrapper;
+
+ const createWrapper = (propsData) => {
+ wrapper = mountExtended(ExternalLinksBlock, {
+ propsData: {
+ ...propsData,
+ },
+ });
+ };
+
+ const findAllLinks = () => wrapper.findAllComponents(GlLink);
+ const findLink = () => findAllLinks().at(0);
+
+ it('renders a list of links', () => {
+ createWrapper({
+ externalLinks: [
+ {
+ label: 'URL 1',
+ url: 'https://url1.example.com/',
+ },
+ {
+ label: 'URL 2',
+ url: 'https://url2.example.com/',
+ },
+ ],
+ });
+
+ expect(findAllLinks()).toHaveLength(2);
+ });
+
+ it('renders a link', () => {
+ createWrapper({
+ externalLinks: [
+ {
+ label: 'Example URL',
+ url: 'https://example.com/',
+ },
+ ],
+ });
+
+ expect(findLink().text()).toBe('Example URL');
+ expect(findLink().attributes('href')).toBe('https://example.com/');
+ });
+});
diff --git a/spec/frontend/ci/job_details/components/sidebar/sidebar_spec.js b/spec/frontend/ci/job_details/components/sidebar/sidebar_spec.js
index 31767b1d0df..88e1f41b270 100644
--- a/spec/frontend/ci/job_details/components/sidebar/sidebar_spec.js
+++ b/spec/frontend/ci/job_details/components/sidebar/sidebar_spec.js
@@ -5,6 +5,7 @@ import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import axios from '~/lib/utils/axios_utils';
import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import ArtifactsBlock from '~/ci/job_details/components/sidebar/artifacts_block.vue';
+import ExternalLinksBlock from '~/ci/job_details/components/sidebar/external_links_block.vue';
import JobRetryForwardDeploymentModal from '~/ci/job_details/components/sidebar/job_retry_forward_deployment_modal.vue';
import JobsContainer from '~/ci/job_details/components/sidebar/jobs_container.vue';
import Sidebar from '~/ci/job_details/components/sidebar/sidebar.vue';
@@ -20,6 +21,7 @@ describe('Sidebar details block', () => {
const forwardDeploymentFailure = 'forward_deployment_failure';
const findModal = () => wrapper.findComponent(JobRetryForwardDeploymentModal);
const findArtifactsBlock = () => wrapper.findComponent(ArtifactsBlock);
+ const findExternalLinksBlock = () => wrapper.findComponent(ExternalLinksBlock);
const findJobStagesDropdown = () => wrapper.findComponent(StagesDropdown);
const findJobsContainer = () => wrapper.findComponent(JobsContainer);
@@ -181,4 +183,40 @@ describe('Sidebar details block', () => {
expect(findArtifactsBlock().exists()).toBe(true);
});
});
+
+ describe('external links', () => {
+ beforeEach(() => {
+ createWrapper();
+ });
+
+ it('external links block is not shown if there are no external links', () => {
+ expect(findExternalLinksBlock().exists()).toBe(false);
+ });
+
+ it('external links block is shown if there are external links', async () => {
+ store.state.job.annotations = [
+ {
+ name: 'external_links',
+ data: [
+ {
+ external_link: {
+ label: 'URL 1',
+ url: 'https://url1.example.com/',
+ },
+ },
+ {
+ external_link: {
+ label: 'URL 2',
+ url: 'https://url2.example.com/',
+ },
+ },
+ ],
+ },
+ ];
+
+ await nextTick();
+
+ expect(findExternalLinksBlock().exists()).toBe(true);
+ });
+ });
});
diff --git a/spec/frontend/ci/job_details/utils_spec.js b/spec/frontend/ci/job_details/utils_spec.js
index 37c3e60f3cf..7b5a97f3939 100644
--- a/spec/frontend/ci/job_details/utils_spec.js
+++ b/spec/frontend/ci/job_details/utils_spec.js
@@ -1,4 +1,4 @@
-import { compactJobLog } from '~/ci/job_details/utils';
+import { compactJobLog, filterAnnotations } from '~/ci/job_details/utils';
import { mockJobLog } from 'jest/ci/jobs_mock_data';
describe('Job utils', () => {
@@ -219,4 +219,47 @@ describe('Job utils', () => {
expect(compactJobLog(mockJobLog)).toStrictEqual(expectedResults);
});
});
+
+ describe('filterAnnotations', () => {
+ it('filters annotations by type', () => {
+ const data = [
+ {
+ name: 'b',
+ data: [
+ {
+ dummy: {},
+ },
+ {
+ external_link: {
+ label: 'URL 2',
+ url: 'https://url2.example.com/',
+ },
+ },
+ ],
+ },
+ {
+ name: 'a',
+ data: [
+ {
+ external_link: {
+ label: 'URL 1',
+ url: 'https://url1.example.com/',
+ },
+ },
+ ],
+ },
+ ];
+
+ expect(filterAnnotations(data, 'external_link')).toEqual([
+ {
+ label: 'URL 1',
+ url: 'https://url1.example.com/',
+ },
+ {
+ label: 'URL 2',
+ url: 'https://url2.example.com/',
+ },
+ ]);
+ });
+ });
});
diff --git a/spec/frontend/ci/jobs_mock_data.js b/spec/frontend/ci/jobs_mock_data.js
index 253e669e889..c428de3b9d8 100644
--- a/spec/frontend/ci/jobs_mock_data.js
+++ b/spec/frontend/ci/jobs_mock_data.js
@@ -989,6 +989,7 @@ export default {
},
erase_path: '/root/ci-mock/-/jobs/4757/erase',
artifacts: [null],
+ annotations: [],
runner: {
id: 1,
short_sha: 'ABCDEFGH',
diff --git a/spec/frontend/protected_branches/protected_branch_edit_spec.js b/spec/frontend/protected_branches/protected_branch_edit_spec.js
index e1966908452..6422856ba22 100644
--- a/spec/frontend/protected_branches/protected_branch_edit_spec.js
+++ b/spec/frontend/protected_branches/protected_branch_edit_spec.js
@@ -20,7 +20,7 @@ describe('ProtectedBranchEdit', () => {
let mock;
beforeEach(() => {
- jest.spyOn(ProtectedBranchEdit.prototype, 'buildDropdowns').mockImplementation();
+ jest.spyOn(ProtectedBranchEdit.prototype, 'initDropdowns').mockImplementation();
mock = new MockAdapter(axios);
});
diff --git a/spec/frontend/search/mock_data.js b/spec/frontend/search/mock_data.js
index a063f20aca6..7bddc4b1c48 100644
--- a/spec/frontend/search/mock_data.js
+++ b/spec/frontend/search/mock_data.js
@@ -194,7 +194,7 @@ export const MOCK_DATA_FOR_NAVIGATION_ACTION_MUTATION = {
label: 'Projects',
scope: 'projects',
link: '/search?scope=projects&search=et',
- count_link: '/search/count?scope=projects&search=et',
+ count_link: null,
},
};
diff --git a/spec/frontend/search/sidebar/components/app_spec.js b/spec/frontend/search/sidebar/components/app_spec.js
index 61a87af476e..3944ba86942 100644
--- a/spec/frontend/search/sidebar/components/app_spec.js
+++ b/spec/frontend/search/sidebar/components/app_spec.js
@@ -4,13 +4,18 @@ import Vue from 'vue';
import Vuex from 'vuex';
import { SEARCH_TYPE_ZOEKT, SEARCH_TYPE_ADVANCED } from '~/search/sidebar/constants';
import { MOCK_QUERY } from 'jest/search/mock_data';
+import { toggleSuperSidebarCollapsed } from '~/super_sidebar/super_sidebar_collapsed_state_manager';
import GlobalSearchSidebar from '~/search/sidebar/components/app.vue';
import IssuesFilters from '~/search/sidebar/components/issues_filters.vue';
import MergeRequestsFilters from '~/search/sidebar/components/merge_requests_filters.vue';
import BlobsFilters from '~/search/sidebar/components/blobs_filters.vue';
import ProjectsFilters from '~/search/sidebar/components/projects_filters.vue';
import ScopeLegacyNavigation from '~/search/sidebar/components/scope_legacy_navigation.vue';
+import SmallScreenDrawerNavigation from '~/search/sidebar/components/small_screen_drawer_navigation.vue';
import ScopeSidebarNavigation from '~/search/sidebar/components/scope_sidebar_navigation.vue';
+import DomElementListener from '~/vue_shared/components/dom_element_listener.vue';
+
+jest.mock('~/super_sidebar/super_sidebar_collapsed_state_manager');
Vue.use(Vuex);
@@ -41,13 +46,16 @@ describe('GlobalSearchSidebar', () => {
const findBlobsFilters = () => wrapper.findComponent(BlobsFilters);
const findProjectsFilters = () => wrapper.findComponent(ProjectsFilters);
const findScopeLegacyNavigation = () => wrapper.findComponent(ScopeLegacyNavigation);
+ const findSmallScreenDrawerNavigation = () => wrapper.findComponent(SmallScreenDrawerNavigation);
const findScopeSidebarNavigation = () => wrapper.findComponent(ScopeSidebarNavigation);
+ const findDomElementListener = () => wrapper.findComponent(DomElementListener);
describe('renders properly', () => {
describe('always', () => {
beforeEach(() => {
createComponent();
});
+
it(`shows section`, () => {
expect(findSidebarSection().exists()).toBe(true);
});
@@ -104,6 +112,7 @@ describe('GlobalSearchSidebar', () => {
it(`${!legacyNavShown ? 'hides' : 'shows'} the legacy navigation`, () => {
expect(findScopeLegacyNavigation().exists()).toBe(legacyNavShown);
+ expect(findSmallScreenDrawerNavigation().exists()).toBe(legacyNavShown);
});
it(`${!sidebarNavShown ? 'hides' : 'shows'} the sidebar navigation`, () => {
@@ -111,4 +120,21 @@ describe('GlobalSearchSidebar', () => {
});
});
});
+
+ describe('when useSidebarNavigation=true', () => {
+ beforeEach(() => {
+ createComponent({ useSidebarNavigation: true });
+ });
+
+ it('toggles super sidebar when button is clicked', () => {
+ const elListener = findDomElementListener();
+
+ expect(toggleSuperSidebarCollapsed).not.toHaveBeenCalled();
+
+ elListener.vm.$emit('click');
+
+ expect(toggleSuperSidebarCollapsed).toHaveBeenCalledTimes(1);
+ expect(elListener.props('selector')).toBe('#js-open-mobile-filters');
+ });
+ });
});
diff --git a/spec/frontend/search/sidebar/components/issues_filters_spec.js b/spec/frontend/search/sidebar/components/issues_filters_spec.js
index 84c4258cbdb..e6188436c81 100644
--- a/spec/frontend/search/sidebar/components/issues_filters_spec.js
+++ b/spec/frontend/search/sidebar/components/issues_filters_spec.js
@@ -7,6 +7,8 @@ import IssuesFilters from '~/search/sidebar/components/issues_filters.vue';
import ConfidentialityFilter from '~/search/sidebar/components/confidentiality_filter/index.vue';
import StatusFilter from '~/search/sidebar/components/status_filter/index.vue';
import LabelFilter from '~/search/sidebar/components/label_filter/index.vue';
+import ArchivedFilter from '~/search/sidebar/components/archived_filter/index.vue';
+import { SEARCH_TYPE_ADVANCED, SEARCH_TYPE_BASIC } from '~/search/sidebar/constants';
Vue.use(Vuex);
@@ -17,10 +19,16 @@ describe('GlobalSearch IssuesFilters', () => {
currentScope: () => 'issues',
};
- const createComponent = (initialState, ff = true) => {
+ const createComponent = ({
+ initialState = {},
+ searchIssueLabelAggregation = true,
+ searchIssuesHideArchivedProjects = true,
+ } = {}) => {
const store = new Vuex.Store({
state: {
urlQuery: MOCK_QUERY,
+ useSidebarNavigation: false,
+ searchType: SEARCH_TYPE_ADVANCED,
...initialState,
},
getters: defaultGetters,
@@ -30,7 +38,8 @@ describe('GlobalSearch IssuesFilters', () => {
store,
provide: {
glFeatures: {
- searchIssueLabelAggregation: ff,
+ searchIssueLabelAggregation,
+ searchIssuesHideArchivedProjects,
},
},
});
@@ -39,12 +48,23 @@ describe('GlobalSearch IssuesFilters', () => {
const findStatusFilter = () => wrapper.findComponent(StatusFilter);
const findConfidentialityFilter = () => wrapper.findComponent(ConfidentialityFilter);
const findLabelFilter = () => wrapper.findComponent(LabelFilter);
+ const findArchivedFilter = () => wrapper.findComponent(ArchivedFilter);
const findDividers = () => wrapper.findAll('hr');
- describe('Renders correctly with FF enabled', () => {
+ describe.each`
+ description | searchIssueLabelAggregation | searchIssuesHideArchivedProjects
+ ${'Renders correctly with Label Filter disabled'} | ${false} | ${true}
+ ${'Renders correctly with Archived Filter disabled'} | ${true} | ${false}
+ ${'Renders correctly with Archived Filter and Label Filter disabled'} | ${false} | ${false}
+ ${'Renders correctly with Archived Filter and Label Filter enabled'} | ${true} | ${true}
+ `('$description', ({ searchIssueLabelAggregation, searchIssuesHideArchivedProjects }) => {
beforeEach(() => {
- createComponent({ urlQuery: MOCK_QUERY });
+ createComponent({
+ searchIssueLabelAggregation,
+ searchIssuesHideArchivedProjects,
+ });
});
+
it('renders StatusFilter', () => {
expect(findStatusFilter().exists()).toBe(true);
});
@@ -53,18 +73,30 @@ describe('GlobalSearch IssuesFilters', () => {
expect(findConfidentialityFilter().exists()).toBe(true);
});
- it('renders LabelFilter', () => {
- expect(findLabelFilter().exists()).toBe(true);
+ it(`renders correctly LabelFilter when searchIssueLabelAggregation is ${searchIssueLabelAggregation}`, () => {
+ expect(findLabelFilter().exists()).toBe(searchIssueLabelAggregation);
});
- it('renders dividers correctly', () => {
- expect(findDividers()).toHaveLength(2);
+ it(`renders correctly ArchivedFilter when searchIssuesHideArchivedProjects is ${searchIssuesHideArchivedProjects}`, () => {
+ expect(findArchivedFilter().exists()).toBe(searchIssuesHideArchivedProjects);
+ });
+
+ it('renders divider correctly', () => {
+ // one divider can't be disabled
+ let dividersCount = 1;
+ if (searchIssueLabelAggregation) {
+ dividersCount += 1;
+ }
+ if (searchIssuesHideArchivedProjects) {
+ dividersCount += 1;
+ }
+ expect(findDividers()).toHaveLength(dividersCount);
});
});
- describe('Renders correctly with FF disabled', () => {
+ describe('Renders correctly with basic search', () => {
beforeEach(() => {
- createComponent({ urlQuery: MOCK_QUERY }, false);
+ createComponent({ initialState: { searchType: SEARCH_TYPE_BASIC } });
});
it('renders StatusFilter', () => {
expect(findStatusFilter().exists()).toBe(true);
@@ -78,15 +110,51 @@ describe('GlobalSearch IssuesFilters', () => {
expect(findLabelFilter().exists()).toBe(false);
});
- it('renders divider correctly', () => {
+ it("doesn't render ArchivedFilter", () => {
+ expect(findArchivedFilter().exists()).toBe(false);
+ });
+
+ it('renders 1 divider', () => {
expect(findDividers()).toHaveLength(1);
});
});
+ describe('Renders correctly in new nav', () => {
+ beforeEach(() => {
+ createComponent({
+ initialState: {
+ searchType: SEARCH_TYPE_ADVANCED,
+ useSidebarNavigation: true,
+ },
+ searchIssueLabelAggregation: true,
+ searchIssuesHideArchivedProjects: true,
+ });
+ });
+ it('renders StatusFilter', () => {
+ expect(findStatusFilter().exists()).toBe(true);
+ });
+
+ it('renders ConfidentialityFilter', () => {
+ expect(findConfidentialityFilter().exists()).toBe(true);
+ });
+
+ it('renders LabelFilter', () => {
+ expect(findLabelFilter().exists()).toBe(true);
+ });
+
+ it('renders ArchivedFilter', () => {
+ expect(findArchivedFilter().exists()).toBe(true);
+ });
+
+ it("doesn't render dividers", () => {
+ expect(findDividers()).toHaveLength(0);
+ });
+ });
+
describe('Renders correctly with wrong scope', () => {
beforeEach(() => {
defaultGetters.currentScope = () => 'blobs';
- createComponent({ urlQuery: MOCK_QUERY });
+ createComponent();
});
it("doesn't render StatusFilter", () => {
expect(findStatusFilter().exists()).toBe(false);
@@ -100,6 +168,10 @@ describe('GlobalSearch IssuesFilters', () => {
expect(findLabelFilter().exists()).toBe(false);
});
+ it("doesn't render ArchivedFilter", () => {
+ expect(findArchivedFilter().exists()).toBe(false);
+ });
+
it("doesn't render dividers", () => {
expect(findDividers()).toHaveLength(0);
});
diff --git a/spec/frontend/search/sidebar/components/small_screen_drawer_navigation_spec.js b/spec/frontend/search/sidebar/components/small_screen_drawer_navigation_spec.js
new file mode 100644
index 00000000000..5ab4afba7f0
--- /dev/null
+++ b/spec/frontend/search/sidebar/components/small_screen_drawer_navigation_spec.js
@@ -0,0 +1,68 @@
+import { nextTick } from 'vue';
+import { GlDrawer } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import DomElementListener from '~/vue_shared/components/dom_element_listener.vue';
+import { DRAWER_Z_INDEX } from '~/lib/utils/constants';
+import SmallScreenDrawerNavigation from '~/search/sidebar/components/small_screen_drawer_navigation.vue';
+
+describe('ScopeLegacyNavigation', () => {
+ let wrapper;
+ let closeSpy;
+ let toggleSpy;
+
+ const createComponent = () => {
+ wrapper = shallowMountExtended(SmallScreenDrawerNavigation, {
+ slots: {
+ default: '<div data-testid="default-slot-content">test</div>',
+ },
+ });
+ };
+
+ const findGlDrawer = () => wrapper.findComponent(GlDrawer);
+ const findTitle = () => wrapper.findComponent('h2');
+ const findSlot = () => wrapper.findByTestId('default-slot-content');
+ const findDomElementListener = () => wrapper.findComponent(DomElementListener);
+
+ describe('small screen navigation', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders drawer', () => {
+ expect(findGlDrawer().exists()).toBe(true);
+ expect(findGlDrawer().attributes('zindex')).toBe(DRAWER_Z_INDEX.toString());
+ expect(findGlDrawer().attributes('headerheight')).toBe('0');
+ });
+
+ it('renders title', () => {
+ expect(findTitle().exists()).toBe(true);
+ });
+
+ it('renders slots', () => {
+ expect(findSlot().exists()).toBe(true);
+ });
+ });
+
+ describe('actions', () => {
+ beforeEach(() => {
+ closeSpy = jest.spyOn(SmallScreenDrawerNavigation.methods, 'closeSmallScreenFilters');
+ toggleSpy = jest.spyOn(SmallScreenDrawerNavigation.methods, 'toggleSmallScreenFilters');
+ createComponent();
+ });
+
+ it('calls onClose', () => {
+ findGlDrawer().vm.$emit('close');
+ expect(closeSpy).toHaveBeenCalled();
+ });
+
+ it('calls toggleSmallScreenFilters', async () => {
+ expect(findGlDrawer().props('open')).toBe(false);
+
+ findDomElementListener().vm.$emit('click');
+ await nextTick();
+
+ expect(toggleSpy).toHaveBeenCalled();
+ expect(findGlDrawer().props('open')).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/search/store/actions_spec.js b/spec/frontend/search/store/actions_spec.js
index cc9c555b6c7..889260fc478 100644
--- a/spec/frontend/search/store/actions_spec.js
+++ b/spec/frontend/search/store/actions_spec.js
@@ -1,4 +1,5 @@
import MockAdapter from 'axios-mock-adapter';
+import { mapValues } from 'lodash';
import testAction from 'helpers/vuex_action_helper';
import Api from '~/api';
import { createAlert } from '~/alert';
@@ -312,6 +313,21 @@ describe('Global Search Store Actions', () => {
});
});
+ describe('fetchSidebarCount with no count_link', () => {
+ beforeEach(() => {
+ state.navigation = mapValues(MOCK_NAVIGATION_DATA, (navItem) => ({
+ ...navItem,
+ count_link: null,
+ }));
+ });
+
+ it('should not request anything', async () => {
+ await testAction({ action: actions.fetchSidebarCount, state, expectedMutations: [] });
+
+ expect(mock.history.get.length).toBe(0);
+ });
+ });
+
describe.each`
action | axiosMock | type | expectedMutations | errorLogs
${actions.fetchAllAggregation} | ${{ method: 'onGet', code: HTTP_STATUS_OK }} | ${'success'} | ${MOCK_RECEIVE_AGGREGATIONS_SUCCESS_MUTATION} | ${0}