Commit e71c8a14 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents e897c593 de6fba24
...@@ -18,20 +18,6 @@ Capybara/CurrentPathExpectation: ...@@ -18,20 +18,6 @@ Capybara/CurrentPathExpectation:
Layout/ArgumentAlignment: Layout/ArgumentAlignment:
Enabled: false Enabled: false
# Offense count: 72
# Cop supports --auto-correct.
Layout/EmptyLinesAroundArguments:
Exclude:
- 'app/models/concerns/discussion_on_diff.rb'
- 'app/models/concerns/resolvable_discussion.rb'
- 'app/models/diff_discussion.rb'
- 'app/models/discussion.rb'
- 'ee/spec/models/geo/project_registry_spec.rb'
- 'lib/banzai/pipeline/broadcast_message_pipeline.rb'
- 'lib/banzai/pipeline/gfm_pipeline.rb'
- 'lib/banzai/pipeline/single_line_pipeline.rb'
- 'spec/features/markdown/copy_as_gfm_spec.rb'
# Offense count: 413 # Offense count: 413
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth. # Configuration parameters: EnforcedStyle, IndentationWidth.
...@@ -101,14 +87,6 @@ Layout/SpaceInsideParens: ...@@ -101,14 +87,6 @@ Layout/SpaceInsideParens:
Lint/MissingCopEnableDirective: Lint/MissingCopEnableDirective:
Enabled: false Enabled: false
# Offense count: 11
# Cop supports --auto-correct.
Lint/NonDeterministicRequireOrder:
Exclude:
- 'ee/spec/spec_helper.rb'
- 'qa/spec/spec_helper.rb'
- 'spec/spec_helper.rb'
# Offense count: 27 # Offense count: 27
# Cop supports --auto-correct. # Cop supports --auto-correct.
Lint/RedundantCopDisableDirective: Lint/RedundantCopDisableDirective:
...@@ -229,15 +207,6 @@ RSpec/ExpectChange: ...@@ -229,15 +207,6 @@ RSpec/ExpectChange:
RSpec/ExpectInHook: RSpec/ExpectInHook:
Enabled: false Enabled: false
# Offense count: 9
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: it_behaves_like, it_should_behave_like
RSpec/ItBehavesLike:
Exclude:
- 'spec/lib/gitlab/git/commit_spec.rb'
- 'spec/services/notification_service_spec.rb'
# Offense count: 68 # Offense count: 68
# Cop supports --auto-correct. # Cop supports --auto-correct.
RSpec/LetBeforeExamples: RSpec/LetBeforeExamples:
...@@ -600,17 +569,6 @@ Style/EmptyLambdaParameter: ...@@ -600,17 +569,6 @@ Style/EmptyLambdaParameter:
- 'app/models/ci/build.rb' - 'app/models/ci/build.rb'
- 'app/models/ci/runner.rb' - 'app/models/ci/runner.rb'
# Offense count: 7
# Cop supports --auto-correct.
Style/EmptyLiteral:
Exclude:
- 'lib/gitlab/fogbugz_import/importer.rb'
- 'lib/gitlab/git/diff_collection.rb'
- 'lib/gitlab/gitaly_client.rb'
- 'spec/helpers/merge_requests_helper_spec.rb'
- 'spec/lib/gitlab/workhorse_spec.rb'
- 'spec/requests/api/jobs_spec.rb'
# Offense count: 170 # Offense count: 170
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle. # Configuration parameters: EnforcedStyle.
......
...@@ -13,14 +13,12 @@ module DiscussionOnDiff ...@@ -13,14 +13,12 @@ module DiscussionOnDiff
:diff_line, :diff_line,
:active?, :active?,
:created_at_diff?, :created_at_diff?,
to: :first_note to: :first_note
delegate :file_path, delegate :file_path,
:blob, :blob,
:highlighted_diff_lines, :highlighted_diff_lines,
:diff_lines, :diff_lines,
to: :diff_file, to: :diff_file,
allow_nil: true allow_nil: true
end end
......
...@@ -31,7 +31,6 @@ module ResolvableDiscussion ...@@ -31,7 +31,6 @@ module ResolvableDiscussion
delegate :resolved_at, delegate :resolved_at,
:resolved_by, :resolved_by,
:resolved_by_push?, :resolved_by_push?,
to: :last_resolved_note, to: :last_resolved_note,
allow_nil: true allow_nil: true
end end
......
...@@ -16,7 +16,6 @@ class DiffDiscussion < Discussion ...@@ -16,7 +16,6 @@ class DiffDiscussion < Discussion
:diff_note_positions, :diff_note_positions,
:on_text?, :on_text?,
:on_image?, :on_image?,
to: :first_note to: :first_note
def legacy_diff_discussion? def legacy_diff_discussion?
......
...@@ -24,7 +24,6 @@ class Discussion ...@@ -24,7 +24,6 @@ class Discussion
:system_note_with_references_visible_for?, :system_note_with_references_visible_for?,
:resource_parent, :resource_parent,
:save, :save,
to: :first_note to: :first_note
def declarative_policy_delegate def declarative_policy_delegate
......
---
title: Fix Layout/EmptyLinesAroundArguments cop
merge_request: 41086
author: Rajendra Kadam
type: fixed
---
title: Fix Style/EmptyLiteral cop
merge_request: 41110
author: Rajendra Kadam
type: fixed
---
title: Fix RSpec/ItBehavesLike cop
merge_request: 41111
author: Rajendra Kadam
type: fixed
---
title: Fix Lint/NonDeterministicRequireOrder cop
merge_request: 41098
author: Rajendra Kadam
type: fixed
...@@ -12,11 +12,12 @@ module EE ...@@ -12,11 +12,12 @@ module EE
def track_advanced_search def track_advanced_search
# track unique users of advanced global search # track unique users of advanced global search
track_unique_redis_hll_event("i_search_advanced", :search_track_unique_users) if search_service.use_elasticsearch? track_unique_redis_hll_event('i_search_advanced', :search_track_unique_users) if search_service.use_elasticsearch?
# track unique users who search against paid groups/projects # track unique paid users (users who already use elasticsearch and users who could use it if they enable elasticsearch integration)
# this line is commented out because of https://gitlab.com/gitlab-org/gitlab/-/issues/243486 # for gitlab.com we check if the search uses elasticsearch
# track_unique_redis_hll_event("i_search_paid", :search_track_unique_users) if (search_service.project || search_service.group)&.feature_available?(:elastic_search) # for self-managed we check if the licensed feature available
track_unique_redis_hll_event('i_search_paid', :search_track_unique_users) if (::Gitlab.com? && search_service.use_elasticsearch?) || (!::Gitlab.com? && License.feature_available?(:elastic_search))
end end
end end
end end
...@@ -5,7 +5,7 @@ module Mutations ...@@ -5,7 +5,7 @@ module Mutations
class AddProject < BaseMutation class AddProject < BaseMutation
graphql_name 'AddProjectToSecurityDashboard' graphql_name 'AddProjectToSecurityDashboard'
authorize :read_vulnerability authorize :developer_access
field :project, Types::ProjectType, field :project, Types::ProjectType,
null: true, null: true,
...@@ -18,10 +18,11 @@ module Mutations ...@@ -18,10 +18,11 @@ module Mutations
def resolve(id:) def resolve(id:)
project = authorized_find!(id: id) project = authorized_find!(id: id)
result = add_project(project) result = add_project(project)
error_message = prepare_error_message(result, project)
{ {
project: result ? project : nil, project: error_message ? nil : project,
errors: result ? [] : ['The project already belongs to your dashboard or you don\'t have permission to perform this action'] errors: [error_message].compact
} }
end end
...@@ -33,9 +34,20 @@ module Mutations ...@@ -33,9 +34,20 @@ module Mutations
def add_project(project) def add_project(project)
Dashboard::Projects::CreateService Dashboard::Projects::CreateService
.new(current_user, current_user.security_dashboard_projects, feature: :security_dashboard) .new(current_user, current_user.security_dashboard_projects, ability: :read_vulnerability)
.execute([project.id]) .execute([project.id])
.then { |result| result.added_project_ids.include?(project.id) } end
def prepare_error_message(result, project)
return if result.added_project_ids.include?(project.id)
if result.duplicate_project_ids.include?(project.id)
_('The project has already been added to your dashboard.')
elsif result.not_licensed_project_ids.include?(project.id)
_('Only projects created under a Gold license are available in Security Dashboards.')
else
_('Project was not found or you do not have permission to add this project to Security Dashboards.')
end
end end
end end
end end
......
...@@ -3,31 +3,58 @@ ...@@ -3,31 +3,58 @@
module Dashboard module Dashboard
module Projects module Projects
class CreateService class CreateService
Result = Struct.new(:added_project_ids, :invalid_project_ids, :duplicate_project_ids) Result = Struct.new(:added_project_ids, :not_found_project_ids, :not_licensed_project_ids, :duplicate_project_ids) do
def invalid_project_ids
not_found_project_ids + not_licensed_project_ids
end
end
def initialize(user, projects_relation, feature:) def initialize(user, projects_relation, feature: nil, ability: nil)
@user = user @user = user
@projects_relation = projects_relation @projects_relation = projects_relation
@feature = feature @feature = feature
@ability = ability
end end
def execute(project_ids) def execute(project_ids)
projects_to_add = load_projects(project_ids) found_projects = find_projects(project_ids)
licensed_projects = select_available_projects(found_projects)
not_found = find_invalid_ids(found_projects, project_ids)
not_licensed = find_invalid_ids(licensed_projects, project_ids) - not_found
invalid = find_invalid_ids(projects_to_add, project_ids) added, duplicate = add_projects(licensed_projects)
added, duplicate = add_projects(projects_to_add)
Result.new(added.map(&:id), invalid, duplicate.map(&:id)) Result.new(added.map(&:id), not_found, not_licensed, duplicate.map(&:id))
end end
private private
attr_reader :feature, attr_reader :feature,
:ability,
:projects_relation, :projects_relation,
:user :user
def load_projects(project_ids) def find_projects(project_ids)
Dashboard::Projects::ListService.new(user, feature: feature).execute(project_ids) ProjectsFinder.new(
current_user: user,
project_ids_relation: project_ids,
params: projects_finder_params
).execute
end
def projects_finder_params
return {} if user.can?(:read_all_resources)
{
min_access_level: ProjectMember::DEVELOPER
}
end
def select_available_projects(projects)
projects
.select { |project| feature.blank? || project.feature_available?(feature) }
.select { |project| ability.blank? || user.can?(ability, project) }
end end
def find_invalid_ids(projects_to_add, project_ids) def find_invalid_ids(projects_to_add, project_ids)
......
...@@ -26,19 +26,26 @@ module Epics ...@@ -26,19 +26,26 @@ module Epics
def set_new_parent def set_new_parent
return unless new_parent && new_parent_different? return unless new_parent && new_parent_different?
moving_object.parent = new_parent service = create_issuable_links(new_parent)
validate_new_parent return unless service[:status] == :error
service[:message]
end end
def new_parent_different? def new_parent_different?
params[:new_parent_id] != GitlabSchema.id_from_object(moving_object.parent) params[:new_parent_id] != GitlabSchema.id_from_object(moving_object.parent)
end end
def validate_new_parent def create_issuable_links(parent)
return unless moving_object.respond_to?(:valid_parent?) service, issuable = if moving_object.is_a?(Epic)
return if moving_object.valid_parent? [EpicLinks::CreateService, moving_object]
elsif moving_object.is_a?(EpicIssue)
[EpicIssues::CreateService, moving_object.issue]
end
return unless service.present?
moving_object.errors[:parent]&.first service.new(parent, current_user, { target_issuable: issuable }).execute
end end
def move! def move!
...@@ -110,6 +117,10 @@ module Epics ...@@ -110,6 +117,10 @@ module Epics
if new_parent if new_parent
return false unless can?(current_user, :admin_epic, new_parent.group) return false unless can?(current_user, :admin_epic, new_parent.group)
return false unless moving_object.parent && can?(current_user, :admin_epic, moving_object.parent.group) return false unless moving_object.parent && can?(current_user, :admin_epic, moving_object.parent.group)
if moving_object.is_a?(Epic)
return false unless can?(current_user, :admin_epic_link, moving_object.parent.group)
end
end end
true true
......
---
title: Update epic inherited dates and create notes when reordering in epic tree
merge_request: 39742
author:
type: fixed
---
title: Enhance error messages for Add Project to Security Dashboard mutation
merge_request: 40607
author:
type: changed
...@@ -30,25 +30,56 @@ RSpec.describe SearchController do ...@@ -30,25 +30,56 @@ RSpec.describe SearchController do
end end
end end
# i_search_paid is commented out because of https://gitlab.com/gitlab-org/gitlab/-/issues/243486 context 'i_search_paid' do
# context 'i_search_paid' do let_it_be(:group) { create(:group) }
# let(:group) { create(:group) }
# let(:request_params) { { group_id: group.id, scope: 'blobs', search: 'term' } }
# let(:target_id) { 'i_search_paid' }
# before do let(:request_params) { { group_id: group.id, scope: 'blobs', search: 'term' } }
# allow(group).to receive(:feature_available?).with(:elastic_search).and_return(true) let(:target_id) { 'i_search_paid' }
# end
# it_behaves_like 'tracking unique hll events', :show context 'on Gitlab.com' do
before do
allow(::Gitlab).to receive(:com?).and_return(true)
stub_ee_application_setting(elasticsearch_search: true, elasticsearch_indexing: true)
end
# it 'does not track if feature flag is disabled' do it_behaves_like 'tracking unique hll events', :show
# stub_feature_flags(search_track_unique_users: false)
# expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event).with(instance_of(String), target_id)
# get :show, params: request_params, format: :html it 'does not track if feature flag is disabled' do
# end stub_feature_flags(search_track_unique_users: false)
# end expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event).with(instance_of(String), target_id)
get :show, params: request_params, format: :html
end
end
context 'self-managed instance' do
before do
allow(::Gitlab).to receive(:com?).and_return(false)
end
context 'license is available' do
before do
stub_licensed_features(elastic_search: true)
end
it_behaves_like 'tracking unique hll events', :show
it 'does not track if feature flag is disabled' do
stub_feature_flags(search_track_unique_users: false)
expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event).with(instance_of(String), target_id)
get :show, params: request_params, format: :html
end
end
it 'does not track if there is no license available' do
stub_licensed_features(elastic_search: false)
expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event).with(instance_of(String), target_id)
get :show, params: request_params, format: :html
end
end
end
end end
end end
end end
...@@ -37,6 +37,18 @@ RSpec.describe Mutations::InstanceSecurityDashboard::AddProject do ...@@ -37,6 +37,18 @@ RSpec.describe Mutations::InstanceSecurityDashboard::AddProject do
end end
end end
context 'when security_dashboard is disabled for my project' do
context 'when project is not licensed to be added to the security dashboard' do
let(:selected_project) { my_project }
it 'does not add project to the security dashboard', :aggregate_failures do
expect(subject[:project]).to be_nil
expect(subject[:errors]).to include('Only projects created under a Gold license are available in Security Dashboards.')
expect(user.security_dashboard_projects).to include(already_added_project)
end
end
end
context 'when security_dashboard is enabled' do context 'when security_dashboard is enabled' do
before do before do
stub_licensed_features(security_dashboard: true) stub_licensed_features(security_dashboard: true)
...@@ -65,7 +77,7 @@ RSpec.describe Mutations::InstanceSecurityDashboard::AddProject do ...@@ -65,7 +77,7 @@ RSpec.describe Mutations::InstanceSecurityDashboard::AddProject do
it 'does not add project to the security dashboard', :aggregate_failures do it 'does not add project to the security dashboard', :aggregate_failures do
expect(subject[:project]).to be_nil expect(subject[:project]).to be_nil
expect(subject[:errors]).to eq(['The project already belongs to your dashboard or you don\'t have permission to perform this action']) expect(subject[:errors]).to include('The project has already been added to your dashboard.')
expect(user.security_dashboard_projects).to include(already_added_project) expect(user.security_dashboard_projects).to include(already_added_project)
end end
end end
......
...@@ -361,7 +361,6 @@ RSpec.describe Geo::ProjectRegistry, :geo do ...@@ -361,7 +361,6 @@ RSpec.describe Geo::ProjectRegistry, :geo do
repository_verification_retry_count: nil, repository_verification_retry_count: nil,
repository_retry_count: nil, repository_retry_count: nil,
repository_retry_at: nil repository_retry_at: nil
) )
end end
end end
...@@ -1182,7 +1181,6 @@ RSpec.describe Geo::ProjectRegistry, :geo do ...@@ -1182,7 +1181,6 @@ RSpec.describe Geo::ProjectRegistry, :geo do
repository_verification_retry_count: nil, repository_verification_retry_count: nil,
repository_retry_count: nil, repository_retry_count: nil,
repository_retry_at: nil repository_retry_at: nil
) )
end end
end end
......
...@@ -49,9 +49,9 @@ RSpec.describe 'Updating an epic tree' do ...@@ -49,9 +49,9 @@ RSpec.describe 'Updating an epic tree' do
end end
end end
context 'when epic feature is enabled' do context 'when epics and subepics features are enabled' do
before do before do
stub_licensed_features(epics: true) stub_licensed_features(epics: true, subepics: true)
end end
context 'when the user does not have permission' do context 'when the user does not have permission' do
...@@ -141,6 +141,24 @@ RSpec.describe 'Updating an epic tree' do ...@@ -141,6 +141,24 @@ RSpec.describe 'Updating an epic tree' do
expect(mutation_response['errors']).to eq(["The sibling object's parent must match the current parent epic."]) expect(mutation_response['errors']).to eq(["The sibling object's parent must match the current parent epic."])
end end
end end
context 'when the new parent is another epic and subepics feature is disabled' do
let(:new_parent_id) { GitlabSchema.id_from_object(base_epic).to_s }
before do
stub_licensed_features(epics: true, subepics: false)
other_epic = create(:epic, group: group)
epic2.update(parent: other_epic)
end
it_behaves_like 'a mutation that does not update the tree'
it 'returns the error message' do
post_graphql_mutation(mutation, current_user: current_user)
expect(mutation_response['errors']).to eq(['You don\'t have permissions to move the objects.'])
end
end
end end
context 'when moving an issue' do context 'when moving an issue' do
......
...@@ -4,18 +4,24 @@ require 'spec_helper' ...@@ -4,18 +4,24 @@ require 'spec_helper'
RSpec.describe Dashboard::Projects::CreateService do RSpec.describe Dashboard::Projects::CreateService do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:service) { described_class.new(user, user.ops_dashboard_projects, feature: :operations_dashboard) } let(:service) { described_class.new(user, user.ops_dashboard_projects, feature: feature, ability: ability) }
let(:feature) { :operations_dashboard }
let(:ability) { nil }
let(:project) { create(:project) } let(:project) { create(:project) }
describe '#execute' do describe '#execute' do
let(:projects_service) { double(Dashboard::Projects::ListService) } let(:projects_finder) { double(ProjectsFinder) }
let(:result) { service.execute(input) } let(:result) { service.execute(input) }
let(:feature_available) { true }
let(:permission_available) { false }
before do before do
allow(Dashboard::Projects::ListService) allow(ProjectsFinder)
.to receive(:new).with(user, feature: :operations_dashboard).and_return(projects_service) .to receive(:new).with(current_user: user, project_ids_relation: input, params: { min_access_level: ProjectMember::DEVELOPER }).and_return(projects_finder)
allow(projects_service) allow(projects_finder)
.to receive(:execute).with(input).and_return(output) .to receive(:execute).and_return(output)
allow(project).to receive(:feature_available?).and_return(feature_available)
allow(user).to receive(:can?).and_return(permission_available)
end end
context 'with projects' do context 'with projects' do
...@@ -37,6 +43,60 @@ RSpec.describe Dashboard::Projects::CreateService do ...@@ -37,6 +43,60 @@ RSpec.describe Dashboard::Projects::CreateService do
end end
end end
context 'with a project that does not exist' do
let(:input) { [non_existing_record_id] }
let(:output) { [] }
it 'does not add a not found project' do
expect(result).to eq(expected_result(not_found_project_ids: [non_existing_record_id]))
end
end
context 'when feature name is provided' do
context 'with project without provided feature enabled' do
let(:input) { [project.id] }
let(:feature_available) { false }
let(:ability) { nil }
it 'checks if feature is available' do
expect(project).to receive(:feature_available?).and_return(false)
result
end
it 'does not check if user has access to the project with given ability' do
expect(user).not_to receive(:can?).with(ability, project)
result
end
it 'does not add a not licensed project' do
expect(result).to eq(expected_result(not_licensed_project_ids: [project.id]))
end
end
end
context 'when ability name is provided' do
context 'with project for which user has no permission' do
let(:input) { [project.id] }
let(:feature) { nil }
let(:ability) { :read_vulnerability }
let(:permission_available) { false }
it 'does not check if feature is available' do
expect(project).not_to receive(:feature_available?)
result
end
it 'checks if user has access to the project with given ability' do
expect(user).to receive(:can?).with(ability, project).and_return(false)
result
end
it 'does not add a not licensed project' do
expect(result).to eq(expected_result(not_licensed_project_ids: [project.id]))
end
end
end
context 'with repeating project id' do context 'with repeating project id' do
let(:input) { [project.id, project.id] } let(:input) { [project.id, project.id] }
...@@ -63,11 +123,12 @@ RSpec.describe Dashboard::Projects::CreateService do ...@@ -63,11 +123,12 @@ RSpec.describe Dashboard::Projects::CreateService do
def expected_result( def expected_result(
added_project_ids: [], added_project_ids: [],
invalid_project_ids: [], not_found_project_ids: [],
not_licensed_project_ids: [],
duplicate_project_ids: [] duplicate_project_ids: []
) )
described_class::Result.new( described_class::Result.new(
added_project_ids, invalid_project_ids, duplicate_project_ids added_project_ids, not_found_project_ids, not_licensed_project_ids, duplicate_project_ids
) )
end end
end end
...@@ -66,7 +66,7 @@ RSpec.describe Epics::TreeReorderService do ...@@ -66,7 +66,7 @@ RSpec.describe Epics::TreeReorderService do
context 'when user does have permission to admin the base epic' do context 'when user does have permission to admin the base epic' do
before do before do
group.add_developer(user) group.add_reporter(user)
end end
context 'when relative_position is not valid' do context 'when relative_position is not valid' do
...@@ -102,6 +102,10 @@ RSpec.describe Epics::TreeReorderService do ...@@ -102,6 +102,10 @@ RSpec.describe Epics::TreeReorderService do
it 'updates the parent' do it 'updates the parent' do
expect { subject }.to change { tree_object_2.reload.epic }.from(epic1).to(epic) expect { subject }.to change { tree_object_2.reload.epic }.from(epic1).to(epic)
end end
it 'creates system notes' do
expect { subject }.to change { Note.system.count }.by(3)
end
end end
context 'when object being moved is from another epic' do context 'when object being moved is from another epic' do
...@@ -207,6 +211,10 @@ RSpec.describe Epics::TreeReorderService do ...@@ -207,6 +211,10 @@ RSpec.describe Epics::TreeReorderService do
expect(tree_object_1.reload.relative_position).to be > tree_object_2.reload.relative_position expect(tree_object_1.reload.relative_position).to be > tree_object_2.reload.relative_position
end end
it 'creates system notes' do
expect { subject }.to change { Note.system.count }.by(3)
end
end end
end end
end end
...@@ -215,86 +223,118 @@ RSpec.describe Epics::TreeReorderService do ...@@ -215,86 +223,118 @@ RSpec.describe Epics::TreeReorderService do
let!(:tree_object_1) { epic1 } let!(:tree_object_1) { epic1 }
let!(:tree_object_2) { epic2 } let!(:tree_object_2) { epic2 }
context 'when user does not have permissions to admin the previous parent' do context 'when subepics feature is disabled' do
let(:other_group) { create(:group) }
let(:other_epic) { create(:epic, group: other_group) }
let(:new_parent_id) { GitlabSchema.id_from_object(epic) } let(:new_parent_id) { GitlabSchema.id_from_object(epic) }
before do before do
epic2.update(parent: other_epic) stub_licensed_features(epics: true, subepics: false)
end end
it_behaves_like 'error for the tree update', 'You don\'t have permissions to move the objects.' it_behaves_like 'error for the tree update', 'You don\'t have permissions to move the objects.'
end end
context 'when there is some other error with the new parent' do context 'when subepics feature is enabled' do
let(:other_group) { create(:group) }
let(:new_parent_id) { GitlabSchema.id_from_object(epic) }
before do before do
other_group.add_developer(user) stub_licensed_features(epics: true, subepics: true)
epic.update(group: other_group)
epic2.update(parent: epic1)
end end
it_behaves_like 'error for the tree update', "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic." context 'when user does not have permissions to admin the previous parent' do
end let(:other_group) { create(:group) }
let(:other_epic) { create(:epic, group: other_group) }
let(:new_parent_id) { GitlabSchema.id_from_object(epic) }
context 'when user does not have permissions to admin the new parent' do before do
let(:other_group) { create(:group) } epic2.update(parent: other_epic)
let(:other_epic) { create(:epic, group: other_group) } end
let(:new_parent_id) { GitlabSchema.id_from_object(other_epic) }
it_behaves_like 'error for the tree update', 'You don\'t have permissions to move the objects.' it_behaves_like 'error for the tree update', 'You don\'t have permissions to move the objects.'
end end
context 'when the reordered epics are not subepics of the base epic' do context 'when user does not have permissions to admin the previous parent links' do
let(:another_group) { create(:group) } let(:new_parent_id) { GitlabSchema.id_from_object(epic) }
let(:another_epic) { create(:epic, group: another_group) }
before do before do
epic1.update(group: another_group, parent: another_epic) group.add_guest(user)
epic2.update(group: another_group, parent: another_epic) end
it_behaves_like 'error for the tree update', 'You don\'t have permissions to move the objects.'
end end
it_behaves_like 'error for the tree update', 'You don\'t have permissions to move the objects.' context 'when there is some other error with the new parent' do
end let(:other_group) { create(:group) }
let(:new_parent_id) { GitlabSchema.id_from_object(epic) }
context 'when moving is successful' do before do
it 'updates the links relative positions' do other_group.add_developer(user)
subject epic.update(group: other_group)
epic2.update(parent: epic1)
end
expect(tree_object_1.reload.relative_position).to be > tree_object_2.reload.relative_position it_behaves_like 'error for the tree update', "This epic cannot be added. An epic must belong to the same group or subgroup as its parent epic."
end end
context 'when new parent is current epic' do context 'when user does not have permissions to admin the new parent' do
let(:new_parent_id) { GitlabSchema.id_from_object(epic) } let(:other_group) { create(:group) }
let(:other_epic) { create(:epic, group: other_group) }
let(:new_parent_id) { GitlabSchema.id_from_object(other_epic) }
it 'updates the relative positions' do it_behaves_like 'error for the tree update', 'You don\'t have permissions to move the objects.'
subject end
expect(tree_object_1.reload.relative_position).to be > tree_object_2.reload.relative_position context 'when user '
end
it 'does not update the parent_id' do context 'when the reordered epics are not subepics of the base epic' do
expect { subject }.not_to change { tree_object_2.reload.parent } let(:another_group) { create(:group) }
let(:another_epic) { create(:epic, group: another_group) }
before do
epic1.update(group: another_group, parent: another_epic)
epic2.update(group: another_group, parent: another_epic)
end end
end
context 'when object being moved is from another epic and new_parent_id matches parent of adjacent object' do it_behaves_like 'error for the tree update', 'You don\'t have permissions to move the objects.'
let(:other_epic) { create(:epic, group: group) } end
let(:new_parent_id) { GitlabSchema.id_from_object(epic) }
let(:epic3) { create(:epic, parent: other_epic, group: group) }
let(:tree_object_2) { epic3 }
it 'updates the relative positions and parent_id' do context 'when moving is successful' do
it 'updates the links relative positions' do
subject subject
expect(tree_object_1.reload.relative_position).to be > tree_object_2.reload.relative_position expect(tree_object_1.reload.relative_position).to be > tree_object_2.reload.relative_position
end end
it 'updates the parent' do context 'when new parent is current epic' do
expect { subject }.to change { tree_object_2.reload.parent }.from(other_epic).to(epic) let(:new_parent_id) { GitlabSchema.id_from_object(epic) }
it 'updates the relative positions' do
subject
expect(tree_object_1.reload.relative_position).to be > tree_object_2.reload.relative_position
end
it 'does not update the parent_id' do
expect { subject }.not_to change { tree_object_2.reload.parent }
end
end
context 'when object being moved is from another epic and new_parent_id matches parent of adjacent object' do
let(:other_epic) { create(:epic, group: group) }
let(:new_parent_id) { GitlabSchema.id_from_object(epic) }
let(:epic3) { create(:epic, parent: other_epic, group: group) }
let(:tree_object_2) { epic3 }
it 'updates the relative positions' do
subject
expect(tree_object_1.reload.relative_position).to be > tree_object_2.reload.relative_position
end
it 'updates the parent' do
expect { subject }.to change { tree_object_2.reload.parent }.from(other_epic).to(epic)
end
it 'creates system notes' do
expect { subject }.to change { Note.system.count }.by(2)
end
end end
end end
end end
......
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
require Rails.root.join("spec/support/helpers/stub_requests.rb") require Rails.root.join("spec/support/helpers/stub_requests.rb")
Dir[Rails.root.join("ee/spec/support/helpers/*.rb")].each { |f| require f } Dir[Rails.root.join("ee/spec/support/helpers/*.rb")].sort.each { |f| require f }
Dir[Rails.root.join("ee/spec/support/shared_contexts/*.rb")].each { |f| require f } Dir[Rails.root.join("ee/spec/support/shared_contexts/*.rb")].sort.each { |f| require f }
Dir[Rails.root.join("ee/spec/support/shared_examples/*.rb")].each { |f| require f } Dir[Rails.root.join("ee/spec/support/shared_examples/*.rb")].sort.each { |f| require f }
Dir[Rails.root.join("ee/spec/support/**/*.rb")].each { |f| require f } Dir[Rails.root.join("ee/spec/support/**/*.rb")].sort.each { |f| require f }
RSpec.configure do |config| RSpec.configure do |config|
config.include EE::LicenseHelpers config.include EE::LicenseHelpers
......
...@@ -7,7 +7,6 @@ module Banzai ...@@ -7,7 +7,6 @@ module Banzai
@filters ||= FilterArray[ @filters ||= FilterArray[
Filter::MarkdownFilter, Filter::MarkdownFilter,
Filter::BroadcastMessageSanitizationFilter, Filter::BroadcastMessageSanitizationFilter,
Filter::EmojiFilter, Filter::EmojiFilter,
Filter::ColorFilter, Filter::ColorFilter,
Filter::AutolinkFilter, Filter::AutolinkFilter,
......
...@@ -12,14 +12,11 @@ module Banzai ...@@ -12,14 +12,11 @@ module Banzai
def self.filters def self.filters
@filters ||= FilterArray[ @filters ||= FilterArray[
Filter::PlantumlFilter, Filter::PlantumlFilter,
# Must always be before the SanitizationFilter to prevent XSS attacks # Must always be before the SanitizationFilter to prevent XSS attacks
Filter::SpacedLinkFilter, Filter::SpacedLinkFilter,
Filter::SanitizationFilter, Filter::SanitizationFilter,
Filter::AssetProxyFilter, Filter::AssetProxyFilter,
Filter::SyntaxHighlightFilter, Filter::SyntaxHighlightFilter,
Filter::MathFilter, Filter::MathFilter,
Filter::ColorFilter, Filter::ColorFilter,
Filter::MermaidFilter, Filter::MermaidFilter,
...@@ -34,13 +31,10 @@ module Banzai ...@@ -34,13 +31,10 @@ module Banzai
Filter::ExternalLinkFilter, Filter::ExternalLinkFilter,
Filter::SuggestionFilter, Filter::SuggestionFilter,
Filter::FootnoteFilter, Filter::FootnoteFilter,
*reference_filters, *reference_filters,
Filter::EmojiFilter, Filter::EmojiFilter,
Filter::TaskListFilter, Filter::TaskListFilter,
Filter::InlineDiffFilter, Filter::InlineDiffFilter,
Filter::SetDirectionFilter Filter::SetDirectionFilter
] ]
end end
......
...@@ -8,11 +8,9 @@ module Banzai ...@@ -8,11 +8,9 @@ module Banzai
Filter::HtmlEntityFilter, Filter::HtmlEntityFilter,
Filter::SanitizationFilter, Filter::SanitizationFilter,
Filter::AssetProxyFilter, Filter::AssetProxyFilter,
Filter::EmojiFilter, Filter::EmojiFilter,
Filter::AutolinkFilter, Filter::AutolinkFilter,
Filter::ExternalLinkFilter, Filter::ExternalLinkFilter,
*reference_filters *reference_filters
] ]
end end
......
...@@ -39,7 +39,7 @@ module Gitlab ...@@ -39,7 +39,7 @@ module Gitlab
def user_map def user_map
@user_map ||= begin @user_map ||= begin
user_map = Hash.new user_map = {}
import_data = project.import_data.try(:data) import_data = project.import_data.try(:data)
stored_user_map = import_data['user_map'] if import_data stored_user_map = import_data['user_map'] if import_data
user_map.update(stored_user_map) if stored_user_map user_map.update(stored_user_map) if stored_user_map
......
...@@ -37,7 +37,7 @@ module Gitlab ...@@ -37,7 +37,7 @@ module Gitlab
@byte_count = 0 @byte_count = 0
@overflow = false @overflow = false
@empty = true @empty = true
@array = Array.new @array = []
end end
def each(&block) def each(&block)
......
...@@ -450,7 +450,7 @@ module Gitlab ...@@ -450,7 +450,7 @@ module Gitlab
stack_string = Gitlab::BacktraceCleaner.clean_backtrace(caller).drop(1).join("\n") stack_string = Gitlab::BacktraceCleaner.clean_backtrace(caller).drop(1).join("\n")
Gitlab::SafeRequestStore[:stack_counter] ||= Hash.new Gitlab::SafeRequestStore[:stack_counter] ||= {}
count = Gitlab::SafeRequestStore[:stack_counter][stack_string] || 0 count = Gitlab::SafeRequestStore[:stack_counter][stack_string] || 0
Gitlab::SafeRequestStore[:stack_counter][stack_string] = count + 1 Gitlab::SafeRequestStore[:stack_counter][stack_string] = count + 1
......
...@@ -17215,6 +17215,9 @@ msgstr "" ...@@ -17215,6 +17215,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped." msgid "Only project members will be imported. Group members will be skipped."
msgstr "" msgstr ""
msgid "Only projects created under a Gold license are available in Security Dashboards."
msgstr ""
msgid "Only verified users with an email address in any of these domains can be added to the group." msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr "" msgstr ""
...@@ -19138,6 +19141,9 @@ msgstr "" ...@@ -19138,6 +19141,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group." msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr "" msgstr ""
msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
msgid "Project: %{name}" msgid "Project: %{name}"
msgstr "" msgstr ""
...@@ -24692,6 +24698,9 @@ msgstr "" ...@@ -24692,6 +24698,9 @@ msgstr ""
msgid "The project can be accessed without any authentication." msgid "The project can be accessed without any authentication."
msgstr "" msgstr ""
msgid "The project has already been added to your dashboard."
msgstr ""
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user." msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr "" msgstr ""
......
...@@ -13,9 +13,9 @@ QA::Runtime::Browser.configure! ...@@ -13,9 +13,9 @@ QA::Runtime::Browser.configure!
QA::Runtime::Scenario.from_env(QA::Runtime::Env.runtime_scenario_attributes) if QA::Runtime::Env.runtime_scenario_attributes QA::Runtime::Scenario.from_env(QA::Runtime::Env.runtime_scenario_attributes) if QA::Runtime::Env.runtime_scenario_attributes
Dir[::File.join(__dir__, "support/helpers/*.rb")].each { |f| require f } Dir[::File.join(__dir__, "support/helpers/*.rb")].sort.each { |f| require f }
Dir[::File.join(__dir__, "support/shared_contexts/*.rb")].each { |f| require f } Dir[::File.join(__dir__, "support/shared_contexts/*.rb")].sort.each { |f| require f }
Dir[::File.join(__dir__, "support/shared_examples/*.rb")].each { |f| require f } Dir[::File.join(__dir__, "support/shared_examples/*.rb")].sort.each { |f| require f }
RSpec.configure do |config| RSpec.configure do |config|
QA::Specs::Helpers::Quarantine.configure_rspec QA::Specs::Helpers::Quarantine.configure_rspec
......
...@@ -149,9 +149,15 @@ RSpec.describe SearchController do ...@@ -149,9 +149,15 @@ RSpec.describe SearchController do
expect(assigns[:search_objects].first).to eq note expect(assigns[:search_objects].first).to eq note
end end
it_behaves_like 'tracking unique hll events', :show do context 'unique users tracking' do
let(:request_params) { { scope: 'projects', search: 'term' } } before do
let(:target_id) { 'i_search_total' } allow(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event)
end
it_behaves_like 'tracking unique hll events', :show do
let(:request_params) { { scope: 'projects', search: 'term' } }
let(:target_id) { 'i_search_total' }
end
end end
context 'on restricted projects' do context 'on restricted projects' do
......
...@@ -30,13 +30,11 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -30,13 +30,11 @@ RSpec.describe 'Copy as GFM', :js do
it 'works', :aggregate_failures do it 'works', :aggregate_failures do
verify( verify(
'nesting', 'nesting',
'> 1. [x] **[$`2 + 2`$ {-=-}{+=+} 2^2 ~~:thumbsup:~~](http://google.com)**' '> 1. [x] **[$`2 + 2`$ {-=-}{+=+} 2^2 ~~:thumbsup:~~](http://google.com)**'
) )
verify( verify(
'a real world example from the gitlab-ce README', 'a real world example from the gitlab-ce README',
<<~GFM <<~GFM
# GitLab # GitLab
...@@ -103,19 +101,16 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -103,19 +101,16 @@ RSpec.describe 'Copy as GFM', :js do
verify( verify(
'InlineDiffFilter', 'InlineDiffFilter',
'{-Deleted text-}', '{-Deleted text-}',
'{+Added text+}' '{+Added text+}'
) )
verify( verify(
'TaskListFilter', 'TaskListFilter',
<<~GFM, <<~GFM,
* [ ] Unchecked task * [ ] Unchecked task
* [x] Checked task * [x] Checked task
GFM GFM
<<~GFM <<~GFM
1. [ ] Unchecked ordered task 1. [ ] Unchecked ordered task
1. [x] Checked ordered task 1. [x] Checked ordered task
...@@ -124,7 +119,6 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -124,7 +119,6 @@ RSpec.describe 'Copy as GFM', :js do
verify( verify(
'ReferenceFilter', 'ReferenceFilter',
# issue reference # issue reference
@feat.issue.to_reference, @feat.issue.to_reference,
# full issue reference # full issue reference
...@@ -141,13 +135,11 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -141,13 +135,11 @@ RSpec.describe 'Copy as GFM', :js do
verify( verify(
'AutolinkFilter', 'AutolinkFilter',
'https://example.com' 'https://example.com'
) )
verify( verify(
'TableOfContentsFilter', 'TableOfContentsFilter',
<<~GFM, <<~GFM,
[[_TOC_]] [[_TOC_]]
...@@ -155,64 +147,53 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -155,64 +147,53 @@ RSpec.describe 'Copy as GFM', :js do
## Heading 2 ## Heading 2
GFM GFM
pipeline: :wiki, pipeline: :wiki,
wiki: @project.wiki wiki: @project.wiki
) )
verify( verify(
'EmojiFilter', 'EmojiFilter',
':thumbsup:' ':thumbsup:'
) )
verify( verify(
'ImageLinkFilter', 'ImageLinkFilter',
'![Image](https://example.com/image.png)' '![Image](https://example.com/image.png)'
) )
verify_media_with_partial_path( verify_media_with_partial_path(
'[test.txt](/uploads/a123/image.txt)', '[test.txt](/uploads/a123/image.txt)',
project_media_uri(@project, '/uploads/a123/image.txt') project_media_uri(@project, '/uploads/a123/image.txt')
) )
verify_media_with_partial_path( verify_media_with_partial_path(
'![Image](/uploads/a123/image.png)', '![Image](/uploads/a123/image.png)',
project_media_uri(@project, '/uploads/a123/image.png') project_media_uri(@project, '/uploads/a123/image.png')
) )
verify( verify(
'VideoLinkFilter', 'VideoLinkFilter',
'![Video](https://example.com/video.mp4)' '![Video](https://example.com/video.mp4)'
) )
verify_media_with_partial_path( verify_media_with_partial_path(
'![Video](/uploads/a123/video.mp4)', '![Video](/uploads/a123/video.mp4)',
project_media_uri(@project, '/uploads/a123/video.mp4') project_media_uri(@project, '/uploads/a123/video.mp4')
) )
verify( verify(
'AudioLinkFilter', 'AudioLinkFilter',
'![Audio](https://example.com/audio.wav)' '![Audio](https://example.com/audio.wav)'
) )
verify_media_with_partial_path( verify_media_with_partial_path(
'![Audio](/uploads/a123/audio.wav)', '![Audio](/uploads/a123/audio.wav)',
project_media_uri(@project, '/uploads/a123/audio.wav') project_media_uri(@project, '/uploads/a123/audio.wav')
) )
verify( verify(
'MathFilter: math as converted from GFM to HTML', 'MathFilter: math as converted from GFM to HTML',
'$`c = \pm\sqrt{a^2 + b^2}`$', '$`c = \pm\sqrt{a^2 + b^2}`$',
# math block # math block
<<~GFM <<~GFM
```math ```math
...@@ -334,7 +315,6 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -334,7 +315,6 @@ RSpec.describe 'Copy as GFM', :js do
verify( verify(
'MermaidFilter: mermaid as converted from GFM to HTML', 'MermaidFilter: mermaid as converted from GFM to HTML',
<<~GFM <<~GFM
```mermaid ```mermaid
graph TD; graph TD;
...@@ -429,7 +409,6 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -429,7 +409,6 @@ RSpec.describe 'Copy as GFM', :js do
verify( verify(
'SuggestionFilter: suggestion as converted from GFM to HTML', 'SuggestionFilter: suggestion as converted from GFM to HTML',
<<~GFM <<~GFM
```suggestion ```suggestion
New New
...@@ -491,7 +470,6 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -491,7 +470,6 @@ RSpec.describe 'Copy as GFM', :js do
verify( verify(
'SanitizationFilter', 'SanitizationFilter',
<<~GFM <<~GFM
<sub>sub</sub> <sub>sub</sub>
...@@ -527,13 +505,11 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -527,13 +505,11 @@ RSpec.describe 'Copy as GFM', :js do
verify( verify(
'SanitizationFilter', 'SanitizationFilter',
<<~GFM, <<~GFM,
``` ```
Plain text Plain text
``` ```
GFM GFM
<<~GFM, <<~GFM,
```ruby ```ruby
def foo def foo
...@@ -541,7 +517,6 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -541,7 +517,6 @@ RSpec.describe 'Copy as GFM', :js do
end end
``` ```
GFM GFM
<<~GFM <<~GFM
Foo Foo
...@@ -553,27 +528,19 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -553,27 +528,19 @@ RSpec.describe 'Copy as GFM', :js do
verify( verify(
'MarkdownFilter', 'MarkdownFilter',
"Line with two spaces at the end \nto insert a linebreak", "Line with two spaces at the end \nto insert a linebreak",
'`code`', '`code`',
'`` code with ` ticks ``', '`` code with ` ticks ``',
'> Quote', '> Quote',
# multiline quote # multiline quote
<<~GFM, <<~GFM,
> Multiline Quote > Multiline Quote
> >
> With multiple paragraphs > With multiple paragraphs
GFM GFM
'![Image](https://example.com/image.png)', '![Image](https://example.com/image.png)',
'# Heading with no anchor link', '# Heading with no anchor link',
'[Link](https://example.com)', '[Link](https://example.com)',
<<~GFM, <<~GFM,
* List item * List item
* List item 2 * List item 2
...@@ -598,7 +565,6 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -598,7 +565,6 @@ RSpec.describe 'Copy as GFM', :js do
> Blockquote > Blockquote
GFM GFM
<<~GFM, <<~GFM,
1. Ordered list item 1. Ordered list item
1. Ordered list item 2 1. Ordered list item 2
...@@ -623,22 +589,16 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -623,22 +589,16 @@ RSpec.describe 'Copy as GFM', :js do
--- ---
GFM GFM
'# Heading', '# Heading',
'## Heading', '## Heading',
'### Heading', '### Heading',
'#### Heading', '#### Heading',
'##### Heading', '##### Heading',
'###### Heading', '###### Heading',
'**Bold**', '**Bold**',
'*Italics*', '*Italics*',
'~~Strikethrough~~', '~~Strikethrough~~',
'---', '---',
# table # table
<<~GFM, <<~GFM,
| Centered | Right | Left | | Centered | Right | Left |
...@@ -696,9 +656,7 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -696,9 +656,7 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as inline code' do it 'copies as inline code' do
verify( verify(
'[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"] .line .no', '[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"] .line .no',
'`RuntimeError`', '`RuntimeError`',
target: '[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]' target: '[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'
) )
end end
...@@ -708,9 +666,7 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -708,9 +666,7 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as inline code' do it 'copies as inline code' do
verify( verify(
'[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]', '[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]',
'`raise RuntimeError, "System commands must be given as an array of strings"`', '`raise RuntimeError, "System commands must be given as an array of strings"`',
target: '[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]' target: '[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'
) )
end end
...@@ -720,14 +676,12 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -720,14 +676,12 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as a code block' do it 'copies as a code block' do
verify( verify(
'[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10"]', '[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10"]',
<<~GFM, <<~GFM,
```ruby ```ruby
raise RuntimeError, "System commands must be given as an array of strings" raise RuntimeError, "System commands must be given as an array of strings"
end end
``` ```
GFM GFM
target: '[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]' target: '[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'
) )
end end
...@@ -755,7 +709,6 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -755,7 +709,6 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as a code block' do it 'copies as a code block' do
verify( verify(
'[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_9_9"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10"]', '[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_9_9"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10"]',
<<~GFM, <<~GFM,
```ruby ```ruby
unless cmd.is_a?(Array) unless cmd.is_a?(Array)
...@@ -763,7 +716,6 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -763,7 +716,6 @@ RSpec.describe 'Copy as GFM', :js do
end end
``` ```
GFM GFM
target: '[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8"].left-side' target: '[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8"].left-side'
) )
end end
...@@ -773,7 +725,6 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -773,7 +725,6 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as a code block' do it 'copies as a code block' do
verify( verify(
'[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_9_9"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10"]', '[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_9_9"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10"]',
<<~GFM, <<~GFM,
```ruby ```ruby
unless cmd.is_a?(Array) unless cmd.is_a?(Array)
...@@ -781,7 +732,6 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -781,7 +732,6 @@ RSpec.describe 'Copy as GFM', :js do
end end
``` ```
GFM GFM
target: '[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8"].right-side' target: '[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8"].right-side'
) )
end end
...@@ -799,7 +749,6 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -799,7 +749,6 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as inline code' do it 'copies as inline code' do
verify( verify(
'.line[id="LC9"] .no', '.line[id="LC9"] .no',
'`RuntimeError`' '`RuntimeError`'
) )
end end
...@@ -809,7 +758,6 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -809,7 +758,6 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as inline code' do it 'copies as inline code' do
verify( verify(
'.line[id="LC9"]', '.line[id="LC9"]',
'`raise RuntimeError, "System commands must be given as an array of strings"`' '`raise RuntimeError, "System commands must be given as an array of strings"`'
) )
end end
...@@ -819,7 +767,6 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -819,7 +767,6 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as a code block' do it 'copies as a code block' do
verify( verify(
'.line[id="LC9"], .line[id="LC10"]', '.line[id="LC9"], .line[id="LC10"]',
<<~GFM <<~GFM
```ruby ```ruby
raise RuntimeError, "System commands must be given as an array of strings" raise RuntimeError, "System commands must be given as an array of strings"
...@@ -841,7 +788,6 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -841,7 +788,6 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as inline code' do it 'copies as inline code' do
verify( verify(
'.line[id="LC27"] .nl', '.line[id="LC27"] .nl',
'`"bio"`' '`"bio"`'
) )
end end
...@@ -851,7 +797,6 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -851,7 +797,6 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as inline code' do it 'copies as inline code' do
verify( verify(
'.line[id="LC27"]', '.line[id="LC27"]',
'`"bio": null,`' '`"bio": null,`'
) )
end end
...@@ -861,7 +806,6 @@ RSpec.describe 'Copy as GFM', :js do ...@@ -861,7 +806,6 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as a code block with the correct language' do it 'copies as a code block with the correct language' do
verify( verify(
'.line[id="LC27"], .line[id="LC28"]', '.line[id="LC27"], .line[id="LC28"]',
<<~GFM <<~GFM
```json ```json
"bio": null, "bio": null,
......
...@@ -75,7 +75,7 @@ RSpec.describe MergeRequestsHelper do ...@@ -75,7 +75,7 @@ RSpec.describe MergeRequestsHelper do
describe '#tab_link_for' do describe '#tab_link_for' do
let(:merge_request) { create(:merge_request, :simple) } let(:merge_request) { create(:merge_request, :simple) }
let(:options) { Hash.new } let(:options) { {} }
subject { tab_link_for(merge_request, :show, options) { 'Discussion' } } subject { tab_link_for(merge_request, :show, options) { 'Discussion' } }
......
...@@ -192,7 +192,7 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do ...@@ -192,7 +192,7 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do
end end
describe '.find with Gitaly enabled' do describe '.find with Gitaly enabled' do
it_should_behave_like '.find' it_behaves_like '.find'
end end
describe '.find with Rugged enabled', :enable_rugged do describe '.find with Rugged enabled', :enable_rugged do
...@@ -204,7 +204,7 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do ...@@ -204,7 +204,7 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do
described_class.find(repository, SeedRepo::Commit::ID) described_class.find(repository, SeedRepo::Commit::ID)
end end
it_should_behave_like '.find' it_behaves_like '.find'
end end
describe '.last_for_path' do describe '.last_for_path' do
...@@ -474,7 +474,7 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do ...@@ -474,7 +474,7 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do
end end
describe '.batch_by_oid with Gitaly enabled' do describe '.batch_by_oid with Gitaly enabled' do
it_should_behave_like '.batch_by_oid' it_behaves_like '.batch_by_oid'
context 'when oids is empty' do context 'when oids is empty' do
it 'makes no Gitaly request' do it 'makes no Gitaly request' do
...@@ -486,7 +486,7 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do ...@@ -486,7 +486,7 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do
end end
describe '.batch_by_oid with Rugged enabled', :enable_rugged do describe '.batch_by_oid with Rugged enabled', :enable_rugged do
it_should_behave_like '.batch_by_oid' it_behaves_like '.batch_by_oid'
it 'calls out to the Rugged implementation' do it 'calls out to the Rugged implementation' do
allow_next_instance_of(Rugged) do |instance| allow_next_instance_of(Rugged) do |instance|
......
...@@ -71,7 +71,7 @@ RSpec.describe Gitlab::Workhorse do ...@@ -71,7 +71,7 @@ RSpec.describe Gitlab::Workhorse do
context "when the repository doesn't have an archive file path" do context "when the repository doesn't have an archive file path" do
before do before do
allow(project.repository).to receive(:archive_metadata).and_return(Hash.new) allow(project.repository).to receive(:archive_metadata).and_return({})
end end
it "raises an error" do it "raises an error" do
......
...@@ -56,7 +56,7 @@ RSpec.describe API::Jobs do ...@@ -56,7 +56,7 @@ RSpec.describe API::Jobs do
end end
describe 'GET /projects/:id/jobs' do describe 'GET /projects/:id/jobs' do
let(:query) { Hash.new } let(:query) { {} }
before do |example| before do |example|
unless example.metadata[:skip_before_request] unless example.metadata[:skip_before_request]
...@@ -167,7 +167,7 @@ RSpec.describe API::Jobs do ...@@ -167,7 +167,7 @@ RSpec.describe API::Jobs do
end end
describe 'GET /projects/:id/pipelines/:pipeline_id/jobs' do describe 'GET /projects/:id/pipelines/:pipeline_id/jobs' do
let(:query) { Hash.new } let(:query) { {} }
before do |example| before do |example|
unless example.metadata[:skip_before_request] unless example.metadata[:skip_before_request]
...@@ -296,7 +296,7 @@ RSpec.describe API::Jobs do ...@@ -296,7 +296,7 @@ RSpec.describe API::Jobs do
project: downstream_pipeline.project) project: downstream_pipeline.project)
end end
let(:query) { Hash.new } let(:query) { {} }
before do |example| before do |example|
unless example.metadata[:skip_before_request] unless example.metadata[:skip_before_request]
......
...@@ -151,9 +151,9 @@ RSpec.describe NotificationService, :mailer do ...@@ -151,9 +151,9 @@ RSpec.describe NotificationService, :mailer do
end end
shared_examples_for 'participating notifications' do shared_examples_for 'participating notifications' do
it_should_behave_like 'participating by note notification' it_behaves_like 'participating by note notification'
it_should_behave_like 'participating by author notification' it_behaves_like 'participating by author notification'
it_should_behave_like 'participating by assignee notification' it_behaves_like 'participating by assignee notification'
end end
describe '#async' do describe '#async' do
...@@ -1682,13 +1682,13 @@ RSpec.describe NotificationService, :mailer do ...@@ -1682,13 +1682,13 @@ RSpec.describe NotificationService, :mailer do
end end
context 'participating' do context 'participating' do
it_should_behave_like 'participating by assignee notification' do it_behaves_like 'participating by assignee notification' do
let(:participant) { create(:user, username: 'user-participant')} let(:participant) { create(:user, username: 'user-participant')}
let(:issuable) { merge_request } let(:issuable) { merge_request }
let(:notification_trigger) { notification.new_merge_request(merge_request, @u_disabled) } let(:notification_trigger) { notification.new_merge_request(merge_request, @u_disabled) }
end end
it_should_behave_like 'participating by note notification' do it_behaves_like 'participating by note notification' do
let(:participant) { create(:user, username: 'user-participant')} let(:participant) { create(:user, username: 'user-participant')}
let(:issuable) { merge_request } let(:issuable) { merge_request }
let(:notification_trigger) { notification.new_merge_request(merge_request, @u_disabled) } let(:notification_trigger) { notification.new_merge_request(merge_request, @u_disabled) }
......
...@@ -47,10 +47,10 @@ require_relative('../ee/spec/spec_helper') if Gitlab.ee? ...@@ -47,10 +47,10 @@ require_relative('../ee/spec/spec_helper') if Gitlab.ee?
require Rails.root.join("spec/support/helpers/git_helpers.rb") require Rails.root.join("spec/support/helpers/git_helpers.rb")
# Then the rest # Then the rest
Dir[Rails.root.join("spec/support/helpers/*.rb")].each { |f| require f } Dir[Rails.root.join("spec/support/helpers/*.rb")].sort.each { |f| require f }
Dir[Rails.root.join("spec/support/shared_contexts/*.rb")].each { |f| require f } Dir[Rails.root.join("spec/support/shared_contexts/*.rb")].sort.each { |f| require f }
Dir[Rails.root.join("spec/support/shared_examples/*.rb")].each { |f| require f } Dir[Rails.root.join("spec/support/shared_examples/*.rb")].sort.each { |f| require f }
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f } Dir[Rails.root.join("spec/support/**/*.rb")].sort.each { |f| require f }
quality_level = Quality::TestLevel.new quality_level = Quality::TestLevel.new
......
...@@ -848,10 +848,10 @@ ...@@ -848,10 +848,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.161.0.tgz#661e8d19862dfba0e4c558e2eb6d64b402c1453e" resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.161.0.tgz#661e8d19862dfba0e4c558e2eb6d64b402c1453e"
integrity sha512-qsbboEICn08ZoEoAX/TuYygsFaXlzsCY+CfmdOzqvJbOdfHhVXmrJBxd2hP2qqjTZm2PkbRRmn+03+ce1jvatQ== integrity sha512-qsbboEICn08ZoEoAX/TuYygsFaXlzsCY+CfmdOzqvJbOdfHhVXmrJBxd2hP2qqjTZm2PkbRRmn+03+ce1jvatQ==
"@gitlab/ui@20.16.0": "@gitlab/ui@20.17.0":
version "20.16.0" version "20.17.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-20.16.0.tgz#45bad5500e6f47bc4bebb95a17b446f254f9ee21" resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-20.17.0.tgz#5a148c778247efc08df5c093acf5e82069823970"
integrity sha512-k1+X8RgBXknCu40dEWTjE0Sd9jzGmpoPWPlgmoo28tE1vewhRmCOa8aL0tAcm6VNg5av5ZEqoQEJvgFKxLQB1Q== integrity sha512-yDZ+B9/rq7t6OqIHMxPk120KzAO7xM1JKlE9ahkDyijC7lohQy9ygQGFlvVHo1Bic4Y/IW7nzeeZErjzJ3PPtA==
dependencies: dependencies:
"@babel/standalone" "^7.0.0" "@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0" "@gitlab/vue-toasted" "^1.3.0"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment