Commit ce69419a authored by Bob Van Landuyt's avatar Bob Van Landuyt

Remove permanent redirects

Removes permanent redirects, this means that redirects will only be
possible as long as the old route isn't taken by a new project/group.
parent 7ea08566
...@@ -17,32 +17,4 @@ class RedirectRoute < ActiveRecord::Base ...@@ -17,32 +17,4 @@ class RedirectRoute < ActiveRecord::Base
where(wheres, path, "#{sanitize_sql_like(path)}/%") where(wheres, path, "#{sanitize_sql_like(path)}/%")
end end
scope :permanent, -> do
if column_permanent_exists?
where(permanent: true)
else
none
end
end
scope :temporary, -> do
if column_permanent_exists?
where(permanent: [false, nil])
else
all
end
end
default_value_for :permanent, false
def permanent=(value)
if self.class.column_permanent_exists?
super
end
end
def self.column_permanent_exists?
ActiveRecord::Base.connection.column_exists?(:redirect_routes, :permanent)
end
end end
...@@ -10,8 +10,6 @@ class Route < ActiveRecord::Base ...@@ -10,8 +10,6 @@ class Route < ActiveRecord::Base
presence: true, presence: true,
uniqueness: { case_sensitive: false } uniqueness: { case_sensitive: false }
validate :ensure_permanent_paths, if: :path_changed?
before_validation :delete_conflicting_orphaned_routes before_validation :delete_conflicting_orphaned_routes
after_create :delete_conflicting_redirects after_create :delete_conflicting_redirects
after_update :delete_conflicting_redirects, if: :path_changed? after_update :delete_conflicting_redirects, if: :path_changed?
...@@ -45,7 +43,7 @@ class Route < ActiveRecord::Base ...@@ -45,7 +43,7 @@ class Route < ActiveRecord::Base
# We are not calling route.delete_conflicting_redirects here, in hopes # We are not calling route.delete_conflicting_redirects here, in hopes
# of avoiding deadlocks. The parent (self, in this method) already # of avoiding deadlocks. The parent (self, in this method) already
# called it, which deletes conflicts for all descendants. # called it, which deletes conflicts for all descendants.
route.create_redirect(old_path, permanent: permanent_redirect?) if attributes[:path] route.create_redirect(old_path) if attributes[:path]
end end
end end
end end
...@@ -55,31 +53,17 @@ class Route < ActiveRecord::Base ...@@ -55,31 +53,17 @@ class Route < ActiveRecord::Base
end end
def conflicting_redirects def conflicting_redirects
RedirectRoute.temporary.matching_path_and_descendants(path) RedirectRoute.matching_path_and_descendants(path)
end end
def create_redirect(path, permanent: false) def create_redirect(path)
RedirectRoute.create(source: source, path: path, permanent: permanent) RedirectRoute.create(source: source, path: path)
end end
private private
def create_redirect_for_old_path def create_redirect_for_old_path
create_redirect(path_was, permanent: permanent_redirect?) if path_changed? create_redirect(path_was) if path_changed?
end
def permanent_redirect?
source_type != "Project"
end
def ensure_permanent_paths
return if path.nil?
errors.add(:path, "has been taken before") if conflicting_redirect_exists?
end
def conflicting_redirect_exists?
RedirectRoute.permanent.matching_path_and_descendants(path).exists?
end end
def delete_conflicting_orphaned_routes def delete_conflicting_orphaned_routes
......
---
title: Don't create permanent redirect routes
merge_request: 17521
author:
type: changed
...@@ -9,20 +9,16 @@ module Gitlab ...@@ -9,20 +9,16 @@ module Gitlab
super(project, user, protocol) super(project, user, protocol)
end end
def message(rejected: false) def message
<<~MESSAGE <<~MESSAGE
Project '#{redirected_path}' was moved to '#{project.full_path}'. Project '#{redirected_path}' was moved to '#{project.full_path}'.
Please update your Git remote: Please update your Git remote:
#{remote_url_message(rejected)} git remote set-url origin #{url_to_repo}
MESSAGE MESSAGE
end end
def permanent_redirect?
RedirectRoute.permanent.exists?(path: redirected_path)
end
private private
attr_reader :redirected_path attr_reader :redirected_path
...@@ -30,18 +26,6 @@ module Gitlab ...@@ -30,18 +26,6 @@ module Gitlab
def self.message_key(user_id, project_id) def self.message_key(user_id, project_id)
"#{REDIRECT_NAMESPACE}:#{user_id}:#{project_id}" "#{REDIRECT_NAMESPACE}:#{user_id}:#{project_id}"
end end
def remote_url_message(rejected)
if rejected
"git remote set-url origin #{url_to_repo} and try again."
else
"git remote set-url origin #{url_to_repo}"
end
end
def url
protocol == 'ssh' ? project.ssh_url_to_repo : project.http_url_to_repo
end
end end
end end
end end
...@@ -53,7 +53,7 @@ module Gitlab ...@@ -53,7 +53,7 @@ module Gitlab
ensure_project_on_push!(cmd, changes) ensure_project_on_push!(cmd, changes)
check_project_accessibility! check_project_accessibility!
check_project_moved! add_project_moved_message!
check_repository_existence! check_repository_existence!
case cmd case cmd
...@@ -125,16 +125,12 @@ module Gitlab ...@@ -125,16 +125,12 @@ module Gitlab
end end
end end
def check_project_moved! def add_project_moved_message!
return if redirected_path.nil? return if redirected_path.nil?
project_moved = Checks::ProjectMoved.new(project, user, protocol, redirected_path) project_moved = Checks::ProjectMoved.new(project, user, protocol, redirected_path)
if project_moved.permanent_redirect? project_moved.add_message
project_moved.add_message
else
raise ProjectMovedError, project_moved.message(rejected: true)
end
end end
def check_command_disabled!(cmd) def check_command_disabled!(cmd)
......
...@@ -2,14 +2,5 @@ FactoryBot.define do ...@@ -2,14 +2,5 @@ FactoryBot.define do
factory :redirect_route do factory :redirect_route do
sequence(:path) { |n| "redirect#{n}" } sequence(:path) { |n| "redirect#{n}" }
source factory: :group source factory: :group
permanent false
trait :permanent do
permanent true
end
trait :temporary do
permanent false
end
end end
end end
...@@ -44,44 +44,17 @@ describe Gitlab::Checks::ProjectMoved, :clean_gitlab_redis_shared_state do ...@@ -44,44 +44,17 @@ describe Gitlab::Checks::ProjectMoved, :clean_gitlab_redis_shared_state do
end end
describe '#message' do describe '#message' do
context 'when the push is rejected' do it 'returns a redirect message' do
it 'returns a redirect message telling the user to try again' do project_moved = described_class.new(project, user, 'http', 'foo/bar')
project_moved = described_class.new(project, user, 'http', 'foo/bar') message = <<~MSG
message = "Project 'foo/bar' was moved to '#{project.full_path}'." + Project 'foo/bar' was moved to '#{project.full_path}'.
"\n\nPlease update your Git remote:" +
"\n\n git remote set-url origin #{project.http_url_to_repo} and try again.\n"
expect(project_moved.message(rejected: true)).to eq(message) Please update your Git remote:
end
end
context 'when the push is not rejected' do git remote set-url origin #{project.http_url_to_repo}
it 'returns a redirect message' do MSG
project_moved = described_class.new(project, user, 'http', 'foo/bar')
message = "Project 'foo/bar' was moved to '#{project.full_path}'." +
"\n\nPlease update your Git remote:" +
"\n\n git remote set-url origin #{project.http_url_to_repo}\n"
expect(project_moved.message).to eq(message) expect(project_moved.message).to eq(message)
end
end
end
describe '#permanent_redirect?' do
context 'with a permanent RedirectRoute' do
it 'returns true' do
project.route.create_redirect('foo/bar', permanent: true)
project_moved = described_class.new(project, user, 'http', 'foo/bar')
expect(project_moved.permanent_redirect?).to be_truthy
end
end
context 'without a permanent RedirectRoute' do
it 'returns false' do
project.route.create_redirect('foo/bar')
project_moved = described_class.new(project, user, 'http', 'foo/bar')
expect(project_moved.permanent_redirect?).to be_falsy
end
end end
end end
end end
...@@ -240,14 +240,21 @@ describe Gitlab::GitAccess do ...@@ -240,14 +240,21 @@ describe Gitlab::GitAccess do
end end
shared_examples 'check_project_moved' do shared_examples 'check_project_moved' do
it 'enqueues a redirected message' do it 'enqueues a redirected message for pushing' do
push_access_check push_access_check
expect(Gitlab::Checks::ProjectMoved.fetch_message(user.id, project.id)).not_to be_nil expect(Gitlab::Checks::ProjectMoved.fetch_message(user.id, project.id)).not_to be_nil
end end
it 'allows push and pull access' do
aggregate_failures do
expect { push_access_check }.not_to raise_error
expect { pull_access_check }.not_to raise_error
end
end
end end
describe '#check_project_moved!', :clean_gitlab_redis_shared_state do describe '#add_project_moved_message!', :clean_gitlab_redis_shared_state do
before do before do
project.add_master(user) project.add_master(user)
end end
...@@ -261,62 +268,18 @@ describe Gitlab::GitAccess do ...@@ -261,62 +268,18 @@ describe Gitlab::GitAccess do
end end
end end
context 'when a permanent redirect and ssh protocol' do context 'with a redirect and ssh protocol' do
let(:redirected_path) { 'some/other-path' } let(:redirected_path) { 'some/other-path' }
before do
allow_any_instance_of(Gitlab::Checks::ProjectMoved).to receive(:permanent_redirect?).and_return(true)
end
it 'allows push and pull access' do
aggregate_failures do
expect { push_access_check }.not_to raise_error
end
end
it_behaves_like 'check_project_moved' it_behaves_like 'check_project_moved'
end end
context 'with a permanent redirect and http protocol' do context 'with a redirect and http protocol' do
let(:redirected_path) { 'some/other-path' } let(:redirected_path) { 'some/other-path' }
let(:protocol) { 'http' } let(:protocol) { 'http' }
before do
allow_any_instance_of(Gitlab::Checks::ProjectMoved).to receive(:permanent_redirect?).and_return(true)
end
it 'allows_push and pull access' do
aggregate_failures do
expect { push_access_check }.not_to raise_error
end
end
it_behaves_like 'check_project_moved' it_behaves_like 'check_project_moved'
end end
context 'with a temporal redirect and ssh protocol' do
let(:redirected_path) { 'some/other-path' }
it 'blocks push and pull access' do
aggregate_failures do
expect { push_access_check }.to raise_error(described_class::ProjectMovedError, /Project '#{redirected_path}' was moved to '#{project.full_path}'/)
expect { push_access_check }.to raise_error(described_class::ProjectMovedError, /git remote set-url origin #{project.ssh_url_to_repo}/)
expect { pull_access_check }.to raise_error(described_class::ProjectMovedError, /Project '#{redirected_path}' was moved to '#{project.full_path}'/)
expect { pull_access_check }.to raise_error(described_class::ProjectMovedError, /git remote set-url origin #{project.ssh_url_to_repo}/)
end
end
end
context 'with a temporal redirect and http protocol' do
let(:redirected_path) { 'some/other-path' }
let(:protocol) { 'http' }
it 'does not allow to push and pull access' do
expect { push_access_check }.to raise_error(described_class::ProjectMovedError, /git remote set-url origin #{project.http_url_to_repo}/)
expect { pull_access_check }.to raise_error(described_class::ProjectMovedError, /git remote set-url origin #{project.http_url_to_repo}/)
end
end
end end
describe '#check_authentication_abilities!' do describe '#check_authentication_abilities!' do
......
...@@ -16,66 +16,6 @@ describe Route do ...@@ -16,66 +16,6 @@ describe Route do
it { is_expected.to validate_presence_of(:source) } it { is_expected.to validate_presence_of(:source) }
it { is_expected.to validate_presence_of(:path) } it { is_expected.to validate_presence_of(:path) }
it { is_expected.to validate_uniqueness_of(:path).case_insensitive } it { is_expected.to validate_uniqueness_of(:path).case_insensitive }
describe '#ensure_permanent_paths' do
context 'when the route is not yet persisted' do
let(:new_route) { described_class.new(path: 'foo', source: build(:group)) }
context 'when permanent conflicting redirects exist' do
it 'is invalid' do
redirect = build(:redirect_route, :permanent, path: 'foo/bar/baz')
redirect.save!(validate: false)
expect(new_route.valid?).to be_falsey
expect(new_route.errors.first[1]).to eq('has been taken before')
end
end
context 'when no permanent conflicting redirects exist' do
it 'is valid' do
expect(new_route.valid?).to be_truthy
end
end
end
context 'when path has changed' do
before do
route.path = 'foo'
end
context 'when permanent conflicting redirects exist' do
it 'is invalid' do
redirect = build(:redirect_route, :permanent, path: 'foo/bar/baz')
redirect.save!(validate: false)
expect(route.valid?).to be_falsey
expect(route.errors.first[1]).to eq('has been taken before')
end
end
context 'when no permanent conflicting redirects exist' do
it 'is valid' do
expect(route.valid?).to be_truthy
end
end
end
context 'when path has not changed' do
context 'when permanent conflicting redirects exist' do
it 'is valid' do
redirect = build(:redirect_route, :permanent, path: 'git_lab/foo/bar')
redirect.save!(validate: false)
expect(route.valid?).to be_truthy
end
end
context 'when no permanent conflicting redirects exist' do
it 'is valid' do
expect(route.valid?).to be_truthy
end
end
end
end
end end
describe 'callbacks' do describe 'callbacks' do
...@@ -211,43 +151,31 @@ describe Route do ...@@ -211,43 +151,31 @@ describe Route do
end end
context 'when the source is a Project' do context 'when the source is a Project' do
it 'creates a temporal RedirectRoute' do it 'creates a RedirectRoute' do
project = create(:project) project = create(:project)
route = project.route route = project.route
redirect_route = route.create_redirect('foo') redirect_route = route.create_redirect('foo')
expect(redirect_route.permanent?).to be_falsy expect(redirect_route).not_to be_nil
end end
end end
context 'when the source is not a project' do context 'when the source is not a project' do
it 'creates a permanent RedirectRoute' do it 'creates a RedirectRoute' do
redirect_route = route.create_redirect('foo', permanent: true) redirect_route = route.create_redirect('foo')
expect(redirect_route.permanent?).to be_truthy expect(redirect_route).not_to be_nil
end end
end end
end end
describe '#delete_conflicting_redirects' do describe '#delete_conflicting_redirects' do
context 'with permanent redirect' do let(:route) { create(:project).route }
it 'does not delete the redirect' do
route.create_redirect("#{route.path}/foo", permanent: true)
expect do
route.delete_conflicting_redirects
end.not_to change { RedirectRoute.count }
end
end
context 'with temporal redirect' do
let(:route) { create(:project).route }
it 'deletes the redirect' do it 'deletes the redirect' do
route.create_redirect("#{route.path}/foo") route.create_redirect("#{route.path}/foo")
expect do expect do
route.delete_conflicting_redirects route.delete_conflicting_redirects
end.to change { RedirectRoute.count }.by(-1) end.to change { RedirectRoute.count }.by(-1)
end
end end
context 'when a redirect route with the same path exists' do context 'when a redirect route with the same path exists' do
...@@ -289,31 +217,18 @@ describe Route do ...@@ -289,31 +217,18 @@ describe Route do
end end
describe '#conflicting_redirects' do describe '#conflicting_redirects' do
let(:route) { create(:project).route }
it 'returns an ActiveRecord::Relation' do it 'returns an ActiveRecord::Relation' do
expect(route.conflicting_redirects).to be_an(ActiveRecord::Relation) expect(route.conflicting_redirects).to be_an(ActiveRecord::Relation)
end end
context 'with permanent redirects' do it 'returns the redirect routes' do
it 'does not return anything' do redirect1 = route.create_redirect("#{route.path}/foo")
route.create_redirect("#{route.path}/foo", permanent: true) redirect2 = route.create_redirect("#{route.path}/foo/bar")
route.create_redirect("#{route.path}/foo/bar", permanent: true) redirect3 = route.create_redirect("#{route.path}/baz/quz")
route.create_redirect("#{route.path}/baz/quz", permanent: true)
expect(route.conflicting_redirects).to be_empty expect(route.conflicting_redirects).to match_array([redirect1, redirect2, redirect3])
end
end
context 'with temporal redirects' do
let(:route) { create(:project).route }
it 'returns the redirect routes' do
route = create(:project).route
redirect1 = route.create_redirect("#{route.path}/foo")
redirect2 = route.create_redirect("#{route.path}/foo/bar")
redirect3 = route.create_redirect("#{route.path}/baz/quz")
expect(route.conflicting_redirects).to match_array([redirect1, redirect2, redirect3])
end
end end
context 'when a redirect route with the same path exists' do context 'when a redirect route with the same path exists' do
...@@ -348,44 +263,6 @@ describe Route do ...@@ -348,44 +263,6 @@ describe Route do
end end
end end
describe "#conflicting_redirect_exists?" do
context 'when a conflicting redirect exists' do
let(:group1) { create(:group, path: 'foo') }
let(:group2) { create(:group, path: 'baz') }
it 'should not be saved' do
group1.path = 'bar'
group1.save
group2.path = 'foo'
expect(group2.save).to be_falsy
end
it 'should return an error on path' do
group1.path = 'bar'
group1.save
group2.path = 'foo'
group2.valid?
expect(group2.errors[:path]).to eq(['has been taken before'])
end
end
context 'when a conflicting redirect does not exist' do
let(:project1) { create(:project, path: 'foo') }
let(:project2) { create(:project, path: 'baz') }
it 'should be saved' do
project1.path = 'bar'
project1.save
project2.path = 'foo'
expect(project2.save).to be_truthy
end
end
end
describe '#delete_conflicting_orphaned_routes' do describe '#delete_conflicting_orphaned_routes' do
context 'when there is a conflicting route' do context 'when there is a conflicting route' do
let!(:conflicting_group) { create(:group, path: 'foo') } let!(:conflicting_group) { create(:group, path: 'foo') }
......
...@@ -126,23 +126,6 @@ describe User do ...@@ -126,23 +126,6 @@ describe User do
end end
end end
context 'when the username was used by another user before' do
let(:username) { 'foo' }
let!(:other_user) { create(:user, username: username) }
before do
other_user.username = 'bar'
other_user.save!
end
it 'is invalid' do
user = build(:user, username: username)
expect(user).not_to be_valid
expect(user.errors.full_messages).to eq(['Username has been taken before'])
end
end
context 'when the username is in use by another user' do context 'when the username is in use by another user' do
let(:username) { 'foo' } let(:username) { 'foo' }
let!(:other_user) { create(:user, username: username) } let!(:other_user) { create(:user, username: username) }
...@@ -2699,27 +2682,19 @@ describe User do ...@@ -2699,27 +2682,19 @@ describe User do
end end
end end
describe "#username_previously_taken?" do context 'changing a username' do
let(:user1) { create(:user, username: 'foo') } let(:user) { create(:user, username: 'foo') }
context 'when the username has been taken before' do it 'creates a redirect route' do
before do expect { user.update!(username: 'bar') }
user1.username = 'bar' .to change { RedirectRoute.where(path: 'foo').count }.by(1)
user1.save!
end
it 'should raise an ActiveRecord::RecordInvalid exception' do
user2 = build(:user, username: 'foo')
expect { user2.save! }.to raise_error(ActiveRecord::RecordInvalid, /Username has been taken before/)
end
end end
context 'when the username has not been taken before' do it 'deletes the redirect when a user with the old username was created' do
it 'should be valid' do user.update!(username: 'bar')
expect(RedirectRoute.count).to eq(0)
user2 = build(:user, username: 'baz') expect { create(:user, username: 'foo') }
expect(user2).to be_valid .to change { RedirectRoute.where(path: 'foo').count }.by(-1)
end
end end
end end
end end
...@@ -344,20 +344,11 @@ describe 'Git HTTP requests' do ...@@ -344,20 +344,11 @@ describe 'Git HTTP requests' do
context 'and the user requests a redirected path' do context 'and the user requests a redirected path' do
let!(:redirect) { project.route.create_redirect('foo/bar') } let!(:redirect) { project.route.create_redirect('foo/bar') }
let(:path) { "#{redirect.path}.git" } let(:path) { "#{redirect.path}.git" }
let(:project_moved_message) do
<<-MSG.strip_heredoc
Project '#{redirect.path}' was moved to '#{project.full_path}'.
Please update your Git remote: it 'downloads get status 200 for redirects' do
git remote set-url origin #{project.http_url_to_repo} and try again.
MSG
end
it 'downloads get status 404 with "project was moved" message' do
clone_get(path, {}) clone_get(path, {})
expect(response).to have_gitlab_http_status(:not_found)
expect(response.body).to match(project_moved_message) expect(response).to have_gitlab_http_status(:ok)
end end
end end
end end
...@@ -559,20 +550,19 @@ describe 'Git HTTP requests' do ...@@ -559,20 +550,19 @@ describe 'Git HTTP requests' do
Please update your Git remote: Please update your Git remote:
git remote set-url origin #{project.http_url_to_repo} and try again. git remote set-url origin #{project.http_url_to_repo}.
MSG MSG
end end
it 'downloads get status 404 with "project was moved" message' do it 'downloads get status 200' do
clone_get(path, env) clone_get(path, env)
expect(response).to have_gitlab_http_status(:not_found)
expect(response.body).to match(project_moved_message) expect(response).to have_gitlab_http_status(:ok)
end end
it 'uploads get status 404 with "project was moved" message' do it 'uploads get status 404 with "project was moved" message' do
upload(path, env) do |response| upload(path, env) do |response|
expect(response).to have_gitlab_http_status(:not_found) expect(response).to have_gitlab_http_status(:ok)
expect(response.body).to match(project_moved_message)
end end
end end
end end
......
...@@ -222,8 +222,8 @@ describe Groups::TransferService, :postgresql do ...@@ -222,8 +222,8 @@ describe Groups::TransferService, :postgresql do
expect(new_parent_group.children.first).to eq(group) expect(new_parent_group.children.first).to eq(group)
end end
it 'should create a permanent redirect for the group' do it 'should create a redirect for the group' do
expect(group.redirect_routes.permanent.count).to eq(1) expect(group.redirect_routes.count).to eq(1)
end end
end end
...@@ -243,10 +243,10 @@ describe Groups::TransferService, :postgresql do ...@@ -243,10 +243,10 @@ describe Groups::TransferService, :postgresql do
end end
end end
it 'should create permanent redirects for the subgroups' do it 'should create redirects for the subgroups' do
expect(group.redirect_routes.permanent.count).to eq(1) expect(group.redirect_routes.count).to eq(1)
expect(subgroup1.redirect_routes.permanent.count).to eq(1) expect(subgroup1.redirect_routes.count).to eq(1)
expect(subgroup2.redirect_routes.permanent.count).to eq(1) expect(subgroup2.redirect_routes.count).to eq(1)
end end
context 'when the new parent has a higher visibility than the children' do context 'when the new parent has a higher visibility than the children' do
...@@ -287,9 +287,9 @@ describe Groups::TransferService, :postgresql do ...@@ -287,9 +287,9 @@ describe Groups::TransferService, :postgresql do
end end
it 'should create permanent redirects for the projects' do it 'should create permanent redirects for the projects' do
expect(group.redirect_routes.permanent.count).to eq(1) expect(group.redirect_routes.count).to eq(1)
expect(project1.redirect_routes.permanent.count).to eq(1) expect(project1.redirect_routes.count).to eq(1)
expect(project2.redirect_routes.permanent.count).to eq(1) expect(project2.redirect_routes.count).to eq(1)
end end
context 'when the new parent has a higher visibility than the projects' do context 'when the new parent has a higher visibility than the projects' do
...@@ -338,12 +338,12 @@ describe Groups::TransferService, :postgresql do ...@@ -338,12 +338,12 @@ describe Groups::TransferService, :postgresql do
end end
end end
it 'should create permanent redirect for the subgroups and projects' do it 'should create redirect for the subgroups and projects' do
expect(group.redirect_routes.permanent.count).to eq(1) expect(group.redirect_routes.count).to eq(1)
expect(subgroup1.redirect_routes.permanent.count).to eq(1) expect(subgroup1.redirect_routes.count).to eq(1)
expect(subgroup2.redirect_routes.permanent.count).to eq(1) expect(subgroup2.redirect_routes.count).to eq(1)
expect(project1.redirect_routes.permanent.count).to eq(1) expect(project1.redirect_routes.count).to eq(1)
expect(project2.redirect_routes.permanent.count).to eq(1) expect(project2.redirect_routes.count).to eq(1)
end end
end end
...@@ -380,12 +380,12 @@ describe Groups::TransferService, :postgresql do ...@@ -380,12 +380,12 @@ describe Groups::TransferService, :postgresql do
end end
end end
it 'should create permanent redirect for the subgroups and projects' do it 'should create redirect for the subgroups and projects' do
expect(group.redirect_routes.permanent.count).to eq(1) expect(group.redirect_routes.count).to eq(1)
expect(project1.redirect_routes.permanent.count).to eq(1) expect(project1.redirect_routes.count).to eq(1)
expect(subgroup1.redirect_routes.permanent.count).to eq(1) expect(subgroup1.redirect_routes.count).to eq(1)
expect(nested_subgroup.redirect_routes.permanent.count).to eq(1) expect(nested_subgroup.redirect_routes.count).to eq(1)
expect(nested_project.redirect_routes.permanent.count).to eq(1) expect(nested_project.redirect_routes.count).to eq(1)
end end
end end
......
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