diff options
Diffstat (limited to 'spec/frontend/projects')
8 files changed, 128 insertions, 200 deletions
diff --git a/spec/frontend/projects/commit/components/branches_dropdown_spec.js b/spec/frontend/projects/commit/components/branches_dropdown_spec.js index a84dd246f5d..7334e007e18 100644 --- a/spec/frontend/projects/commit/components/branches_dropdown_spec.js +++ b/spec/frontend/projects/commit/components/branches_dropdown_spec.js @@ -1,9 +1,8 @@ -import { GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui'; +import { GlCollapsibleListbox } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; -import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants'; import BranchesDropdown from '~/projects/commit/components/branches_dropdown.vue'; Vue.use(Vuex); @@ -34,12 +33,7 @@ describe('BranchesDropdown', () => { }), ); }; - - const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem); - const findSearchBoxByType = () => wrapper.findComponent(GlSearchBoxByType); - const findDropdownItemByIndex = (index) => wrapper.findAllComponents(GlDropdownItem).at(index); - const findNoResults = () => wrapper.findByTestId('empty-result-message'); - const findLoading = () => wrapper.findByTestId('dropdown-text-loading-icon'); + const findDropdown = () => wrapper.findComponent(GlCollapsibleListbox); afterEach(() => { wrapper.destroy(); @@ -55,72 +49,6 @@ describe('BranchesDropdown', () => { it('invokes fetchBranches', () => { expect(spyFetchBranches).toHaveBeenCalled(); }); - - describe('with a value but visually blanked', () => { - beforeEach(() => { - createComponent({ value: '_main_', blanked: true }, { branch: '_main_' }); - }); - - it('renders all branches', () => { - expect(findAllDropdownItems()).toHaveLength(3); - expect(findDropdownItemByIndex(0).text()).toBe('_main_'); - expect(findDropdownItemByIndex(1).text()).toBe('_branch_1_'); - expect(findDropdownItemByIndex(2).text()).toBe('_branch_2_'); - }); - - it('selects the active branch', () => { - expect(wrapper.vm.isSelected('_main_')).toBe(true); - }); - }); - }); - - describe('Loading states', () => { - it('shows loading icon while fetching', () => { - createComponent({ value: '' }, { isFetching: true }); - - expect(findLoading().isVisible()).toBe(true); - }); - - it('does not show loading icon', () => { - createComponent({ value: '' }); - - expect(findLoading().isVisible()).toBe(false); - }); - }); - - describe('No branches found', () => { - beforeEach(() => { - createComponent({ value: '_non_existent_branch_' }); - }); - - it('renders empty results message', () => { - expect(findNoResults().text()).toBe('No matching results'); - }); - - it('shows GlSearchBoxByType with default attributes', () => { - expect(findSearchBoxByType().exists()).toBe(true); - expect(findSearchBoxByType().vm.$attrs).toMatchObject({ - placeholder: 'Search branches', - debounce: DEFAULT_DEBOUNCE_AND_THROTTLE_MS, - }); - }); - }); - - describe('Search term is empty', () => { - beforeEach(() => { - createComponent({ value: '' }); - }); - - it('renders all branches when search term is empty', () => { - expect(findAllDropdownItems()).toHaveLength(3); - expect(findDropdownItemByIndex(0).text()).toBe('_main_'); - expect(findDropdownItemByIndex(1).text()).toBe('_branch_1_'); - expect(findDropdownItemByIndex(2).text()).toBe('_branch_2_'); - }); - - it('should not be selected on the inactive branch', () => { - expect(wrapper.vm.isSelected('_main_')).toBe(false); - }); }); describe('When searching', () => { @@ -131,7 +59,7 @@ describe('BranchesDropdown', () => { it('invokes fetchBranches', async () => { const spy = jest.spyOn(wrapper.vm, 'fetchBranches'); - findSearchBoxByType().vm.$emit('input', '_anything_'); + findDropdown().vm.$emit('search', '_anything_'); await nextTick(); @@ -140,46 +68,13 @@ describe('BranchesDropdown', () => { }); }); - describe('Branches found', () => { - beforeEach(() => { - createComponent({ value: '_branch_1_' }, { branch: '_branch_1_' }); - }); - - it('renders only the branch searched for', () => { - expect(findAllDropdownItems()).toHaveLength(1); - expect(findDropdownItemByIndex(0).text()).toBe('_branch_1_'); - }); - - it('should not display empty results message', () => { - expect(findNoResults().exists()).toBe(false); - }); - - it('should signify this branch is selected', () => { - expect(wrapper.vm.isSelected('_branch_1_')).toBe(true); - }); - - it('should signify the branch is not selected', () => { - expect(wrapper.vm.isSelected('_not_selected_branch_')).toBe(false); - }); - - describe('Custom events', () => { - it('should emit selectBranch if an branch is clicked', () => { - findDropdownItemByIndex(0).vm.$emit('click'); - - expect(wrapper.emitted('selectBranch')).toEqual([['_branch_1_']]); - expect(wrapper.vm.searchTerm).toBe('_branch_1_'); - }); - }); - }); - describe('Case insensitive for search term', () => { beforeEach(() => { createComponent({ value: '_BrAnCh_1_' }); }); - it('renders only the branch searched for', () => { - expect(findAllDropdownItems()).toHaveLength(1); - expect(findDropdownItemByIndex(0).text()).toBe('_branch_1_'); + it('returns only the branch searched for', () => { + expect(findDropdown().props('items')).toEqual([{ text: '_branch_1_', value: '_branch_1_' }]); }); }); }); diff --git a/spec/frontend/projects/commit/components/projects_dropdown_spec.js b/spec/frontend/projects/commit/components/projects_dropdown_spec.js index bb20918e0cd..0e213ff388a 100644 --- a/spec/frontend/projects/commit/components/projects_dropdown_spec.js +++ b/spec/frontend/projects/commit/components/projects_dropdown_spec.js @@ -1,4 +1,4 @@ -import { GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui'; +import { GlCollapsibleListbox } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import Vue from 'vue'; import Vuex from 'vuex'; @@ -35,78 +35,23 @@ describe('ProjectsDropdown', () => { ); }; - const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem); - const findSearchBoxByType = () => wrapper.findComponent(GlSearchBoxByType); - const findDropdownItemByIndex = (index) => wrapper.findAllComponents(GlDropdownItem).at(index); - const findNoResults = () => wrapper.findByTestId('empty-result-message'); + const findDropdown = () => wrapper.findComponent(GlCollapsibleListbox); afterEach(() => { wrapper.destroy(); spyFetchProjects.mockReset(); }); - describe('No projects found', () => { - beforeEach(() => { - createComponent('_non_existent_project_'); - }); - - it('renders empty results message', () => { - expect(findNoResults().text()).toBe('No matching results'); - }); - - it('shows GlSearchBoxByType with default attributes', () => { - expect(findSearchBoxByType().exists()).toBe(true); - expect(findSearchBoxByType().vm.$attrs).toMatchObject({ - placeholder: 'Search projects', - }); - }); - }); - - describe('Search term is empty', () => { - beforeEach(() => { - createComponent(''); - }); - - it('renders all projects when search term is empty', () => { - expect(findAllDropdownItems()).toHaveLength(3); - expect(findDropdownItemByIndex(0).text()).toBe('_project_1_'); - expect(findDropdownItemByIndex(1).text()).toBe('_project_2_'); - expect(findDropdownItemByIndex(2).text()).toBe('_project_3_'); - }); - - it('should not be selected on the inactive project', () => { - expect(wrapper.vm.isSelected('_project_1_')).toBe(false); - }); - }); - describe('Projects found', () => { beforeEach(() => { createComponent('_project_1_', { targetProjectId: '1' }); }); - it('renders only the project searched for', () => { - expect(findAllDropdownItems()).toHaveLength(1); - expect(findDropdownItemByIndex(0).text()).toBe('_project_1_'); - }); - - it('should not display empty results message', () => { - expect(findNoResults().exists()).toBe(false); - }); - - it('should signify this project is selected', () => { - expect(findDropdownItemByIndex(0).props('isChecked')).toBe(true); - }); - - it('should signify the project is not selected', () => { - expect(wrapper.vm.isSelected('_not_selected_project_')).toBe(false); - }); - describe('Custom events', () => { it('should emit selectProject if a project is clicked', () => { - findDropdownItemByIndex(0).vm.$emit('click'); + findDropdown().vm.$emit('select', '1'); expect(wrapper.emitted('selectProject')).toEqual([['1']]); - expect(wrapper.vm.filterTerm).toBe('_project_1_'); }); }); }); @@ -117,8 +62,7 @@ describe('ProjectsDropdown', () => { }); it('renders only the project searched for', () => { - expect(findAllDropdownItems()).toHaveLength(1); - expect(findDropdownItemByIndex(0).text()).toBe('_project_1_'); + expect(findDropdown().props('items')).toEqual([{ text: '_project_1_', value: '1' }]); }); }); }); diff --git a/spec/frontend/projects/merge_requests/components/report_abuse_dropdown_item_spec.js b/spec/frontend/projects/merge_requests/components/report_abuse_dropdown_item_spec.js new file mode 100644 index 00000000000..35b10375821 --- /dev/null +++ b/spec/frontend/projects/merge_requests/components/report_abuse_dropdown_item_spec.js @@ -0,0 +1,73 @@ +import { nextTick } from 'vue'; +import { GlDropdownItem } from '@gitlab/ui'; +import { MountingPortal } from 'portal-vue'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; + +import ReportAbuseDropdownItem from '~/projects/merge_requests/components/report_abuse_dropdown_item.vue'; +import AbuseCategorySelector from '~/abuse_reports/components/abuse_category_selector.vue'; + +describe('ReportAbuseDropdownItem', () => { + let wrapper; + + const ACTION_PATH = '/abuse_reports/add_category'; + const USER_ID = '1'; + const REPORTED_FROM_URL = 'http://example.com'; + + const createComponent = (props) => { + wrapper = shallowMountExtended(ReportAbuseDropdownItem, { + propsData: { + ...props, + }, + provide: { + reportAbusePath: ACTION_PATH, + reportedUserId: USER_ID, + reportedFromUrl: REPORTED_FROM_URL, + }, + }); + }; + + beforeEach(() => { + createComponent(); + }); + + const findReportAbuseItem = () => wrapper.findComponent(GlDropdownItem); + const findAbuseCategorySelector = () => wrapper.findComponent(AbuseCategorySelector); + const findMountingPortal = () => wrapper.findComponent(MountingPortal); + + it('renders report abuse dropdown item', () => { + expect(findReportAbuseItem().text()).toBe(ReportAbuseDropdownItem.i18n.reportAbuse); + }); + + it('renders abuse category selector with the drawer initially closed', () => { + expect(findAbuseCategorySelector().exists()).toBe(true); + + expect(findAbuseCategorySelector().props('showDrawer')).toBe(false); + }); + + it('renders abuse category selector inside MountingPortal', () => { + expect(findMountingPortal().props()).toMatchObject({ + mountTo: '#js-report-abuse-drawer', + append: true, + name: 'abuse-category-selector', + }); + }); + + describe('when dropdown item is clicked', () => { + beforeEach(() => { + findReportAbuseItem().vm.$emit('click'); + return nextTick(); + }); + + it('opens the abuse category selector', () => { + expect(findAbuseCategorySelector().props('showDrawer')).toBe(true); + }); + + it('closes the abuse category selector', async () => { + findAbuseCategorySelector().vm.$emit('close-drawer'); + + await nextTick(); + + expect(findAbuseCategorySelector().props('showDrawer')).toBe(false); + }); + }); +}); diff --git a/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js index 8c18d2992ea..cf28eda5349 100644 --- a/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js +++ b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js @@ -5,25 +5,32 @@ import CiCdAnalyticsCharts from '~/vue_shared/components/ci_cd_analytics/ci_cd_a import SegmentedControlButtonGroup from '~/vue_shared/components/segmented_control_button_group.vue'; import { transformedAreaChartData, chartOptions } from '../mock_data'; +const charts = [ + { + range: 'test range 1', + title: 'title 1', + data: transformedAreaChartData, + }, + { + range: 'test range 2', + title: 'title 2', + data: transformedAreaChartData, + }, + { + range: 'test range 3', + title: 'title 3', + data: transformedAreaChartData, + }, + { + range: 'test range 4', + title: 'title 4', + data: transformedAreaChartData, + }, +]; + const DEFAULT_PROPS = { chartOptions, - charts: [ - { - range: 'test range 1', - title: 'title 1', - data: transformedAreaChartData, - }, - { - range: 'test range 2', - title: 'title 2', - data: transformedAreaChartData, - }, - { - range: 'test range 3', - title: 'title 3', - data: transformedAreaChartData, - }, - ], + charts, }; describe('~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue', () => { @@ -55,13 +62,13 @@ describe('~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue', ( wrapper = createWrapper(); }); - it('should default to the first chart', () => { - expect(findSegmentedControl().props('value')).toBe(0); + it('should default to the 3rd chart (last 90 days)', () => { + expect(findSegmentedControl().props('value')).toBe(2); }); it('should use the title and index as values', () => { const options = findSegmentedControl().props('options'); - expect(options).toHaveLength(3); + expect(options).toHaveLength(charts.length); expect(options).toEqual([ { text: 'title 1', @@ -75,6 +82,10 @@ describe('~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue', ( text: 'title 3', value: 2, }, + { + text: 'title 4', + value: 3, + }, ]); }); 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 94648d87524..bfbf3e234f4 100644 --- a/spec/frontend/projects/settings/components/default_branch_selector_spec.js +++ b/spec/frontend/projects/settings/components/default_branch_selector_spec.js @@ -32,6 +32,7 @@ describe('projects/settings/components/default_branch_selector', () => { value: persistedDefaultBranch, enabledRefTypes: [REF_TYPE_BRANCHES], projectId, + refType: null, state: true, translations: { dropdownHeader: expect.any(String), diff --git a/spec/frontend/projects/settings/repository/branch_rules/components/branch_rule_spec.js b/spec/frontend/projects/settings/repository/branch_rules/components/branch_rule_spec.js index 49c45c080b4..8d0fd390e35 100644 --- a/spec/frontend/projects/settings/repository/branch_rules/components/branch_rule_spec.js +++ b/spec/frontend/projects/settings/repository/branch_rules/components/branch_rule_spec.js @@ -20,6 +20,7 @@ describe('Branch rule', () => { }; const findDefaultBadge = () => wrapper.findByText(i18n.defaultLabel); + const findProtectedBadge = () => wrapper.findByText(i18n.protectedLabel); const findBranchName = () => wrapper.findByText(branchRulePropsMock.name); const findProtectionDetailsList = () => wrapper.findByRole('list'); const findProtectionDetailsListItems = () => wrapper.findAllByRole('listitem'); @@ -32,17 +33,23 @@ describe('Branch rule', () => { }); describe('badges', () => { - it('renders default badge', () => { + it('renders both default and protected badges', () => { expect(findDefaultBadge().exists()).toBe(true); + expect(findProtectedBadge().exists()).toBe(true); }); it('does not render default badge if isDefault is set to false', () => { createComponent({ isDefault: false }); expect(findDefaultBadge().exists()).toBe(false); }); + + it('does not render default badge if branchProtection is null', () => { + createComponent(branchRuleWithoutDetailsPropsMock); + expect(findProtectedBadge().exists()).toBe(false); + }); }); - it('does not render the protection details list if no details are present', () => { + it('does not render the protection details list when branchProtection is null', () => { createComponent(branchRuleWithoutDetailsPropsMock); expect(findProtectionDetailsList().exists()).toBe(false); }); diff --git a/spec/frontend/projects/settings/repository/branch_rules/mock_data.js b/spec/frontend/projects/settings/repository/branch_rules/mock_data.js index 6f506882c36..de7f6c8b88d 100644 --- a/spec/frontend/projects/settings/repository/branch_rules/mock_data.js +++ b/spec/frontend/projects/settings/repository/branch_rules/mock_data.js @@ -92,10 +92,7 @@ export const branchRuleWithoutDetailsPropsMock = { name: 'branch-1', isDefault: false, matchingBranchesCount: 1, - branchProtection: { - allowForcePush: false, - codeOwnerApprovalRequired: false, - }, + branchProtection: null, approvalRulesTotal: 0, statusChecksTotal: 0, }; diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js index 13f3eea277a..5fc9f9ba629 100644 --- a/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js +++ b/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js @@ -3,7 +3,7 @@ import { shallowMount } from '@vue/test-utils'; import AxiosMockAdapter from 'axios-mock-adapter'; import waitForPromises from 'helpers/wait_for_promises'; import axios from '~/lib/utils/axios_utils'; -import httpStatusCodes from '~/lib/utils/http_status'; +import { HTTP_STATUS_OK } from '~/lib/utils/http_status'; import ServiceDeskRoot from '~/projects/settings_service_desk/components/service_desk_root.vue'; import ServiceDeskSetting from '~/projects/settings_service_desk/components/service_desk_setting.vue'; @@ -95,7 +95,7 @@ describe('ServiceDeskRoot', () => { }); it('sends a request to turn service desk on', () => { - axiosMock.onPut(provideData.endpoint).replyOnce(httpStatusCodes.OK); + axiosMock.onPut(provideData.endpoint).replyOnce(HTTP_STATUS_OK); expect(spy).toHaveBeenCalledWith(provideData.endpoint, { service_desk_enabled: true }); }); @@ -117,7 +117,7 @@ describe('ServiceDeskRoot', () => { }); it('sends a request to turn service desk off', () => { - axiosMock.onPut(provideData.endpoint).replyOnce(httpStatusCodes.OK); + axiosMock.onPut(provideData.endpoint).replyOnce(HTTP_STATUS_OK); expect(spy).toHaveBeenCalledWith(provideData.endpoint, { service_desk_enabled: false }); }); @@ -133,7 +133,7 @@ describe('ServiceDeskRoot', () => { describe('save event', () => { describe('successful request', () => { beforeEach(async () => { - axiosMock.onPut(provideData.endpoint).replyOnce(httpStatusCodes.OK); + axiosMock.onPut(provideData.endpoint).replyOnce(HTTP_STATUS_OK); wrapper = createComponent(); |