diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-02-24 18:11:10 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-02-24 18:11:10 +0300 |
commit | 958d8a85d32fece017eac7d99bf28860b01a49d8 (patch) | |
tree | 3c84c8447a8d9a6f7ccf7401eeb3cd268570c94f /spec | |
parent | 35c5f0c35c83f3c5f8d33fb61713495e29bdec4d (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
8 files changed, 264 insertions, 97 deletions
diff --git a/spec/finders/users_finder_spec.rb b/spec/finders/users_finder_spec.rb index d9cc71106d5..b0f8b803141 100644 --- a/spec/finders/users_finder_spec.rb +++ b/spec/finders/users_finder_spec.rb @@ -12,7 +12,7 @@ RSpec.describe UsersFinder do it 'returns all users' do users = described_class.new(user).execute - expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user, internal_user, admin_user) + expect(users).to contain_exactly(user, normal_user, blocked_user, external_user, omniauth_user, internal_user, admin_user) end it 'filters by username' do @@ -48,12 +48,18 @@ RSpec.describe UsersFinder do it 'filters by active users' do users = described_class.new(user, active: true).execute - expect(users).to contain_exactly(user, normal_user, omniauth_user, admin_user) + expect(users).to contain_exactly(user, normal_user, external_user, omniauth_user, admin_user) end - it 'returns no external users' do + it 'filters by external users' do users = described_class.new(user, external: true).execute + expect(users).to contain_exactly(external_user) + end + + it 'filters by non external users' do + users = described_class.new(user, non_external: true).execute + expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user, internal_user, admin_user) end @@ -71,7 +77,7 @@ RSpec.describe UsersFinder do it 'filters by non internal users' do users = described_class.new(user, non_internal: true).execute - expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user, admin_user) + expect(users).to contain_exactly(user, normal_user, external_user, blocked_user, omniauth_user, admin_user) end it 'does not filter by custom attributes' do @@ -80,18 +86,18 @@ RSpec.describe UsersFinder do custom_attributes: { foo: 'bar' } ).execute - expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user, internal_user, admin_user) + expect(users).to contain_exactly(user, normal_user, blocked_user, external_user, omniauth_user, internal_user, admin_user) end it 'orders returned results' do users = described_class.new(user, sort: 'id_asc').execute - expect(users).to eq([normal_user, admin_user, blocked_user, omniauth_user, internal_user, user]) + expect(users).to eq([normal_user, admin_user, blocked_user, external_user, omniauth_user, internal_user, user]) end it 'does not filter by admins' do users = described_class.new(user, admins: true).execute - expect(users).to contain_exactly(user, normal_user, admin_user, blocked_user, omniauth_user, internal_user) + expect(users).to contain_exactly(user, normal_user, external_user, admin_user, blocked_user, omniauth_user, internal_user) end end diff --git a/spec/frontend/import_entities/import_groups/components/import_table_row_spec.js b/spec/frontend/import_entities/import_groups/components/import_table_row_spec.js index 074d6cf3786..7a83136e785 100644 --- a/spec/frontend/import_entities/import_groups/components/import_table_row_spec.js +++ b/spec/frontend/import_entities/import_groups/components/import_table_row_spec.js @@ -1,10 +1,15 @@ -import { GlButton, GlLink, GlFormInput } from '@gitlab/ui'; +import { GlButton, GlDropdown, GlDropdownItem, GlLink, GlFormInput } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import Vue, { nextTick } from 'vue'; +import VueApollo from 'vue-apollo'; +import createMockApollo from 'helpers/mock_apollo_helper'; import { STATUSES } from '~/import_entities/constants'; import ImportTableRow from '~/import_entities/import_groups/components/import_table_row.vue'; -import Select2Select from '~/vue_shared/components/select2_select.vue'; +import groupQuery from '~/import_entities/import_groups/graphql/queries/group.query.graphql'; import { availableNamespacesFixture } from '../graphql/fixtures'; +Vue.use(VueApollo); + const getFakeGroup = (status) => ({ web_url: 'https://fake.host/', full_path: 'fake_group_1', @@ -17,8 +22,12 @@ const getFakeGroup = (status) => ({ status, }); +const EXISTING_GROUP_TARGET_NAMESPACE = 'existing-group'; +const EXISTING_GROUP_PATH = 'existing-path'; + describe('import table row', () => { let wrapper; + let apolloProvider; let group; const findByText = (cmp, text) => { @@ -26,12 +35,27 @@ describe('import table row', () => { }; const findImportButton = () => findByText(GlButton, 'Import'); const findNameInput = () => wrapper.find(GlFormInput); - const findNamespaceDropdown = () => wrapper.find(Select2Select); + const findNamespaceDropdown = () => wrapper.find(GlDropdown); const createComponent = (props) => { + apolloProvider = createMockApollo([ + [ + groupQuery, + ({ fullPath }) => { + const existingGroup = + fullPath === `${EXISTING_GROUP_TARGET_NAMESPACE}/${EXISTING_GROUP_PATH}` + ? { id: 1 } + : null; + return Promise.resolve({ data: { existingGroup } }); + }, + ], + ]); + wrapper = shallowMount(ImportTableRow, { + apolloProvider, propsData: { availableNamespaces: availableNamespacesFixture, + groupPathRegex: /.*/, ...props, }, }); @@ -49,15 +73,24 @@ describe('import table row', () => { }); it.each` - selector | sourceEvent | payload | event - ${findNamespaceDropdown} | ${'input'} | ${'demo'} | ${'update-target-namespace'} - ${findNameInput} | ${'input'} | ${'demo'} | ${'update-new-name'} - ${findImportButton} | ${'click'} | ${undefined} | ${'import-group'} + selector | sourceEvent | payload | event + ${findNameInput} | ${'input'} | ${'demo'} | ${'update-new-name'} + ${findImportButton} | ${'click'} | ${undefined} | ${'import-group'} `('invokes $event', ({ selector, sourceEvent, payload, event }) => { selector().vm.$emit(sourceEvent, payload); expect(wrapper.emitted(event)).toBeDefined(); expect(wrapper.emitted(event)[0][0]).toBe(payload); }); + + it('emits update-target-namespace when dropdown option is clicked', () => { + const dropdownItem = findNamespaceDropdown().findAllComponents(GlDropdownItem).at(2); + const dropdownItemText = dropdownItem.text(); + + dropdownItem.vm.$emit('click'); + + expect(wrapper.emitted('update-target-namespace')).toBeDefined(); + expect(wrapper.emitted('update-target-namespace')[0][0]).toBe(dropdownItemText); + }); }); describe('when entity status is NONE', () => { @@ -81,12 +114,12 @@ describe('import table row', () => { availableNamespaces: [], }); - const dropdownData = findNamespaceDropdown().props().options.data; - const noParentOption = dropdownData.find((o) => o.text === 'No parent'); - const existingGroupOption = dropdownData.find((o) => o.text === 'Existing groups'); + const items = findNamespaceDropdown() + .findAllComponents(GlDropdownItem) + .wrappers.map((w) => w.text()); - expect(noParentOption.id).toBe(''); - expect(existingGroupOption).toBeUndefined(); + expect(items[0]).toBe('No parent'); + expect(items).toHaveLength(1); }); it('renders both no parent option and available namespaces list when available namespaces list is not empty', () => { @@ -95,12 +128,12 @@ describe('import table row', () => { availableNamespaces: availableNamespacesFixture, }); - const dropdownData = findNamespaceDropdown().props().options.data; - const noParentOption = dropdownData.find((o) => o.text === 'No parent'); - const existingGroupOption = dropdownData.find((o) => o.text === 'Existing groups'); + const [firstItem, ...rest] = findNamespaceDropdown() + .findAllComponents(GlDropdownItem) + .wrappers.map((w) => w.text()); - expect(noParentOption.id).toBe(''); - expect(existingGroupOption.children).toHaveLength(availableNamespacesFixture.length); + expect(firstItem).toBe('No parent'); + expect(rest).toHaveLength(availableNamespacesFixture.length); }); describe('when entity status is SCHEDULING', () => { @@ -137,4 +170,38 @@ describe('import table row', () => { expect(findByText(GlLink, TARGET_LINK).exists()).toBe(true); }); }); + + describe('validations', () => { + it('Reports invalid group name when name is not matching regex', () => { + createComponent({ + group: { + ...getFakeGroup(STATUSES.NONE), + import_target: { + target_namespace: 'root', + new_name: 'very`bad`name', + }, + }, + groupPathRegex: /^[a-zA-Z]+$/, + }); + + expect(wrapper.text()).toContain('Please choose a group URL with no special characters.'); + }); + + it('Reports invalid group name if group already exists', async () => { + createComponent({ + group: { + ...getFakeGroup(STATUSES.NONE), + import_target: { + target_namespace: EXISTING_GROUP_TARGET_NAMESPACE, + new_name: EXISTING_GROUP_PATH, + }, + }, + }); + + jest.runOnlyPendingTimers(); + await nextTick(); + + expect(wrapper.text()).toContain('Name already exists.'); + }); + }); }); diff --git a/spec/frontend/import_entities/import_groups/components/import_table_spec.js b/spec/frontend/import_entities/import_groups/components/import_table_spec.js index 59330e58e26..14445132f48 100644 --- a/spec/frontend/import_entities/import_groups/components/import_table_spec.js +++ b/spec/frontend/import_entities/import_groups/components/import_table_spec.js @@ -43,6 +43,7 @@ describe('import table', () => { wrapper = shallowMount(ImportTable, { propsData: { sourceUrl: 'https://demo.host', + groupPathRegex: /.*/, }, stubs: { GlSprintf, diff --git a/spec/lib/gitlab/analytics/cycle_analytics/sorting_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/sorting_spec.rb new file mode 100644 index 00000000000..8f5be709a11 --- /dev/null +++ b/spec/lib/gitlab/analytics/cycle_analytics/sorting_spec.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Analytics::CycleAnalytics::Sorting do + let(:stage) { build(:cycle_analytics_project_stage, start_event_identifier: :merge_request_created, end_event_identifier: :merge_request_merged) } + + subject(:order_values) { described_class.apply(MergeRequest.joins(:metrics), stage, sort, direction).order_values } + + context 'when invalid sorting params are given' do + let(:sort) { :unknown_sort } + let(:direction) { :unknown_direction } + + it 'falls back to end_event DESC sorting' do + expect(order_values).to eq([stage.end_event.timestamp_projection.desc]) + end + end + + context 'sorting end_event' do + let(:sort) { :end_event } + + context 'direction desc' do + let(:direction) { :desc } + + specify do + expect(order_values).to eq([stage.end_event.timestamp_projection.desc]) + end + end + + context 'direction asc' do + let(:direction) { :asc } + + specify do + expect(order_values).to eq([stage.end_event.timestamp_projection.asc]) + end + end + end + + context 'sorting duration' do + let(:sort) { :duration } + + context 'direction desc' do + let(:direction) { :desc } + + specify do + expect(order_values).to eq([Arel::Nodes::Subtraction.new(stage.end_event.timestamp_projection, stage.start_event.timestamp_projection).desc]) + end + end + + context 'direction asc' do + let(:direction) { :asc } + + specify do + expect(order_values).to eq([Arel::Nodes::Subtraction.new(stage.end_event.timestamp_projection, stage.start_event.timestamp_projection).asc]) + end + end + end +end diff --git a/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb b/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb index 8e74935e127..07b1d99d333 100644 --- a/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb +++ b/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb @@ -27,12 +27,33 @@ RSpec.describe Gitlab::BackgroundMigration::PopulateFindingUuidForVulnerabilityF let(:finding_1) { finding_creator.call(sast_report, location_fingerprint_1) } let(:finding_2) { finding_creator.call(dast_report, location_fingerprint_2) } let(:finding_3) { finding_creator.call(secret_detection_report, location_fingerprint_3) } - let(:uuid_1_components) { ['sast', identifier.fingerprint, location_fingerprint_1, project.id].join('-') } - let(:uuid_2_components) { ['dast', identifier.fingerprint, location_fingerprint_2, project.id].join('-') } - let(:uuid_3_components) { ['secret_detection', identifier.fingerprint, location_fingerprint_3, project.id].join('-') } - let(:expected_uuid_1) { Gitlab::UUID.v5(uuid_1_components) } - let(:expected_uuid_2) { Gitlab::UUID.v5(uuid_2_components) } - let(:expected_uuid_3) { Gitlab::UUID.v5(uuid_3_components) } + let(:expected_uuid_1) do + Security::VulnerabilityUUID.generate( + report_type: 'sast', + primary_identifier_fingerprint: identifier.fingerprint, + location_fingerprint: location_fingerprint_1, + project_id: project.id + ) + end + + let(:expected_uuid_2) do + Security::VulnerabilityUUID.generate( + report_type: 'dast', + primary_identifier_fingerprint: identifier.fingerprint, + location_fingerprint: location_fingerprint_2, + project_id: project.id + ) + end + + let(:expected_uuid_3) do + Security::VulnerabilityUUID.generate( + report_type: 'secret_detection', + primary_identifier_fingerprint: identifier.fingerprint, + location_fingerprint: location_fingerprint_3, + project_id: project.id + ) + end + let(:finding_creator) do -> (report_type, location_fingerprint) do findings.create!( diff --git a/spec/models/list_spec.rb b/spec/models/list_spec.rb index 922d6b01b82..ad07ee1115b 100644 --- a/spec/models/list_spec.rb +++ b/spec/models/list_spec.rb @@ -5,6 +5,7 @@ require 'spec_helper' RSpec.describe List do it_behaves_like 'having unique enum values' it_behaves_like 'boards listable model', :list + it_behaves_like 'list_preferences_for user', :list, :list_id describe 'relationships' do it { is_expected.to belong_to(:board) } @@ -29,71 +30,4 @@ RSpec.describe List do expect(lists.where(board: board)).to match_array([backlog_list]) end end - - describe '#update_preferences_for' do - let(:user) { create(:user) } - let(:list) { create(:list) } - - context 'when user is present' do - context 'when there are no preferences for user' do - it 'creates new user preferences' do - expect { list.update_preferences_for(user, collapsed: true) }.to change { ListUserPreference.count }.by(1) - expect(list.preferences_for(user).collapsed).to eq(true) - end - end - - context 'when there are preferences for user' do - it 'updates user preferences' do - list.update_preferences_for(user, collapsed: false) - - expect { list.update_preferences_for(user, collapsed: true) }.not_to change { ListUserPreference.count } - expect(list.preferences_for(user).collapsed).to eq(true) - end - end - - context 'when user is nil' do - it 'does not create user preferences' do - expect { list.update_preferences_for(nil, collapsed: true) }.not_to change { ListUserPreference.count } - end - end - end - end - - describe '#preferences_for' do - let(:user) { create(:user) } - let(:list) { create(:list) } - - context 'when user is nil' do - it 'returns not persisted preferences' do - preferences = list.preferences_for(nil) - - expect(preferences.persisted?).to eq(false) - expect(preferences.list_id).to eq(list.id) - expect(preferences.user_id).to be_nil - end - end - - context 'when a user preference already exists' do - before do - list.update_preferences_for(user, collapsed: true) - end - - it 'loads preference for user' do - preferences = list.preferences_for(user) - - expect(preferences).to be_persisted - expect(preferences.collapsed).to eq(true) - end - end - - context 'when preferences for user does not exist' do - it 'returns not persisted preferences' do - preferences = list.preferences_for(user) - - expect(preferences.persisted?).to eq(false) - expect(preferences.user_id).to eq(user.id) - expect(preferences.list_id).to eq(list.id) - end - end - end end diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index 44b7a38ed2b..4a7232d6316 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -320,6 +320,18 @@ RSpec.describe API::Users do expect(json_response).to all(include('state' => /(blocked|ldap_blocked)/)) end + it "returns an array of external users" do + create(:user) + external_user = create(:user, external: true) + + get api("/users?external=true", user) + + expect(response).to match_response_schema('public_api/v4/user/basics') + expect(response).to include_pagination_headers + expect(json_response.size).to eq(1) + expect(json_response[0]['id']).to eq(external_user.id) + end + it "returns one user" do get api("/users?username=#{omniauth_user.username}", user) diff --git a/spec/support/shared_examples/models/boards/user_preferences_shared_examples.rb b/spec/support/shared_examples/models/boards/user_preferences_shared_examples.rb new file mode 100644 index 00000000000..766aeac9476 --- /dev/null +++ b/spec/support/shared_examples/models/boards/user_preferences_shared_examples.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'list_preferences_for user' do |list_factory, list_id_attribute| + subject { create(list_factory) } # rubocop:disable Rails/SaveBang + + let_it_be(:user) { create(:user) } + + describe '#preferences_for' do + context 'when user is nil' do + it 'returns not persisted preferences' do + preferences = subject.preferences_for(nil) + + expect(preferences).not_to be_persisted + expect(preferences[list_id_attribute]).to eq(subject.id) + expect(preferences.user_id).to be_nil + end + end + + context 'when a user preference already exists' do + before do + subject.update_preferences_for(user, collapsed: true) + end + + it 'loads preference for user' do + preferences = subject.preferences_for(user) + + expect(preferences).to be_persisted + expect(preferences.collapsed).to eq(true) + end + end + + context 'when preferences for user does not exist' do + it 'returns not persisted preferences' do + preferences = subject.preferences_for(user) + + expect(preferences).not_to be_persisted + expect(preferences.user_id).to eq(user.id) + expect(preferences.public_send(list_id_attribute)).to eq(subject.id) + end + end + end + + describe '#update_preferences_for' do + context 'when user is present' do + context 'when there are no preferences for user' do + it 'creates new user preferences' do + expect { subject.update_preferences_for(user, collapsed: true) }.to change { subject.preferences.count }.by(1) + expect(subject.preferences_for(user).collapsed).to eq(true) + end + end + + context 'when there are preferences for user' do + it 'updates user preferences' do + subject.update_preferences_for(user, collapsed: false) + + expect { subject.update_preferences_for(user, collapsed: true) }.not_to change { subject.preferences.count } + expect(subject.preferences_for(user).collapsed).to eq(true) + end + end + + context 'when user is nil' do + it 'does not create user preferences' do + expect { subject.update_preferences_for(nil, collapsed: true) }.not_to change { subject.preferences.count } + end + end + end + end +end |