diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-12-15 00:13:08 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-12-15 00:13:08 +0300 |
commit | 30f908f6b9689ecda34474e68c55ce4dba1a9974 (patch) | |
tree | 980f904604222360eefcee2e01a7068539488713 /spec | |
parent | 0c6a209989efe28789e8580aedbac25677af9ca2 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
14 files changed, 293 insertions, 20 deletions
diff --git a/spec/experiments/application_experiment_spec.rb b/spec/experiments/application_experiment_spec.rb index e01c5522b51..5146fe3e752 100644 --- a/spec/experiments/application_experiment_spec.rb +++ b/spec/experiments/application_experiment_spec.rb @@ -233,6 +233,75 @@ RSpec.describe ApplicationExperiment, :experiment do ] ) end + + context "when using known context resources" do + let(:user) { build(:user, id: non_existing_record_id) } + let(:project) { build(:project, id: non_existing_record_id) } + let(:namespace) { build(:namespace, id: non_existing_record_id) } + let(:group) { build(:group, id: non_existing_record_id) } + let(:actor) { user } + + let(:context) { { user: user, project: project, namespace: namespace } } + + it "includes those using the gitlab standard context" do + subject.track(:action) + + expect_snowplow_event( + category: 'namespaced/stub', + action: 'action', + user: user, + project: project, + namespace: namespace, + context: an_instance_of(Array) + ) + end + + it "falls back to using the group key" do + subject.context(namespace: nil, group: group) + + subject.track(:action) + + expect_snowplow_event( + category: 'namespaced/stub', + action: 'action', + user: user, + project: project, + namespace: group, + context: an_instance_of(Array) + ) + end + + context "with the actor key" do + it "provides it to the tracking call as the user" do + subject.context(user: nil, actor: actor) + + subject.track(:action) + + expect_snowplow_event( + category: 'namespaced/stub', + action: 'action', + user: actor, + project: project, + namespace: namespace, + context: an_instance_of(Array) + ) + end + + it "handles when it's not a user record" do + subject.context(user: nil, actor: nil) + + subject.track(:action) + + expect_snowplow_event( + category: 'namespaced/stub', + action: 'action', + project: project, + namespace: namespace, + context: an_instance_of(Array) + ) + end + end + end end describe "#key_for" do diff --git a/spec/frontend/ci_lint/components/ci_lint_spec.js b/spec/frontend/ci_lint/components/ci_lint_spec.js index 36d860b1ccd..70d116c12d3 100644 --- a/spec/frontend/ci_lint/components/ci_lint_spec.js +++ b/spec/frontend/ci_lint/components/ci_lint_spec.js @@ -3,7 +3,7 @@ import { shallowMount } from '@vue/test-utils'; import waitForPromises from 'helpers/wait_for_promises'; import CiLint from '~/ci_lint/components/ci_lint.vue'; import CiLintResults from '~/pipeline_editor/components/lint/ci_lint_results.vue'; -import lintCIMutation from '~/pipeline_editor/graphql/mutations/lint_ci.mutation.graphql'; +import lintCIMutation from '~/pipeline_editor/graphql/mutations/client/lint_ci.mutation.graphql'; import SourceEditor from '~/vue_shared/components/source_editor.vue'; import { mockLintDataValid } from '../mock_data'; diff --git a/spec/frontend/ide/services/index_spec.js b/spec/frontend/ide/services/index_spec.js index d250eb7f6ad..3cf6240c2c5 100644 --- a/spec/frontend/ide/services/index_spec.js +++ b/spec/frontend/ide/services/index_spec.js @@ -6,7 +6,7 @@ import dismissUserCallout from '~/graphql_shared/mutations/dismiss_user_callout. import services from '~/ide/services'; import { query, mutate } from '~/ide/services/gql'; import { escapeFileUrl } from '~/lib/utils/url_utility'; -import ciConfig from '~/pipeline_editor/graphql/queries/ci_config.graphql'; +import ciConfig from '~/pipeline_editor/graphql/queries/ci_config.query.graphql'; import { projectData } from '../mock_data'; jest.mock('~/api'); diff --git a/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js b/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js index 7ec322d355f..bc77b7045eb 100644 --- a/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js +++ b/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js @@ -12,7 +12,7 @@ import { COMMIT_SUCCESS, } from '~/pipeline_editor/constants'; import commitCreate from '~/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql'; -import updatePipelineEtag from '~/pipeline_editor/graphql/mutations/update_pipeline_etag.mutation.graphql'; +import updatePipelineEtag from '~/pipeline_editor/graphql/mutations/client/update_pipeline_etag.mutation.graphql'; import { mockCiConfigPath, diff --git a/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js b/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js index 6532c4e289d..3235842dca3 100644 --- a/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js +++ b/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js @@ -11,7 +11,7 @@ import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; import BranchSwitcher from '~/pipeline_editor/components/file_nav/branch_switcher.vue'; import { DEFAULT_FAILURE } from '~/pipeline_editor/constants'; -import getAvailableBranchesQuery from '~/pipeline_editor/graphql/queries/available_branches.graphql'; +import getAvailableBranchesQuery from '~/pipeline_editor/graphql/queries/available_branches.query.graphql'; import { mockBranchPaginationLimit, mockDefaultBranch, diff --git a/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js b/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js index a30edb4778b..c101b1d21c7 100644 --- a/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js +++ b/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js @@ -4,7 +4,7 @@ import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; import PipelineStatus, { i18n } from '~/pipeline_editor/components/header/pipeline_status.vue'; -import getPipelineQuery from '~/pipeline_editor/graphql/queries/client/pipeline.graphql'; +import getPipelineQuery from '~/pipeline_editor/graphql/queries/pipeline.query.graphql'; import PipelineEditorMiniGraph from '~/pipeline_editor/components/header/pipeline_editor_mini_graph.vue'; import { mockCommitSha, mockProjectPipeline, mockProjectFullPath } from '../../mock_data'; diff --git a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js index b8755e2ced1..09d7d4f7ca6 100644 --- a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js +++ b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js @@ -9,12 +9,11 @@ import PipelineEditorTabs from '~/pipeline_editor/components/pipeline_editor_tab import PipelineEditorEmptyState from '~/pipeline_editor/components/ui/pipeline_editor_empty_state.vue'; import PipelineEditorMessages from '~/pipeline_editor/components/ui/pipeline_editor_messages.vue'; import { COMMIT_SUCCESS, COMMIT_FAILURE, LOAD_FAILURE_UNKNOWN } from '~/pipeline_editor/constants'; -import getBlobContent from '~/pipeline_editor/graphql/queries/blob_content.graphql'; -import getCiConfigData from '~/pipeline_editor/graphql/queries/ci_config.graphql'; +import getBlobContent from '~/pipeline_editor/graphql/queries/blob_content.query.graphql'; +import getCiConfigData from '~/pipeline_editor/graphql/queries/ci_config.query.graphql'; import getTemplate from '~/pipeline_editor/graphql/queries/get_starter_template.query.graphql'; import getLatestCommitShaQuery from '~/pipeline_editor/graphql/queries/latest_commit_sha.query.graphql'; - -import getPipelineQuery from '~/pipeline_editor/graphql/queries/client/pipeline.graphql'; +import getPipelineQuery from '~/pipeline_editor/graphql/queries/pipeline.query.graphql'; import PipelineEditorApp from '~/pipeline_editor/pipeline_editor_app.vue'; import PipelineEditorHome from '~/pipeline_editor/pipeline_editor_home.vue'; diff --git a/spec/lib/feature/definition_spec.rb b/spec/lib/feature/definition_spec.rb index 21120012927..2f95f8eeab7 100644 --- a/spec/lib/feature/definition_spec.rb +++ b/spec/lib/feature/definition_spec.rb @@ -161,6 +161,41 @@ RSpec.describe Feature::Definition do end end + describe '.for_upcoming_milestone?' do + using RSpec::Parameterized::TableSyntax + + let(:definition) do + Feature::Definition.new("development/enabled_feature_flag.yml", + name: :enabled_feature_flag, + type: 'development', + milestone: milestone, + default_enabled: false) + end + + before do + allow(Feature::Definition).to receive(:definitions) do + { definition.key => definition } + end + + allow(Gitlab).to receive(:version_info).and_return(Gitlab::VersionInfo.parse(current_milestone)) + end + + subject { definition.for_upcoming_milestone? } + + where(:ctx, :milestone, :current_milestone, :expected) do + 'no milestone' | nil | '1.0.0' | false + 'upcoming milestone - major' | '2.3' | '1.9.999' | true + 'upcoming milestone - minor' | '2.3' | '2.2.999' | true + 'current milestone' | '2.3' | '2.3.999' | true + 'past milestone - major' | '1.9' | '2.3.999' | false + 'past milestone - minor' | '2.2' | '2.3.999' | false + end + + with_them do + it {is_expected.to be(expected)} + end + end + describe '.valid_usage!' do before do allow(described_class).to receive(:definitions) do @@ -215,7 +250,42 @@ RSpec.describe Feature::Definition do end end - describe '.defaul_enabled?' do + describe '.log_states?' do + using RSpec::Parameterized::TableSyntax + + let(:definition) do + Feature::Definition.new("development/enabled_feature_flag.yml", + name: :enabled_feature_flag, + type: 'development', + milestone: milestone, + log_state_changes: log_state_change, + default_enabled: false) + end + + before do + allow(Feature::Definition).to receive(:definitions) do + { definition.key => definition } + end + + allow(Gitlab).to receive(:version_info).and_return(Gitlab::VersionInfo.new(10, 0, 0)) + end + + subject { Feature::Definition.log_states?(key) } + + where(:ctx, :key, :milestone, :log_state_change, :expected) do + 'When flag does not exist' | :no_flag | "0.0" | true | false + 'When flag is old, and logging is not forced' | :enabled_feature_flag | "0.0" | false | false + 'When flag is old, but logging is forced' | :enabled_feature_flag | "0.0" | true | true + 'When flag is current' | :enabled_feature_flag | "10.0" | true | true + 'Flag is upcoming' | :enabled_feature_flag | "10.0" | true | true + end + + with_them do + it { is_expected.to be(expected) } + end + end + + describe '.default_enabled?' do subject { described_class.default_enabled?(key) } context 'when feature flag exist' do diff --git a/spec/lib/feature_spec.rb b/spec/lib/feature_spec.rb index 2c4b0a85537..82580d5d700 100644 --- a/spec/lib/feature_spec.rb +++ b/spec/lib/feature_spec.rb @@ -186,6 +186,17 @@ RSpec.describe Feature, stub_feature_flags: false do context 'logging is enabled', :request_store do before do allow(Feature).to receive(:log_feature_flag_states?).and_call_original + + definition = Feature::Definition.new("development/enabled_feature_flag.yml", + name: :enabled_feature_flag, + type: 'development', + log_state_changes: true, + default_enabled: false) + + allow(Feature::Definition).to receive(:definitions) do + { definition.key => definition } + end + described_class.enable(:feature_flag_state_logs) described_class.enable(:enabled_feature_flag) described_class.enabled?(:enabled_feature_flag) @@ -513,6 +524,82 @@ RSpec.describe Feature, stub_feature_flags: false do end end + describe '.log_feature_flag_states?' do + let(:log_state_changes) { false } + let(:milestone) { "0.0" } + let(:flag_name) { :some_flag } + let(:definition) do + Feature::Definition.new("development/#{flag_name}.yml", + name: flag_name, + type: 'development', + milestone: milestone, + log_state_changes: log_state_changes, + default_enabled: false) + end + + before do + Feature.enable(:feature_flag_state_logs) + Feature.enable(:some_flag) + + allow(Feature).to receive(:log_feature_flag_states?).and_return(false) + allow(Feature).to receive(:log_feature_flag_states?).with(:feature_flag_state_logs).and_call_original + allow(Feature).to receive(:log_feature_flag_states?).with(:some_flag).and_call_original + + allow(Feature::Definition).to receive(:definitions) do + { definition.key => definition } + end + end + + subject { described_class.log_feature_flag_states?(flag_name) } + + context 'when flag is feature_flag_state_logs' do + let(:milestone) { "14.6" } + let(:flag_name) { :feature_flag_state_logs } + let(:log_state_changes) { true } + + it { is_expected.to be_falsey } + end + + context 'when flag is old' do + it { is_expected.to be_falsey } + end + + context 'when flag is old while log_state_changes is not present ' do + let(:definition) do + Feature::Definition.new("development/#{flag_name}.yml", + name: flag_name, + type: 'development', + milestone: milestone, + default_enabled: false) + end + + it { is_expected.to be_falsey } + end + + context 'when flag is old but log_state_changes is true' do + let(:log_state_changes) { true } + + it { is_expected.to be_truthy } + end + + context 'when flag is new and not feature_flag_state_logs' do + let(:milestone) { "14.6" } + + it { is_expected.to be_truthy } + end + + context 'when milestone is nil' do + let(:definition) do + Feature::Definition.new("development/#{flag_name}.yml", + name: flag_name, + type: 'development', + default_enabled: false) + end + + it { is_expected.to be_falsey } + end + end + context 'caching with stale reads from the database', :use_clean_rails_redis_caching, :request_store, :aggregate_failures do let(:actor) { stub_feature_flag_gate('CustomActor:5') } let(:another_actor) { stub_feature_flag_gate('CustomActor:10') } diff --git a/spec/lib/gitlab/lograge/custom_options_spec.rb b/spec/lib/gitlab/lograge/custom_options_spec.rb index 5c9cd86ce7d..d8f351bb8a3 100644 --- a/spec/lib/gitlab/lograge/custom_options_spec.rb +++ b/spec/lib/gitlab/lograge/custom_options_spec.rb @@ -98,15 +98,23 @@ RSpec.describe Gitlab::Lograge::CustomOptions do context 'when feature flags are present', :request_store do before do - allow(Feature::Definition).to receive(:valid_usage!).and_return(true) - allow(Feature).to receive(:log_feature_flag_states?).and_return(false) + definitions = {} + [:enabled_feature, :disabled_feature].each do |flag_name| + definitions[flag_name] = Feature::Definition.new("development/enabled_feature.yml", + name: flag_name, + type: 'development', + log_state_changes: true, + default_enabled: false) + + allow(Feature).to receive(:log_feature_flag_states?).with(flag_name).and_call_original + end + + allow(Feature::Definition).to receive(:definitions).and_return(definitions) + Feature.enable(:enabled_feature) Feature.disable(:disabled_feature) - - allow(Feature).to receive(:log_feature_flag_states?).with(:enabled_feature).and_call_original - allow(Feature).to receive(:log_feature_flag_states?).with(:disabled_feature).and_call_original end context 'and :feature_flag_log_states is enabled' do diff --git a/spec/models/merge_request/metrics_spec.rb b/spec/models/merge_request/metrics_spec.rb index 13ff239a306..a4bdac39074 100644 --- a/spec/models/merge_request/metrics_spec.rb +++ b/spec/models/merge_request/metrics_spec.rb @@ -48,4 +48,10 @@ RSpec.describe MergeRequest::Metrics do end end end + + it_behaves_like 'cleanup by a loose foreign key' do + let!(:merge_request) { create(:merge_request) } + let!(:parent) { create(:ci_pipeline, project: merge_request.target_project) } + let!(:model) { merge_request.metrics.tap { |metrics| metrics.update!(pipeline: parent) } } + end end diff --git a/spec/models/terraform/state_version_spec.rb b/spec/models/terraform/state_version_spec.rb index ac2e8d167b3..7af9b7897ff 100644 --- a/spec/models/terraform/state_version_spec.rb +++ b/spec/models/terraform/state_version_spec.rb @@ -92,4 +92,9 @@ RSpec.describe Terraform::StateVersion do end end end + + it_behaves_like 'cleanup by a loose foreign key' do + let!(:model) { create(:terraform_state_version) } + let!(:parent) { model.build } + end end diff --git a/spec/support/helpers/snowplow_helpers.rb b/spec/support/helpers/snowplow_helpers.rb index 553739b5d30..c8b194919ed 100644 --- a/spec/support/helpers/snowplow_helpers.rb +++ b/spec/support/helpers/snowplow_helpers.rb @@ -48,11 +48,15 @@ module SnowplowHelpers # ) def expect_snowplow_event(category:, action:, context: nil, **kwargs) if context - kwargs[:context] = [] - context.each do |c| - expect(SnowplowTracker::SelfDescribingJson).to have_received(:new) - .with(c[:schema], c[:data]).at_least(:once) - kwargs[:context] << an_instance_of(SnowplowTracker::SelfDescribingJson) + if context.is_a?(Array) + kwargs[:context] = [] + context.each do |c| + expect(SnowplowTracker::SelfDescribingJson).to have_received(:new) + .with(c[:schema], c[:data]).at_least(:once) + kwargs[:context] << an_instance_of(SnowplowTracker::SelfDescribingJson) + end + else + kwargs[:context] = context end end diff --git a/spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb b/spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb index 8c98254e134..8f3a93de509 100644 --- a/spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb +++ b/spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb @@ -47,3 +47,28 @@ RSpec.shared_examples 'it has loose foreign keys' do expect(deleted_records.status_processed.count).to be(1) end end + +RSpec.shared_examples 'cleanup by a loose foreign key' do + let(:foreign_key_definition) do + foreign_keys_for_parent = Gitlab::Database::LooseForeignKeys.definitions_by_table[parent.class.table_name] + foreign_keys_for_parent.find { |definition| definition.from_table == model.class.table_name } + end + + def find_model + model.class.find_by(id: model.id) + end + + it 'deletes the model' do + parent.delete + + expect(find_model).to be_present + + LooseForeignKeys::ProcessDeletedRecordsService.new(connection: model.connection).execute + + if foreign_key_definition.on_delete.eql?(:async_delete) + expect(find_model).not_to be_present + else + expect(find_model[foreign_key_definition.column]).to eq(nil) + end + end +end |