Commit 6038355f authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'dz-nested-groups-improvements-3' into 'master'

Nested groups improvements pt 3

See merge request !9227
parents fea03a73 dcdab2ae
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
if (selected.id == null) { if (selected.id == null) {
return selected.text; return selected.text;
} else { } else {
return selected.kind + ": " + selected.path; return selected.kind + ": " + selected.full_path;
} }
}, },
data: function(term, dataCallback) { data: function(term, dataCallback) {
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
if (namespace.id == null) { if (namespace.id == null) {
return namespace.text; return namespace.text;
} else { } else {
return namespace.kind + ": " + namespace.path; return namespace.kind + ": " + namespace.full_path;
} }
}, },
renderRow: this.renderRow, renderRow: this.renderRow,
......
...@@ -10,7 +10,7 @@ module NamespacesHelper ...@@ -10,7 +10,7 @@ module NamespacesHelper
data_attr_users = { 'data-options-parent' => 'users' } data_attr_users = { 'data-options-parent' => 'users' }
group_opts = [ group_opts = [
"Groups", groups.sort_by(&:human_name).map { |g| [display_path ? g.path : g.human_name, g.id, data_attr_group] } "Groups", groups.sort_by(&:human_name).map { |g| [display_path ? g.full_path : g.human_name, g.id, data_attr_group] }
] ]
users_opts = [ users_opts = [
......
...@@ -63,7 +63,7 @@ module SubmoduleHelper ...@@ -63,7 +63,7 @@ module SubmoduleHelper
namespace = components.pop.gsub(/^\.\.$/, '') namespace = components.pop.gsub(/^\.\.$/, '')
if namespace.empty? if namespace.empty?
namespace = @project.namespace.path namespace = @project.namespace.full_path
end end
[ [
......
...@@ -598,7 +598,7 @@ class MergeRequest < ActiveRecord::Base ...@@ -598,7 +598,7 @@ class MergeRequest < ActiveRecord::Base
def source_project_namespace def source_project_namespace
if source_project && source_project.namespace if source_project && source_project.namespace
source_project.namespace.path source_project.namespace.full_path
else else
"(removed)" "(removed)"
end end
...@@ -606,7 +606,7 @@ class MergeRequest < ActiveRecord::Base ...@@ -606,7 +606,7 @@ class MergeRequest < ActiveRecord::Base
def target_project_namespace def target_project_namespace
if target_project && target_project.namespace if target_project && target_project.namespace
target_project.namespace.path target_project.namespace.full_path
else else
"(removed)" "(removed)"
end end
......
...@@ -454,7 +454,7 @@ class Project < ActiveRecord::Base ...@@ -454,7 +454,7 @@ class Project < ActiveRecord::Base
if forked? if forked?
job_id = RepositoryForkWorker.perform_async(id, forked_from_project.repository_storage_path, job_id = RepositoryForkWorker.perform_async(id, forked_from_project.repository_storage_path,
forked_from_project.path_with_namespace, forked_from_project.path_with_namespace,
self.namespace.path) self.namespace.full_path)
else else
job_id = RepositoryImportWorker.perform_async(self.id) job_id = RepositoryImportWorker.perform_async(self.id)
end end
...@@ -942,8 +942,8 @@ class Project < ActiveRecord::Base ...@@ -942,8 +942,8 @@ class Project < ActiveRecord::Base
Gitlab::AppLogger.info "Project was renamed: #{old_path_with_namespace} -> #{new_path_with_namespace}" Gitlab::AppLogger.info "Project was renamed: #{old_path_with_namespace} -> #{new_path_with_namespace}"
Gitlab::UploadsTransfer.new.rename_project(path_was, path, namespace.path) Gitlab::UploadsTransfer.new.rename_project(path_was, path, namespace.full_path)
Gitlab::PagesTransfer.new.rename_project(path_was, path, namespace.path) Gitlab::PagesTransfer.new.rename_project(path_was, path, namespace.full_path)
end end
# Expires various caches before a project is renamed. # Expires various caches before a project is renamed.
...@@ -1150,19 +1150,25 @@ class Project < ActiveRecord::Base ...@@ -1150,19 +1150,25 @@ class Project < ActiveRecord::Base
end end
def pages_url def pages_url
subdomain, _, url_path = full_path.partition('/')
# The hostname always needs to be in downcased # The hostname always needs to be in downcased
# All web servers convert hostname to lowercase # All web servers convert hostname to lowercase
host = "#{namespace.path}.#{Settings.pages.host}".downcase host = "#{subdomain}.#{Settings.pages.host}".downcase
# The host in URL always needs to be downcased # The host in URL always needs to be downcased
url = Gitlab.config.pages.url.sub(/^https?:\/\//) do |prefix| url = Gitlab.config.pages.url.sub(/^https?:\/\//) do |prefix|
"#{prefix}#{namespace.path}." "#{prefix}#{subdomain}."
end.downcase end.downcase
# If the project path is the same as host, we serve it as group page # If the project path is the same as host, we serve it as group page
return url if host == path return url if host == url_path
"#{url}/#{url_path}"
end
"#{url}/#{path}" def pages_subdomain
full_path.partition('/').first
end end
def pages_path def pages_path
...@@ -1179,8 +1185,8 @@ class Project < ActiveRecord::Base ...@@ -1179,8 +1185,8 @@ class Project < ActiveRecord::Base
# 3. We asynchronously remove pages with force # 3. We asynchronously remove pages with force
temp_path = "#{path}.#{SecureRandom.hex}.deleted" temp_path = "#{path}.#{SecureRandom.hex}.deleted"
if Gitlab::PagesTransfer.new.rename_project(path, temp_path, namespace.path) if Gitlab::PagesTransfer.new.rename_project(path, temp_path, namespace.full_path)
PagesWorker.perform_in(5.minutes, :remove, namespace.path, temp_path) PagesWorker.perform_in(5.minutes, :remove, namespace.full_path, temp_path)
end end
end end
...@@ -1230,7 +1236,7 @@ class Project < ActiveRecord::Base ...@@ -1230,7 +1236,7 @@ class Project < ActiveRecord::Base
end end
def ensure_dir_exist def ensure_dir_exist
gitlab_shell.add_namespace(repository_storage_path, namespace.path) gitlab_shell.add_namespace(repository_storage_path, namespace.full_path)
end end
def predefined_variables def predefined_variables
...@@ -1238,7 +1244,7 @@ class Project < ActiveRecord::Base ...@@ -1238,7 +1244,7 @@ class Project < ActiveRecord::Base
{ key: 'CI_PROJECT_ID', value: id.to_s, public: true }, { key: 'CI_PROJECT_ID', value: id.to_s, public: true },
{ key: 'CI_PROJECT_NAME', value: path, public: true }, { key: 'CI_PROJECT_NAME', value: path, public: true },
{ key: 'CI_PROJECT_PATH', value: path_with_namespace, public: true }, { key: 'CI_PROJECT_PATH', value: path_with_namespace, public: true },
{ key: 'CI_PROJECT_NAMESPACE', value: namespace.path, public: true }, { key: 'CI_PROJECT_NAMESPACE', value: namespace.full_path, public: true },
{ key: 'CI_PROJECT_URL', value: web_url, public: true } { key: 'CI_PROJECT_URL', value: web_url, public: true }
] ]
end end
......
...@@ -12,7 +12,7 @@ class DroneCiService < CiService ...@@ -12,7 +12,7 @@ class DroneCiService < CiService
def compose_service_hook def compose_service_hook
hook = service_hook || build_service_hook hook = service_hook || build_service_hook
# If using a service template, project may not be available # If using a service template, project may not be available
hook.url = [drone_url, "/api/hook", "?owner=#{project.namespace.path}", "&name=#{project.path}", "&access_token=#{token}"].join if project hook.url = [drone_url, "/api/hook", "?owner=#{project.namespace.full_path}", "&name=#{project.path}", "&access_token=#{token}"].join if project
hook.enable_ssl_verification = !!enable_ssl_verification hook.enable_ssl_verification = !!enable_ssl_verification
hook.save hook.save
end end
...@@ -38,7 +38,7 @@ class DroneCiService < CiService ...@@ -38,7 +38,7 @@ class DroneCiService < CiService
def commit_status_path(sha, ref) def commit_status_path(sha, ref)
url = [drone_url, url = [drone_url,
"gitlab/#{project.namespace.path}/#{project.path}/commits/#{sha}", "gitlab/#{project.full_path}/commits/#{sha}",
"?branch=#{URI::encode(ref.to_s)}&access_token=#{token}"] "?branch=#{URI::encode(ref.to_s)}&access_token=#{token}"]
URI.join(*url).to_s URI.join(*url).to_s
...@@ -73,7 +73,7 @@ class DroneCiService < CiService ...@@ -73,7 +73,7 @@ class DroneCiService < CiService
def build_page(sha, ref) def build_page(sha, ref)
url = [drone_url, url = [drone_url,
"gitlab/#{project.namespace.path}/#{project.path}/redirect/commits/#{sha}", "gitlab/#{project.full_path}/redirect/commits/#{sha}",
"?branch=#{URI::encode(ref.to_s)}"] "?branch=#{URI::encode(ref.to_s)}"]
URI.join(*url).to_s URI.join(*url).to_s
......
...@@ -30,7 +30,7 @@ module Projects ...@@ -30,7 +30,7 @@ module Projects
Project.transaction do Project.transaction do
old_path = project.path_with_namespace old_path = project.path_with_namespace
old_group = project.group old_group = project.group
new_path = File.join(new_namespace.try(:path) || '', project.path) new_path = File.join(new_namespace.try(:full_path) || '', project.path)
if Project.where(path: project.path, namespace_id: new_namespace.try(:id)).present? if Project.where(path: project.path, namespace_id: new_namespace.try(:id)).present?
raise TransferError.new("Project with same path in target namespace already exists") raise TransferError.new("Project with same path in target namespace already exists")
...@@ -63,10 +63,10 @@ module Projects ...@@ -63,10 +63,10 @@ module Projects
Labels::TransferService.new(current_user, old_group, project).execute Labels::TransferService.new(current_user, old_group, project).execute
# Move uploads # Move uploads
Gitlab::UploadsTransfer.new.move_project(project.path, old_namespace.path, new_namespace.path) Gitlab::UploadsTransfer.new.move_project(project.path, old_namespace.full_path, new_namespace.full_path)
# Move pages # Move pages
Gitlab::PagesTransfer.new.move_project(project.path, old_namespace.path, new_namespace.path) Gitlab::PagesTransfer.new.move_project(project.path, old_namespace.full_path, new_namespace.full_path)
project.old_path_with_namespace = old_path project.old_path_with_namespace = old_path
......
...@@ -163,6 +163,6 @@ ...@@ -163,6 +163,6 @@
- @groups.each do |group| - @groups.each do |group|
%p %p
= link_to [:admin, group], class: 'str-truncated-60' do = link_to [:admin, group], class: 'str-truncated-60' do
= group.name = group.full_name
%span.light.pull-right %span.light.pull-right
#{time_ago_with_tooltip(group.created_at)} #{time_ago_with_tooltip(group.created_at)}
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
- toggle_text = 'Namespace' - toggle_text = 'Namespace'
- if params[:namespace_id].present? - if params[:namespace_id].present?
- namespace = Namespace.find(params[:namespace_id]) - namespace = Namespace.find(params[:namespace_id])
- toggle_text = "#{namespace.kind}: #{namespace.path}" - toggle_text = "#{namespace.kind}: #{namespace.full_path}"
= dropdown_toggle(toggle_text, { toggle: 'dropdown' }, { toggle_class: 'js-namespace-select large' }) = dropdown_toggle(toggle_text, { toggle: 'dropdown' }, { toggle_class: 'js-namespace-select large' })
.dropdown-menu.dropdown-select.dropdown-menu-align-right .dropdown-menu.dropdown-select.dropdown-menu-align-right
= dropdown_title('Namespaces') = dropdown_title('Namespaces')
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
import_button = tr.find(".btn-import") import_button = tr.find(".btn-import")
origin_target = target_field.text() origin_target = target_field.text()
project_name = "#{@project_name}" project_name = "#{@project_name}"
origin_namespace = "#{@target_namespace.path}" origin_namespace = "#{@target_namespace.full_path}"
target_field.empty() target_field.empty()
target_field.append("<p class='alert alert-danger'>This namespace has already been taken! Please choose another one.</p>") target_field.append("<p class='alert alert-danger'>This namespace has already been taken! Please choose another one.</p>")
target_field.append("<input type='text' name='target_namespace' />") target_field.append("<input type='text' name='target_namespace' />")
......
...@@ -232,7 +232,7 @@ ...@@ -232,7 +232,7 @@
.form-group .form-group
.input-group .input-group
.input-group-addon .input-group-addon
#{URI.join(root_url, @project.namespace.path)}/ #{URI.join(root_url, @project.namespace.full_path)}/
= f.text_field :path, class: 'form-control' = f.text_field :path, class: 'form-control'
%ul %ul
%li Be careful. Renaming a project's repository can have unintended side effects. %li Be careful. Renaming a project's repository can have unintended side effects.
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
= icon("folder-open-o", class: "settings-list-icon") = icon("folder-open-o", class: "settings-list-icon")
.pull-left .pull-left
= link_to group do = link_to group do
= group.name = group.full_name
%br %br
up to #{group_link.human_access} up to #{group_link.human_access}
- if group_link.expires? - if group_link.expires?
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
%p %p
To access the domain create a new DNS record: To access the domain create a new DNS record:
%pre %pre
#{@domain.domain} CNAME #{@domain.project.namespace.path}.#{Settings.pages.host}. #{@domain.domain} CNAME #{@domain.project.pages_subdomain}.#{Settings.pages.host}.
%tr %tr
%td %td
Certificate Certificate
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
%span.list-item-name %span.list-item-name
= image_tag group_icon(group), class: "avatar s40", alt: '' = image_tag group_icon(group), class: "avatar s40", alt: ''
%strong %strong
= link_to group.name, group_path(group) = link_to group.full_name, group_path(group)
.cgray .cgray
Joined #{time_ago_with_tooltip(group.created_at)} Joined #{time_ago_with_tooltip(group.created_at)}
- if group_link.expires? - if group_link.expires?
......
...@@ -35,6 +35,12 @@ Example response: ...@@ -35,6 +35,12 @@ Example response:
"id": 2, "id": 2,
"path": "group1", "path": "group1",
"kind": "group" "kind": "group"
},
{
"id": 3,
"path": "bar",
"kind": "group",
"full_path": "foo/bar",
} }
] ]
``` ```
...@@ -64,7 +70,8 @@ Example response: ...@@ -64,7 +70,8 @@ Example response:
{ {
"id": 4, "id": 4,
"path": "twitter", "path": "twitter",
"kind": "group" "kind": "group",
"full_path": "twitter",
} }
] ]
``` ```
...@@ -77,7 +77,8 @@ Parameters: ...@@ -77,7 +77,8 @@ Parameters:
"id": 3, "id": 3,
"name": "Diaspora", "name": "Diaspora",
"path": "diaspora", "path": "diaspora",
"kind": "group" "kind": "group",
"full_path": "diaspora"
}, },
"archived": false, "archived": false,
"avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png", "avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png",
...@@ -127,7 +128,8 @@ Parameters: ...@@ -127,7 +128,8 @@ Parameters:
"id": 4, "id": 4,
"name": "Brightbox", "name": "Brightbox",
"path": "brightbox", "path": "brightbox",
"kind": "group" "kind": "group",
"full_path": "brightbox"
}, },
"permissions": { "permissions": {
"project_access": { "project_access": {
...@@ -207,7 +209,8 @@ Parameters: ...@@ -207,7 +209,8 @@ Parameters:
"id": 3, "id": 3,
"name": "Diaspora", "name": "Diaspora",
"path": "diaspora", "path": "diaspora",
"kind": "group" "kind": "group",
"full_path": "diaspora"
}, },
"permissions": { "permissions": {
"project_access": { "project_access": {
...@@ -585,7 +588,8 @@ Example response: ...@@ -585,7 +588,8 @@ Example response:
"id": 3, "id": 3,
"name": "Diaspora", "name": "Diaspora",
"path": "diaspora", "path": "diaspora",
"kind": "group" "kind": "group",
"full_path": "diaspora"
}, },
"archived": true, "archived": true,
"avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png", "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png",
...@@ -650,7 +654,8 @@ Example response: ...@@ -650,7 +654,8 @@ Example response:
"id": 3, "id": 3,
"name": "Diaspora", "name": "Diaspora",
"path": "diaspora", "path": "diaspora",
"kind": "group" "kind": "group",
"full_path": "diaspora"
}, },
"archived": true, "archived": true,
"avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png", "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png",
...@@ -721,7 +726,8 @@ Example response: ...@@ -721,7 +726,8 @@ Example response:
"id": 3, "id": 3,
"name": "Diaspora", "name": "Diaspora",
"path": "diaspora", "path": "diaspora",
"kind": "group" "kind": "group",
"full_path": "diaspora"
}, },
"permissions": { "permissions": {
"project_access": { "project_access": {
...@@ -803,7 +809,8 @@ Example response: ...@@ -803,7 +809,8 @@ Example response:
"id": 3, "id": 3,
"name": "Diaspora", "name": "Diaspora",
"path": "diaspora", "path": "diaspora",
"kind": "group" "kind": "group",
"full_path": "diaspora"
}, },
"permissions": { "permissions": {
"project_access": { "project_access": {
......
...@@ -414,7 +414,7 @@ module API ...@@ -414,7 +414,7 @@ module API
end end
class Namespace < Grape::Entity class Namespace < Grape::Entity
expose :id, :name, :path, :kind expose :id, :name, :path, :kind, :full_path
end end
class MemberAccess < Grape::Entity class MemberAccess < Grape::Entity
......
...@@ -12,7 +12,7 @@ module Backup ...@@ -12,7 +12,7 @@ module Backup
path_to_project_bundle = path_to_bundle(project) path_to_project_bundle = path_to_bundle(project)
# Create namespace dir if missing # Create namespace dir if missing
FileUtils.mkdir_p(File.join(backup_repos_path, project.namespace.path)) if project.namespace FileUtils.mkdir_p(File.join(backup_repos_path, project.namespace.full_path)) if project.namespace
if project.empty_repo? if project.empty_repo?
$progress.puts "[SKIPPED]".color(:cyan) $progress.puts "[SKIPPED]".color(:cyan)
......
...@@ -310,7 +310,7 @@ module Gitlab ...@@ -310,7 +310,7 @@ module Gitlab
if name == project.import_source if name == project.import_source
"##{id}" "##{id}"
else else
"#{project.namespace.path}/#{name}##{id}" "#{project.namespace.full_path}/#{name}##{id}"
end end
text = "~~#{text}~~" if deleted text = "~~#{text}~~" if deleted
text text
......
...@@ -35,7 +35,7 @@ module Gitlab ...@@ -35,7 +35,7 @@ module Gitlab
end end
def export_filename(project:) def export_filename(project:)
basename = "#{Time.now.strftime('%Y-%m-%d_%H-%M-%3N')}_#{project.namespace.path}_#{project.path}" basename = "#{Time.now.strftime('%Y-%m-%d_%H-%M-%3N')}_#{project.namespace.full_path}_#{project.path}"
"#{basename[0..FILENAME_LIMIT]}_export.tar.gz" "#{basename[0..FILENAME_LIMIT]}_export.tar.gz"
end end
......
...@@ -56,7 +56,7 @@ module Gitlab ...@@ -56,7 +56,7 @@ module Gitlab
end end
def path_with_namespace def path_with_namespace
File.join(@project.namespace.path, @project.path) File.join(@project.namespace.full_path, @project.path)
end end
def repo_path def repo_path
......
...@@ -172,7 +172,7 @@ module Gitlab ...@@ -172,7 +172,7 @@ module Gitlab
# add_namespace("/path/to/storage", "gitlab") # add_namespace("/path/to/storage", "gitlab")
# #
def add_namespace(storage, name) def add_namespace(storage, name)
FileUtils.mkdir(full_path(storage, name), mode: 0770) unless exists?(storage, name) FileUtils.mkdir_p(full_path(storage, name), mode: 0770) unless exists?(storage, name)
end end
# Remove directory from repositories storage # Remove directory from repositories storage
......
...@@ -2,14 +2,15 @@ require 'spec_helper' ...@@ -2,14 +2,15 @@ require 'spec_helper'
describe Gitlab::ImportExport, services: true do describe Gitlab::ImportExport, services: true do
describe 'export filename' do describe 'export filename' do
let(:project) { create(:empty_project, :public, path: 'project-path') } let(:group) { create(:group, :nested) }
let(:project) { create(:empty_project, :public, path: 'project-path', namespace: group) }
it 'contains the project path' do it 'contains the project path' do
expect(described_class.export_filename(project: project)).to include(project.path) expect(described_class.export_filename(project: project)).to include(project.path)
end end
it 'contains the namespace path' do it 'contains the namespace path' do
expect(described_class.export_filename(project: project)).to include(project.namespace.path) expect(described_class.export_filename(project: project)).to include(project.namespace.full_path)
end end
it 'does not go over a certain length' do it 'does not go over a certain length' do
......
...@@ -1852,8 +1852,8 @@ describe Project, models: true do ...@@ -1852,8 +1852,8 @@ describe Project, models: true do
end end
describe '#pages_url' do describe '#pages_url' do
let(:group) { create :group, name: group_name } let(:group) { create :group, name: 'Group' }
let(:project) { create :empty_project, namespace: group, name: project_name } let(:nested_group) { create :group, parent: group }
let(:domain) { 'Example.com' } let(:domain) { 'Example.com' }
subject { project.pages_url } subject { project.pages_url }
...@@ -1863,18 +1863,37 @@ describe Project, models: true do ...@@ -1863,18 +1863,37 @@ describe Project, models: true do
allow(Gitlab.config.pages).to receive(:url).and_return('http://example.com') allow(Gitlab.config.pages).to receive(:url).and_return('http://example.com')
end end
context 'top-level group' do
let(:project) { create :empty_project, namespace: group, name: project_name }
context 'group page' do context 'group page' do
let(:group_name) { 'Group' }
let(:project_name) { 'group.example.com' } let(:project_name) { 'group.example.com' }
it { is_expected.to eq("http://group.example.com") } it { is_expected.to eq("http://group.example.com") }
end end
context 'project page' do context 'project page' do
let(:group_name) { 'Group' }
let(:project_name) { 'Project' } let(:project_name) { 'Project' }
it { is_expected.to eq("http://group.example.com/project") } it { is_expected.to eq("http://group.example.com/project") }
end end
end end
context 'nested group' do
let(:project) { create :empty_project, namespace: nested_group, name: project_name }
let(:expected_url) { "http://group.example.com/#{nested_group.path}/#{project.path}" }
context 'group page' do
let(:project_name) { 'group.example.com' }
it { is_expected.to eq(expected_url) }
end
context 'project page' do
let(:project_name) { 'Project' }
it { is_expected.to eq(expected_url) }
end
end
end
end end
...@@ -5,7 +5,7 @@ describe API::Namespaces, api: true do ...@@ -5,7 +5,7 @@ describe API::Namespaces, api: true do
let(:admin) { create(:admin) } let(:admin) { create(:admin) }
let(:user) { create(:user) } let(:user) { create(:user) }
let!(:group1) { create(:group) } let!(:group1) { create(:group) }
let!(:group2) { create(:group) } let!(:group2) { create(:group, :nested) }
describe "GET /namespaces" do describe "GET /namespaces" do
context "when unauthenticated" do context "when unauthenticated" do
...@@ -25,11 +25,13 @@ describe API::Namespaces, api: true do ...@@ -25,11 +25,13 @@ describe API::Namespaces, api: true do
end end
it "admin: returns an array of matched namespaces" do it "admin: returns an array of matched namespaces" do
get api("/namespaces?search=#{group1.name}", admin) get api("/namespaces?search=#{group2.name}", admin)
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
expect(json_response).to be_an Array expect(json_response).to be_an Array
expect(json_response.length).to eq(1) expect(json_response.length).to eq(1)
expect(json_response.last['path']).to eq(group2.path)
expect(json_response.last['full_path']).to eq(group2.full_path)
end end
end end
......
...@@ -585,6 +585,7 @@ describe API::Projects, api: true do ...@@ -585,6 +585,7 @@ describe API::Projects, api: true do
'name' => user.namespace.name, 'name' => user.namespace.name,
'path' => user.namespace.path, 'path' => user.namespace.path,
'kind' => user.namespace.kind, 'kind' => user.namespace.kind,
'full_path' => user.namespace.full_path,
}) })
end end
......
...@@ -682,6 +682,7 @@ describe API::V3::Projects, api: true do ...@@ -682,6 +682,7 @@ describe API::V3::Projects, api: true do
'name' => user.namespace.name, 'name' => user.namespace.name,
'path' => user.namespace.path, 'path' => user.namespace.path,
'kind' => user.namespace.kind, 'kind' => user.namespace.kind,
'full_path' => user.namespace.full_path,
}) })
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