mirror of
https://gitlab.com/gitlab-org/gitlab-foss.git
synced 2025-07-25 16:03:48 +00:00
286 lines
8.5 KiB
Ruby
286 lines
8.5 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'spec_helper'
|
|
|
|
RSpec.describe ApplicationController, type: :request, feature_category: :shared do
|
|
let_it_be_with_reload(:user) { create(:user) }
|
|
|
|
it_behaves_like 'Base action controller' do
|
|
before do
|
|
sign_in(user)
|
|
end
|
|
|
|
subject(:request) { get root_path }
|
|
end
|
|
|
|
it 'does not send Link header', :use_clean_rails_redis_caching do
|
|
sign_in(user)
|
|
|
|
get root_path
|
|
|
|
expect(response.headers['Link']).to be_nil
|
|
end
|
|
|
|
describe 'session expiration' do
|
|
context 'when user is authenticated' do
|
|
it 'sets the redis_expiry option from session_expire_delay setting' do
|
|
sign_in(user)
|
|
|
|
get root_path
|
|
|
|
expect(request.env['rack.session.options'][:redis_expiry]).to eq(
|
|
Settings.gitlab['session_expire_delay'] * 60
|
|
)
|
|
end
|
|
end
|
|
|
|
context 'when user is unauthenticated' do
|
|
it 'sets the redis_expiry option from unauthenticated_session_expire_delay' do
|
|
get root_path
|
|
|
|
expect(request.env['rack.session.options'][:redis_expiry]).to eq(
|
|
Settings.gitlab['unauthenticated_session_expire_delay']
|
|
)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'unknown route' do
|
|
# This spec targets CI environment with precompiled assets to trigger
|
|
# Sprockets' `File.binread` and find encoding issues.
|
|
#
|
|
# See https://gitlab.com/gitlab-com/gl-infra/production/-/issues/17627#note_1782396646
|
|
it 'returns 404 even when locale contains UTF-8 chars' do
|
|
user.update!(preferred_language: 'ZH-cn')
|
|
|
|
sign_in(user)
|
|
|
|
get "/some/undefined/path"
|
|
|
|
expect(response).to have_gitlab_http_status(:not_found)
|
|
expect(response.body.encoding.name).to eq('UTF-8')
|
|
end
|
|
end
|
|
|
|
describe 'User-Agent header' do
|
|
before do
|
|
sign_in(user)
|
|
|
|
get root_path, headers: { 'User-Agent': user_agent }
|
|
end
|
|
|
|
context 'when missing' do
|
|
let(:user_agent) { nil }
|
|
|
|
it { expect(response).to have_gitlab_http_status(:ok) }
|
|
end
|
|
|
|
context 'when correct' do
|
|
let(:user_agent) { 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)' }
|
|
|
|
it { expect(response).to have_gitlab_http_status(:ok) }
|
|
end
|
|
|
|
context 'when too long' do
|
|
let(:user_agent) { 'a' * 3000 }
|
|
|
|
it { expect(response).to have_gitlab_http_status(:forbidden) }
|
|
end
|
|
end
|
|
|
|
describe 'HTTP Router headers' do
|
|
before do
|
|
sign_in(user)
|
|
end
|
|
|
|
let(:headers) do
|
|
{
|
|
'X-Gitlab-Http-Router-Rule-Action' => 'classify',
|
|
'X-Gitlab-Http-Router-Rule-Type' => 'FIRST_CELL'
|
|
}
|
|
end
|
|
|
|
subject(:perform_request) do
|
|
get root_path, headers: headers
|
|
end
|
|
|
|
it 'includes the HTTP ROUTER headers in ApplicationContext' do
|
|
expect_next_instance_of(RootController) do |controller|
|
|
expect(controller).to receive(:index).and_wrap_original do |m, *args|
|
|
m.call(*args)
|
|
|
|
expect(Gitlab::ApplicationContext.current).to include(
|
|
'meta.http_router_rule_action' => 'classify',
|
|
'meta.http_router_rule_type' => 'FIRST_CELL'
|
|
)
|
|
end
|
|
end
|
|
|
|
perform_request
|
|
end
|
|
|
|
context 'for counters' do
|
|
let(:http_router_rule_counter) { Gitlab::Metrics.counter(:gitlab_http_router_rule_total, 'description') }
|
|
|
|
context 'when the headers are present' do
|
|
context 'for classify action' do
|
|
it 'increments the counter' do
|
|
expect { perform_request }.to change {
|
|
http_router_rule_counter.get(rule_action: 'classify', rule_type: 'FIRST_CELL')
|
|
}.by(1)
|
|
end
|
|
end
|
|
|
|
context 'for classify action by SESSION_PREFIX' do
|
|
let(:headers) do
|
|
{
|
|
'X-Gitlab-Http-Router-Rule-Action' => 'classify',
|
|
'X-Gitlab-Http-Router-Rule-Type' => 'SESSION_PREFIX'
|
|
}
|
|
end
|
|
|
|
it 'increments the counter with labels' do
|
|
expect { perform_request }.to change {
|
|
http_router_rule_counter.get(rule_action: 'classify', rule_type: 'SESSION_PREFIX')
|
|
}.by(1)
|
|
end
|
|
end
|
|
|
|
context 'for classify action by CELL_ID' do
|
|
let(:headers) do
|
|
{
|
|
'X-Gitlab-Http-Router-Rule-Action' => 'classify',
|
|
'X-Gitlab-Http-Router-Rule-Type' => 'CELL_ID'
|
|
}
|
|
end
|
|
|
|
it 'increments the counter with labels' do
|
|
expect { perform_request }.to change {
|
|
http_router_rule_counter.get(rule_action: 'classify', rule_type: 'CELL_ID')
|
|
}.by(1)
|
|
end
|
|
end
|
|
|
|
context 'for proxy action' do
|
|
let(:headers) do
|
|
{
|
|
'X-Gitlab-Http-Router-Rule-Action' => 'proxy'
|
|
}
|
|
end
|
|
|
|
it 'increments the counter' do
|
|
expect { perform_request }.to change {
|
|
http_router_rule_counter.get(rule_action: 'proxy', rule_type: nil)
|
|
}.by(1)
|
|
end
|
|
end
|
|
|
|
context 'for invalid action and type' do
|
|
let(:headers) do
|
|
{
|
|
'X-Gitlab-Http-Router-Rule-Action' => 'invalid',
|
|
'X-Gitlab-Http-Router-Rule-Type' => 'invalid'
|
|
}
|
|
end
|
|
|
|
it 'does not increment the counter' do
|
|
expect { perform_request }.to change {
|
|
http_router_rule_counter.get(rule_action: 'invalid', rule_type: 'invalid')
|
|
}.by(0)
|
|
end
|
|
end
|
|
|
|
context 'when action is not present and type is present' do
|
|
let(:headers) do
|
|
{
|
|
'X-Gitlab-Http-Router-Rule-Type' => 'FIRST_CELL'
|
|
}
|
|
end
|
|
|
|
it 'does not increment the counter' do
|
|
expect { perform_request }.to change {
|
|
http_router_rule_counter.get(rule_action: nil, rule_type: 'FIRST_CELL')
|
|
}.by(0)
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'when the headers are absent' do
|
|
let(:headers) { {} }
|
|
|
|
it 'does not increment the counter' do
|
|
expect { perform_request }.to change {
|
|
http_router_rule_counter.get(rule_action: nil, rule_type: nil)
|
|
}.by(0)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'static context middleware', feature_category: :error_budgets do
|
|
# to check the middleware tests, go to spec/lib/gitlab/middleware/static_context_middleware_spec.rb
|
|
|
|
let(:expected_context) do
|
|
{ 'meta.feature_category' => 'groups_and_projects',
|
|
'meta.caller_id' => 'Dashboard::GroupsController#index' }
|
|
end
|
|
|
|
context 'when action is successfully called' do
|
|
it 'pushes static context to current context' do
|
|
context = {}
|
|
allow_next_instance_of(Dashboard::GroupsController) do |_controller|
|
|
context.merge!(Gitlab::ApplicationContext.current.to_h)
|
|
end
|
|
|
|
get '/dashboard/groups' # randomly picked route
|
|
|
|
expect(response).to have_gitlab_http_status(:found)
|
|
expect(context).to include expected_context
|
|
end
|
|
end
|
|
|
|
context 'when an exception is thrown before action' do
|
|
it 'pushes static context to current context before controller callbacks' do
|
|
context = {}
|
|
unexpected_error = 'boom 💣💥'
|
|
|
|
allow_next_instance_of(Dashboard::GroupsController) do |controller|
|
|
# picking up a random before_action method to raise an "unexpected" exception
|
|
allow(controller).to receive(:authenticate_user!).and_raise(unexpected_error)
|
|
|
|
context.merge!(Gitlab::ApplicationContext.current.to_h)
|
|
end
|
|
|
|
expect { get '/dashboard/groups' }.to raise_error(unexpected_error)
|
|
expect(context).to include expected_context
|
|
end
|
|
end
|
|
|
|
context 'when controller overrides feature_category with nil' do
|
|
it 'ignores nil feature category override' do
|
|
context = {}
|
|
|
|
allow_next_instance_of(Projects::NotesController) do |controller|
|
|
# mimicking a bug overriding feature_category with nil
|
|
allow(controller).to receive(:feature_category).and_return(nil)
|
|
|
|
context.merge!(Gitlab::ApplicationContext.current.to_h)
|
|
end
|
|
|
|
project = create(:project, :public)
|
|
project_snippet = create(:project_snippet, project: project)
|
|
create(:note_on_project_snippet, project: project, noteable: project_snippet)
|
|
# picking a route targeting a controller that overrides feature_category
|
|
get project_noteable_notes_path(
|
|
project,
|
|
target_type: 'project_snippet',
|
|
target_id: project_snippet.id,
|
|
html: true
|
|
)
|
|
|
|
expect(context).to include({ 'meta.feature_category' => 'team_planning' })
|
|
end
|
|
end
|
|
end
|
|
end
|