diff options
Diffstat (limited to 'spec')
7 files changed, 221 insertions, 124 deletions
diff --git a/spec/controllers/admin/groups_controller_spec.rb b/spec/controllers/admin/groups_controller_spec.rb index 3f32209543f..38f4ce54e5c 100644 --- a/spec/controllers/admin/groups_controller_spec.rb +++ b/spec/controllers/admin/groups_controller_spec.rb @@ -25,6 +25,20 @@ RSpec.describe Admin::GroupsController do end end + describe 'POST #create' do + it 'creates group' do + expect do + post :create, params: { group: { path: 'test', name: 'test' } } + end.to change { Group.count }.by(1) + end + + it 'creates namespace_settings for group' do + expect do + post :create, params: { group: { path: 'test', name: 'test' } } + end.to change { NamespaceSetting.count }.by(1) + end + end + describe 'PUT #members_update' do let(:group_user) { create(:user) } diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js index a9350bc059d..e8a126d8774 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js @@ -1,9 +1,14 @@ import Vuex from 'vuex'; import { shallowMount, createLocalVue } from '@vue/test-utils'; -import { GlButton, GlLoadingIcon, GlSearchBoxByType, GlLink } from '@gitlab/ui'; +import { + GlIntersectionObserver, + GlButton, + GlLoadingIcon, + GlSearchBoxByType, + GlLink, +} from '@gitlab/ui'; import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes'; -import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue'; import DropdownContentsLabelsView from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue'; import LabelItem from '~/vue_shared/components/sidebar/labels_select_vue/label_item.vue'; @@ -88,20 +93,25 @@ describe('DropdownContentsLabelsView', () => { }); }); - describe('showListContainer', () => { + describe('showNoMatchingResultsMessage', () => { it.each` - variant | loading | showList - ${'sidebar'} | ${false} | ${true} - ${'sidebar'} | ${true} | ${false} - ${'not-sidebar'} | ${true} | ${true} - ${'not-sidebar'} | ${false} | ${true} + searchKey | labels | labelsDescription | returnValue + ${''} | ${[]} | ${'empty'} | ${false} + ${'bug'} | ${[]} | ${'empty'} | ${true} + ${''} | ${mockLabels} | ${'not empty'} | ${false} + ${'bug'} | ${mockLabels} | ${'not empty'} | ${false} `( - 'returns $showList if `state.variant` is "$variant" and `labelsFetchInProgress` is $loading', - ({ variant, loading, showList }) => { - createComponent({ ...mockConfig, variant }); - wrapper.vm.$store.state.labelsFetchInProgress = loading; + 'returns $returnValue when searchKey is "$searchKey" and visibleLabels is $labelsDescription', + async ({ searchKey, labels, returnValue }) => { + wrapper.setData({ + searchKey, + }); - expect(wrapper.vm.showListContainer).toBe(showList); + wrapper.vm.$store.dispatch('receiveLabelsSuccess', labels); + + await wrapper.vm.$nextTick(); + + expect(wrapper.vm.showNoMatchingResultsMessage).toBe(returnValue); }, ); }); @@ -118,6 +128,28 @@ describe('DropdownContentsLabelsView', () => { }); }); + describe('handleComponentDisappear', () => { + it('calls action `receiveLabelsSuccess` with empty array', () => { + jest.spyOn(wrapper.vm, 'receiveLabelsSuccess'); + + wrapper.vm.handleComponentDisappear(); + + expect(wrapper.vm.receiveLabelsSuccess).toHaveBeenCalledWith([]); + }); + }); + + describe('handleCreateLabelClick', () => { + it('calls actions `receiveLabelsSuccess` with empty array and `toggleDropdownContentsCreateView`', () => { + jest.spyOn(wrapper.vm, 'receiveLabelsSuccess'); + jest.spyOn(wrapper.vm, 'toggleDropdownContentsCreateView'); + + wrapper.vm.handleCreateLabelClick(); + + expect(wrapper.vm.receiveLabelsSuccess).toHaveBeenCalledWith([]); + expect(wrapper.vm.toggleDropdownContentsCreateView).toHaveBeenCalled(); + }); + }); + describe('handleKeyDown', () => { it('decreases `currentHighlightItem` value by 1 when Up arrow key is pressed', () => { wrapper.setData({ @@ -226,8 +258,8 @@ describe('DropdownContentsLabelsView', () => { }); describe('template', () => { - it('renders component container element with class `labels-select-contents-list`', () => { - expect(wrapper.attributes('class')).toContain('labels-select-contents-list'); + it('renders gl-intersection-observer as component root', () => { + expect(wrapper.find(GlIntersectionObserver).exists()).toBe(true); }); it('renders gl-loading-icon component when `labelsFetchInProgress` prop is true', () => { @@ -272,15 +304,11 @@ describe('DropdownContentsLabelsView', () => { expect(searchInputEl.attributes('autofocus')).toBe('true'); }); - it('renders smart-virtual-list element', () => { - expect(wrapper.find(SmartVirtualList).exists()).toBe(true); - }); - it('renders label elements for all labels', () => { expect(wrapper.findAll(LabelItem)).toHaveLength(mockLabels.length); }); - it('renders label element with "is-focused" when value of `currentHighlightItem` is more than -1', () => { + it('renders label element with `highlight` set to true when value of `currentHighlightItem` is more than -1', () => { wrapper.setData({ currentHighlightItem: 0, }); @@ -288,7 +316,7 @@ describe('DropdownContentsLabelsView', () => { return wrapper.vm.$nextTick(() => { const labelItemEl = findDropdownContent().find(LabelItem); - expect(labelItemEl.props('highlight')).toBe(true); + expect(labelItemEl.attributes('highlight')).toBe('true'); }); }); @@ -310,9 +338,12 @@ describe('DropdownContentsLabelsView', () => { return wrapper.vm.$nextTick(() => { const dropdownContent = findDropdownContent(); + const loadingIcon = findLoadingIcon(); expect(dropdownContent.exists()).toBe(true); - expect(dropdownContent.isVisible()).toBe(false); + expect(dropdownContent.isVisible()).toBe(true); + expect(loadingIcon.exists()).toBe(true); + expect(loadingIcon.isVisible()).toBe(true); }); }); diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/label_item_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/label_item_spec.js index ad3f073fdf9..a6ec01ad7e1 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/label_item_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/label_item_spec.js @@ -6,11 +6,15 @@ import { mockRegularLabel } from './mock_data'; const mockLabel = { ...mockRegularLabel, set: true }; -const createComponent = ({ label = mockLabel, highlight = true } = {}) => +const createComponent = ({ + label = mockLabel, + isLabelSet = mockLabel.set, + highlight = true, +} = {}) => shallowMount(LabelItem, { propsData: { label, - isLabelSet: label.set, + isLabelSet, highlight, }, }); @@ -26,94 +30,44 @@ describe('LabelItem', () => { wrapper.destroy(); }); - describe('computed', () => { - describe('labelBoxStyle', () => { - it('returns an object containing `backgroundColor` based on `label` prop', () => { - expect(wrapper.vm.labelBoxStyle).toEqual( - expect.objectContaining({ - backgroundColor: mockLabel.color, - }), - ); - }); - }); - }); - - describe('watchers', () => { - describe('isLabelSet', () => { - it('sets value of `isLabelSet` to `isSet` data prop', () => { - expect(wrapper.vm.isSet).toBe(true); - - wrapper.setProps({ - isLabelSet: false, - }); - - return wrapper.vm.$nextTick(() => { - expect(wrapper.vm.isSet).toBe(false); - }); - }); - }); - }); - - describe('methods', () => { - describe('handleClick', () => { - it('sets value of `isSet` data prop to opposite of its current value', () => { - wrapper.setData({ - isSet: true, - }); - - wrapper.vm.handleClick(); - expect(wrapper.vm.isSet).toBe(false); - wrapper.vm.handleClick(); - expect(wrapper.vm.isSet).toBe(true); - }); - - it('emits event `clickLabel` on component with `label` prop as param', () => { - wrapper.vm.handleClick(); - - expect(wrapper.emitted('clickLabel')).toBeTruthy(); - expect(wrapper.emitted('clickLabel')[0]).toEqual([mockLabel]); - }); - }); - }); - describe('template', () => { it('renders gl-link component', () => { expect(wrapper.find(GlLink).exists()).toBe(true); }); - it('renders gl-link component with class `is-focused` when `highlight` prop is true', () => { - wrapper.setProps({ + it('renders component root with class `is-focused` when `highlight` prop is true', () => { + const wrapperTemp = createComponent({ highlight: true, }); - return wrapper.vm.$nextTick(() => { - expect(wrapper.find(GlLink).classes()).toContain('is-focused'); - }); + expect(wrapperTemp.classes()).toContain('is-focused'); + + wrapperTemp.destroy(); }); - it('renders visible gl-icon component when `isSet` prop is true', () => { - wrapper.setData({ - isSet: true, + it('renders visible gl-icon component when `isLabelSet` prop is true', () => { + const wrapperTemp = createComponent({ + isLabelSet: true, }); - return wrapper.vm.$nextTick(() => { - const iconEl = wrapper.find(GlIcon); + const iconEl = wrapperTemp.find(GlIcon); - expect(iconEl.isVisible()).toBe(true); - expect(iconEl.props('name')).toBe('mobile-issue-close'); - }); + expect(iconEl.isVisible()).toBe(true); + expect(iconEl.props('name')).toBe('mobile-issue-close'); + + wrapperTemp.destroy(); }); - it('renders visible span element as placeholder instead of gl-icon when `isSet` prop is false', () => { - wrapper.setData({ - isSet: false, + it('renders visible span element as placeholder instead of gl-icon when `isLabelSet` prop is false', () => { + const wrapperTemp = createComponent({ + isLabelSet: false, }); - return wrapper.vm.$nextTick(() => { - const placeholderEl = wrapper.find('[data-testid="no-icon"]'); + const placeholderEl = wrapperTemp.find('[data-testid="no-icon"]'); - expect(placeholderEl.isVisible()).toBe(true); - }); + expect(placeholderEl.isVisible()).toBe(true); + + wrapperTemp.destroy(); }); it('renders label color element', () => { diff --git a/spec/migrations/ensure_namespace_settings_creation_spec.rb b/spec/migrations/ensure_namespace_settings_creation_spec.rb new file mode 100644 index 00000000000..8574063f7fe --- /dev/null +++ b/spec/migrations/ensure_namespace_settings_creation_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require 'spec_helper' +require Rails.root.join('db', 'post_migrate', '20201104124300_ensure_namespace_settings_creation.rb') + +RSpec.describe EnsureNamespaceSettingsCreation do + context 'when there are namespaces without namespace settings' do + let(:namespaces) { table(:namespaces) } + let(:namespace_settings) { table(:namespace_settings) } + let!(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') } + let!(:namespace_2) { namespaces.create!(name: 'gitlab', path: 'gitlab-org2') } + + it 'migrates namespaces without namespace_settings' do + stub_const("#{described_class.name}::BATCH_SIZE", 2) + + Sidekiq::Testing.fake! do + freeze_time do + migrate! + + expect(described_class::MIGRATION) + .to be_scheduled_delayed_migration(2.minutes.to_i, namespace.id, namespace_2.id) + end + end + end + + it 'schedules migrations in batches ' do + stub_const("#{described_class.name}::BATCH_SIZE", 2) + + namespace_3 = namespaces.create!(name: 'gitlab', path: 'gitlab-org3') + namespace_4 = namespaces.create!(name: 'gitlab', path: 'gitlab-org4') + + Sidekiq::Testing.fake! do + freeze_time do + migrate! + + expect(described_class::MIGRATION) + .to be_scheduled_delayed_migration(2.minutes.to_i, namespace.id, namespace_2.id) + expect(described_class::MIGRATION) + .to be_scheduled_delayed_migration(4.minutes.to_i, namespace_3.id, namespace_4.id) + end + end + end + end +end diff --git a/spec/migrations/migrate_compliance_framework_enum_to_database_framework_record_spec.rb b/spec/migrations/migrate_compliance_framework_enum_to_database_framework_record_spec.rb index cd2ec81abb7..5c3ca281d49 100644 --- a/spec/migrations/migrate_compliance_framework_enum_to_database_framework_record_spec.rb +++ b/spec/migrations/migrate_compliance_framework_enum_to_database_framework_record_spec.rb @@ -30,41 +30,23 @@ RSpec.describe MigrateComplianceFrameworkEnumToDatabaseFrameworkRecord, schema: subject { described_class.new.up } - context 'when Gitlab.ee? is true' do - before do - expect(Gitlab).to receive(:ee?).and_return(true) - end + it 'updates the project settings' do + subject - it 'updates the project settings' do - subject + gdpr_framework = compliance_management_frameworks.find_by(namespace_id: root_group.id, name: 'GDPR') + expect(project_on_root_level_compliance_setting.reload.framework_id).to eq(gdpr_framework.id) + expect(project_on_sub_sub_level_compliance_setting_2.reload.framework_id).to eq(gdpr_framework.id) - gdpr_framework = compliance_management_frameworks.find_by(namespace_id: root_group.id, name: 'GDPR') - expect(project_on_root_level_compliance_setting.reload.framework_id).to eq(gdpr_framework.id) - expect(project_on_sub_sub_level_compliance_setting_2.reload.framework_id).to eq(gdpr_framework.id) + sox_framework = compliance_management_frameworks.find_by(namespace_id: root_group.id, name: 'SOX') + expect(project_on_sub_sub_level_compliance_setting_1.reload.framework_id).to eq(sox_framework.id) - sox_framework = compliance_management_frameworks.find_by(namespace_id: root_group.id, name: 'SOX') - expect(project_on_sub_sub_level_compliance_setting_1.reload.framework_id).to eq(sox_framework.id) - - gdpr_framework = compliance_management_frameworks.find_by(namespace_id: namespace.id, name: 'GDPR') - expect(project_on_namespace_level_compliance_setting.reload.framework_id).to eq(gdpr_framework.id) - end - - it 'adds two framework records' do - subject - - expect(compliance_management_frameworks.count).to eq(3) - end + gdpr_framework = compliance_management_frameworks.find_by(namespace_id: namespace.id, name: 'GDPR') + expect(project_on_namespace_level_compliance_setting.reload.framework_id).to eq(gdpr_framework.id) end - context 'when Gitlab.ee? is false' do - before do - expect(Gitlab).to receive(:ee?).and_return(false) - end - - it 'does nothing' do - subject + it 'adds two framework records' do + subject - expect(compliance_management_frameworks.count).to eq(0) - end + expect(compliance_management_frameworks.count).to eq(3) end end diff --git a/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb b/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb index e03e75653ff..f0fd243f0ca 100644 --- a/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb +++ b/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb @@ -77,6 +77,42 @@ RSpec.describe Projects::HashedStorage::MigrateRepositoryService do end end + context 'when exception happens' do + it 'handles OpenSSL::Cipher::CipherError' do + expect(project).to receive(:ensure_runners_token).and_raise(OpenSSL::Cipher::CipherError) + + expect { service.execute }.not_to raise_exception + end + + it 'ensures rollback when OpenSSL::Cipher::CipherError' do + expect(project).to receive(:ensure_runners_token).and_raise(OpenSSL::Cipher::CipherError) + expect(service).to receive(:rollback_folder_move).and_call_original + + service.execute + project.reload + + expect(project.legacy_storage?).to be_truthy + expect(project.repository_read_only?).to be_falsey + end + + it 'handles Gitlab::Git::CommandError' do + expect(project).to receive(:write_repository_config).and_raise(Gitlab::Git::CommandError) + + expect { service.execute }.not_to raise_exception + end + + it 'ensures rollback when Gitlab::Git::CommandError' do + expect(project).to receive(:write_repository_config).and_raise(Gitlab::Git::CommandError) + expect(service).to receive(:rollback_folder_move).and_call_original + + service.execute + project.reload + + expect(project.legacy_storage?).to be_truthy + expect(project.repository_read_only?).to be_falsey + end + end + context 'when one move fails' do it 'rollsback repositories to original name' do allow(service).to receive(:move_repository).and_call_original diff --git a/spec/services/projects/hashed_storage/rollback_repository_service_spec.rb b/spec/services/projects/hashed_storage/rollback_repository_service_spec.rb index f2b1ce30a54..492eb0956aa 100644 --- a/spec/services/projects/hashed_storage/rollback_repository_service_spec.rb +++ b/spec/services/projects/hashed_storage/rollback_repository_service_spec.rb @@ -77,6 +77,42 @@ RSpec.describe Projects::HashedStorage::RollbackRepositoryService, :clean_gitlab end end + context 'when exception happens' do + it 'handles OpenSSL::Cipher::CipherError' do + expect(project).to receive(:ensure_runners_token).and_raise(OpenSSL::Cipher::CipherError) + + expect { service.execute }.not_to raise_exception + end + + it 'ensures rollback when OpenSSL::Cipher::CipherError' do + expect(project).to receive(:ensure_runners_token).and_raise(OpenSSL::Cipher::CipherError) + expect(service).to receive(:rollback_folder_move).and_call_original + + service.execute + project.reload + + expect(project.hashed_storage?(:repository)).to be_truthy + expect(project.repository_read_only?).to be_falsey + end + + it 'handles Gitlab::Git::CommandError' do + expect(project).to receive(:write_repository_config).and_raise(Gitlab::Git::CommandError) + + expect { service.execute }.not_to raise_exception + end + + it 'ensures rollback when Gitlab::Git::CommandError' do + expect(project).to receive(:write_repository_config).and_raise(Gitlab::Git::CommandError) + expect(service).to receive(:rollback_folder_move).and_call_original + + service.execute + project.reload + + expect(project.hashed_storage?(:repository)).to be_truthy + expect(project.repository_read_only?).to be_falsey + end + end + context 'when one move fails' do it 'rolls repositories back to original name' do allow(service).to receive(:move_repository).and_call_original |