diff options
Diffstat (limited to 'spec')
13 files changed, 282 insertions, 39 deletions
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index e5ca2226111..608e4a58e5a 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -1152,13 +1152,6 @@ describe Projects::IssuesController do expect(controller).to set_flash[:notice].to(/The issue was successfully deleted\./) end - it "deletes the issue" do - delete :destroy, params: { namespace_id: project.namespace, project_id: project, id: issue.iid, destroy_confirm: true } - - expect(response).to have_gitlab_http_status(:found) - expect(controller).to set_flash[:notice].to(/The issue was successfully deleted\./) - end - it "prevents deletion if destroy_confirm is not set" do expect(Gitlab::ErrorTracking).to receive(:track_exception).and_call_original diff --git a/spec/features/groups/navbar_spec.rb b/spec/features/groups/navbar_spec.rb index e348eb80b1a..5662465d431 100644 --- a/spec/features/groups/navbar_spec.rb +++ b/spec/features/groups/navbar_spec.rb @@ -7,14 +7,22 @@ describe 'Group navbar' do let(:user) { create(:user) } let(:group) { create(:group) } + let(:analytics_nav_item) do + { + nav_item: _('Analytics'), + nav_sub_items: [ + _('Contribution Analytics') + ] + } + end + let(:structure) do [ { nav_item: _('Group overview'), nav_sub_items: [ _('Details'), - _('Activity'), - (_('Contribution Analytics') if Gitlab.ee?) + _('Activity') ] }, { @@ -34,6 +42,7 @@ describe 'Group navbar' do nav_item: _('Kubernetes'), nav_sub_items: [] }, + (analytics_nav_item if Gitlab.ee?), { nav_item: _('Members'), nav_sub_items: [] diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb index f87bd5ca529..4917a0b0a59 100644 --- a/spec/features/projects/navbar_spec.rb +++ b/spec/features/projects/navbar_spec.rb @@ -59,13 +59,13 @@ describe 'Project navbar' do _('Environments'), _('Error Tracking'), _('Serverless'), - _('Kubernetes'), - _('Auto DevOps') + _('Kubernetes') ] }, { nav_item: _('Analytics'), nav_sub_items: [ + _('CI / CD Analytics'), (_('Code Review') if Gitlab.ee?), _('Cycle Analytics'), _('Repository Analytics') diff --git a/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap b/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap index 2b9668c1b56..2ed93396376 100644 --- a/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap +++ b/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap @@ -44,7 +44,7 @@ exports[`Dashboard template matches the default snapshot 1`] = ` class="d-flex flex-column overflow-hidden" > <gl-dropdown-header-stub - class="text-center" + class="monitor-environment-dropdown-header text-center" > Environment </gl-dropdown-header-stub> diff --git a/spec/frontend/monitoring/components/dashboards_dropdown_spec.js b/spec/frontend/monitoring/components/dashboards_dropdown_spec.js index 6af5ab4ba75..51c7b22f242 100644 --- a/spec/frontend/monitoring/components/dashboards_dropdown_spec.js +++ b/spec/frontend/monitoring/components/dashboards_dropdown_spec.js @@ -35,13 +35,17 @@ describe('DashboardsDropdown', () => { const findItems = () => wrapper.findAll(GlDropdownItem); const findItemAt = i => wrapper.findAll(GlDropdownItem).at(i); + const findSearchInput = () => wrapper.find({ ref: 'monitorDashboardsDropdownSearch' }); + const findNoItemsMsg = () => wrapper.find({ ref: 'monitorDashboardsDropdownMsg' }); + const setSearchTerm = searchTerm => wrapper.setData({ searchTerm }); describe('when it receives dashboards data', () => { beforeEach(() => { wrapper = createComponent(); }); + it('displays an item for each dashboard', () => { - expect(wrapper.findAll(GlDropdownItem).length).toEqual(dashboardGitResponse.length); + expect(findItems().length).toEqual(dashboardGitResponse.length); }); it('displays items with the dashboard display name', () => { @@ -49,6 +53,32 @@ describe('DashboardsDropdown', () => { expect(findItemAt(1).text()).toBe(dashboardGitResponse[1].display_name); expect(findItemAt(2).text()).toBe(dashboardGitResponse[2].display_name); }); + + it('displays a search input', () => { + expect(findSearchInput().isVisible()).toBe(true); + }); + + it('hides no message text by default', () => { + expect(findNoItemsMsg().isVisible()).toBe(false); + }); + + it('filters dropdown items when searched for item exists in the list', () => { + const searchTerm = 'Default'; + setSearchTerm(searchTerm); + + return wrapper.vm.$nextTick(() => { + expect(findItems()).toHaveLength(1); + }); + }); + + it('shows no items found message when searched for item does not exists in the list', () => { + const searchTerm = 'does-not-exist'; + setSearchTerm(searchTerm); + + return wrapper.vm.$nextTick(() => { + expect(findNoItemsMsg().isVisible()).toBe(true); + }); + }); }); describe('when a system dashboard is selected', () => { @@ -224,7 +254,7 @@ describe('DashboardsDropdown', () => { it('displays an item for each dashboard', () => { const item = wrapper.findAll({ ref: 'duplicateDashboardItem' }); - expect(findItems().length).toEqual(dashboardGitResponse.length); + expect(findItems()).toHaveLength(dashboardGitResponse.length); expect(item.length).toBe(0); }); diff --git a/spec/frontend/monitoring/mock_data.js b/spec/frontend/monitoring/mock_data.js index e3357394551..5fd73b73e0d 100644 --- a/spec/frontend/monitoring/mock_data.js +++ b/spec/frontend/monitoring/mock_data.js @@ -518,6 +518,15 @@ export const metricsDashboardPayload = { ], }; +const customDashboardsData = new Array(30).fill(null).map((_, idx) => ({ + default: false, + display_name: `Custom Dashboard ${idx}`, + can_edit: true, + system_dashboard: false, + project_blob_path: `${mockProjectDir}/blob/master/dashboards/.gitlab/dashboards/dashboard_${idx}.yml`, + path: `.gitlab/dashboards/dashboard_${idx}.yml`, +})); + export const dashboardGitResponse = [ { default: true, @@ -527,22 +536,7 @@ export const dashboardGitResponse = [ project_blob_path: null, path: 'config/prometheus/common_metrics.yml', }, - { - default: false, - display_name: 'Custom Dashboard 1', - can_edit: true, - system_dashboard: false, - project_blob_path: `${mockProjectDir}/blob/master/dashboards/.gitlab/dashboards/dashboard_1.yml`, - path: '.gitlab/dashboards/dashboard_1.yml', - }, - { - default: false, - display_name: 'Custom Dashboard 2', - can_edit: true, - system_dashboard: false, - project_blob_path: `${mockProjectDir}/blob/master/dashboards/.gitlab/dashboards/dashboard_2.yml`, - path: '.gitlab/dashboards/dashboard_2.yml', - }, + ...customDashboardsData, ]; export const graphDataPrometheusQuery = { diff --git a/spec/frontend/registry/settings/components/__snapshots__/settings_form_spec.js.snap b/spec/frontend/registry/settings/components/__snapshots__/settings_form_spec.js.snap index 8d4e1243418..06f73c8f456 100644 --- a/spec/frontend/registry/settings/components/__snapshots__/settings_form_spec.js.snap +++ b/spec/frontend/registry/settings/components/__snapshots__/settings_form_spec.js.snap @@ -159,6 +159,7 @@ exports[`Settings Form renders 1`] = ` > <glbutton-stub class="mr-2 d-block" + disabled="true" size="md" type="reset" variant="secondary" diff --git a/spec/frontend/registry/settings/components/settings_form_spec.js b/spec/frontend/registry/settings/components/settings_form_spec.js index 5b81d034e14..89dd161ec3e 100644 --- a/spec/frontend/registry/settings/components/settings_form_spec.js +++ b/spec/frontend/registry/settings/components/settings_form_spec.js @@ -124,11 +124,35 @@ describe('Settings Form', () => { form = findForm(); }); - describe('form cancel event', () => { + describe('cancel button', () => { it('has type reset', () => { expect(findCancelButton().attributes('type')).toBe('reset'); }); + it('is disabled the form was not changed from his original value', () => { + store.dispatch('receiveSettingsSuccess', { foo: 'bar' }); + return wrapper.vm.$nextTick().then(() => { + expect(findCancelButton().attributes('disabled')).toBe('true'); + }); + }); + + it('is disabled when the form data is loading', () => { + store.dispatch('toggleLoading'); + return wrapper.vm.$nextTick().then(() => { + expect(findCancelButton().attributes('disabled')).toBe('true'); + }); + }); + + it('is enabled when the user changed something in the form and the data is not being loaded', () => { + store.dispatch('receiveSettingsSuccess', { foo: 'bar' }); + store.dispatch('updateSettings', { foo: 'baz' }); + return wrapper.vm.$nextTick().then(() => { + expect(findCancelButton().attributes('disabled')).toBe(undefined); + }); + }); + }); + + describe('form cancel event', () => { it('calls the appropriate function', () => { dispatchSpy.mockReturnValue(); form.trigger('reset'); diff --git a/spec/frontend/registry/settings/store/getters_spec.js b/spec/frontend/registry/settings/store/getters_spec.js new file mode 100644 index 00000000000..d9ee53766d6 --- /dev/null +++ b/spec/frontend/registry/settings/store/getters_spec.js @@ -0,0 +1,44 @@ +import * as getters from '~/registry/settings/store/getters'; +import * as utils from '~/registry/settings/utils'; +import { formOptions } from '../mock_data'; + +describe('Getters registry settings store', () => { + const settings = { + cadence: 'foo', + keep_n: 'bar', + older_than: 'baz', + }; + + describe.each` + getter | variable | formOption + ${'getCadence'} | ${'cadence'} | ${'cadence'} + ${'getKeepN'} | ${'keep_n'} | ${'keepN'} + ${'getOlderThan'} | ${'older_than'} | ${'olderThan'} + `('Options getter', ({ getter, variable, formOption }) => { + beforeEach(() => { + utils.findDefaultOption = jest.fn(); + }); + + it(`${getter} returns ${variable} when ${variable} exists in settings`, () => { + expect(getters[getter]({ settings })).toBe(settings[variable]); + }); + + it(`${getter} calls findDefaultOption when ${variable} does not exists in settings`, () => { + getters[getter]({ settings: {}, formOptions }); + expect(utils.findDefaultOption).toHaveBeenCalledWith(formOptions[formOption]); + }); + }); + + describe('getIsDisabled', () => { + it('returns false when original is equal to settings', () => { + const same = { foo: 'bar' }; + expect(getters.getIsEdited({ original: same, settings: same })).toBe(false); + }); + + it('returns true when original is different from settings', () => { + expect(getters.getIsEdited({ original: { foo: 'bar' }, settings: { foo: 'baz' } })).toBe( + true, + ); + }); + }); +}); diff --git a/spec/frontend/vue_alerts_spec.js b/spec/frontend/vue_alerts_spec.js new file mode 100644 index 00000000000..b2ee6f895a8 --- /dev/null +++ b/spec/frontend/vue_alerts_spec.js @@ -0,0 +1,87 @@ +import Vue from 'vue'; +import initVueAlerts from '~/vue_alerts'; +import { setHTMLFixture } from 'helpers/fixtures'; +import { TEST_HOST } from 'helpers/test_constants'; + +describe('VueAlerts', () => { + const alerts = [ + { + title: 'Lorem', + html: 'Lorem <strong>Ipsum</strong>', + dismissible: true, + primaryButtonText: 'Okay!', + primaryButtonLink: `${TEST_HOST}/okay`, + variant: 'tip', + }, + { + title: 'Hello', + html: 'Hello <strong>World</strong>', + dismissible: false, + primaryButtonText: 'No!', + primaryButtonLink: `${TEST_HOST}/no`, + variant: 'info', + }, + ]; + + beforeEach(() => { + setHTMLFixture( + alerts + .map( + x => ` + <div class="js-vue-alert" + data-dismissible="${x.dismissible}" + data-title="${x.title}" + data-primary-button-text="${x.primaryButtonText}" + data-primary-button-link="${x.primaryButtonLink}" + data-variant="${x.variant}">${x.html}</div> + `, + ) + .join('\n'), + ); + }); + + const findJsHooks = () => document.querySelectorAll('.js-vue-alert'); + const findAlerts = () => document.querySelectorAll('.gl-alert'); + const findAlertDismiss = alert => alert.querySelector('.gl-alert-dismiss'); + + const serializeAlert = alert => ({ + title: alert.querySelector('.gl-alert-title').textContent.trim(), + html: alert.querySelector('.gl-alert-body div').innerHTML, + dismissible: Boolean(alert.querySelector('.gl-alert-dismiss')), + primaryButtonText: alert.querySelector('.gl-alert-action').textContent.trim(), + primaryButtonLink: alert.querySelector('.gl-alert-action').href, + variant: [...alert.classList].find(x => x.match('gl-alert-')).replace('gl-alert-', ''), + }); + + it('starts with only JsHooks', () => { + expect(findJsHooks().length).toEqual(alerts.length); + expect(findAlerts().length).toEqual(0); + }); + + describe('when mounted', () => { + beforeEach(() => { + initVueAlerts(); + }); + + it('replaces JsHook with GlAlert', () => { + expect(findJsHooks().length).toEqual(0); + expect(findAlerts().length).toEqual(alerts.length); + }); + + it('passes along props to gl-alert', () => { + expect([...findAlerts()].map(serializeAlert)).toEqual(alerts); + }); + + describe('when dismissed', () => { + beforeEach(() => { + findAlertDismiss(findAlerts()[0]).click(); + + return Vue.nextTick(); + }); + + it('hides the alert', () => { + expect(findAlerts().length).toEqual(alerts.length - 1); + }); + }); + }); +}); diff --git a/spec/frontend/vue_shared/components/dismissible_alert_spec.js b/spec/frontend/vue_shared/components/dismissible_alert_spec.js new file mode 100644 index 00000000000..17905254292 --- /dev/null +++ b/spec/frontend/vue_shared/components/dismissible_alert_spec.js @@ -0,0 +1,57 @@ +import { shallowMount } from '@vue/test-utils'; +import { GlAlert } from '@gitlab/ui'; +import DismissibleAlert from '~/vue_shared/components/dismissible_alert.vue'; + +const TEST_HTML = 'Hello World! <strong>Foo</strong>'; + +describe('vue_shared/components/dismissible_alert', () => { + const testAlertProps = { + primaryButtonText: 'Lorem ipsum', + primaryButtonLink: '/lorem/ipsum', + }; + + let wrapper; + + const createComponent = (props = {}) => { + wrapper = shallowMount(DismissibleAlert, { + propsData: { + html: TEST_HTML, + ...testAlertProps, + ...props, + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + const findAlert = () => wrapper.find(GlAlert); + + describe('with default', () => { + beforeEach(() => { + createComponent(); + }); + + it('shows alert', () => { + const alert = findAlert(); + + expect(alert.exists()).toBe(true); + expect(alert.props()).toEqual(expect.objectContaining(testAlertProps)); + }); + + it('shows given HTML', () => { + expect(findAlert().html()).toContain(TEST_HTML); + }); + + describe('when dismissed', () => { + beforeEach(() => { + findAlert().vm.$emit('dismiss'); + }); + + it('hides the alert', () => { + expect(findAlert().exists()).toBe(false); + }); + }); + }); +}); diff --git a/spec/support/helpers/filter_spec_helper.rb b/spec/support/helpers/filter_spec_helper.rb index 45d49696e06..279f87efb46 100644 --- a/spec/support/helpers/filter_spec_helper.rb +++ b/spec/support/helpers/filter_spec_helper.rb @@ -55,6 +55,7 @@ module FilterSpecHelper def reference_pipeline(context = {}) context.reverse_merge!(project: project) if defined?(project) + context.reverse_merge!(current_user: current_user) if defined?(current_user) filters = [ Banzai::Filter::AutolinkFilter, diff --git a/spec/support/shared_examples/features/navbar_shared_examples.rb b/spec/support/shared_examples/features/navbar_shared_examples.rb index a963739878e..91a4048fa7c 100644 --- a/spec/support/shared_examples/features/navbar_shared_examples.rb +++ b/spec/support/shared_examples/features/navbar_shared_examples.rb @@ -1,20 +1,23 @@ # frozen_string_literal: true RSpec.shared_examples 'verified navigation bar' do + let(:expected_structure) do + structure.compact! + structure.each { |s| s[:nav_sub_items].compact! } + structure + end + it 'renders correctly' do - current_structure = page.find_all('.sidebar-top-level-items > li', class: ['!hidden']).map do |item| + current_structure = page.all('.sidebar-top-level-items > li', class: ['!hidden']).map do |item| nav_item = item.find_all('a').first.text.gsub(/\s+\d+$/, '') # remove counts at the end - nav_sub_items = item - .find_all('.sidebar-sub-level-items a') - .map(&:text) - .drop(1) # remove the first hidden item + nav_sub_items = item.all('.sidebar-sub-level-items > li', class: ['!fly-out-top-item']).map do |list_item| + list_item.all('a').first.text + end { nav_item: nav_item, nav_sub_items: nav_sub_items } end - structure.each { |s| s[:nav_sub_items].compact! } - - expect(current_structure).to eq(structure) + expect(current_structure).to eq(expected_structure) end end |