Commit e2d0476d authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents 31c33cc1 52df80ba
6e72a649c1b92f962ba8c82bec29ffe4f91ff957
67520d7b374eea77f7412600271a90193bdd2e8a
......@@ -33,10 +33,10 @@ module Boards
service = Boards::Lists::UpdateService.new(board_parent, current_user, update_list_params)
result = service.execute(list)
if result[:status] == :success
if result.success?
head :ok
else
head result[:http_status]
head result.http_status
end
end
......
......@@ -20,8 +20,8 @@ module Mutations
update_result = update_list(list, args)
{
list: update_result[:list],
errors: list.errors.full_messages
list: update_result.payload[:list],
errors: update_result.errors
}
end
......
......@@ -39,7 +39,8 @@ module SidebarsHelper
current_user: user,
container: project,
learn_gitlab_experiment_enabled: learn_gitlab_experiment_enabled?(project),
current_ref: current_ref
current_ref: current_ref,
jira_issues_integration: project_jira_issues_integration?
}
end
end
......@@ -5,6 +5,9 @@ module Ci
# Data will be removed after transitioning from running to any state.
class BuildRunnerSession < ApplicationRecord
extend Gitlab::Ci::Model
include IgnorableColumns
ignore_columns :build_id_convert_to_bigint, remove_with: '14.1', remove_after: '2021-07-22'
TERMINAL_SUBPROTOCOL = 'terminal.gitlab.com'
DEFAULT_SERVICE_NAME = 'build'
......
......@@ -3,16 +3,30 @@
module Boards
module Lists
class BaseUpdateService < Boards::BaseService
extend ::Gitlab::Utils::Override
def execute(list)
if execute_by_params(list)
success(list: list)
else
error(list.errors.messages, 422)
message = list.errors.empty? ? 'The update was not successful.' : list.errors.messages
error(message, { list: list })
end
end
private
override :error
def error(message, pass_back = {})
ServiceResponse.error(message: message, http_status: :unprocessable_entity, payload: pass_back)
end
override :success
def success(pass_back = {})
ServiceResponse.success(payload: pass_back)
end
def execute_by_params(list)
update_preferences_result = update_preferences(list) if can_read?(list)
update_position_result = update_position(list) if can_admin?(list)
......
- if project_nav_tab?(:external_issue_tracker)
- issue_tracker = @project.external_issue_tracker
- if issue_tracker.is_a?(JiraService) && project_jira_issues_integration?
= render_if_exists 'layouts/nav/sidebar/project_jira_issues_link', issue_tracker: issue_tracker
- else
= nav_link do
= link_to issue_tracker.issue_tracker_path, target: '_blank', rel: 'noopener noreferrer', class: 'shortcuts-external_tracker' do
.nav-icon-container
= sprite_icon('external-link')
%span.nav-item-name
= issue_tracker.title
%ul.sidebar-sub-level-items.is-fly-out-only
= nav_link(html_options: { class: "fly-out-top-item" } ) do
= link_to issue_tracker.issue_tracker_path, target: '_blank', rel: 'noopener noreferrer' do
%strong.fly-out-top-item-name
= issue_tracker.title
- if (project_nav_tab? :labels) && !@project.issues_enabled?
= nav_link(controller: [:labels]) do
= link_to project_labels_path(@project), title: _('Labels'), class: 'shortcuts-labels qa-labels-items' do
.nav-icon-container
= sprite_icon('label')
%span.nav-item-name#js-onboarding-labels-link
= _('Labels')
- if project_nav_tab? :merge_requests
= nav_link(controller: @project.issues_enabled? ? :merge_requests : [:merge_requests, :milestones]) do
= link_to project_merge_requests_path(@project), class: 'shortcuts-merge_requests', data: { qa_selector: 'merge_requests_link' } do
......
......@@ -15,7 +15,7 @@
%ul.sidebar-sub-level-items{ class: ('is-fly-out-only' unless sidebar_menu.has_items?) }
= nav_link(**sidebar_menu.all_active_routes, html_options: { class: 'fly-out-top-item' } ) do
= link_to sidebar_menu.link, aria: { label: sidebar_menu.title } do
= link_to sidebar_menu.link, **sidebar_menu.collapsed_container_html_options do
%strong.fly-out-top-item-name
= sidebar_menu.title
- if sidebar_menu.has_pill?
......
---
title: Initialize conversion of ci_builds_runner_session.build_id to bigint
merge_request: 60366
author:
type: other
---
title: Improve errors reporting for board lists update
merge_request: 59549
author:
type: added
---
key_path: database.pg_system_id
description: ''
product_section: ''
product_stage: ''
product_group: ''
product_category: ''
description: TBD
product_section: enablement
product_stage: enablement
product_group: group::distribution
product_category:
value_type: number
status: data_available
time_frame: all
......
# frozen_string_literal: true
class InitializeConversionOfCiBuildsRunnerSessionToBigint < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
TABLE = :ci_builds_runner_session
COLUMNS = %i(build_id)
def up
initialize_conversion_of_integer_to_bigint(TABLE, COLUMNS)
end
def down
revert_initialize_conversion_of_integer_to_bigint(TABLE, COLUMNS)
end
end
# frozen_string_literal: true
class BackfillCiBuildsRunnerSessionForBigintConversion < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
TABLE = :ci_builds_runner_session
COLUMNS = %i(build_id)
def up
return unless should_run?
backfill_conversion_of_integer_to_bigint(TABLE, COLUMNS)
end
def down
return unless should_run?
revert_backfill_conversion_of_integer_to_bigint(TABLE, COLUMNS)
end
private
def should_run?
Gitlab.dev_or_test_env? || Gitlab.com?
end
end
a2fcf3576de4ee5afdab8d07ffc6c2c8f96d6cc85c332f6ab69f2936bf9e58ae
\ No newline at end of file
2e30910d106dd6805f42ffc226d9008b826fa88eaec7091960e11db850b714c4
\ No newline at end of file
......@@ -125,6 +125,15 @@ BEGIN
END;
$$;
CREATE FUNCTION trigger_51ab7cef8934() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
NEW."build_id_convert_to_bigint" := NEW."build_id";
RETURN NEW;
END;
$$;
CREATE FUNCTION trigger_69523443cc10() RETURNS trigger
LANGUAGE plpgsql
AS $$
......@@ -10486,7 +10495,8 @@ CREATE TABLE ci_builds_runner_session (
build_id integer NOT NULL,
url character varying NOT NULL,
certificate character varying,
"authorization" character varying
"authorization" character varying,
build_id_convert_to_bigint bigint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE ci_builds_runner_session_id_seq
......@@ -24768,6 +24778,8 @@ CREATE TRIGGER trigger_21e7a2602957 BEFORE INSERT OR UPDATE ON ci_build_needs FO
CREATE TRIGGER trigger_3f6129be01d2 BEFORE INSERT OR UPDATE ON ci_builds FOR EACH ROW EXECUTE PROCEDURE trigger_3f6129be01d2();
CREATE TRIGGER trigger_51ab7cef8934 BEFORE INSERT OR UPDATE ON ci_builds_runner_session FOR EACH ROW EXECUTE PROCEDURE trigger_51ab7cef8934();
CREATE TRIGGER trigger_69523443cc10 BEFORE INSERT OR UPDATE ON events FOR EACH ROW EXECUTE PROCEDURE trigger_69523443cc10();
CREATE TRIGGER trigger_8485e97c00e3 BEFORE INSERT OR UPDATE ON ci_sources_pipelines FOR EACH ROW EXECUTE PROCEDURE trigger_8485e97c00e3();
......@@ -101,7 +101,7 @@ with [domain expertise](#domain-experts).
1. If your merge request includes frontend changes (*1*), it must be
**approved by a [frontend maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_frontend)**.
1. If your merge request includes user-facing changes (*3*), it must be
**approved by a [Product Designer](https://about.gitlab.com/handbook/engineering/ux/product-design/)**,
**approved by a [Product Designer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_reviewers_UX)**,
based on assignments in the appropriate [DevOps stage group](https://about.gitlab.com/handbook/product/categories/#devops-stages).
1. If your merge request includes adding a new JavaScript library (*1*)...
- If the library significantly increases the
......@@ -114,8 +114,8 @@ with [domain expertise](#domain-experts).
1. If your merge request includes a new dependency or a file system change, it must be
**approved by a [Distribution team member](https://about.gitlab.com/company/team/)**. See how to work with the [Distribution team](https://about.gitlab.com/handbook/engineering/development/enablement/distribution/#how-to-work-with-distribution) for more details.
1. If your merge request includes documentation changes, it must be **approved
by a [Technical writer](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments)**, based on
the appropriate [product category](https://about.gitlab.com/handbook/product/categories/).
by a [Technical writer](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments)**,
based on assignments in the appropriate [DevOps stage group](https://about.gitlab.com/handbook/product/categories/#devops-stages).
1. If your merge request includes end-to-end **and** non-end-to-end changes (*4*), it must be **approved
by a [Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors)**.
1. If your merge request only includes end-to-end changes (*4*) **or** if the MR author is a [Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors), it must be **approved by a [Quality maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_qa)**
......
......@@ -6350,7 +6350,7 @@ Missing description
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/counts_all/20210216183248_pg_system_id.yml)
Group: ``
Group: `group::distribution`
Status: `data_available`
......
......@@ -100,27 +100,39 @@ To use the KAS:
### Define a configuration repository
Next, you need a GitLab repository to contain your Agent configuration. The minimal
repository layout looks like this:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259669) in GitLab 13.7, the Agent manifest configuration can be added to multiple directories (or subdirectories) of its repository.
To configure an Agent, you need:
1. A GitLab repository to hold the configuration file.
1. Install the Agent in a cluster.
After installed, when you update the configuration file, GitLab transmits the
information to the cluster automatically without downtime.
In your repository, add the Agent configuration file under:
```plaintext
.gitlab/agents/<agent-name>/config.yaml
```
Your `config.yaml` file can specify multiple manifest projects in the
section `manifest_projects`:
Your `config.yaml` file specifies all configurations of the Agent, such as:
- The manifest projects to synchronize.
- The address of the `hubble-relay` for the Network Security policy integrations.
As an example, a minimal Agent configuration that sets up only the manifest
synchronizations is:
```yaml
gitops:
manifest_projects:
- id: "path-to/your-manifest-project-number1"
...
- id: "path-to/your-manifest-project-1"
paths:
- glob: '/**/*.{yaml,yml,json}'
```
GitLab [versions 13.7 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/259669) also
supports manifest projects containing
multiple directories (or subdirectories) of YAML files. For more information see our
documentation on the [Kubernetes Agent configuration repository](repository.md).
All the options for the [Kubernetes Agent configuration repository](repository.md) are documented separately.
### Create an Agent record in GitLab
......
......@@ -46,8 +46,8 @@ module Mutations
update_result = update_list(args)
{
list: update_result[:list],
errors: list.errors.full_messages
list: update_result.payload.fetch(:list),
errors: update_result.errors
}
end
......
......@@ -198,12 +198,6 @@ module EE
]
end
def sidebar_external_tracker_paths
%w[
projects/integrations/jira/issues#index
]
end
def sidebar_on_demand_scans_paths
%w[
projects/on_demand_scans#index
......
......@@ -6,7 +6,7 @@ module EE
override :project_jira_issues_integration?
def project_jira_issues_integration?
@project.jira_issues_integration_available? && @project.jira_service.issues_enabled
@project.jira_issues_integration_available? && @project.jira_service&.issues_enabled
end
override :integration_form_data
......
= nav_link(path: sidebar_external_tracker_paths) do
= link_to project_integrations_jira_issues_path(@project) do
.nav-icon-container
-# Hardcode sizes so image doesn't flash before CSS loads https://gitlab.com/gitlab-org/gitlab/-/issues/321022
= image_tag('logos/jira-gray.svg', size: 16)
%span.nav-item-name.qa-settings-item#js-onboarding-settings-link
= s_('JiraService|Jira Issues')
%ul.sidebar-sub-level-items
= nav_link(path: sidebar_external_tracker_paths, html_options: { class: 'fly-out-top-item' } ) do
= link_to project_integrations_jira_issues_path(@project) do
%strong.fly-out-top-item-name
= s_('JiraService|Jira Issues')
%li.divider.fly-out-top-item
= nav_link(path: sidebar_external_tracker_paths[0]) do
= link_to project_integrations_jira_issues_path(@project), title: s_('JiraService|Issue List') do
%span
= s_('JiraService|Issue List')
= nav_link do
= link_to issue_tracker.issue_tracker_path, target: '_blank', rel: 'noopener noreferrer' do
%span
= s_('JiraService|Open Jira')
= sprite_icon('external-link', css_class: 'gl-vertical-align-text-bottom')
# frozen_string_literal: true
module EE
module Sidebars
module Projects
module Panel
extend ::Gitlab::Utils::Override
override :configure_menus
def configure_menus
super
if jira_menu.render?
replace_menu(::Sidebars::Projects::Menus::ExternalIssueTrackerMenu, jira_menu)
end
end
private
def jira_menu
@jira_menu ||= ::Sidebars::Projects::Menus::JiraMenu.new(context)
end
end
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
class JiraMenu < ::Sidebars::Menu
override :configure_menu_items
def configure_menu_items
return false unless external_issue_tracker
add_item(issue_list_menu_item)
add_item(open_jira_menu_item)
true
end
override :link
def link
project_integrations_jira_issues_path(context.project)
end
override :title
def title
s_('JiraService|Jira Issues')
end
override :title_html_options
def title_html_options
{
id: 'js-onboarding-settings-link'
}
end
override :image_path
def image_path
'logos/jira-gray.svg'
end
# Hardcode sizes so image doesn't flash before CSS loads https://gitlab.com/gitlab-org/gitlab/-/issues/321022
override :image_html_options
def image_html_options
{
size: 16
}
end
override :render?
def render?
external_issue_tracker.is_a?(JiraService) && context.jira_issues_integration
end
private
def external_issue_tracker
@external_issue_tracker ||= context.project.external_issue_tracker
end
def issue_list_menu_item
::Sidebars::MenuItem.new(
title: s_('JiraService|Issue List'),
link: project_integrations_jira_issues_path(context.project),
active_routes: { path: 'projects/integrations/jira/issues#index' },
item_id: :issue_list
)
end
def open_jira_menu_item
::Sidebars::MenuItem.new(
title: s_('JiraService|Open Jira'),
link: external_issue_tracker.issue_tracker_path,
active_routes: {},
item_id: :open_jira,
sprite_icon: 'external-link',
sprite_icon_html_options: { css_class: 'gl-vertical-align-text-bottom' },
container_html_options: {
target: '_blank',
rel: 'noopener noreferrer'
}
)
end
end
end
end
end
......@@ -38,6 +38,10 @@ RSpec.describe Mutations::Boards::Lists::UpdateLimitMetrics do
expect(reloaded_list.max_issue_count).to eq(10)
expect(reloaded_list.max_issue_weight).to eq(50)
end
it 'returns the correct response' do
expect(subject.keys).to match_array([:list, :errors])
end
end
context 'without admin rights' do
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::JiraMenu do
let_it_be_with_refind(:project) { create(:project, has_external_issue_tracker: true) }
let(:user) { project.owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project, jira_issues_integration: jira_issues_integration) }
let(:jira_issues_integration) { false }
subject { described_class.new(context) }
describe 'render?' do
context 'when issue tracker is not a JiraService' do
it 'returns false' do
create(:custom_issue_tracker_service, active: true, project: project, project_url: 'http://test.com')
expect(subject.render?).to eq false
end
end
context 'when issue tracker is a JiraService' do
let!(:jira) { create(:jira_service, project: project, project_key: 'GL') }
context 'when issues integration is disabled' do
it 'returns false' do
expect(subject.render?).to eq false
end
end
context 'when issues integration is enabled' do
let(:jira_issues_integration) { true }
it 'returns true' do
expect(subject.render?).to eq true
end
it 'contains issue list and open jira menu items' do
expect(subject.items).not_to be_empty
expect(subject.items[0].item_id).to eq :issue_list
expect(subject.items[1].item_id).to eq :open_jira
end
end
end
end
end
......@@ -6,7 +6,8 @@ RSpec.describe Boards::EpicLists::UpdateService do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group, :private) }
let_it_be(:board) { create(:epic_board, group: group) }
let_it_be(:list) { create(:epic_list, epic_board: board, position: 0) }
let_it_be_with_reload(:list) { create(:epic_list, epic_board: board, position: 0) }
let_it_be_with_reload(:list2) { create(:epic_list, epic_board: board, position: 1) }
before do
stub_licensed_features(epics: true)
......
......@@ -36,8 +36,8 @@ RSpec.describe 'EE::Boards::Lists::UpdateService' do
service = Boards::Lists::UpdateService.new(board, user, { limit_metric: 'foo' })
result = service.execute(list)
expect(result[:http_status]).to eq(422)
expect(result[:status]).to eq(:error)
expect(result.http_status).to eq(:unprocessable_entity)
expect(result.status).to eq(:error)
reloaded_list = list.reload
expect(reloaded_list.limit_metric).to be_nil
......@@ -200,7 +200,7 @@ RSpec.describe 'EE::Boards::Lists::UpdateService' do
service = Boards::Lists::UpdateService.new(board, user, initialization_params)
result = service.execute(list)
expect(result[:status]).to eq(expected_service_result)
expect(result.status).to eq(expected_service_result)
reloaded_list = list.reload
......
......@@ -39,6 +39,48 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end
end
describe 'Jira' do
let_it_be_with_refind(:project) { create(:project, has_external_issue_tracker: true) }
context 'when Jira service integration is not set' do
it 'does not have a link to the Jira issues menu' do
render
expect(rendered).not_to have_link('Jira Issues', href: project_integrations_jira_issues_path(project))
end
end
context 'when Jira service integration is set' do
let!(:jira) { create(:jira_service, project: project, issues_enabled: true, project_key: 'GL') }
before do
stub_licensed_features(jira_issues_integration: true)
end
it 'has a link to the Jira issue tracker' do
render
expect(rendered).to have_link('Jira Issues', href: project_integrations_jira_issues_path(project))
end
describe 'Issue List' do
it 'has a link to Jira issue list' do
render
expect(rendered).to have_link('Issue List', href: project_integrations_jira_issues_path(project))
end
end
describe 'Open Jira' do
it 'has a link to open Jira' do
render
expect(rendered).to have_link('Open Jira', href: project.external_issue_tracker.issue_tracker_path)
end
end
end
end
describe 'Operations main link' do
let(:user) { create(:user) }
......
......@@ -17,6 +17,8 @@ module Gitlab
delegate :aborted?, :job_class, :table_name, :column_name, :job_arguments,
to: :batched_migration, prefix: :migration
attribute :pause_ms, :integer, default: 100
end
end
end
......
......@@ -23,6 +23,8 @@ module Gitlab
finished: 3
}
attribute :pause_ms, :integer, default: 100
def self.active_migration
active.queue_order.first
end
......
......@@ -18,6 +18,22 @@ module Sidebars
{}
end
# The attributes returned from this method
# will be applied to helper methods like
# `link_to` or the div containing the container
# when it is collapsed.
def collapsed_container_html_options
{
aria: { label: title }
}.merge(extra_collapsed_container_html_options)
end
# Classes should mostly override this method
# and not `collapsed_container_html_options`.
def extra_collapsed_container_html_options
{}
end
# Attributes to pass to the html_options attribute
# in the helper method that sets the active class
# on each element.
......
......@@ -34,6 +34,16 @@ module Sidebars
end
end
def replace_element(list, element_to_replace, new_element)
return unless new_element
index = index_of(list, element_to_replace)
return unless index
list[index] = new_element
end
private
# Classes including this method will have to define
......
......@@ -32,6 +32,10 @@ module Sidebars
insert_element_after(@menus, after_menu, new_menu)
end
def replace_menu(menu_to_replace, new_menu)
replace_element(@menus, menu_to_replace, new_menu)
end
def set_scope_menu(scope_menu)
@scope_menu = scope_menu
end
......
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
class ExternalIssueTrackerMenu < ::Sidebars::Menu
override :link
def link
external_issue_tracker.issue_tracker_path
end
override :extra_container_html_options
def extra_container_html_options
{
target: '_blank',
rel: 'noopener noreferrer',
class: 'shortcuts-external_tracker'
}
end
override :extra_collapsed_container_html_options
def extra_collapsed_container_html_options
{
target: '_blank',
rel: 'noopener noreferrer'
}
end
override :title
def title
external_issue_tracker.title
end
override :title_html_options
def title_html_options
{
id: 'js-onboarding-issues-link'
}
end
override :sprite_icon
def sprite_icon
'external-link'
end
override :render?
def render?
external_issue_tracker.present?
end
private
def external_issue_tracker
@external_issue_tracker ||= context.project.external_issue_tracker
end
end
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
class LabelsMenu < ::Sidebars::Menu
override :link
def link
project_labels_path(context.project)
end
override :extra_container_html_options
def extra_container_html_options
{
class: 'shortcuts-labels'
}
end
override :title
def title
_('Labels')
end
override :title_html_options
def title_html_options
{
id: 'js-onboarding-labels-link'
}
end
override :active_routes
def active_routes
{ controller: :labels }
end
override :sprite_icon
def sprite_icon
'label'
end
override :render?
def render?
can?(context.current_user, :read_label, context.project) && !context.project.issues_enabled?
end
end
end
end
end
......@@ -11,6 +11,8 @@ module Sidebars
add_menu(Sidebars::Projects::Menus::LearnGitlabMenu.new(context))
add_menu(Sidebars::Projects::Menus::RepositoryMenu.new(context))
add_menu(Sidebars::Projects::Menus::IssuesMenu.new(context))
add_menu(Sidebars::Projects::Menus::ExternalIssueTrackerMenu.new(context))
add_menu(Sidebars::Projects::Menus::LabelsMenu.new(context))
end
override :render_raw_menus_partial
......@@ -25,3 +27,5 @@ module Sidebars
end
end
end
Sidebars::Projects::Panel.prepend_if_ee('EE::Sidebars::Projects::Panel')
......@@ -18,4 +18,10 @@ RSpec.describe Sidebars::Concerns::ContainerWithHtmlOptions do
expect(subject.container_html_options).to eq(aria: { label: 'Foo' })
end
end
describe '#collapsed_container_html_options' do
it 'includes by default aria-label attribute' do
expect(subject.collapsed_container_html_options).to eq(aria: { label: 'Foo' })
end
end
end
......@@ -101,4 +101,27 @@ RSpec.describe Sidebars::Panel do
end
end
end
describe '#replace_element' do
let(:user) { build(:user) }
let(:list) { [1, user] }
it 'replace existing element in the list' do
panel.replace_element(list, Integer, 2)
expect(list).to eq [2, user]
end
it 'does not add nil elements' do
panel.replace_element(list, Integer, nil)
expect(list).to eq [1, user]
end
it 'does not add the element if the other element is not found' do
panel.replace_element(list, Project, 2)
expect(list).to eq [1, user]
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::ExternalIssueTrackerMenu do
let(:project) { build(:project) }
let(:user) { project.owner }
let(:jira_issues_integration_active) { false }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project, jira_issues_integration: jira_issues_integration_active) }
subject { described_class.new(context) }
it 'does not contain any sub menu' do
expect(subject.items).to be_empty
end
describe '#render?' do
before do
expect(subject).to receive(:external_issue_tracker).and_return(external_issue_tracker).at_least(1)
end
context 'when active external issue tracker' do
let(:external_issue_tracker) { build(:custom_issue_tracker_service, project: project) }
context 'is present' do
it 'returns true' do
expect(subject.render?).to be_truthy
end
end
context 'is not present' do
let(:external_issue_tracker) { nil }
it 'returns false' do
expect(subject.render?).to be_falsey
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::LabelsMenu do
let(:project) { build(:project) }
let(:user) { project.owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
subject { described_class.new(context) }
it 'does not contain any sub menu' do
expect(subject.items).to be_empty
end
describe '#render?' do
let(:issues_enabled) { true }
before do
allow(project).to receive(:issues_enabled?).and_return(issues_enabled)
end
context 'when user can read labels' do
context 'when issues feature is enabled' do
it 'returns false' do
expect(subject.render?).to be_falsey
end
end
context 'when issues feature is disabled' do
let(:issues_enabled) { false }
it 'returns true' do
expect(subject.render?).to be_truthy
end
end
end
context 'when user cannot read labels' do
let(:user) { nil }
it 'returns false' do
expect(subject.render?).to be_falsey
end
end
end
end
......@@ -11,6 +11,7 @@ RSpec.describe 'Update of an existing board list' do
let_it_be(:list) { create(:list, board: board, position: 0) }
let_it_be(:list2) { create(:list, board: board) }
let_it_be(:input) { { list_id: list.to_global_id.to_s, position: 1, collapsed: true } }
let(:mutation) { graphql_mutation(:update_board_list, input) }
let(:mutation_response) { graphql_mutation_response(:update_board_list) }
......
......@@ -3,8 +3,10 @@
require 'spec_helper'
RSpec.describe Boards::Lists::UpdateService do
let(:user) { create(:user) }
let_it_be(:user) { create(:user) }
let!(:list) { create(:list, board: board, position: 0) }
let!(:list2) { create(:list, board: board, position: 1) }
describe '#execute' do
let(:service) { described_class.new(board.resource_parent, user, params) }
......
......@@ -2,14 +2,30 @@
RSpec.shared_examples 'moving list' do
context 'when user can admin list' do
it 'calls Lists::MoveService to update list position' do
before do
board.resource_parent.add_developer(user)
end
context 'when the new position is valid' do
it 'calls Lists::MoveService to update list position' do
expect_next_instance_of(Boards::Lists::MoveService, board.resource_parent, user, params) do |move_service|
expect(move_service).to receive(:execute).with(list).and_call_original
end
expect_next_instance_of(Boards::Lists::MoveService, board.resource_parent, user, params) do |move_service|
expect(move_service).to receive(:execute).with(list).and_call_original
service.execute(list)
end
service.execute(list)
it 'returns a success response' do
expect(service.execute(list)).to be_success
end
end
context 'when the new position is invalid' do
let(:params) { { position: 10 } }
it 'returns error response' do
expect(service.execute(list)).to be_error
end
end
end
......@@ -19,6 +35,10 @@ RSpec.shared_examples 'moving list' do
service.execute(list)
end
it 'returns an error response' do
expect(service.execute(list)).to be_error
end
end
end
......
......@@ -181,6 +181,68 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end
end
describe 'External Issue Tracker' do
let_it_be_with_refind(:project) { create(:project, has_external_issue_tracker: true) }
context 'with custom external issue tracker' do
let(:external_issue_tracker_url) { 'http://test.com' }
let!(:external_issue_tracker) do
create(:custom_issue_tracker_service, active: external_issue_tracker_active, project: project, project_url: external_issue_tracker_url)
end
context 'when external issue tracker is configured and active' do
let(:external_issue_tracker_active) { true }
it 'has a link to the external issue tracker' do
render
expect(rendered).to have_link(external_issue_tracker.title, href: external_issue_tracker_url)
end
end
context 'when external issue tracker is not configured and active' do
let(:external_issue_tracker_active) { false }
it 'does not have a link to the external issue tracker' do
render
expect(rendered).not_to have_link(external_issue_tracker.title)
end
end
end
context 'with Jira issue tracker' do
let_it_be(:jira) { create(:jira_service, project: project, issues_enabled: false) }
it 'has a link to the Jira issue tracker' do
render
expect(rendered).to have_link('Jira', href: project.external_issue_tracker.issue_tracker_path)
end
end
end
describe 'Labels' do
context 'when issues are not enabled' do
it 'has a link to the labels path' do
project.project_feature.update!(issues_access_level: ProjectFeature::DISABLED)
render
expect(rendered).to have_link('Labels', href: project_labels_path(project), class: 'shortcuts-labels')
end
end
context 'when issues are enabled' do
it 'does not have a link to the labels path' do
render
expect(rendered).not_to have_link('Labels', href: project_labels_path(project), class: 'shortcuts-labels')
end
end
end
describe 'packages tab' do
before do
stub_container_registry_config(enabled: true)
......
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