diff options
Diffstat (limited to 'spec')
14 files changed, 422 insertions, 53 deletions
diff --git a/spec/frontend/diffs/utils/uuids_spec.js b/spec/frontend/diffs/utils/uuids_spec.js new file mode 100644 index 00000000000..79d3ebadd4f --- /dev/null +++ b/spec/frontend/diffs/utils/uuids_spec.js @@ -0,0 +1,92 @@ +import { uuids } from '~/diffs/utils/uuids'; + +const HEX = /[a-f0-9]/i; +const HEX_RE = HEX.source; +const UUIDV4 = new RegExp( + `${HEX_RE}{8}-${HEX_RE}{4}-4${HEX_RE}{3}-[89ab]${HEX_RE}{3}-${HEX_RE}{12}`, + 'i', +); + +describe('UUIDs Util', () => { + describe('uuids', () => { + const SEQUENCE_FOR_GITLAB_SEED = [ + 'a1826a44-316c-480e-a93d-8cdfeb36617c', + 'e049db1f-a4cf-4cba-aa60-6d95e3b547dc', + '6e3c737c-13a7-4380-b17d-601f187d7e69', + 'bee5cc7f-c486-45c0-8ad3-d1ac5402632d', + 'af248c9f-a3a6-4d4f-a311-fe151ffab25a', + ]; + const SEQUENCE_FOR_12345_SEED = [ + 'edfb51e2-e3e1-4de5-90fd-fd1d21760881', + '2f154da4-0a2d-4da9-b45e-0ffed391517e', + '91566d65-8836-4222-9875-9e1df4d0bb01', + 'f6ea6c76-7640-4d71-a736-9d3bec7a1a8e', + 'bfb85869-5fb9-4c5b-a750-5af727ac5576', + ]; + + it('returns version 4 UUIDs', () => { + expect(uuids()[0]).toMatch(UUIDV4); + }); + + it('outputs an array of UUIDs', () => { + const ids = uuids({ count: 11 }); + + expect(ids.length).toEqual(11); + expect(ids.every(id => UUIDV4.test(id))).toEqual(true); + }); + + it.each` + seeds | uuid + ${['some', 'special', 'seed']} | ${'6fa53e51-0f70-4072-9c84-1c1eee1b9934'} + ${['magic']} | ${'fafae8cd-7083-44f3-b82d-43b30bd27486'} + ${['seeded']} | ${'e06ed291-46c5-4e42-836b-e7c772d48b49'} + ${['GitLab']} | ${'a1826a44-316c-480e-a93d-8cdfeb36617c'} + ${['JavaScript']} | ${'12dfb297-1560-4c38-9775-7178ef8472fb'} + ${[99, 169834, 2619]} | ${'3ecc8ad6-5b7c-4c9b-94a8-c7271c2fa083'} + ${[12]} | ${'2777374b-723b-469b-bd73-e586df964cfd'} + ${[9876, 'mixed!', 7654]} | ${'865212e0-4a16-4934-96f9-103cf36a6931'} + ${[123, 1234, 12345, 6]} | ${'40aa2ee6-0a11-4e67-8f09-72f5eba04244'} + ${[0]} | ${'8c7f0aac-97c4-4a2f-b716-a675d821ccc0'} + `( + 'should always output the UUID $uuid when the options.seeds argument is $seeds', + ({ uuid, seeds }) => { + expect(uuids({ seeds })[0]).toEqual(uuid); + }, + ); + + describe('unseeded UUID randomness', () => { + const nonRandom = Array(6) + .fill(0) + .map((_, i) => uuids({ seeds: [i] })[0]); + const random = uuids({ count: 6 }); + const moreRandom = uuids({ count: 6 }); + + it('is different from a seeded result', () => { + random.forEach((id, i) => { + expect(id).not.toEqual(nonRandom[i]); + }); + }); + + it('is different from other random results', () => { + random.forEach((id, i) => { + expect(id).not.toEqual(moreRandom[i]); + }); + }); + + it('never produces any duplicates', () => { + expect(new Set(random).size).toEqual(random.length); + }); + }); + + it.each` + seed | sequence + ${'GitLab'} | ${SEQUENCE_FOR_GITLAB_SEED} + ${12345} | ${SEQUENCE_FOR_12345_SEED} + `( + 'should output the same sequence of UUIDs for the given seed "$seed"', + ({ seed, sequence }) => { + expect(uuids({ seeds: [seed], count: 5 })).toEqual(sequence); + }, + ); + }); +}); diff --git a/spec/frontend/monitoring/components/dashboard_spec.js b/spec/frontend/monitoring/components/dashboard_spec.js index 5e2d2847cad..7bb4c68b4cd 100644 --- a/spec/frontend/monitoring/components/dashboard_spec.js +++ b/spec/frontend/monitoring/components/dashboard_spec.js @@ -16,6 +16,7 @@ import DashboardsDropdown from '~/monitoring/components/dashboards_dropdown.vue' import EmptyState from '~/monitoring/components/empty_state.vue'; import GroupEmptyState from '~/monitoring/components/group_empty_state.vue'; import DashboardPanel from '~/monitoring/components/dashboard_panel.vue'; +import LinksSection from '~/monitoring/components/links_section.vue'; import { createStore } from '~/monitoring/stores'; import * as types from '~/monitoring/stores/mutation_types'; import { @@ -24,6 +25,7 @@ import { setMetricResult, setupStoreWithData, setupStoreWithVariable, + setupStoreWithLinks, } from '../store_utils'; import { environmentData, dashboardGitResponse, propsData } from '../mock_data'; import { metricsDashboardViewModel, metricsDashboardPanelCount } from '../fixture_data'; @@ -483,6 +485,21 @@ describe('Dashboard', () => { }); }); + describe('links section', () => { + beforeEach(() => { + createShallowWrapper({ hasMetrics: true }); + setupStoreWithData(store); + setupStoreWithLinks(store); + + return wrapper.vm.$nextTick(); + }); + + it('shows the links section', () => { + expect(wrapper.vm.shouldShowLinksSection).toBe(true); + expect(wrapper.find(LinksSection)).toExist(); + }); + }); + describe('single panel expands to "full screen" mode', () => { const findExpandedPanel = () => wrapper.find({ ref: 'expandedPanel' }); diff --git a/spec/frontend/monitoring/store/utils_spec.js b/spec/frontend/monitoring/store/utils_spec.js index f6c2b5b9682..02cdd3d7f41 100644 --- a/spec/frontend/monitoring/store/utils_spec.js +++ b/spec/frontend/monitoring/store/utils_spec.js @@ -16,6 +16,8 @@ describe('mapToDashboardViewModel', () => { expect(mapToDashboardViewModel({})).toEqual({ dashboard: '', panelGroups: [], + links: [], + variables: {}, }); }); @@ -44,6 +46,8 @@ describe('mapToDashboardViewModel', () => { expect(mapToDashboardViewModel(response)).toEqual({ dashboard: 'Dashboard Name', + links: [], + variables: {}, panelGroups: [ { group: 'Group 1', @@ -76,6 +80,8 @@ describe('mapToDashboardViewModel', () => { it('key', () => { const response = { dashboard: 'Dashboard Name', + links: [], + variables: {}, panel_groups: [ { group: 'Group A', diff --git a/spec/frontend/monitoring/store_utils.js b/spec/frontend/monitoring/store_utils.js index 8ac8b4367c6..eb2578aa9db 100644 --- a/spec/frontend/monitoring/store_utils.js +++ b/spec/frontend/monitoring/store_utils.js @@ -38,6 +38,18 @@ export const setupStoreWithVariable = store => { }); }; +export const setupStoreWithLinks = store => { + store.commit(`monitoringDashboard/${types.RECEIVE_METRICS_DASHBOARD_SUCCESS}`, { + ...metricsDashboardPayload, + links: [ + { + title: 'GitLab Website', + url: `https://gitlab.com/website`, + }, + ], + }); +}; + export const setupStoreWithData = store => { setupAllDashboards(store); setupStoreWithDashboard(store); diff --git a/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js b/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js index 691e98236e4..6d1ebe85aa0 100644 --- a/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js +++ b/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js @@ -110,4 +110,26 @@ describe('ProjectSelector component', () => { ); }); }); + + describe('the search results legend', () => { + it.each` + count | total | expected + ${0} | ${0} | ${'Showing 0 projects'} + ${1} | ${0} | ${'Showing 1 project'} + ${2} | ${0} | ${'Showing 2 projects'} + ${2} | ${3} | ${'Showing 2 of 3 projects'} + `( + 'is "$expected" given $count results are showing out of $total', + ({ count, total, expected }) => { + wrapper.setProps({ + projectSearchResults: searchResults.slice(0, count), + totalResults: total, + }); + + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.text()).toContain(expected); + }); + }, + ); + }); }); diff --git a/spec/initializers/google_api_client_spec.rb b/spec/initializers/google_api_client_spec.rb deleted file mode 100644 index 44a1bc0836c..00000000000 --- a/spec/initializers/google_api_client_spec.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe './config/initializers/google_api_client.rb' do - subject { Google::Apis::ContainerV1beta1 } - - it 'is needed' do |example| - is_expected.not_to be_const_defined(:CloudRunConfig), - <<-MSG.strip_heredoc - The google-api-client gem has been upgraded! - Remove: - #{example.example_group.description} - #{example.file_path} - MSG - end -end diff --git a/spec/lib/gitlab/auth/ldap/person_spec.rb b/spec/lib/gitlab/auth/ldap/person_spec.rb index e90917cfce1..403a48d40ef 100644 --- a/spec/lib/gitlab/auth/ldap/person_spec.rb +++ b/spec/lib/gitlab/auth/ldap/person_spec.rb @@ -57,14 +57,17 @@ describe Gitlab::Auth::Ldap::Person do 'attributes' => { 'name' => 'cn', 'email' => 'mail', - 'username' => %w(uid mail memberof) + 'username' => %w(uid mail), + 'first_name' => '' } } ) config = Gitlab::Auth::Ldap::Config.new('ldapmain') ldap_attributes = described_class.ldap_attributes(config) - expect(ldap_attributes).to match_array(%w(dn uid cn mail memberof)) + expect(ldap_attributes).to include('dn', 'uid', 'cn', 'mail') + expect(ldap_attributes).to be_present + expect(ldap_attributes.uniq!).to eq(nil) end end diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 6d903ce5fc9..432190b4318 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -599,6 +599,7 @@ design: &design - versions - notes - user_mentions +- events designs: *design actions: - design diff --git a/spec/models/project_services/prometheus_service_spec.rb b/spec/models/project_services/prometheus_service_spec.rb index a85dbe3a7df..ec5bef92cde 100644 --- a/spec/models/project_services/prometheus_service_spec.rb +++ b/spec/models/project_services/prometheus_service_spec.rb @@ -252,6 +252,26 @@ describe PrometheusService, :use_clean_rails_memory_store_caching do end end end + + context 'behind IAP' do + let(:manual_configuration) { true } + + before do + # dummy private key generated only for this test to pass openssl validation + service.google_iap_service_account_json = '{"type":"service_account","private_key":"-----BEGIN RSA PRIVATE KEY-----\nMIIBOAIBAAJAU85LgUY5o6j6j/07GMLCNUcWJOBA1buZnNgKELayA6mSsHrIv31J\nY8kS+9WzGPQninea7DcM4hHA7smMgQD1BwIDAQABAkAqKxMy6PL3tn7dFL43p0ex\nJyOtSmlVIiAZG1t1LXhE/uoLpYi5DnbYqGgu0oih+7nzLY/dXpNpXUmiRMOUEKmB\nAiEAoTi2rBXbrLSi2C+H7M/nTOjMQQDuZ8Wr4uWpKcjYJTMCIQCFEskL565oFl/7\nRRQVH+cARrAsAAoJSbrOBAvYZ0PI3QIgIEFwis10vgEF86rOzxppdIG/G+JL0IdD\n9IluZuXAGPECIGUo7qSaLr75o2VEEgwtAFH5aptIPFjrL5LFCKwtdB4RAiAYZgFV\nHCMmaooAw/eELuMoMWNYmujZ7VaAnOewGDW0uw==\n-----END RSA PRIVATE KEY-----\n"}' + service.google_iap_audience_client_id = "IAP_CLIENT_ID.apps.googleusercontent.com" + + stub_request(:post, "https://oauth2.googleapis.com/token").to_return(status: 200, body: '{"id_token": "FOO"}', headers: { 'Content-Type': 'application/json; charset=UTF-8' }) + + stub_feature_flags(prometheus_service_iap_auth: true) + end + + it 'includes the authorization header' do + expect(service.prometheus_client).not_to be_nil + expect(service.prometheus_client.send(:options)).to have_key(:headers) + expect(service.prometheus_client.send(:options)[:headers]).to eq(authorization: "Bearer FOO") + end + end end describe '#prometheus_available?' do @@ -457,9 +477,33 @@ describe PrometheusService, :use_clean_rails_memory_store_caching do } ] end + let(:feature_flagged_fields) do + [ + { + type: 'text', + name: 'google_iap_audience_client_id', + title: 'Google IAP Audience Client ID', + placeholder: s_('PrometheusService|Client ID of the IAP secured resource (looks like IAP_CLIENT_ID.apps.googleusercontent.com)'), + required: false + }, + { + type: 'textarea', + name: 'google_iap_service_account_json', + title: 'Google IAP Service Account JSON', + placeholder: s_('PrometheusService|Contents of the credentials.json file of your service account, like: { "type": "service_account", "project_id": ... }'), + required: false + } + ] + end it 'returns fields' do + stub_feature_flags(prometheus_service_iap_auth: false) expect(service.fields).to eq(expected_fields) end + + it 'returns fields with feature flag on' do + stub_feature_flags(prometheus_service_iap_auth: true) + expect(service.fields).to eq(expected_fields + feature_flagged_fields) + end end end diff --git a/spec/presenters/projects/prometheus/alert_presenter_spec.rb b/spec/presenters/projects/prometheus/alert_presenter_spec.rb index 967a0fb2c09..8ee5a4d7b3f 100644 --- a/spec/presenters/projects/prometheus/alert_presenter_spec.rb +++ b/spec/presenters/projects/prometheus/alert_presenter_spec.rb @@ -24,18 +24,25 @@ describe Projects::Prometheus::AlertPresenter do it { is_expected.to eq(project.full_path) } end - describe '#starts_at' do - subject { presenter.starts_at } + describe '#start_time' do + subject { presenter.start_time } + + let(:starts_at) { '2020-10-31T14:02:04Z' } before do payload['startsAt'] = starts_at end - context 'with valid datetime' do - let(:datetime) { Time.now } - let(:starts_at) { datetime.rfc3339 } + context 'with valid utc datetime' do + it { is_expected.to eq('31 October 2020, 2:02PM (UTC)') } - it { is_expected.to eq(datetime.rfc3339) } + context 'with admin time zone not UTC' do + before do + allow(Time).to receive(:zone).and_return(ActiveSupport::TimeZone.new('Perth')) + end + + it { is_expected.to eq('31 October 2020, 2:02PM (UTC)') } + end end context 'with invalid datetime' do @@ -56,7 +63,7 @@ describe Projects::Prometheus::AlertPresenter do <<~MARKDOWN.chomp #### Summary - **Start time:** #{presenter.starts_at} + **Start time:** #{presenter.start_time} MARKDOWN ) @@ -73,7 +80,7 @@ describe Projects::Prometheus::AlertPresenter do <<~MARKDOWN.chomp #### Summary - **Start time:** #{presenter.starts_at} + **Start time:** #{presenter.start_time} #### Alert Details @@ -94,7 +101,7 @@ describe Projects::Prometheus::AlertPresenter do <<~MARKDOWN.chomp #### Summary - **Start time:** #{presenter.starts_at}#{markdown_line_break} + **Start time:** #{presenter.start_time}#{markdown_line_break} **full_query:** `query` MARKDOWN @@ -122,7 +129,7 @@ describe Projects::Prometheus::AlertPresenter do <<~MARKDOWN.chomp #### Summary - **Start time:** #{presenter.starts_at}#{markdown_line_break} + **Start time:** #{presenter.start_time}#{markdown_line_break} **Service:** service_name#{markdown_line_break} **Monitoring tool:** monitoring_tool_name#{markdown_line_break} **Hosts:** http://localhost:3000 http://localhost:3001 @@ -144,7 +151,7 @@ describe Projects::Prometheus::AlertPresenter do <<~MARKDOWN.chomp #### Summary - **Start time:** #{presenter.starts_at}#{markdown_line_break} + **Start time:** #{presenter.start_time}#{markdown_line_break} **Hosts:** http://localhost:3000 MARKDOWN @@ -161,7 +168,7 @@ describe Projects::Prometheus::AlertPresenter do <<~MARKDOWN.chomp #### Summary - **Start time:** #{presenter.starts_at}#{markdown_line_break} + **Start time:** #{presenter.start_time}#{markdown_line_break} **full_query:** `avg(metric) > 1.0` [](#{url}) @@ -253,7 +260,7 @@ describe Projects::Prometheus::AlertPresenter do <<~MARKDOWN.chomp #### Summary - **Start time:** #{presenter.starts_at}#{markdown_line_break} + **Start time:** #{presenter.start_time}#{markdown_line_break} **full_query:** `avg(metric) > 1.0` MARKDOWN @@ -280,7 +287,7 @@ describe Projects::Prometheus::AlertPresenter do <<~MARKDOWN.chomp #### Summary - **Start time:** #{presenter.starts_at} + **Start time:** #{presenter.start_time} MARKDOWN end diff --git a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb new file mode 100644 index 00000000000..217f538c53e --- /dev/null +++ b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb @@ -0,0 +1,80 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Mutations::Metrics::Dashboard::Annotations::Delete do + include GraphqlHelpers + + let_it_be(:current_user) { create(:user) } + let_it_be(:project) { create(:project, :private, :repository) } + let_it_be(:environment) { create(:environment, project: project) } + let_it_be(:annotation) { create(:metrics_dashboard_annotation, environment: environment) } + let(:mutation) do + variables = { + id: GitlabSchema.id_from_object(annotation).to_s + } + + graphql_mutation(:delete_annotation, variables) + end + + def mutation_response + graphql_mutation_response(:delete_annotation) + end + + specify { expect(described_class).to require_graphql_authorizations(:delete_metrics_dashboard_annotation) } + + context 'when the user has permission to delete the annotation' do + before do + project.add_developer(current_user) + end + + context 'with valid params' do + it 'deletes the annotation' do + expect do + post_graphql_mutation(mutation, current_user: current_user) + end.to change { Metrics::Dashboard::Annotation.count }.by(-1) + end + end + + context 'with invalid params' do + let(:mutation) do + variables = { + id: 'invalid_id' + } + + graphql_mutation(:delete_annotation, variables) + end + + it_behaves_like 'a mutation that returns top-level errors', errors: ['invalid_id is not a valid GitLab id.'] + end + + context 'when the delete fails' do + let(:service_response) { { message: 'Annotation has not been deleted', status: :error, last_step: :delete } } + + before do + allow_next_instance_of(Metrics::Dashboard::Annotations::DeleteService) do |delete_service| + allow(delete_service).to receive(:execute).and_return(service_response) + end + end + it 'returns the error' do + post_graphql_mutation(mutation, current_user: current_user) + + expect(mutation_response['errors']).to eq([service_response[:message]]) + end + end + end + + context 'when the user does not have permission to delete the annotation' do + before do + project.add_reporter(current_user) + end + + it_behaves_like 'a mutation that returns top-level errors', errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR] + + it 'does not delete the annotation' do + expect do + post_graphql_mutation(mutation, current_user: current_user) + end.not_to change { Metrics::Dashboard::Annotation.count } + end + end +end diff --git a/spec/services/design_management/delete_designs_service_spec.rb b/spec/services/design_management/delete_designs_service_spec.rb index 2c0c1570cb4..bf5d6b443e6 100644 --- a/spec/services/design_management/delete_designs_service_spec.rb +++ b/spec/services/design_management/delete_designs_service_spec.rb @@ -56,6 +56,10 @@ describe DesignManagement::DeleteDesignsService do let(:enabled) { false } it_behaves_like "a service error" + + it 'does not create any events in the activity stream' do + expect { run_service rescue nil }.not_to change { Event.count } + end end context "when the feature is available" do @@ -72,7 +76,9 @@ describe DesignManagement::DeleteDesignsService do it 'does not log any events' do counter = ::Gitlab::UsageDataCounters::DesignsCounter - expect { run_service rescue nil }.not_to change { counter.totals } + + expect { run_service rescue nil } + .not_to change { [counter.totals, Event.count] } end end @@ -92,6 +98,12 @@ describe DesignManagement::DeleteDesignsService do expect { run_service }.to change { counter.read(:delete) }.by(1) end + it 'creates an event in the activity stream' do + expect { run_service } + .to change { Event.count }.by(1) + .and change { Event.destroyed_action.for_design.count }.by(1) + end + it 'informs the new-version-worker' do expect(::DesignManagement::NewVersionWorker).to receive(:perform_async).with(Integer) @@ -129,14 +141,14 @@ describe DesignManagement::DeleteDesignsService do let!(:designs) { create_designs(2) } - it 'removes those designs' do + it 'makes the correct changes' do + counter = ::Gitlab::UsageDataCounters::DesignsCounter + expect { run_service } .to change { issue.designs.current.count }.from(3).to(1) - end - - it 'logs the correct number of deletion events' do - counter = ::Gitlab::UsageDataCounters::DesignsCounter - expect { run_service }.to change { counter.read(:delete) }.by(2) + .and change { counter.read(:delete) }.by(2) + .and change { Event.count }.by(2) + .and change { Event.destroyed_action.for_design.count }.by(2) end it_behaves_like "a success" diff --git a/spec/services/design_management/save_designs_service_spec.rb b/spec/services/design_management/save_designs_service_spec.rb index 013d5473860..3be3ac9daca 100644 --- a/spec/services/design_management/save_designs_service_spec.rb +++ b/spec/services/design_management/save_designs_service_spec.rb @@ -65,6 +65,10 @@ describe DesignManagement::SaveDesignsService do end it_behaves_like 'a service error' + + it 'does not create an event in the activity stream' do + expect { run_service }.not_to change { Event.count } + end end context 'when the feature is available' do @@ -89,6 +93,12 @@ describe DesignManagement::SaveDesignsService do expect { run_service }.to change { counter.read(:create) }.by(1) end + it 'creates an event in the activity stream' do + expect { run_service } + .to change { Event.count }.by(1) + .and change { Event.for_design.created_action.count }.by(1) + end + it 'creates a commit in the repository' do run_service @@ -166,9 +176,12 @@ describe DesignManagement::SaveDesignsService do expect(updated_designs.first.versions.size).to eq(2) end - it 'increments the update counter' do + it 'records the correct events' do counter = Gitlab::UsageDataCounters::DesignsCounter - expect { run_service }.to change { counter.read(:update) }.by 1 + expect { run_service } + .to change { counter.read(:update) }.by(1) + .and change { Event.count }.by(1) + .and change { Event.for_design.updated_action.count }.by(1) end context 'when uploading a new design' do @@ -217,6 +230,14 @@ describe DesignManagement::SaveDesignsService do .and change { counter.read(:update) }.by(1) end + it 'creates the correct activity stream events' do + expect { run_service } + .to change { Event.count }.by(2) + .and change { Event.for_design.count }.by(2) + .and change { Event.created_action.count }.by(1) + .and change { Event.updated_action.count }.by(1) + end + it 'creates a single commit' do commit_count = -> do design_repository.expire_all_method_caches diff --git a/spec/services/event_create_service_spec.rb b/spec/services/event_create_service_spec.rb index a43678626f7..73c089334ed 100644 --- a/spec/services/event_create_service_spec.rb +++ b/spec/services/event_create_service_spec.rb @@ -5,6 +5,9 @@ require 'spec_helper' describe EventCreateService do let(:service) { described_class.new } + let_it_be(:user, reload: true) { create :user } + let_it_be(:project) { create(:project) } + describe 'Issues' do describe '#open_issue' do let(:issue) { create(:issue) } @@ -87,8 +90,6 @@ describe EventCreateService do end describe 'Milestone' do - let(:user) { create :user } - describe '#open_milestone' do let(:milestone) { create(:milestone) } @@ -210,9 +211,6 @@ describe EventCreateService do end describe '#push', :clean_gitlab_redis_shared_state do - let(:project) { create(:project) } - let(:user) { create(:user) } - let(:push_data) do { commits: [ @@ -234,9 +232,6 @@ describe EventCreateService do end describe '#bulk_push', :clean_gitlab_redis_shared_state do - let(:project) { create(:project) } - let(:user) { create(:user) } - let(:push_data) do { action: :created, @@ -251,9 +246,6 @@ describe EventCreateService do end describe 'Project' do - let(:user) { create :user } - let(:project) { create(:project) } - describe '#join_project' do subject { service.join_project(project, user) } @@ -268,4 +260,81 @@ describe EventCreateService do it { expect { subject }.to change { Event.count }.from(0).to(1) } end end + + describe 'design events' do + let_it_be(:design) { create(:design, project: project) } + let_it_be(:author) { user } + + shared_examples 'feature flag gated multiple event creation' do + context 'the feature flag is off' do + before do + stub_feature_flags(design_activity_events: false) + end + + specify { expect(result).to be_empty } + specify { expect { result }.not_to change { Event.count } } + specify { expect { result }.not_to exceed_query_limit(0) } + end + + context 'the feature flag is enabled for a single project' do + before do + stub_feature_flags(design_activity_events: project) + end + + specify { expect(result).not_to be_empty } + specify { expect { result }.to change { Event.count }.by(1) } + end + end + + describe '#save_designs' do + let_it_be(:updated) { create_list(:design, 5) } + let_it_be(:created) { create_list(:design, 3) } + + let(:result) { service.save_designs(author, create: created, update: updated) } + + specify { expect { result }.to change { Event.count }.by(8) } + + specify { expect { result }.not_to exceed_query_limit(1) } + + it 'creates 3 created design events' do + ids = result.pluck('id') + events = Event.created_action.where(id: ids) + + expect(events.map(&:design)).to match_array(created) + end + + it 'creates 5 created design events' do + ids = result.pluck('id') + events = Event.updated_action.where(id: ids) + + expect(events.map(&:design)).to match_array(updated) + end + + it_behaves_like 'feature flag gated multiple event creation' do + let(:project) { created.first.project } + end + end + + describe '#destroy_designs' do + let_it_be(:designs) { create_list(:design, 5) } + let_it_be(:author) { create(:user) } + + let(:result) { service.destroy_designs(designs, author) } + + specify { expect { result }.to change { Event.count }.by(5) } + + specify { expect { result }.not_to exceed_query_limit(1) } + + it 'creates 5 destroyed design events' do + ids = result.pluck('id') + events = Event.destroyed_action.where(id: ids) + + expect(events.map(&:design)).to match_array(designs) + end + + it_behaves_like 'feature flag gated multiple event creation' do + let(:project) { designs.first.project } + end + end + end end |