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

Merge branch '221259-move-packages-to-core-ui' into 'master'

Move package UI to core [RUN AS-IF-FOSS]

Closes #221259

See merge request gitlab-org/gitlab!36667
parents 2c1600a8 fb58018a
import Api from 'ee/api'; import Api from '~/api';
import createFlash from '~/flash'; import createFlash from '~/flash';
import { FETCH_PACKAGE_VERSIONS_ERROR } from '../constants'; import { FETCH_PACKAGE_VERSIONS_ERROR } from '../constants';
import * as types from './mutation_types'; import * as types from './mutation_types';
......
import Api from 'ee/api'; import Api from '~/api';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash'; import createFlash from '~/flash';
import * as types from './mutation_types'; import * as types from './mutation_types';
......
import initPackageList from 'ee/packages/list/packages_list_app_bundle'; import initPackageList from '~/packages/list/packages_list_app_bundle';
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
if (document.getElementById('js-vue-packages-list')) { if (document.getElementById('js-vue-packages-list')) {
......
import initPackageList from 'ee/packages/list/packages_list_app_bundle'; import initPackageList from '~/packages/list/packages_list_app_bundle';
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
if (document.getElementById('js-vue-packages-list')) { if (document.getElementById('js-vue-packages-list')) {
......
import initPackageDetail from 'ee/packages/details/'; import initPackageDetail from '~/packages/details/';
document.addEventListener('DOMContentLoaded', initPackageDetail); document.addEventListener('DOMContentLoaded', initPackageDetail);
...@@ -11,8 +11,7 @@ module PackagesAccess ...@@ -11,8 +11,7 @@ module PackagesAccess
private private
def verify_packages_enabled! def verify_packages_enabled!
render_404 unless Gitlab.config.packages.enabled && render_404 unless Gitlab.config.packages.enabled
project.feature_available?(:packages)
end end
def verify_read_package! def verify_read_package!
......
...@@ -7,7 +7,7 @@ module Groups ...@@ -7,7 +7,7 @@ module Groups
private private
def verify_packages_enabled! def verify_packages_enabled!
render_404 unless group.packages_feature_available? render_404 unless group.packages_feature_enabled?
end end
end end
end end
...@@ -392,6 +392,7 @@ class ProjectsController < Projects::ApplicationController ...@@ -392,6 +392,7 @@ class ProjectsController < Projects::ApplicationController
:initialize_with_readme, :initialize_with_readme,
:autoclose_referenced_issues, :autoclose_referenced_issues,
:suggestion_commit_message, :suggestion_commit_message,
:packages_enabled,
:service_desk_enabled, :service_desk_enabled,
project_feature_attributes: %i[ project_feature_attributes: %i[
......
...@@ -28,6 +28,7 @@ module GroupsHelper ...@@ -28,6 +28,7 @@ module GroupsHelper
def group_packages_nav_link_paths def group_packages_nav_link_paths
%w[ %w[
groups/packages#index
groups/container_registries#index groups/container_registries#index
] ]
end end
...@@ -157,6 +158,15 @@ module GroupsHelper ...@@ -157,6 +158,15 @@ module GroupsHelper
groups.to_json groups.to_json
end end
def group_packages_nav?
group_packages_list_nav? ||
group_container_registry_nav?
end
def group_packages_list_nav?
@group.packages_feature_enabled?
end
private private
def get_group_sidebar_links def get_group_sidebar_links
......
# frozen_string_literal: true
module PackagesHelper
def package_sort_path(options = {})
"#{request.path}?#{options.to_param}"
end
def nuget_package_registry_url(project_id)
expose_url(api_v4_projects_packages_nuget_index_path(id: project_id, format: '.json'))
end
def package_registry_instance_url(registry_type)
expose_url("api/#{::API::API.version}/packages/#{registry_type}")
end
def package_registry_project_url(project_id, registry_type = :maven)
project_api_path = expose_path(api_v4_projects_path(id: project_id))
package_registry_project_path = "#{project_api_path}/packages/#{registry_type}"
expose_url(package_registry_project_path)
end
def package_from_presenter(package)
presenter = ::Packages::Detail::PackagePresenter.new(package)
presenter.detail_view.to_json
end
def pypi_registry_url(project_id)
full_url = expose_url(api_v4_projects_packages_pypi_simple_package_name_path({ id: project_id, package_name: '' }, true))
full_url.sub!('://', '://__token__:<your_personal_token>@')
end
def packages_coming_soon_enabled?(resource)
::Feature.enabled?(:packages_coming_soon, resource) && ::Gitlab.dev_env_or_com?
end
def packages_coming_soon_data(resource)
return unless packages_coming_soon_enabled?(resource)
{
project_path: ::Gitlab.com? ? 'gitlab-org/gitlab' : 'gitlab-org/gitlab-test',
suggested_contributions: help_page_path('user/packages/index', anchor: 'suggested-contributions')
}
end
def packages_list_data(type, resource)
{
resource_id: resource.id,
page_type: type,
empty_list_help_url: help_page_path('administration/packages/index'),
empty_list_illustration: image_path('illustrations/no-packages.svg'),
coming_soon_json: packages_coming_soon_data(resource).to_json
}
end
end
...@@ -429,9 +429,19 @@ module ProjectsHelper ...@@ -429,9 +429,19 @@ module ProjectsHelper
apply_external_nav_tabs(nav_tabs, project) apply_external_nav_tabs(nav_tabs, project)
nav_tabs += package_nav_tabs(project, current_user)
nav_tabs nav_tabs
end end
def package_nav_tabs(project, current_user)
[].tap do |tabs|
if ::Gitlab.config.packages.enabled && can?(current_user, :read_package, project)
tabs << :packages
end
end
end
def apply_external_nav_tabs(nav_tabs, project) def apply_external_nav_tabs(nav_tabs, project)
nav_tabs << :external_issue_tracker if project.external_issue_tracker nav_tabs << :external_issue_tracker if project.external_issue_tracker
nav_tabs << :external_wiki if project.external_wiki nav_tabs << :external_wiki if project.external_wiki
...@@ -584,6 +594,7 @@ module ProjectsHelper ...@@ -584,6 +594,7 @@ module ProjectsHelper
def project_permissions_settings(project) def project_permissions_settings(project)
feature = project.project_feature feature = project.project_feature
{ {
packagesEnabled: !!project.packages_enabled,
visibilityLevel: project.visibility_level, visibilityLevel: project.visibility_level,
requestAccessEnabled: !!project.request_access_enabled, requestAccessEnabled: !!project.request_access_enabled,
issuesAccessLevel: feature.issues_access_level, issuesAccessLevel: feature.issues_access_level,
...@@ -604,6 +615,8 @@ module ProjectsHelper ...@@ -604,6 +615,8 @@ module ProjectsHelper
def project_permissions_panel_data(project) def project_permissions_panel_data(project)
{ {
packagesAvailable: ::Gitlab.config.packages.enabled,
packagesHelpPath: help_page_path('user/packages/index'),
currentSettings: project_permissions_settings(project), currentSettings: project_permissions_settings(project),
canDisableEmails: can_disable_emails?(project, current_user), canDisableEmails: can_disable_emails?(project, current_user),
canChangeVisibilityLevel: can_change_visibility_level?(project, current_user), canChangeVisibilityLevel: can_change_visibility_level?(project, current_user),
......
...@@ -581,6 +581,47 @@ module SortingHelper ...@@ -581,6 +581,47 @@ module SortingHelper
def sort_value_expire_date def sort_value_expire_date
'expired_asc' 'expired_asc'
end end
def packages_sort_options_hash
{
sort_value_recently_created => sort_title_created_date,
sort_value_oldest_created => sort_title_created_date,
sort_value_name => sort_title_name,
sort_value_name_desc => sort_title_name,
sort_value_version_desc => sort_title_version,
sort_value_version_asc => sort_title_version,
sort_value_type_desc => sort_title_type,
sort_value_type_asc => sort_title_type,
sort_value_project_name_desc => sort_title_project_name,
sort_value_project_name_asc => sort_title_project_name
}
end
def packages_reverse_sort_order_hash
{
sort_value_recently_created => sort_value_oldest_created,
sort_value_oldest_created => sort_value_recently_created,
sort_value_name => sort_value_name_desc,
sort_value_name_desc => sort_value_name,
sort_value_version_desc => sort_value_version_asc,
sort_value_version_asc => sort_value_version_desc,
sort_value_type_desc => sort_value_type_asc,
sort_value_type_asc => sort_value_type_desc,
sort_value_project_name_desc => sort_value_project_name_asc,
sort_value_project_name_asc => sort_value_project_name_desc
}
end
def packages_sort_option_title(sort_value)
packages_sort_options_hash[sort_value] || sort_title_created_date
end
def packages_sort_direction_button(sort_value)
reverse_sort = packages_reverse_sort_order_hash[sort_value]
url = package_sort_path(sort: reverse_sort)
sort_direction_button(url, reverse_sort, sort_value)
end
end end
SortingHelper.prepend_if_ee('::EE::SortingHelper') SortingHelper.prepend_if_ee('::EE::SortingHelper')
...@@ -45,7 +45,7 @@ class Packages::PackageFile < ApplicationRecord ...@@ -45,7 +45,7 @@ class Packages::PackageFile < ApplicationRecord
end end
def download_path def download_path
Gitlab::Routing.url_helpers.download_project_package_file_path(project, self) if ::Gitlab.ee? Gitlab::Routing.url_helpers.download_project_package_file_path(project, self)
end end
def local? def local?
......
- if group_container_registry_nav? - packages_link = group_packages_list_nav? ? group_packages_path(@group) : group_container_registries_path(@group)
= nav_link(controller: 'groups/registry/repositories') do
= link_to group_container_registries_path(@group), title: _('Container Registry') do - if group_packages_nav?
= nav_link(controller: ['groups/packages', 'groups/registry/repositories']) do
= link_to packages_link, title: _('Packages') do
.nav-icon-container .nav-icon-container
= sprite_icon('package') = sprite_icon('package')
%span.nav-item-name %span.nav-item-name
= _('Packages & Registries') = _('Packages & Registries')
%ul.sidebar-sub-level-items %ul.sidebar-sub-level-items
= nav_link(controller: 'groups/registry/repositories', html_options: { class: "fly-out-top-item" } ) do = nav_link(controller: [:packages, :repositories], html_options: { class: "fly-out-top-item" } ) do
= link_to group_container_registries_path(@group), title: _('Container Registry') do = link_to packages_link, title: _('Packages & Registries') do
%strong.fly-out-top-item-name %strong.fly-out-top-item-name
= _('Packages & Registries') = _('Packages & Registries')
%li.divider.fly-out-top-item %li.divider.fly-out-top-item
= nav_link(controller: 'groups/registry/repositories') do - if group_packages_list_nav?
= link_to group_container_registries_path(@group), title: _('Container Registry') do = nav_link(controller: 'groups/packages') do
%span= _('Container Registry') = link_to group_packages_path(@group), title: _('Packages') do
%span= _('Package Registry')
- if group_container_registry_nav?
= nav_link(controller: 'groups/registry/repositories') do
= link_to group_container_registries_path(@group), title: _('Container Registry') do
%span= _('Container Registry')
- if project_nav_tab? :container_registry - packages_link = project_nav_tab?(:packages) ? project_packages_path(@project) : project_container_registry_index_path(@project)
= nav_link controller: :repositories do
= link_to project_container_registry_index_path(@project) do - if (project_nav_tab?(:packages) || project_nav_tab?(:container_registry))
= nav_link controller: [:packages, :repositories] do
= link_to packages_link, data: { qa_selector: 'packages_link' } do
.nav-icon-container .nav-icon-container
= sprite_icon('package') = sprite_icon('package')
%span.nav-item-name %span.nav-item-name
= _('Packages & Registries') = _('Packages & Registries')
%ul.sidebar-sub-level-items %ul.sidebar-sub-level-items
= nav_link(controller: :repositories, html_options: { class: "fly-out-top-item" } ) do = nav_link(controller: [:packages, :repositories], html_options: { class: "fly-out-top-item" } ) do
= link_to project_container_registry_index_path(@project) do = link_to packages_link do
%strong.fly-out-top-item-name %strong.fly-out-top-item-name
= _('Packages & Registries') = _('Packages & Registries')
%li.divider.fly-out-top-item %li.divider.fly-out-top-item
= nav_link controller: :repositories do - if project_nav_tab? :packages
= link_to project_container_registry_index_path(@project), class: 'shortcuts-container-registry', title: _('Container Registry') do = nav_link controller: :packages do
%span= _('Container Registry') = link_to project_packages_path(@project), title: _('Package Registry') do
%span= _('Package Registry')
- if project_nav_tab? :container_registry
= nav_link controller: :repositories do
= link_to project_container_registry_index_path(@project), class: 'shortcuts-container-registry', title: _('Container Registry') do
%span= _('Container Registry')
---
title: Package feature moved to core
merge_request: 36667
author:
type: changed
...@@ -55,6 +55,8 @@ constraints(::Constraints::GroupUrlConstrainer.new) do ...@@ -55,6 +55,8 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
post :toggle_subscription, on: :member post :toggle_subscription, on: :member
end end
resources :packages, only: [:index]
resources :milestones, constraints: { id: %r{[^/]+} } do resources :milestones, constraints: { id: %r{[^/]+} } do
member do member do
get :merge_requests get :merge_requests
......
...@@ -30,6 +30,13 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do ...@@ -30,6 +30,13 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resources :artifacts, only: [:index, :destroy] resources :artifacts, only: [:index, :destroy]
resources :packages, only: [:index, :show, :destroy], module: :packages
resources :package_files, only: [], module: :packages do
member do
get :download
end
end
resources :jobs, only: [:index, :show], constraints: { id: /\d+/ } do resources :jobs, only: [:index, :show], constraints: { id: /\d+/ } do
collection do collection do
resources :artifacts, only: [] do resources :artifacts, only: [] do
......
...@@ -39,7 +39,7 @@ module EE ...@@ -39,7 +39,7 @@ module EE
adjourned_deletion_for_projects_and_groups: :deletion_adjourned_period, adjourned_deletion_for_projects_and_groups: :deletion_adjourned_period,
required_ci_templates: :required_instance_ci_template, required_ci_templates: :required_instance_ci_template,
disable_name_update_for_users: :updating_name_disabled_for_users, disable_name_update_for_users: :updating_name_disabled_for_users,
packages: :npm_package_requests_forwarding, package_forwarding: :npm_package_requests_forwarding,
default_branch_protection_restriction_in_groups: :group_owners_can_manage_default_branch_protection default_branch_protection_restriction_in_groups: :group_owners_can_manage_default_branch_protection
}.each do |license_feature, attribute_name| }.each do |license_feature, attribute_name|
if License.feature_available?(license_feature) if License.feature_available?(license_feature)
......
...@@ -77,7 +77,6 @@ module EE ...@@ -77,7 +77,6 @@ module EE
reset_approvals_on_push reset_approvals_on_push
ci_cd_only ci_cd_only
use_custom_template use_custom_template
packages_enabled
require_password_to_approve require_password_to_approve
group_with_project_templates_id group_with_project_templates_id
] ]
......
...@@ -42,14 +42,9 @@ module EE ...@@ -42,14 +42,9 @@ module EE
] ]
end end
override :group_packages_nav?
def group_packages_nav? def group_packages_nav?
group_packages_list_nav? || super || group_dependency_proxy_nav?
group_dependency_proxy_nav? ||
group_container_registry_nav?
end
def group_packages_list_nav?
@group.packages_feature_available?
end end
def group_dependency_proxy_nav? def group_dependency_proxy_nav?
......
# frozen_string_literal: true
module EE
module PackagesHelper
def package_sort_path(options = {})
"#{request.path}?#{options.to_param}"
end
def nuget_package_registry_url(project_id)
expose_url(api_v4_projects_packages_nuget_index_path(id: project_id, format: '.json'))
end
def package_registry_instance_url(registry_type)
expose_url("api/#{::API::API.version}/packages/#{registry_type}")
end
def package_registry_project_url(project_id, registry_type = :maven)
project_api_path = expose_path(api_v4_projects_path(id: project_id))
package_registry_project_path = "#{project_api_path}/packages/#{registry_type}"
expose_url(package_registry_project_path)
end
def package_from_presenter(package)
presenter = ::Packages::Detail::PackagePresenter.new(package)
presenter.detail_view.to_json
end
def pypi_registry_url(project_id)
full_url = expose_url(api_v4_projects_packages_pypi_simple_package_name_path({ id: project_id, package_name: '' }, true))
full_url.sub!('://', '://__token__:<your_personal_token>@')
end
def packages_coming_soon_enabled?(resource)
::Feature.enabled?(:packages_coming_soon, resource) && ::Gitlab.dev_env_or_com?
end
def packages_coming_soon_data(resource)
return unless packages_coming_soon_enabled?(resource)
{
project_path: ::Gitlab.com? ? 'gitlab-org/gitlab' : 'gitlab-org/gitlab-test',
suggested_contributions: help_page_path('user/packages/index', anchor: 'suggested-contributions')
}
end
def packages_list_data(type, resource)
{
resource_id: resource.id,
page_type: type,
empty_list_help_url: help_page_path('administration/packages/index'),
empty_list_illustration: image_path('illustrations/no-packages.svg'),
coming_soon_json: packages_coming_soon_data(resource).to_json
}
end
end
end
...@@ -31,12 +31,6 @@ module EE ...@@ -31,12 +31,6 @@ module EE
nav_tabs += get_project_security_nav_tabs(project, current_user) nav_tabs += get_project_security_nav_tabs(project, current_user)
if ::Gitlab.config.packages.enabled &&
project.feature_available?(:packages) &&
can?(current_user, :read_package, project)
nav_tabs << :packages
end
if can?(current_user, :read_code_review_analytics, project) if can?(current_user, :read_code_review_analytics, project)
nav_tabs << :code_review nav_tabs << :code_review
end end
...@@ -63,21 +57,6 @@ module EE ...@@ -63,21 +57,6 @@ module EE
tab_ability_map tab_ability_map
end end
override :project_permissions_settings
def project_permissions_settings(project)
super.merge(
packagesEnabled: !!project.packages_enabled
)
end
override :project_permissions_panel_data
def project_permissions_panel_data(project)
super.merge(
packagesAvailable: ::Gitlab.config.packages.enabled && project.feature_available?(:packages),
packagesHelpPath: help_page_path('user/packages/index')
)
end
override :default_url_to_repo override :default_url_to_repo
def default_url_to_repo(project = @project) def default_url_to_repo(project = @project)
case default_clone_protocol case default_clone_protocol
......
...@@ -64,47 +64,6 @@ module EE ...@@ -64,47 +64,6 @@ module EE
end end
end end
def packages_sort_options_hash
{
sort_value_recently_created => sort_title_created_date,
sort_value_oldest_created => sort_title_created_date,
sort_value_name => sort_title_name,
sort_value_name_desc => sort_title_name,
sort_value_version_desc => sort_title_version,
sort_value_version_asc => sort_title_version,
sort_value_type_desc => sort_title_type,
sort_value_type_asc => sort_title_type,
sort_value_project_name_desc => sort_title_project_name,
sort_value_project_name_asc => sort_title_project_name
}
end
def packages_reverse_sort_order_hash
{
sort_value_recently_created => sort_value_oldest_created,
sort_value_oldest_created => sort_value_recently_created,
sort_value_name => sort_value_name_desc,
sort_value_name_desc => sort_value_name,
sort_value_version_desc => sort_value_version_asc,
sort_value_version_asc => sort_value_version_desc,
sort_value_type_desc => sort_value_type_asc,
sort_value_type_asc => sort_value_type_desc,
sort_value_project_name_desc => sort_value_project_name_asc,
sort_value_project_name_asc => sort_value_project_name_desc
}
end
def packages_sort_option_title(sort_value)
packages_sort_options_hash[sort_value] || sort_title_created_date
end
def packages_sort_direction_button(sort_value)
reverse_sort = packages_reverse_sort_order_hash[sort_value]
url = package_sort_path(sort: reverse_sort)
sort_direction_button(url, reverse_sort, sort_value)
end
# Creates a button with the opposite ordering for the current field in UI. # Creates a button with the opposite ordering for the current field in UI.
def sort_order_button(sort) def sort_order_button(sort)
opposite_sorting_param = epics_ordering_options_hash[sort] || epics_ordering_options_hash.key(sort) opposite_sorting_param = epics_ordering_options_hash[sort] || epics_ordering_options_hash.key(sort)
......
...@@ -303,10 +303,6 @@ module EE ...@@ -303,10 +303,6 @@ module EE
end end
end end
def packages_feature_available?
packages_feature_enabled? && feature_available?(:packages)
end
def dependency_proxy_feature_available? def dependency_proxy_feature_available?
::Gitlab.config.dependency_proxy.enabled && feature_available?(:dependency_proxy) ::Gitlab.config.dependency_proxy.enabled && feature_available?(:dependency_proxy)
end end
......
...@@ -94,7 +94,7 @@ class License < ApplicationRecord ...@@ -94,7 +94,7 @@ class License < ApplicationRecord
object_storage object_storage
operations_dashboard operations_dashboard
opsgenie_integration opsgenie_integration
packages package_forwarding
pages_size_limit pages_size_limit
productivity_analytics productivity_analytics
project_aliases project_aliases
......
- packages_link = project_nav_tab?(:packages) ? project_packages_path(@project) : project_container_registry_index_path(@project)
- if (project_nav_tab?(:packages) || project_nav_tab?(:container_registry))
= nav_link controller: [:packages, :repositories] do
= link_to packages_link, data: { qa_selector: 'packages_link' } do
.nav-icon-container
= sprite_icon('package')
%span.nav-item-name
= _('Packages & Registries')
%ul.sidebar-sub-level-items
= nav_link(controller: [:packages, :repositories], html_options: { class: "fly-out-top-item" } ) do
= link_to packages_link do
%strong.fly-out-top-item-name
= _('Packages & Registries')
%li.divider.fly-out-top-item
- if project_nav_tab? :packages
= nav_link controller: :packages do
= link_to project_packages_path(@project), title: _('Package Registry') do
%span= _('Package Registry')
- if project_nav_tab? :container_registry
= nav_link controller: :repositories do
= link_to project_container_registry_index_path(@project), class: 'shortcuts-container-registry', title: _('Container Registry') do
%span= _('Container Registry')
...@@ -176,7 +176,6 @@ constraints(::Constraints::GroupUrlConstrainer.new) do ...@@ -176,7 +176,6 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
resource :roadmap, only: [:show], controller: 'roadmap' resource :roadmap, only: [:show], controller: 'roadmap'
resource :dependency_proxy, only: [:show, :update] resource :dependency_proxy, only: [:show, :update]
resources :packages, only: [:index]
post '/restore' => '/groups#restore', as: :restore post '/restore' => '/groups#restore', as: :restore
end end
......
...@@ -15,13 +15,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do ...@@ -15,13 +15,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resources :requirements, only: [:index] resources :requirements, only: [:index]
end end
resources :packages, only: [:index, :show, :destroy], module: :packages
resources :package_files, only: [], module: :packages do
member do
get :download
end
end
resources :feature_flags, param: :iid do resources :feature_flags, param: :iid do
resources :feature_flag_issues, only: [:index, :create, :destroy], as: 'issues', path: 'issues' resources :feature_flag_issues, only: [:index, :create, :destroy], as: 'issues', path: 'issues'
end end
......
...@@ -18,7 +18,7 @@ module EE ...@@ -18,7 +18,7 @@ module EE
expose :default_project_deletion_protection, if: ->(_instance, _opts) { ::License.feature_available?(:default_project_deletion_protection) } expose :default_project_deletion_protection, if: ->(_instance, _opts) { ::License.feature_available?(:default_project_deletion_protection) }
expose :deletion_adjourned_period, if: ->(_instance, _opts) { ::License.feature_available?(:adjourned_deletion_for_projects_and_groups) } expose :deletion_adjourned_period, if: ->(_instance, _opts) { ::License.feature_available?(:adjourned_deletion_for_projects_and_groups) }
expose :updating_name_disabled_for_users, if: ->(_instance, _opts) { ::License.feature_available?(:disable_name_update_for_users) } expose :updating_name_disabled_for_users, if: ->(_instance, _opts) { ::License.feature_available?(:disable_name_update_for_users) }
expose :npm_package_requests_forwarding, if: ->(_instance, _opts) { ::License.feature_available?(:packages) } expose :npm_package_requests_forwarding, if: ->(_instance, _opts) { ::License.feature_available?(:package_forwarding) }
expose :group_owners_can_manage_default_branch_protection, if: ->(_instance, _opts) { ::License.feature_available?(:default_branch_protection_restriction_in_groups) } expose :group_owners_can_manage_default_branch_protection, if: ->(_instance, _opts) { ::License.feature_available?(:default_branch_protection_restriction_in_groups) }
expose :maintenance_mode, if: ->(_instance, _opts) { ::Gitlab::Geo.license_allows? && ::Feature.enabled?(:maintenance_mode) } expose :maintenance_mode, if: ->(_instance, _opts) { ::Gitlab::Geo.license_allows? && ::Feature.enabled?(:maintenance_mode) }
expose :maintenance_mode_message, if: ->(_instance, _opts) { ::Gitlab::Geo.license_allows? && ::Feature.enabled?(:maintenance_mode) } expose :maintenance_mode_message, if: ->(_instance, _opts) { ::Gitlab::Geo.license_allows? && ::Feature.enabled?(:maintenance_mode) }
......
...@@ -24,7 +24,6 @@ module EE ...@@ -24,7 +24,6 @@ module EE
expose :mirror_overwrites_diverged_branches, if: ->(project, _) { project.mirror? } expose :mirror_overwrites_diverged_branches, if: ->(project, _) { project.mirror? }
expose :external_authorization_classification_label, expose :external_authorization_classification_label,
if: ->(_, _) { License.feature_available?(:external_authorization_service_api_management) } if: ->(_, _) { License.feature_available?(:external_authorization_service_api_management) }
expose :packages_enabled, if: ->(project, _) { project.feature_available?(:packages) }
expose :marked_for_deletion_at, if: ->(project, _) { project.feature_available?(:adjourned_deletion_for_projects_and_groups) } expose :marked_for_deletion_at, if: ->(project, _) { project.feature_available?(:adjourned_deletion_for_projects_and_groups) }
expose :marked_for_deletion_on, if: ->(project, _) { project.feature_available?(:adjourned_deletion_for_projects_and_groups) } do |project, _| expose :marked_for_deletion_on, if: ->(project, _) { project.feature_available?(:adjourned_deletion_for_projects_and_groups) } do |project, _|
project.marked_for_deletion_at project.marked_for_deletion_at
......
...@@ -32,7 +32,6 @@ module EE ...@@ -32,7 +32,6 @@ module EE
optional :only_mirror_protected_branches, type: Grape::API::Boolean, desc: 'Only mirror protected branches' optional :only_mirror_protected_branches, type: Grape::API::Boolean, desc: 'Only mirror protected branches'
optional :mirror_overwrites_diverged_branches, type: Grape::API::Boolean, desc: 'Pull mirror overwrites diverged branches' optional :mirror_overwrites_diverged_branches, type: Grape::API::Boolean, desc: 'Pull mirror overwrites diverged branches'
optional :import_url, type: String, desc: 'URL from which the project is imported' optional :import_url, type: String, desc: 'URL from which the project is imported'
optional :packages_enabled, type: Grape::API::Boolean, desc: 'Enable project packages feature'
optional :fallback_approvals_required, type: Integer, desc: 'Overall approvals required when no rule is present' optional :fallback_approvals_required, type: Integer, desc: 'Overall approvals required when no rule is present'
end end
end end
...@@ -50,7 +49,6 @@ module EE ...@@ -50,7 +49,6 @@ module EE
:approvals_before_merge, :approvals_before_merge,
:external_authorization_classification_label, :external_authorization_classification_label,
:import_url, :import_url,
:packages_enabled,
:fallback_approvals_required :fallback_approvals_required
] ]
end end
......
...@@ -39,7 +39,7 @@ module EE ...@@ -39,7 +39,7 @@ module EE
attrs = attrs.except(*EE::ApplicationSettingsHelper.merge_request_appovers_rules_attributes) attrs = attrs.except(*EE::ApplicationSettingsHelper.merge_request_appovers_rules_attributes)
end end
unless License.feature_available?(:packages) unless License.feature_available?(:package_forwarding)
attrs = attrs.except(:npm_package_requests_forwarding) attrs = attrs.except(:npm_package_requests_forwarding)
end end
......
...@@ -120,7 +120,7 @@ RSpec.describe Admin::ApplicationSettingsController do ...@@ -120,7 +120,7 @@ RSpec.describe Admin::ApplicationSettingsController do
context 'updating npm packages request forwarding setting' do context 'updating npm packages request forwarding setting' do
let(:settings) { { npm_package_requests_forwarding: true } } let(:settings) { { npm_package_requests_forwarding: true } }
let(:feature) { :packages } let(:feature) { :package_forwarding }
it_behaves_like 'settings for licensed features' it_behaves_like 'settings for licensed features'
end end
......
...@@ -17,6 +17,8 @@ RSpec.describe 'Group navbar' do ...@@ -17,6 +17,8 @@ RSpec.describe 'Group navbar' do
stub_feature_flags(group_iterations: false) stub_feature_flags(group_iterations: false)
stub_feature_flags(group_wiki: false) stub_feature_flags(group_wiki: false)
sign_in(user) sign_in(user)
insert_package_nav(_('Kubernetes'))
end end
context 'when productivity analytics is available' do context 'when productivity analytics is available' do
...@@ -148,20 +150,10 @@ RSpec.describe 'Group navbar' do ...@@ -148,20 +150,10 @@ RSpec.describe 'Group navbar' do
context 'when packages are available' do context 'when packages are available' do
before do before do
stub_config(packages: { enabled: true }, registry: { enabled: false }) stub_config(packages: { enabled: true }, registry: { enabled: false })
stub_licensed_features(packages: true)
insert_after_nav_item(
_('Kubernetes'),
new_nav_item: {
nav_item: _('Packages & Registries'),
nav_sub_items: [_('Package Registry')]
}
)
visit group_path(group) visit group_path(group)
end end
it_behaves_like 'verified navigation bar'
context 'when container registry is available' do context 'when container registry is available' do
before do before do
stub_config(registry: { enabled: true }) stub_config(registry: { enabled: true })
......
...@@ -11,6 +11,8 @@ RSpec.describe 'Project navbar' do ...@@ -11,6 +11,8 @@ RSpec.describe 'Project navbar' do
let_it_be(:project) { create(:project, :repository) } let_it_be(:project) { create(:project, :repository) }
before do before do
insert_package_nav(_('Operations'))
project.add_maintainer(user) project.add_maintainer(user)
sign_in(user) sign_in(user)
end end
...@@ -56,21 +58,10 @@ RSpec.describe 'Project navbar' do ...@@ -56,21 +58,10 @@ RSpec.describe 'Project navbar' do
context 'when packages are available' do context 'when packages are available' do
before do before do
stub_config(packages: { enabled: true }, registry: { enabled: false }) stub_config(packages: { enabled: true }, registry: { enabled: false })
stub_licensed_features(packages: true)
insert_after_nav_item(
_('Operations'),
new_nav_item: {
nav_item: _('Packages & Registries'),
nav_sub_items: [_('Package Registry')]
}
)
visit project_path(project) visit project_path(project)
end end
it_behaves_like 'verified navigation bar'
context 'when container registry is available' do context 'when container registry is available' do
before do before do
stub_config(registry: { enabled: true }) stub_config(registry: { enabled: true })
......
...@@ -142,24 +142,6 @@ RSpec.describe API::Projects do ...@@ -142,24 +142,6 @@ RSpec.describe API::Projects do
end end
end end
describe 'packages_enabled attribute' do
it 'is exposed when the feature is available' do
stub_licensed_features(packages: true)
get api("/projects/#{project.id}", user)
expect(json_response).to have_key 'packages_enabled'
end
it 'is not exposed when the feature is not available' do
stub_licensed_features(packages: false)
get api("/projects/#{project.id}", user)
expect(json_response).not_to have_key 'packages_enabled'
end
end
describe 'compliance_frameworks attribute' do describe 'compliance_frameworks attribute' do
context 'when compliance_framework feature is available' do context 'when compliance_framework feature is available' do
context 'when project has a compliance framework' do context 'when project has a compliance framework' do
...@@ -810,40 +792,6 @@ RSpec.describe API::Projects do ...@@ -810,40 +792,6 @@ RSpec.describe API::Projects do
end end
end end
describe 'updating packages_enabled attribute' do
it 'is enabled by default' do
expect(project.packages_enabled).to be true
end
context 'packages feature is allowed by license' do
before do
stub_licensed_features(packages: true)
end
it 'disables project packages feature' do
put(api("/projects/#{project.id}", user), params: { packages_enabled: false })
expect(response).to have_gitlab_http_status(:ok)
expect(project.reload.packages_enabled).to be false
expect(json_response['packages_enabled']).to eq(false)
end
end
context 'packages feature is not allowed by license' do
before do
stub_licensed_features(packages: false)
end
it 'disables project packages feature but does not return packages_enabled attribute' do
put(api("/projects/#{project.id}", user), params: { packages_enabled: false })
expect(response).to have_gitlab_http_status(:ok)
expect(project.reload.packages_enabled).to be false
expect(json_response['packages_enabled']).to be_nil
end
end
end
describe 'updating approvals_before_merge attribute' do describe 'updating approvals_before_merge attribute' do
context 'when authenticated as project owner' do context 'when authenticated as project owner' do
it 'updates approvals_before_merge' do it 'updates approvals_before_merge' do
......
...@@ -186,7 +186,7 @@ RSpec.describe API::Settings, 'EE Settings' do ...@@ -186,7 +186,7 @@ RSpec.describe API::Settings, 'EE Settings' do
context 'updating npm packages request forwarding' do context 'updating npm packages request forwarding' do
let(:settings) { { npm_package_requests_forwarding: true } } let(:settings) { { npm_package_requests_forwarding: true } }
let(:feature) { :packages } let(:feature) { :package_forwarding }
it_behaves_like 'settings for licensed features' it_behaves_like 'settings for licensed features'
end end
......
...@@ -10,7 +10,6 @@ RSpec.describe Groups::TransferService, '#execute' do ...@@ -10,7 +10,6 @@ RSpec.describe Groups::TransferService, '#execute' do
let(:transfer_service) { described_class.new(group, user) } let(:transfer_service) { described_class.new(group, user) }
before do before do
stub_licensed_features(packages: true)
group.add_owner(user) group.add_owner(user)
new_group&.add_owner(user) new_group&.add_owner(user)
end end
......
...@@ -10,7 +10,7 @@ RSpec.describe 'layouts/nav/sidebar/_project' do ...@@ -10,7 +10,7 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
assign(:repository, project.repository) assign(:repository, project.repository)
allow(view).to receive(:current_ref).and_return('master') allow(view).to receive(:current_ref).and_return('master')
stub_licensed_features(tracing: true, packages: true) stub_licensed_features(tracing: true)
end end
describe 'issue boards' do describe 'issue boards' do
...@@ -221,96 +221,6 @@ RSpec.describe 'layouts/nav/sidebar/_project' do ...@@ -221,96 +221,6 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end end
end end
describe 'Packages' do
let(:user) { create(:user) }
let_it_be(:package_menu_name) { 'Packages & Registries' }
let_it_be(:package_entry_name) { 'Package Registry' }
before do
project.team.add_developer(user)
sign_in(user)
stub_container_registry_config(enabled: true)
end
context 'when packages is enabled' do
it 'packages link is visible' do
render
expect(rendered).to have_link(package_menu_name, href: project_packages_path(project))
end
it 'packages list link is visible' do
render
expect(rendered).to have_link(package_entry_name, href: project_packages_path(project))
end
it 'container registry link is visible' do
render
expect(rendered).to have_link('Container Registry', href: project_container_registry_index_path(project))
end
end
context 'when packages are disabled' do
before do
stub_licensed_features(packages: false)
end
it 'packages list link is not visible' do
render
expect(rendered).not_to have_link(package_entry_name, href: project_packages_path(project))
end
it 'top level packages link links to container registry' do
render
expect(rendered).to have_link(package_menu_name, href: project_container_registry_index_path(project))
end
it 'packages top level and container registry links are visible' do
render
expect(rendered).to have_link(package_menu_name, href: project_container_registry_index_path(project))
expect(rendered).to have_link('Container Registry', href: project_container_registry_index_path(project))
end
end
context 'when container registry is disabled' do
before do
stub_container_registry_config(enabled: false)
end
it 'packages top level and list link are visible' do
render
expect(rendered).to have_link(package_menu_name, href: project_packages_path(project))
expect(rendered).to have_link(package_entry_name, href: project_packages_path(project))
end
it 'container registry link is not visible' do
render
expect(rendered).not_to have_link('Container Registry', href: project_container_registry_index_path(project))
end
end
context 'when both packages and container registry are disabled' do
before do
stub_licensed_features(packages: false)
stub_container_registry_config(enabled: false)
end
it 'packages top level item is not visible' do
render
expect(rendered).not_to have_link(package_menu_name, href: project_packages_path(project))
end
end
end
describe 'Settings > Operations' do describe 'Settings > Operations' do
it 'is not visible when no valid license' do it 'is not visible when no valid license' do
allow(view).to receive(:can?).and_return(true) allow(view).to receive(:can?).and_return(true)
......
...@@ -13,9 +13,7 @@ module API ...@@ -13,9 +13,7 @@ module API
expose :_links do expose :_links do
expose :web_path do |package| expose :web_path do |package|
if ::Gitlab.ee? ::Gitlab::Routing.url_helpers.project_package_path(package.project, package)
::Gitlab::Routing.url_helpers.project_package_path(package.project, package)
end
end end
expose :delete_api_path, if: can_destroy(:package, &:project) do |package| expose :delete_api_path, if: can_destroy(:package, &:project) do |package|
......
...@@ -35,6 +35,7 @@ module API ...@@ -35,6 +35,7 @@ module API
end end
end end
expose :packages_enabled
expose :empty_repo?, as: :empty_repo expose :empty_repo?, as: :empty_repo
expose :archived?, as: :archived expose :archived?, as: :archived
expose :visibility expose :visibility
......
...@@ -61,6 +61,7 @@ module API ...@@ -61,6 +61,7 @@ module API
optional :auto_devops_deploy_strategy, type: String, values: %w(continuous manual timed_incremental), desc: 'Auto Deploy strategy' optional :auto_devops_deploy_strategy, type: String, values: %w(continuous manual timed_incremental), desc: 'Auto Deploy strategy'
optional :autoclose_referenced_issues, type: Boolean, desc: 'Flag indication if referenced issues auto-closing is enabled' optional :autoclose_referenced_issues, type: Boolean, desc: 'Flag indication if referenced issues auto-closing is enabled'
optional :repository_storage, type: String, desc: 'Which storage shard the repository is on. Available only to admins' optional :repository_storage, type: String, desc: 'Which storage shard the repository is on. Available only to admins'
optional :packages_enabled, type: Boolean, desc: 'Enable project packages feature'
end end
params :optional_project_params_ee do params :optional_project_params_ee do
...@@ -137,6 +138,7 @@ module API ...@@ -137,6 +138,7 @@ module API
:suggestion_commit_message, :suggestion_commit_message,
:repository_storage, :repository_storage,
:compliance_framework_setting, :compliance_framework_setting,
:packages_enabled,
:service_desk_enabled, :service_desk_enabled,
# TODO: remove in API v5, replaced by *_access_level # TODO: remove in API v5, replaced by *_access_level
......
...@@ -277,6 +277,11 @@ module QA ...@@ -277,6 +277,11 @@ module QA
autoload :Show, 'qa/page/project/job/show' autoload :Show, 'qa/page/project/job/show'
end end
module Packages
autoload :Index, 'qa/page/project/packages/index'
autoload :Show, 'qa/page/project/packages/show'
end
module Settings module Settings
autoload :Advanced, 'qa/page/project/settings/advanced' autoload :Advanced, 'qa/page/project/settings/advanced'
autoload :Main, 'qa/page/project/settings/main' autoload :Main, 'qa/page/project/settings/main'
...@@ -315,6 +320,7 @@ module QA ...@@ -315,6 +320,7 @@ module QA
autoload :Repository, 'qa/page/project/sub_menus/repository' autoload :Repository, 'qa/page/project/sub_menus/repository'
autoload :Settings, 'qa/page/project/sub_menus/settings' autoload :Settings, 'qa/page/project/sub_menus/settings'
autoload :Project, 'qa/page/project/sub_menus/project' autoload :Project, 'qa/page/project/sub_menus/project'
autoload :Packages, 'qa/page/project/sub_menus/packages'
end end
module Issue module Issue
......
...@@ -101,7 +101,6 @@ module QA ...@@ -101,7 +101,6 @@ module QA
autoload :Menu, 'qa/ee/page/project/menu' autoload :Menu, 'qa/ee/page/project/menu'
module SubMenus module SubMenus
autoload :Packages, 'qa/ee/page/project/sub_menus/packages'
autoload :SecurityCompliance, 'qa/ee/page/project/sub_menus/security_compliance' autoload :SecurityCompliance, 'qa/ee/page/project/sub_menus/security_compliance'
autoload :Repository, 'qa/ee/page/project/sub_menus/repository' autoload :Repository, 'qa/ee/page/project/sub_menus/repository'
autoload :Settings, 'qa/ee/page/project/sub_menus/settings' autoload :Settings, 'qa/ee/page/project/sub_menus/settings'
...@@ -140,11 +139,6 @@ module QA ...@@ -140,11 +139,6 @@ module QA
end end
end end
module Packages
autoload :Index, 'qa/ee/page/project/packages/index'
autoload :Show, 'qa/ee/page/project/packages/show'
end
module Pipeline module Pipeline
autoload :Show, 'qa/ee/page/project/pipeline/show' autoload :Show, 'qa/ee/page/project/pipeline/show'
end end
......
...@@ -13,7 +13,6 @@ module QA ...@@ -13,7 +13,6 @@ module QA
base.class_eval do base.class_eval do
prepend QA::Page::Project::SubMenus::Common prepend QA::Page::Project::SubMenus::Common
prepend SubMenus::SecurityCompliance prepend SubMenus::SecurityCompliance
prepend SubMenus::Packages
prepend SubMenus::Project prepend SubMenus::Project
prepend SubMenus::Repository prepend SubMenus::Repository
prepend SubMenus::Settings prepend SubMenus::Settings
......
# frozen_string_literal: true
module QA
module EE
module Page
module Project
module Packages
class Index < QA::Page::Base
view 'ee/app/views/projects/packages/packages/_legacy_package_list.html.haml' do
element :package_row
element :package_link
end
def click_package(name)
click_element(:package_link, text: name)
end
def has_package?(name)
has_element?(:package_link, text: name)
end
def has_no_package?(name)
has_no_element?(:package_link, text: name)
end
end
end
end
end
end
end
# frozen_string_literal: true
module QA
module EE
module Page
module Project
module Packages
class Show < QA::Page::Base
view 'ee/app/assets/javascripts/packages/details/components/app.vue' do
element :delete_button
element :delete_modal_button
element :package_information_content
end
def has_package_info?(name, version)
has_element?(:package_information_content, text: /#{name}.*#{version}/)
end
def click_delete
click_element(:delete_button)
wait_for_animated_element(:delete_modal_button)
click_element(:delete_modal_button)
end
end
end
end
end
end
end
# frozen_string_literal: true
module QA
module EE
module Page
module Project
module SubMenus
module Packages
extend QA::Page::PageConcern
def self.prepended(base)
base.class_eval do
view 'ee/app/views/layouts/nav/sidebar/_project_packages_link.html.haml' do
element :packages_link
end
end
end
def click_packages_link
within_sidebar do
click_element :packages_link
end
end
end
end
end
end
end
end
...@@ -11,6 +11,7 @@ module QA ...@@ -11,6 +11,7 @@ module QA
include SubMenus::Operations include SubMenus::Operations
include SubMenus::Repository include SubMenus::Repository
include SubMenus::Settings include SubMenus::Settings
include SubMenus::Packages
view 'app/views/layouts/nav/sidebar/_project.html.haml' do view 'app/views/layouts/nav/sidebar/_project.html.haml' do
element :activity_link element :activity_link
......
# frozen_string_literal: true
module QA
module Page
module Project
module Packages
class Index < QA::Page::Base
view 'app/views/projects/packages/packages/_legacy_package_list.html.haml' do
element :package_row
element :package_link
end
def click_package(name)
click_element(:package_link, text: name)
end
def has_package?(name)
has_element?(:package_link, text: name)
end
def has_no_package?(name)
has_no_element?(:package_link, text: name)
end
end
end
end
end
end
# frozen_string_literal: true
module QA
module Page
module Project
module Packages
class Show < QA::Page::Base
view 'app/assets/javascripts/packages/details/components/app.vue' do
element :delete_button
element :delete_modal_button
element :package_information_content
end
def has_package_info?(name, version)
has_element?(:package_information_content, text: /#{name}.*#{version}/)
end
def click_delete
click_element(:delete_button)
wait_for_animated_element(:delete_modal_button)
click_element(:delete_modal_button)
end
end
end
end
end
end
# frozen_string_literal: true
module QA
module Page
module Project
module SubMenus
module Packages
extend QA::Page::PageConcern
def self.included(base)
super
base.class_eval do
view 'app/views/layouts/nav/sidebar/_project_packages_link.html.haml' do
element :packages_link
end
end
end
def click_packages_link
within_sidebar do
click_element :packages_link
end
end
end
end
end
end
end
...@@ -80,19 +80,20 @@ module QA ...@@ -80,19 +80,20 @@ module QA
project.visit! project.visit!
Page::Project::Menu.perform(&:click_packages_link) Page::Project::Menu.perform(&:click_packages_link)
EE::Page::Project::Packages::Index.perform do |index|
Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package_name) expect(index).to have_package(package_name)
index.click_package(package_name) index.click_package(package_name)
end end
EE::Page::Project::Packages::Show.perform do |show| Page::Project::Packages::Show.perform do |show|
expect(show).to have_package_info(package_name, "1.0") expect(show).to have_package_info(package_name, "1.0")
show.click_delete show.click_delete
end end
EE::Page::Project::Packages::Index.perform do |index| Page::Project::Packages::Index.perform do |index|
expect(index).to have_content("Package was removed") expect(index).to have_content("Package was removed")
expect(index).to have_no_package(package_name) expect(index).to have_no_package(package_name)
end end
......
...@@ -53,19 +53,20 @@ module QA ...@@ -53,19 +53,20 @@ module QA
project.visit! project.visit!
Page::Project::Menu.perform(&:click_packages_link) Page::Project::Menu.perform(&:click_packages_link)
EE::Page::Project::Packages::Index.perform do |index|
Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package_name) expect(index).to have_package(package_name)
index.click_package(package_name) index.click_package(package_name)
end end
EE::Page::Project::Packages::Show.perform do |show| Page::Project::Packages::Show.perform do |show|
expect(show).to have_package_info(package_name, "1.0.0") expect(show).to have_package_info(package_name, "1.0.0")
show.click_delete show.click_delete
end end
EE::Page::Project::Packages::Index.perform do |index| Page::Project::Packages::Index.perform do |index|
expect(index).to have_content("Package was removed") expect(index).to have_content("Package was removed")
expect(index).to have_no_package(package_name) expect(index).to have_no_package(package_name)
end end
......
...@@ -45,6 +45,8 @@ RSpec.describe 'Group navbar' do ...@@ -45,6 +45,8 @@ RSpec.describe 'Group navbar' do
end end
before do before do
insert_package_nav(_('Kubernetes'))
stub_feature_flags(group_push_rules: false) stub_feature_flags(group_push_rules: false)
stub_feature_flags(group_iterations: false) stub_feature_flags(group_iterations: false)
stub_feature_flags(group_wiki: false) stub_feature_flags(group_wiki: false)
...@@ -62,13 +64,8 @@ RSpec.describe 'Group navbar' do ...@@ -62,13 +64,8 @@ RSpec.describe 'Group navbar' do
before do before do
stub_config(registry: { enabled: true }) stub_config(registry: { enabled: true })
insert_after_nav_item( insert_container_nav(_('Kubernetes'))
_('Kubernetes'),
new_nav_item: {
nav_item: _('Packages & Registries'),
nav_sub_items: [_('Container Registry')]
}
)
visit group_path(group) visit group_path(group)
end end
......
...@@ -10,22 +10,9 @@ RSpec.describe 'Group Packages' do ...@@ -10,22 +10,9 @@ RSpec.describe 'Group Packages' do
before do before do
sign_in(user) sign_in(user)
group.add_maintainer(user) group.add_maintainer(user)
stub_licensed_features(packages: true)
end end
context 'when feature is not available' do context 'when feature is not available' do
context 'packages feature is not available because of license' do
before do
stub_licensed_features(packages: false)
end
it 'gives 404' do
visit_group_packages
expect(page).to have_gitlab_http_status(:not_found)
end
end
context 'packages feature is disabled by config' do context 'packages feature is disabled by config' do
before do before do
allow(Gitlab.config.packages).to receive(:enabled).and_return(false) allow(Gitlab.config.packages).to receive(:enabled).and_return(false)
......
...@@ -186,7 +186,7 @@ RSpec.describe 'Edit Project Settings' do ...@@ -186,7 +186,7 @@ RSpec.describe 'Edit Project Settings' do
click_button "Save changes" click_button "Save changes"
end end
expect(find(".sharing-permissions")).to have_selector(".project-feature-toggle.is-disabled", count: 3) expect(find(".sharing-permissions")).to have_selector(".project-feature-toggle.is-disabled", count: 4)
end end
it "shows empty features project homepage" do it "shows empty features project homepage" do
......
...@@ -12,6 +12,8 @@ RSpec.describe 'Project navbar' do ...@@ -12,6 +12,8 @@ RSpec.describe 'Project navbar' do
let_it_be(:project) { create(:project, :repository) } let_it_be(:project) { create(:project, :repository) }
before do before do
insert_package_nav(_('Operations'))
project.add_maintainer(user) project.add_maintainer(user)
sign_in(user) sign_in(user)
end end
...@@ -58,13 +60,8 @@ RSpec.describe 'Project navbar' do ...@@ -58,13 +60,8 @@ RSpec.describe 'Project navbar' do
before do before do
stub_config(registry: { enabled: true }) stub_config(registry: { enabled: true })
insert_after_nav_item( insert_container_nav(_('Operations'))
_('Operations'),
new_nav_item: {
nav_item: _('Packages & Registries'),
nav_sub_items: [_('Container Registry')]
}
)
visit project_path(project) visit project_path(project)
end end
......
...@@ -10,7 +10,6 @@ RSpec.describe 'PackageFiles' do ...@@ -10,7 +10,6 @@ RSpec.describe 'PackageFiles' do
before do before do
sign_in(user) sign_in(user)
stub_licensed_features(packages: true)
end end
context 'user with master role' do context 'user with master role' do
...@@ -40,14 +39,6 @@ RSpec.describe 'PackageFiles' do ...@@ -40,14 +39,6 @@ RSpec.describe 'PackageFiles' do
expect(status_code).to eq(404) expect(status_code).to eq(404)
end end
it 'gives 404 when packages feature is not available' do
stub_licensed_features(packages: false)
visit download_project_package_file_path(project, package_file)
expect(status_code).to eq(404)
end
end end
it 'does not allow direct download when no access to the project' do it 'does not allow direct download when no access to the project' do
......
...@@ -9,22 +9,9 @@ RSpec.describe 'Packages' do ...@@ -9,22 +9,9 @@ RSpec.describe 'Packages' do
before do before do
sign_in(user) sign_in(user)
project.add_maintainer(user) project.add_maintainer(user)
stub_licensed_features(packages: true)
end end
context 'when feature is not available' do context 'when feature is not available' do
context 'packages feature is not available because of license' do
before do
stub_licensed_features(packages: false)
end
it 'gives 404' do
visit_project_packages
expect(status_code).to eq(404)
end
end
context 'packages feature is disabled by config' do context 'packages feature is disabled by config' do
before do before do
allow(Gitlab.config.packages).to receive(:enabled).and_return(false) allow(Gitlab.config.packages).to receive(:enabled).and_return(false)
......
...@@ -16,11 +16,7 @@ RSpec.describe 'Projects > Settings > Packages', :js do ...@@ -16,11 +16,7 @@ RSpec.describe 'Projects > Settings > Packages', :js do
allow(Gitlab.config.packages).to receive(:enabled).and_return(true) allow(Gitlab.config.packages).to receive(:enabled).and_return(true)
end end
context 'allowed by license' do context 'without the need for a license' do
before do
stub_licensed_features(packages: true)
end
it 'displays the packages toggle button' do it 'displays the packages toggle button' do
visit edit_project_path(project) visit edit_project_path(project)
...@@ -28,18 +24,6 @@ RSpec.describe 'Projects > Settings > Packages', :js do ...@@ -28,18 +24,6 @@ RSpec.describe 'Projects > Settings > Packages', :js do
expect(page).to have_selector('input[name="project[packages_enabled]"] + button', visible: true) expect(page).to have_selector('input[name="project[packages_enabled]"] + button', visible: true)
end end
end end
context 'not allowed by license' do
before do
stub_licensed_features(packages: false)
end
it 'does not show up in UI' do
visit edit_project_path(project)
expect(page).not_to have_content('Packages')
end
end
end end
context 'Packages disabled in config' do context 'Packages disabled in config' do
......
import Vuex from 'vuex'; import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils'; import { shallowMount, createLocalVue } from '@vue/test-utils';
import PackageActivity from 'ee/packages/details/components/activity.vue'; import PackageActivity from '~/packages/details/components/activity.vue';
import { import {
npmPackage, npmPackage,
mavenPackage as packageWithoutBuildInfo, mavenPackage as packageWithoutBuildInfo,
......
...@@ -2,20 +2,20 @@ import Vuex from 'vuex'; ...@@ -2,20 +2,20 @@ import Vuex from 'vuex';
import { mount, createLocalVue } from '@vue/test-utils'; import { mount, createLocalVue } from '@vue/test-utils';
import { GlEmptyState, GlModal } from '@gitlab/ui'; import { GlEmptyState, GlModal } from '@gitlab/ui';
import Tracking from '~/tracking'; import Tracking from '~/tracking';
import * as getters from 'ee/packages/details/store/getters'; import * as getters from '~/packages/details/store/getters';
import PackagesApp from 'ee/packages/details/components/app.vue'; import PackagesApp from '~/packages/details/components/app.vue';
import PackageTitle from 'ee/packages/details/components/package_title.vue'; import PackageTitle from '~/packages/details/components/package_title.vue';
import PackageInformation from 'ee/packages/details/components/information.vue'; import PackageInformation from '~/packages/details/components/information.vue';
import NpmInstallation from 'ee/packages/details/components/npm_installation.vue'; import NpmInstallation from '~/packages/details/components/npm_installation.vue';
import MavenInstallation from 'ee/packages/details/components/maven_installation.vue'; import MavenInstallation from '~/packages/details/components/maven_installation.vue';
import * as SharedUtils from 'ee/packages/shared/utils'; import * as SharedUtils from '~/packages/shared/utils';
import { TrackingActions } from 'ee/packages/shared/constants'; import { TrackingActions } from '~/packages/shared/constants';
import PackagesListLoader from 'ee/packages/shared/components/packages_list_loader.vue'; import PackagesListLoader from '~/packages/shared/components/packages_list_loader.vue';
import PackageListRow from 'ee/packages/shared/components/package_list_row.vue'; import PackageListRow from '~/packages/shared/components/package_list_row.vue';
import ConanInstallation from 'ee/packages/details/components/conan_installation.vue'; import ConanInstallation from '~/packages/details/components/conan_installation.vue';
import NugetInstallation from 'ee/packages/details/components/nuget_installation.vue'; import NugetInstallation from '~/packages/details/components/nuget_installation.vue';
import PypiInstallation from 'ee/packages/details/components/pypi_installation.vue'; import PypiInstallation from '~/packages/details/components/pypi_installation.vue';
import DependencyRow from 'ee/packages/details/components/dependency_row.vue'; import DependencyRow from '~/packages/details/components/dependency_row.vue';
import { import {
conanPackage, conanPackage,
mavenPackage, mavenPackage,
......
import { mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import CodeInstruction from 'ee/packages/details/components/code_instruction.vue'; import CodeInstruction from '~/packages/details/components/code_instruction.vue';
import { TrackingLabels } from 'ee/packages/details/constants'; import { TrackingLabels } from '~/packages/details/constants';
import Tracking from '~/tracking'; import Tracking from '~/tracking';
describe('Package code instruction', () => { describe('Package code instruction', () => {
......
import Vuex from 'vuex'; import Vuex from 'vuex';
import { mount, createLocalVue } from '@vue/test-utils'; import { mount, createLocalVue } from '@vue/test-utils';
import ConanInstallation from 'ee/packages/details/components/conan_installation.vue'; import ConanInstallation from '~/packages/details/components/conan_installation.vue';
import { conanPackage as packageEntity } from '../../mock_data'; import { conanPackage as packageEntity } from '../../mock_data';
import { registryUrl as conanPath } from '../mock_data'; import { registryUrl as conanPath } from '../mock_data';
import { GlTabs } from '@gitlab/ui'; import { GlTabs } from '@gitlab/ui';
......
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import DependencyRow from 'ee/packages/details/components/dependency_row.vue'; import DependencyRow from '~/packages/details/components/dependency_row.vue';
import { dependencyLinks } from '../../mock_data'; import { dependencyLinks } from '../../mock_data';
describe('DependencyRow', () => { describe('DependencyRow', () => {
......
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import PackageInformation from 'ee/packages/details/components/information.vue'; import PackageInformation from '~/packages/details/components/information.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import { GlLink } from '@gitlab/ui'; import { GlLink } from '@gitlab/ui';
......
import { mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import InstallationTabs from 'ee/packages/details/components/installation_tabs.vue'; import InstallationTabs from '~/packages/details/components/installation_tabs.vue';
import Tracking from '~/tracking'; import Tracking from '~/tracking';
import { TrackingActions } from 'ee/packages/details/constants'; import { TrackingActions } from '~/packages/details/constants';
describe('InstallationTabs', () => { describe('InstallationTabs', () => {
let wrapper; let wrapper;
......
import Vuex from 'vuex'; import Vuex from 'vuex';
import { mount, createLocalVue } from '@vue/test-utils'; import { mount, createLocalVue } from '@vue/test-utils';
import MavenInstallation from 'ee/packages/details/components/maven_installation.vue'; import MavenInstallation from '~/packages/details/components/maven_installation.vue';
import { registryUrl as mavenPath } from '../mock_data'; import { registryUrl as mavenPath } from '../mock_data';
import { mavenPackage as packageEntity } from '../../mock_data'; import { mavenPackage as packageEntity } from '../../mock_data';
import { GlTabs } from '@gitlab/ui'; import { GlTabs } from '@gitlab/ui';
......
import Vuex from 'vuex'; import Vuex from 'vuex';
import { mount, createLocalVue } from '@vue/test-utils'; import { mount, createLocalVue } from '@vue/test-utils';
import NpmInstallation from 'ee/packages/details/components/npm_installation.vue'; import NpmInstallation from '~/packages/details/components/npm_installation.vue';
import { npmPackage as packageEntity } from '../../mock_data'; import { npmPackage as packageEntity } from '../../mock_data';
import { registryUrl as nugetPath } from '../mock_data'; import { registryUrl as nugetPath } from '../mock_data';
import { GlTabs } from '@gitlab/ui'; import { GlTabs } from '@gitlab/ui';
......
import Vuex from 'vuex'; import Vuex from 'vuex';
import { mount, createLocalVue } from '@vue/test-utils'; import { mount, createLocalVue } from '@vue/test-utils';
import NugetInstallation from 'ee/packages/details/components/nuget_installation.vue'; import NugetInstallation from '~/packages/details/components/nuget_installation.vue';
import { nugetPackage as packageEntity } from '../../mock_data'; import { nugetPackage as packageEntity } from '../../mock_data';
import { registryUrl as nugetPath } from '../mock_data'; import { registryUrl as nugetPath } from '../mock_data';
import { GlTabs } from '@gitlab/ui'; import { GlTabs } from '@gitlab/ui';
......
import Vuex from 'vuex'; import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils'; import { shallowMount, createLocalVue } from '@vue/test-utils';
import PackageTitle from 'ee/packages/details/components/package_title.vue'; import PackageTitle from '~/packages/details/components/package_title.vue';
import PackageTags from 'ee/packages/shared/components/package_tags.vue'; import PackageTags from '~/packages/shared/components/package_tags.vue';
import { import {
conanPackage, conanPackage,
mavenFiles, mavenFiles,
......
import Vuex from 'vuex'; import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils'; import { shallowMount, createLocalVue } from '@vue/test-utils';
import PypiInstallation from 'ee/packages/details/components/pypi_installation.vue'; import PypiInstallation from '~/packages/details/components/pypi_installation.vue';
import InstallationTabs from 'ee/packages/details/components/installation_tabs.vue'; import InstallationTabs from '~/packages/details/components/installation_tabs.vue';
import { pypiPackage as packageEntity } from '../../mock_data'; import { pypiPackage as packageEntity } from '../../mock_data';
import { GlTabs } from '@gitlab/ui'; import { GlTabs } from '@gitlab/ui';
......
import Api from 'ee/api'; import Api from '~/api';
import createFlash from '~/flash'; import createFlash from '~/flash';
import fetchPackageVersions from 'ee/packages/details/store/actions'; import fetchPackageVersions from '~/packages/details/store/actions';
import * as types from 'ee/packages/details/store/mutation_types'; import * as types from '~/packages/details/store/mutation_types';
import { FETCH_PACKAGE_VERSIONS_ERROR } from 'ee/packages/details/constants'; import { FETCH_PACKAGE_VERSIONS_ERROR } from '~/packages/details/constants';
import testAction from 'helpers/vuex_action_helper'; import testAction from 'helpers/vuex_action_helper';
import { npmPackage as packageEntity } from '../../mock_data'; import { npmPackage as packageEntity } from '../../mock_data';
jest.mock('~/flash.js'); jest.mock('~/flash.js');
jest.mock('ee/api.js'); jest.mock('~/api.js');
describe('Actions Package details store', () => { describe('Actions Package details store', () => {
describe('fetchPackageVersions', () => { describe('fetchPackageVersions', () => {
......
...@@ -13,7 +13,7 @@ import { ...@@ -13,7 +13,7 @@ import {
nugetSetupCommand, nugetSetupCommand,
pypiPipCommand, pypiPipCommand,
pypiSetupCommand, pypiSetupCommand,
} from 'ee/packages/details/store/getters'; } from '~/packages/details/store/getters';
import { import {
conanPackage, conanPackage,
npmPackage, npmPackage,
...@@ -29,8 +29,8 @@ import { ...@@ -29,8 +29,8 @@ import {
registryUrl, registryUrl,
pypiSetupCommandStr, pypiSetupCommandStr,
} from '../mock_data'; } from '../mock_data';
import { generateConanRecipe } from 'ee/packages/details/utils'; import { generateConanRecipe } from '~/packages/details/utils';
import { NpmManager } from 'ee/packages/details/constants'; import { NpmManager } from '~/packages/details/constants';
describe('Getters PackageDetails Store', () => { describe('Getters PackageDetails Store', () => {
let state; let state;
......
import mutations from 'ee/packages/details/store/mutations'; import mutations from '~/packages/details/store/mutations';
import * as types from 'ee/packages/details/store/mutation_types'; import * as types from '~/packages/details/store/mutation_types';
import { npmPackage as packageEntity } from '../../mock_data'; import { npmPackage as packageEntity } from '../../mock_data';
describe('Mutations package details Store', () => { describe('Mutations package details Store', () => {
......
import { generateConanRecipe, generatePackageInfo } from 'ee/packages/details/utils'; import { generateConanRecipe, generatePackageInfo } from '~/packages/details/utils';
import { conanPackage, mavenPackage, npmPackage, nugetPackage } from '../mock_data'; import { conanPackage, mavenPackage, npmPackage, nugetPackage } from '../mock_data';
import { import {
generateConanInformation, generateConanInformation,
......
import * as comingSoon from 'ee/packages/list/coming_soon/helpers'; import * as comingSoon from '~/packages/list/coming_soon/helpers';
import { fakeIssues, asGraphQLResponse, asViewModel } from './mock_data'; import { fakeIssues, asGraphQLResponse, asViewModel } from './mock_data';
jest.mock('ee/api.js'); jest.mock('~/api.js');
describe('Coming Soon Helpers', () => { describe('Coming Soon Helpers', () => {
const [noLabels, acceptingMergeRequestLabel, workflowLabel] = fakeIssues; const [noLabels, acceptingMergeRequestLabel, workflowLabel] = fakeIssues;
......
import { GlEmptyState, GlSkeletonLoader, GlLabel } from '@gitlab/ui'; import { GlEmptyState, GlSkeletonLoader, GlLabel } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils'; import { mount, createLocalVue } from '@vue/test-utils';
import ComingSoon from 'ee/packages/list/coming_soon/packages_coming_soon.vue'; import ComingSoon from '~/packages/list/coming_soon/packages_coming_soon.vue';
import { TrackingActions } from 'ee/packages/shared/constants'; import { TrackingActions } from '~/packages/shared/constants';
import { asViewModel } from './mock_data'; import { asViewModel } from './mock_data';
import Tracking from '~/tracking'; import Tracking from '~/tracking';
import VueApollo, { ApolloQuery } from 'vue-apollo'; import VueApollo, { ApolloQuery } from 'vue-apollo';
jest.mock('ee/packages/list/coming_soon/helpers.js'); jest.mock('~/packages/list/coming_soon/helpers.js');
const localVue = createLocalVue(); const localVue = createLocalVue();
localVue.use(VueApollo); localVue.use(VueApollo);
......
import Vuex from 'vuex'; import Vuex from 'vuex';
import { GlSearchBoxByClick } from '@gitlab/ui'; import { GlSearchBoxByClick } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils'; import { createLocalVue, shallowMount } from '@vue/test-utils';
import PackagesFilter from 'ee/packages/list/components/packages_filter.vue'; import PackagesFilter from '~/packages/list/components/packages_filter.vue';
const localVue = createLocalVue(); const localVue = createLocalVue();
localVue.use(Vuex); localVue.use(Vuex);
......
import Vuex from 'vuex'; import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils'; import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlEmptyState, GlTab, GlTabs, GlSprintf, GlLink } from '@gitlab/ui'; import { GlEmptyState, GlTab, GlTabs, GlSprintf, GlLink } from '@gitlab/ui';
import PackageListApp from 'ee/packages/list/components/packages_list_app.vue'; import PackageListApp from '~/packages/list/components/packages_list_app.vue';
const localVue = createLocalVue(); const localVue = createLocalVue();
localVue.use(Vuex); localVue.use(Vuex);
......
...@@ -3,11 +3,11 @@ import { last } from 'lodash'; ...@@ -3,11 +3,11 @@ import { last } from 'lodash';
import { GlTable, GlPagination, GlModal } from '@gitlab/ui'; import { GlTable, GlPagination, GlModal } from '@gitlab/ui';
import Tracking from '~/tracking'; import Tracking from '~/tracking';
import { mount, createLocalVue } from '@vue/test-utils'; import { mount, createLocalVue } from '@vue/test-utils';
import PackagesList from 'ee/packages/list/components/packages_list.vue'; import PackagesList from '~/packages/list/components/packages_list.vue';
import PackagesListLoader from 'ee/packages/shared/components/packages_list_loader.vue'; import PackagesListLoader from '~/packages/shared/components/packages_list_loader.vue';
import PackagesListRow from 'ee/packages/shared/components/package_list_row.vue'; import PackagesListRow from '~/packages/shared/components/package_list_row.vue';
import * as SharedUtils from 'ee/packages/shared/utils'; import * as SharedUtils from '~/packages/shared/utils';
import { TrackingActions } from 'ee/packages/shared/constants'; import { TrackingActions } from '~/packages/shared/constants';
import stubChildren from 'helpers/stub_children'; import stubChildren from 'helpers/stub_children';
import { packageList } from '../../mock_data'; import { packageList } from '../../mock_data';
......
import Vuex from 'vuex'; import Vuex from 'vuex';
import { GlSorting } from '@gitlab/ui'; import { GlSorting } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils'; import { mount, createLocalVue } from '@vue/test-utils';
import PackagesSort from 'ee/packages/list/components/packages_sort.vue'; import PackagesSort from '~/packages/list/components/packages_sort.vue';
import stubChildren from 'helpers/stub_children'; import stubChildren from 'helpers/stub_children';
const localVue = createLocalVue(); const localVue = createLocalVue();
......
import axios from 'axios'; import axios from 'axios';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import Api from 'ee/api'; import Api from '~/api';
import createFlash from '~/flash'; import createFlash from '~/flash';
import * as actions from 'ee/packages/list/stores/actions'; import * as actions from '~/packages/list/stores/actions';
import * as types from 'ee/packages/list/stores/mutation_types'; import * as types from '~/packages/list/stores/mutation_types';
import { import { MISSING_DELETE_PATH_ERROR, DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages/list/constants';
MISSING_DELETE_PATH_ERROR,
DELETE_PACKAGE_ERROR_MESSAGE,
} from 'ee/packages/list/constants';
import testAction from 'helpers/vuex_action_helper'; import testAction from 'helpers/vuex_action_helper';
jest.mock('~/flash.js'); jest.mock('~/flash.js');
jest.mock('ee/api.js'); jest.mock('~/api.js');
describe('Actions Package list store', () => { describe('Actions Package list store', () => {
const headers = 'bar'; const headers = 'bar';
......
import getList from 'ee/packages/list/stores/getters'; import getList from '~/packages/list/stores/getters';
import { packageList } from '../../mock_data'; import { packageList } from '../../mock_data';
describe('Getters registry list store', () => { describe('Getters registry list store', () => {
......
import mutations from 'ee/packages/list/stores/mutations'; import mutations from '~/packages/list/stores/mutations';
import * as types from 'ee/packages/list/stores/mutation_types'; import * as types from '~/packages/list/stores/mutation_types';
import createState from 'ee/packages/list/stores/state'; import createState from '~/packages/list/stores/state';
import * as commonUtils from '~/lib/utils/common_utils'; import * as commonUtils from '~/lib/utils/common_utils';
import { npmPackage, mavenPackage } from '../../mock_data'; import { npmPackage, mavenPackage } from '../../mock_data';
......
import { getNewPaginationPage } from 'ee/packages/list/utils'; import { getNewPaginationPage } from '~/packages/list/utils';
describe('Packages list utils', () => { describe('Packages list utils', () => {
describe('packageTypeDisplay', () => { describe('packageTypeDisplay', () => {
......
import { mount, shallowMount } from '@vue/test-utils'; import { mount, shallowMount } from '@vue/test-utils';
import PackagesListRow from 'ee/packages/shared/components/package_list_row.vue'; import PackagesListRow from '~/packages/shared/components/package_list_row.vue';
import PackageTags from 'ee/packages/shared/components/package_tags.vue'; import PackageTags from '~/packages/shared/components/package_tags.vue';
import { packageList } from '../../mock_data'; import { packageList } from '../../mock_data';
describe('packages_list_row', () => { describe('packages_list_row', () => {
......
import { mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import PackageTags from 'ee/packages/shared/components/package_tags.vue'; import PackageTags from '~/packages/shared/components/package_tags.vue';
import { mockTags } from '../../mock_data'; import { mockTags } from '../../mock_data';
describe('PackageTags', () => { describe('PackageTags', () => {
......
import { mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import PackagesListLoader from 'ee/packages/shared/components/packages_list_loader.vue'; import PackagesListLoader from '~/packages/shared/components/packages_list_loader.vue';
describe('PackagesListLoader', () => { describe('PackagesListLoader', () => {
let wrapper; let wrapper;
......
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import PublishMethod from 'ee/packages/shared/components/publish_method.vue'; import PublishMethod from '~/packages/shared/components/publish_method.vue';
import { packageList } from '../../mock_data'; import { packageList } from '../../mock_data';
describe('publish_method', () => { describe('publish_method', () => {
......
...@@ -3,8 +3,8 @@ import { ...@@ -3,8 +3,8 @@ import {
beautifyPath, beautifyPath,
getPackageTypeLabel, getPackageTypeLabel,
getCommitLink, getCommitLink,
} from 'ee/packages/shared/utils'; } from '~/packages/shared/utils';
import { PackageType, TrackingCategories } from 'ee/packages/shared/constants'; import { PackageType, TrackingCategories } from '~/packages/shared/constants';
import { packageList } from '../mock_data'; import { packageList } from '../mock_data';
describe('Packages shared utils', () => { describe('Packages shared utils', () => {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe EE::PackagesHelper do RSpec.describe PackagesHelper do
let_it_be(:base_url) { "#{Gitlab.config.gitlab.url}/api/v4/" } let_it_be(:base_url) { "#{Gitlab.config.gitlab.url}/api/v4/" }
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }
......
...@@ -475,6 +475,46 @@ RSpec.describe Project do ...@@ -475,6 +475,46 @@ RSpec.describe Project do
end end
end end
describe '#has_packages?' do
let(:project) { create(:project, :public) }
subject { project.has_packages?(package_type) }
shared_examples 'returning true examples' do
let!(:package) { create("#{package_type}_package", project: project) }
it { is_expected.to be true }
end
shared_examples 'returning false examples' do
it { is_expected.to be false }
end
context 'with maven packages' do
it_behaves_like 'returning true examples' do
let(:package_type) { :maven }
end
end
context 'with npm packages' do
it_behaves_like 'returning true examples' do
let(:package_type) { :npm }
end
end
context 'with conan packages' do
it_behaves_like 'returning true examples' do
let(:package_type) { :conan }
end
end
context 'with no package type' do
it_behaves_like 'returning false examples' do
let(:package_type) { nil }
end
end
end
describe '#ci_pipelines' do describe '#ci_pipelines' do
let(:project) { create(:project) } let(:project) { create(:project) }
......
...@@ -1586,6 +1586,7 @@ RSpec.describe API::Projects do ...@@ -1586,6 +1586,7 @@ RSpec.describe API::Projects do
expect(json_response['ci_default_git_depth']).to eq(project.ci_default_git_depth) expect(json_response['ci_default_git_depth']).to eq(project.ci_default_git_depth)
expect(json_response['merge_method']).to eq(project.merge_method.to_s) expect(json_response['merge_method']).to eq(project.merge_method.to_s)
expect(json_response['readme_url']).to eq(project.readme_url) expect(json_response['readme_url']).to eq(project.readme_url)
expect(json_response).to have_key 'packages_enabled'
end end
it 'returns a group link with expiration date' do it 'returns a group link with expiration date' do
...@@ -2339,6 +2340,22 @@ RSpec.describe API::Projects do ...@@ -2339,6 +2340,22 @@ RSpec.describe API::Projects do
expect(project_member).to be_persisted expect(project_member).to be_persisted
end end
describe 'updating packages_enabled attribute' do
it 'is enabled by default' do
expect(project.packages_enabled).to be true
end
context 'without the need for a license' do
it 'disables project packages feature' do
put(api("/projects/#{project.id}", user), params: { packages_enabled: false })
expect(response).to have_gitlab_http_status(:ok)
expect(project.reload.packages_enabled).to be false
expect(json_response['packages_enabled']).to eq(false)
end
end
end
it 'returns 400 when nothing sent' do it 'returns 400 when nothing sent' do
project_param = {} project_param = {}
......
...@@ -18,4 +18,22 @@ module NavbarStructureHelper ...@@ -18,4 +18,22 @@ module NavbarStructureHelper
index = hash[:nav_sub_items].find_index(before_sub_nav_item_name) index = hash[:nav_sub_items].find_index(before_sub_nav_item_name)
hash[:nav_sub_items].insert(index + 1, new_sub_nav_item_name) hash[:nav_sub_items].insert(index + 1, new_sub_nav_item_name)
end end
def insert_package_nav(within)
insert_after_nav_item(
within,
new_nav_item: {
nav_item: _('Packages & Registries'),
nav_sub_items: [_('Package Registry')]
}
)
end
def insert_container_nav(within)
insert_after_sub_nav_item(
_('Package Registry'),
within: _('Packages & Registries'),
new_sub_nav_item_name: _('Container Registry')
)
end
end end
...@@ -47,6 +47,58 @@ RSpec.describe 'layouts/nav/sidebar/_project' do ...@@ -47,6 +47,58 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end end
end end
describe 'Packages' do
let(:user) { create(:user) }
let_it_be(:package_menu_name) { 'Packages & Registries' }
let_it_be(:package_entry_name) { 'Package Registry' }
before do
project.team.add_developer(user)
sign_in(user)
stub_container_registry_config(enabled: true)
end
context 'when packages is enabled' do
it 'packages link is visible' do
render
expect(rendered).to have_link(package_menu_name, href: project_packages_path(project))
end
it 'packages list link is visible' do
render
expect(rendered).to have_link(package_entry_name, href: project_packages_path(project))
end
it 'container registry link is visible' do
render
expect(rendered).to have_link('Container Registry', href: project_container_registry_index_path(project))
end
end
context 'when container registry is disabled' do
before do
stub_container_registry_config(enabled: false)
end
it 'packages top level and list link are visible' do
render
expect(rendered).to have_link(package_menu_name, href: project_packages_path(project))
expect(rendered).to have_link(package_entry_name, href: project_packages_path(project))
end
it 'container registry link is not visible' do
render
expect(rendered).not_to have_link('Container Registry', href: project_container_registry_index_path(project))
end
end
end
describe 'releases entry' do describe 'releases entry' do
it 'renders releases link' do it 'renders releases link' do
render render
......
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