# frozen_string_literal: true
FactoryBot.define do
factory :user_highest_role do
user
end
end
...@@ -230,7 +230,7 @@ describe 'Merge request > User creates image diff notes', :js do ...@@ -230,7 +230,7 @@ describe 'Merge request > User creates image diff notes', :js do
it_behaves_like 'onion skin' it_behaves_like 'onion skin'
end end
describe 'swipe view' do describe 'swipe view', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/209999' do
before do before do
switch_to_swipe_view switch_to_swipe_view
end end
... ...
......
...@@ -7,8 +7,6 @@ describe 'Project active tab' do ...@@ -7,8 +7,6 @@ describe 'Project active tab' do
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
before do before do
stub_feature_flags(analytics_pages_under_project_analytics_sidebar: { enabled: false, thing: project })
project.add_maintainer(user) project.add_maintainer(user)
sign_in(user) sign_in(user)
end end
...@@ -45,7 +43,7 @@ describe 'Project active tab' do ...@@ -45,7 +43,7 @@ describe 'Project active tab' do
it_behaves_like 'page has active tab', 'Repository' it_behaves_like 'page has active tab', 'Repository'
%w(Files Commits Graph Compare Charts Branches Tags).each do |sub_menu| %w(Files Commits Graph Compare Branches Tags).each do |sub_menu|
context "on project Repository/#{sub_menu}" do context "on project Repository/#{sub_menu}" do
before do before do
click_tab(sub_menu) click_tab(sub_menu)
...@@ -124,11 +122,6 @@ describe 'Project active tab' do ...@@ -124,11 +122,6 @@ describe 'Project active tab' do
end end
end end
context 'when `analytics_pages_under_project_analytics_sidebar` feature flag is enabled' do
before do
stub_feature_flags(analytics_pages_under_project_analytics_sidebar: { enabled: true, thing: project })
end
context 'on project Analytics' do context 'on project Analytics' do
before do before do
visit charts_project_graph_path(project, 'master') visit charts_project_graph_path(project, 'master')
...@@ -149,4 +142,3 @@ describe 'Project active tab' do ...@@ -149,4 +142,3 @@ describe 'Project active tab' do
end end
end end
end end
end
...@@ -7,8 +7,6 @@ describe 'User uses shortcuts', :js do ...@@ -7,8 +7,6 @@ describe 'User uses shortcuts', :js do
let(:user) { create(:user) } let(:user) { create(:user) }
before do before do
stub_feature_flags(analytics_pages_under_project_analytics_sidebar: { enabled: false, thing: project })
project.add_maintainer(user) project.add_maintainer(user)
sign_in(user) sign_in(user)
...@@ -119,8 +117,8 @@ describe 'User uses shortcuts', :js do ...@@ -119,8 +117,8 @@ describe 'User uses shortcuts', :js do
find('body').native.send_key('g') find('body').native.send_key('g')
find('body').native.send_key('d') find('body').native.send_key('d')
expect(page).to have_active_navigation('Repository') expect(page).to have_active_navigation(_('Analytics'))
expect(page).to have_active_sub_navigation('Charts') expect(page).to have_active_sub_navigation(_('Repository'))
end end
end end
...@@ -211,18 +209,4 @@ describe 'User uses shortcuts', :js do ...@@ -211,18 +209,4 @@ describe 'User uses shortcuts', :js do
expect(page).to have_active_navigation('Wiki') expect(page).to have_active_navigation('Wiki')
end end
end end
context 'when `analytics_pages_under_project_analytics_sidebar` feature flag is enabled' do
before do
stub_feature_flags(analytics_pages_under_project_analytics_sidebar: { enabled: true, thing: project })
end
it 'redirects to the repository charts page' do
find('body').native.send_key('g')
find('body').native.send_key('d')
expect(page).to have_active_navigation(_('Analytics'))
expect(page).to have_active_sub_navigation(_('Repository'))
end
end
end end
File moved
File moved
...@@ -205,6 +205,75 @@ describe Gitlab::Ci::Parsers::Test::Junit do ...@@ -205,6 +205,75 @@ describe Gitlab::Ci::Parsers::Test::Junit do
end end
end end
context 'when data contains an attachment tag' do
let(:junit) do
<<~EOF
<testsuites>
<testsuite>
<testcase classname='Calculator' name='sumTest1' time='0.01'>
<failure>Some failure</failure>
<system-out>[[ATTACHMENT|some/path.png]]</system-out>
</testcase>
</testsuite>
</testsuites>
EOF
end
it 'add attachment to a test case' do
expect { subject }.not_to raise_error
expect(test_cases[0].has_attachment?).to be_truthy
expect(test_cases[0].attachment).to eq("some/path.png")
end
end
context 'when data contains multiple attachments tag' do
let(:junit) do
<<~EOF
<testsuites>
<testsuite>
<testcase classname='Calculator' name='sumTest1' time='0.01'>
<failure>Some failure</failure>
<system-out>
[[ATTACHMENT|some/path.png]]
[[ATTACHMENT|some/path.html]]
</system-out>
</testcase>
</testsuite>
</testsuites>
EOF
end
it 'adds the first match attachment to a test case' do
expect { subject }.not_to raise_error
expect(test_cases[0].has_attachment?).to be_truthy
expect(test_cases[0].attachment).to eq("some/path.png")
end
end
context 'when data does not match attachment tag regex' do
let(:junit) do
<<~EOF
<testsuites>
<testsuite>
<testcase classname='Calculator' name='sumTest1' time='0.01'>
<failure>Some failure</failure>
<system-out>[[attachment]some/path.png]]</system-out>
</testcase>
</testsuite>
</testsuites>
EOF
end
it 'does not add attachment to a test case' do
expect { subject }.not_to raise_error
expect(test_cases[0].has_attachment?).to be_falsy
expect(test_cases[0].attachment).to be_nil
end
end
private private
def flattened_test_cases(test_suite) def flattened_test_cases(test_suite)
... ...
......
...@@ -88,5 +88,17 @@ describe Gitlab::Ci::Reports::TestCase do ...@@ -88,5 +88,17 @@ describe Gitlab::Ci::Reports::TestCase do
expect { test_case }.to raise_error(ArgumentError) expect { test_case }.to raise_error(ArgumentError)
end end
end end
context 'when attachment is present' do
let(:attachment_test_case) { build(:test_case, :with_attachment) }
it "initializes the attachment if present" do
expect(attachment_test_case.attachment).to eq("some/path.png")
end
it '#has_attachment?' do
expect(attachment_test_case.has_attachment?).to be_truthy
end
end
end end
end end
...@@ -124,7 +124,7 @@ describe Gitlab::SidekiqConfig::CliMethods do ...@@ -124,7 +124,7 @@ describe Gitlab::SidekiqConfig::CliMethods do
name: 'a', name: 'a',
feature_category: :category_a, feature_category: :category_a,
has_external_dependencies: false, has_external_dependencies: false,
urgency: :default, urgency: :low,
resource_boundary: :cpu resource_boundary: :cpu
}, },
{ {
...@@ -145,7 +145,7 @@ describe Gitlab::SidekiqConfig::CliMethods do ...@@ -145,7 +145,7 @@ describe Gitlab::SidekiqConfig::CliMethods do
name: 'c', name: 'c',
feature_category: :category_c, feature_category: :category_c,
has_external_dependencies: false, has_external_dependencies: false,
urgency: :none, urgency: :throttled,
resource_boundary: :memory resource_boundary: :memory
} }
] ]
...@@ -168,9 +168,9 @@ describe Gitlab::SidekiqConfig::CliMethods do ...@@ -168,9 +168,9 @@ describe Gitlab::SidekiqConfig::CliMethods do
# urgency # urgency
'urgency=high' | %w(a:2 b) 'urgency=high' | %w(a:2 b)
'urgency=default' | %w(a) 'urgency=low' | %w(a)
'urgency=high,default,none' | %w(a a:2 b c) 'urgency=high,low,throttled' | %w(a a:2 b c)
'urgency=default|urgency=none' | %w(a c) 'urgency=low|urgency=throttled' | %w(a c)
'urgency!=high' | %w(a c) 'urgency!=high' | %w(a c)
# name # name
... ...
......
...@@ -88,7 +88,7 @@ describe Gitlab::SidekiqConfig::Worker do ...@@ -88,7 +88,7 @@ describe Gitlab::SidekiqConfig::Worker do
attributes_a = { attributes_a = {
feature_category: :source_code_management, feature_category: :source_code_management,
has_external_dependencies: false, has_external_dependencies: false,
urgency: :default, urgency: :low,
resource_boundary: :memory, resource_boundary: :memory,
weight: 2, weight: 2,
idempotent: true idempotent: true
... ...
......
...@@ -9,7 +9,7 @@ describe Gitlab::SidekiqMiddleware::ClientMetrics do ...@@ -9,7 +9,7 @@ describe Gitlab::SidekiqMiddleware::ClientMetrics do
let(:queue) { :test } let(:queue) { :test }
let(:worker_class) { worker.class } let(:worker_class) { worker.class }
let(:job) { {} } let(:job) { {} }
let(:default_labels) { { queue: queue.to_s, boundary: "", external_dependencies: "no", feature_category: "", urgency: "default" } } let(:default_labels) { { queue: queue.to_s, boundary: "", external_dependencies: "no", feature_category: "", urgency: "low" } }
shared_examples "a metrics client middleware" do shared_examples "a metrics client middleware" do
context "with mocked prometheus" do context "with mocked prometheus" do
...@@ -80,8 +80,8 @@ describe Gitlab::SidekiqMiddleware::ClientMetrics do ...@@ -80,8 +80,8 @@ describe Gitlab::SidekiqMiddleware::ClientMetrics do
context "no urgency" do context "no urgency" do
it_behaves_like "a metrics client middleware" do it_behaves_like "a metrics client middleware" do
let(:urgency) { :none } let(:urgency) { :throttled }
let(:labels) { default_labels.merge(urgency: "none") } let(:labels) { default_labels.merge(urgency: "throttled") }
end end
end end
... ...
......
...@@ -11,7 +11,7 @@ describe Gitlab::SidekiqMiddleware::ServerMetrics do ...@@ -11,7 +11,7 @@ describe Gitlab::SidekiqMiddleware::ServerMetrics do
let(:job) { {} } let(:job) { {} }
let(:job_status) { :done } let(:job_status) { :done }
let(:labels_with_job_status) { labels.merge(job_status: job_status.to_s) } let(:labels_with_job_status) { labels.merge(job_status: job_status.to_s) }
let(:default_labels) { { queue: queue.to_s, boundary: "", external_dependencies: "no", feature_category: "", urgency: "default" } } let(:default_labels) { { queue: queue.to_s, boundary: "", external_dependencies: "no", feature_category: "", urgency: "low" } }
shared_examples "a metrics middleware" do shared_examples "a metrics middleware" do
context "with mocked prometheus" do context "with mocked prometheus" do
...@@ -202,11 +202,11 @@ describe Gitlab::SidekiqMiddleware::ServerMetrics do ...@@ -202,11 +202,11 @@ describe Gitlab::SidekiqMiddleware::ServerMetrics do
end end
context "combined" do context "combined" do
let(:urgency) { :none } let(:urgency) { :throttled }
let(:external_dependencies) { true } let(:external_dependencies) { true }
let(:resource_boundary) { :cpu } let(:resource_boundary) { :cpu }
let(:feature_category) { :authentication } let(:feature_category) { :authentication }
let(:labels) { default_labels.merge(urgency: "none", external_dependencies: "yes", boundary: "cpu", feature_category: "authentication") } let(:labels) { default_labels.merge(urgency: "throttled", external_dependencies: "yes", boundary: "cpu", feature_category: "authentication") }
it_behaves_like "a metrics middleware" it_behaves_like "a metrics middleware"
end end
... ...
......
...@@ -201,6 +201,26 @@ describe Namespace do ...@@ -201,6 +201,26 @@ describe Namespace do
expect(described_class.find_by_pages_host(host)).to eq(namespace) expect(described_class.find_by_pages_host(host)).to eq(namespace)
end end
context 'when there is non-top-level group with searched name' do
before do
create(:group, :nested, path: 'pages')
end
it 'ignores this group' do
host = "pages.#{Settings.pages.host.upcase}"
expect(described_class.find_by_pages_host(host)).to be_nil
end
it 'finds right top level group' do
group = create(:group, path: 'pages')
host = "pages.#{Settings.pages.host.upcase}"
expect(described_class.find_by_pages_host(host)).to eq(group)
end
end
it "returns no result if the provided host is not subdomain of the Pages host" do it "returns no result if the provided host is not subdomain of the Pages host" do
create(:namespace, name: 'namespace.io') create(:namespace, name: 'namespace.io')
host = "namespace.io" host = "namespace.io"
... ...
......
# frozen_string_literal: true
require 'spec_helper'
describe UserHighestRole do
describe 'associations' do
it { is_expected.to belong_to(:user).required }
end
describe 'validations' do
it { is_expected.to validate_inclusion_of(:highest_access_level).in_array([nil, *Gitlab::Access.all_values]) }
end
end
...@@ -30,6 +30,7 @@ describe User, :do_not_mock_admin_mode do ...@@ -30,6 +30,7 @@ describe User, :do_not_mock_admin_mode do
it { is_expected.to have_one(:status) } it { is_expected.to have_one(:status) }
it { is_expected.to have_one(:max_access_level_membership) } it { is_expected.to have_one(:max_access_level_membership) }
it { is_expected.to have_one(:user_detail) } it { is_expected.to have_one(:user_detail) }
it { is_expected.to have_one(:user_highest_role) }
it { is_expected.to have_many(:snippets).dependent(:destroy) } it { is_expected.to have_many(:snippets).dependent(:destroy) }
it { is_expected.to have_many(:members) } it { is_expected.to have_many(:members) }
it { is_expected.to have_many(:project_members) } it { is_expected.to have_many(:project_members) }
... ...
......
...@@ -48,7 +48,7 @@ describe API::Groups do ...@@ -48,7 +48,7 @@ describe API::Groups do
context 'when file format is not supported' do context 'when file format is not supported' do
let(:file_path) { 'spec/fixtures/doc_sample.txt' } let(:file_path) { 'spec/fixtures/doc_sample.txt' }
let(:message) { 'file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico' } let(:message) { 'file format is not supported. Please try one of the following supported formats: image/png, image/jpeg, image/gif, image/bmp, image/tiff, image/vnd.microsoft.icon' }
it_behaves_like 'invalid file upload request' it_behaves_like 'invalid file upload request'
end end
... ...
......
...@@ -20,6 +20,7 @@ RSpec.shared_context 'uploader with type check' do ...@@ -20,6 +20,7 @@ RSpec.shared_context 'uploader with type check' do
end end
end end
# This works with the UploadTypeCheck::Concern
RSpec.shared_context 'stubbed MimeMagic mime type detection' do RSpec.shared_context 'stubbed MimeMagic mime type detection' do
let(:mime_type) { '' } let(:mime_type) { '' }
let(:magic_mime) { mime_type } let(:magic_mime) { mime_type }
...@@ -31,3 +32,19 @@ RSpec.shared_context 'stubbed MimeMagic mime type detection' do ...@@ -31,3 +32,19 @@ RSpec.shared_context 'stubbed MimeMagic mime type detection' do
allow(MimeMagic).to receive(:by_path).with(anything).and_return(ext_mime_obj) allow(MimeMagic).to receive(:by_path).with(anything).and_return(ext_mime_obj)
end end
end end
# @param uploader [CarrierWave::Uploader::Base] uploader with extension_whitelist method.
RSpec.shared_context 'ignore extension whitelist check' do
before do
allow(uploader).to receive(:extension_whitelist).and_return(nil)
end
end
# This works with a content_type_whitelist and content_type_blacklist type check.
# @param mime_type [String] mime type to forcibly detect.
RSpec.shared_context 'force content type detection to mime_type' do
before do
magic_mime_obj = MimeMagic.new(mime_type)
allow(MimeMagic).to receive(:by_magic).with(anything).and_return(magic_mime_obj)
end
end
# frozen_string_literal: true # frozen_string_literal: true
# @param path [String] the path to file to upload. E.g. File.join('spec', 'fixtures', 'sanitized.svg')
# @param uploader [CarrierWave::Uploader::Base] uploader to handle the upload.
shared_examples 'denied carrierwave upload' do
it 'will deny upload' do
fixture_file = fixture_file_upload(path)
expect { uploader.cache!(fixture_file) }.to raise_exception(CarrierWave::IntegrityError)
end
end
# @param path [String] the path to file to upload. E.g. File.join('spec', 'fixtures', 'sanitized.svg')
# @param uploader [CarrierWave::Uploader::Base] uploader to handle the upload.
shared_examples 'accepted carrierwave upload' do
let(:fixture_file) { fixture_file_upload(path) }
before do
uploader.remove!
end
it 'will accept upload' do
expect { uploader.cache!(fixture_file) }.not_to raise_exception
end
it 'will cache uploaded file' do
expect { uploader.cache!(fixture_file) }.to change { uploader.file }.from(nil).to(kind_of(CarrierWave::SanitizedFile))
end
end
def check_content_matches_extension!(file = double(read: nil, path: '')) def check_content_matches_extension!(file = double(read: nil, path: ''))
magic_file = UploadTypeCheck::MagicFile.new(file) magic_file = UploadTypeCheck::MagicFile.new(file)
uploader.check_content_matches_extension!(magic_file) uploader.check_content_matches_extension!(magic_file)
... ...
......
...@@ -47,15 +47,29 @@ describe AvatarUploader do ...@@ -47,15 +47,29 @@ describe AvatarUploader do
end end
end end
context 'upload type check' do context 'accept whitelist file content type' do
AvatarUploader::SAFE_IMAGE_EXT.each do |ext| # We need to feed through a valid path, but we force the parsed mime type
context "#{ext} extension" do # in a stub below so we can set any path.
it_behaves_like 'type checked uploads', filenames: "image.#{ext}" let_it_be(:path) { File.join('spec', 'fixtures', 'video_sample.mp4') }
where(:mime_type) { described_class::MIME_WHITELIST }
with_them do
include_context 'force content type detection to mime_type'
it_behaves_like 'accepted carrierwave upload'
end end
end end
context 'skip image/svg+xml integrity check' do context 'upload non-whitelisted file content type' do
it_behaves_like 'skipped type checked uploads', filenames: 'image.svg' let_it_be(:path) { File.join('spec', 'fixtures', 'sanitized.svg') }
it_behaves_like 'denied carrierwave upload'
end end
context 'upload misnamed non-whitelisted file content type' do
let_it_be(:path) { File.join('spec', 'fixtures', 'not_a_png.png') }
it_behaves_like 'denied carrierwave upload'
end end
end end
# frozen_string_literal: true
require 'spec_helper'
describe ContentTypeWhitelist do
class DummyUploader < CarrierWave::Uploader::Base
include ContentTypeWhitelist::Concern
def content_type_whitelist
%w[image/png image/jpeg]
end
end
let_it_be(:model) { build_stubbed(:user) }
let_it_be(:uploader) { DummyUploader.new(model, :dummy) }
context 'upload whitelisted file content type' do
let(:path) { File.join('spec', 'fixtures', 'rails_sample.jpg') }
it_behaves_like 'accepted carrierwave upload'
end
context 'upload non-whitelisted file content type' do
let(:path) { File.join('spec', 'fixtures', 'sanitized.svg') }
it_behaves_like 'denied carrierwave upload'
end
context 'upload misnamed non-whitelisted file content type' do
let(:path) { File.join('spec', 'fixtures', 'not_a_png.png') }
it_behaves_like 'denied carrierwave upload'
end
end