Commit 3b71d015 authored by Mario Celi's avatar Mario Celi

Revert "Merge branch '300897-add-iteration-arguments-to-board-issue-creation-api' into 'master'"

This reverts merge request !70007
parent a6d3e124
......@@ -71,7 +71,7 @@ module Mutations
def resolve(project_path:, **attributes)
project = authorized_find!(project_path)
params = build_create_issue_params(attributes.merge(author_id: current_user.id), project)
params = build_create_issue_params(attributes.merge(author_id: current_user.id))
spam_params = ::Spam::SpamParams.new_from_request(request: context[:request])
issue = ::Issues::CreateService.new(project: project, current_user: current_user, params: params, spam_params: spam_params).execute
......@@ -88,8 +88,7 @@ module Mutations
private
# _project argument is unused here, but it is necessary on the EE version of the method
def build_create_issue_params(params, _project)
def build_create_issue_params(params)
params[:milestone_id] &&= params[:milestone_id]&.model_id
params[:assignee_ids] &&= params[:assignee_ids].map { |assignee_id| assignee_id&.model_id }
params[:label_ids] &&= params[:label_ids].map { |label_id| label_id&.model_id }
......
......@@ -2,8 +2,6 @@
# Base class, scoped by project
class BaseProjectService < ::BaseContainerService
include ::Gitlab::Utils::StrongMemoize
attr_accessor :project
def initialize(project:, current_user: nil, params: {})
......@@ -13,12 +11,4 @@ class BaseProjectService < ::BaseContainerService
end
delegate :repository, to: :project
private
def project_group
strong_memoize(:project_group) do
project.group
end
end
end
......@@ -1267,9 +1267,6 @@ Input type: `CreateIssueInput`
| <a id="mutationcreateissueepicid"></a>`epicId` | [`EpicID`](#epicid) | ID of an epic to associate the issue with. |
| <a id="mutationcreateissuehealthstatus"></a>`healthStatus` | [`HealthStatus`](#healthstatus) | Desired health status. |
| <a id="mutationcreateissueiid"></a>`iid` | [`Int`](#int) | IID (internal ID) of a project issue. Only admins and project owners can modify. |
| <a id="mutationcreateissueiterationcadenceid"></a>`iterationCadenceId` | [`IterationsCadenceID`](#iterationscadenceid) | Global iteration cadence ID. Required when `iterationWildcardId` is provided. |
| <a id="mutationcreateissueiterationid"></a>`iterationId` | [`IterationID`](#iterationid) | Global iteration ID. Mutually exlusive argument with `iterationWildcardId`. |
| <a id="mutationcreateissueiterationwildcardid"></a>`iterationWildcardId` | [`IssueCreationIterationWildcardId`](#issuecreationiterationwildcardid) | Iteration wildcard ID. Supported values are: `CURRENT`. Mutually exclusive argument with `iterationId`. iterationCadenceId also required when this argument is provided. |
| <a id="mutationcreateissuelabelids"></a>`labelIds` | [`[LabelID!]`](#labelid) | IDs of labels to be added to the issue. |
| <a id="mutationcreateissuelabels"></a>`labels` | [`[String!]`](#string) | Labels of the issue. |
| <a id="mutationcreateissuelocked"></a>`locked` | [`Boolean`](#boolean) | Indicates discussion is locked on the issue. |
......@@ -15815,14 +15812,6 @@ State of a GitLab issue or merge request.
| <a id="issuablestatelocked"></a>`locked` | Discussion has been locked. |
| <a id="issuablestateopened"></a>`opened` | In open state. |
### `IssueCreationIterationWildcardId`
Iteration ID wildcard values for issue creation.
| Value | Description |
| ----- | ----------- |
| <a id="issuecreationiterationwildcardidcurrent"></a>`CURRENT` | Current iteration. |
### `IssueSort`
Values for sorting issues.
......
......@@ -116,7 +116,9 @@ module EE
{
parent: params.parent,
include_ancestors: true,
iteration_wildcard_id: ::Iteration::Predefined::Current.title
state: 'opened',
start_date: Date.today,
end_date: Date.today
}
end
end
......
......@@ -23,8 +23,6 @@ class IterationsFinder
def execute(skip_authorization: false)
@skip_authorization = skip_authorization
handle_wildcard_params
items = Iteration.all
items = by_id(items)
items = by_iid(items)
......@@ -42,14 +40,6 @@ class IterationsFinder
attr_reader :skip_authorization
# wildcard params do not override other explicitely given params
def handle_wildcard_params
if params[:iteration_wildcard_id] && params[:iteration_wildcard_id].casecmp?(::Iteration::Predefined::Current.title)
params[:start_date] ||= Date.today
params[:end_date] ||= Date.today
end
end
def by_groups(items)
return Iteration.none unless skip_authorization || Ability.allowed?(current_user, :read_iteration, params[:parent])
......
......@@ -13,17 +13,6 @@ module EE
argument :epic_id, ::Types::GlobalIDType[::Epic],
required: false,
description: 'ID of an epic to associate the issue with.'
argument :iteration_id, ::Types::GlobalIDType[::Iteration],
required: false,
description: 'Global iteration ID. Mutually exlusive argument with `iterationWildcardId`.'
argument :iteration_wildcard_id, ::Types::IssueCreationIterationWildcardIdEnum,
required: false,
description: 'Iteration wildcard ID. Supported values are: `CURRENT`.' \
' Mutually exclusive argument with `iterationId`.' \
' iterationCadenceId also required when this argument is provided.'
argument :iteration_cadence_id, ::Types::GlobalIDType[::Iterations::Cadence],
required: false,
description: 'Global iteration cadence ID. Required when `iterationWildcardId` is provided.'
end
override :resolve
......@@ -31,53 +20,18 @@ module EE
super
rescue ActiveRecord::RecordNotFound => e
{ errors: [e.message], issue: nil }
rescue ::Issues::BaseService::IterationAssignmentError => e
raise(
::Gitlab::Graphql::Errors::ArgumentError,
transform_field_names(e.message)
)
end
private
override :build_create_issue_params
def build_create_issue_params(params, project)
def build_create_issue_params(params)
# TODO: remove this line when the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
params[:epic_id] = ::Types::GlobalIDType[::Epic].coerce_isolated_input(params[:epic_id]) if params[:epic_id]
params[:epic_id] = params[:epic_id]&.model_id if params.key?(:epic_id)
handle_iteration_params(params, project)
super
end
def handle_iteration_params(params, project)
group = project.group
return unless group && group.licensed_feature_available?(:iterations)
# TODO: remove this line when the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
params[:iteration_id] = ::Types::GlobalIDType[::Iteration].coerce_isolated_input(params[:iteration_id]) if params[:iteration_id]
params[:iteration_id] = params[:iteration_id]&.model_id
# TODO: remove this line when the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
params[:iteration_cadence_id] = ::Types::GlobalIDType[::Iterations::Cadence].coerce_isolated_input(params[:iteration_cadence_id]) if params[:iteration_cadence_id]
params[:iteration_cadence_id] = params[:iteration_cadence_id]&.model_id
end
def name_mappings
{
'iteration_wildcard_id' => 'iterationWildcardId',
'iteration_cadence_id' => 'iterationCadenceId',
'iteration_id' => 'iterationId'
}
end
def transform_field_names(message)
name_mappings.reduce(message) do |transformed_message, (k, v)|
transformed_message.gsub(k, v)
end
super(params)
end
end
end
......
# frozen_string_literal: true
module Types
class IssueCreationIterationWildcardIdEnum < BaseEnum
graphql_name 'IssueCreationIterationWildcardId'
description 'Iteration ID wildcard values for issue creation'
value 'CURRENT', 'Current iteration.'
end
end
......@@ -21,10 +21,6 @@ module EE
params.delete(:health_status)
end
# Filter these iteration params unconditionally as they do not exist on the model.
# They must be used before reaching this filter if present.
[:iteration_wildcard_id, :iteration_cadence_id, :iteration_id].each { |iteration_param| params.delete(iteration_param) }
super
end
......
......@@ -5,8 +5,7 @@ module EE
module BaseService
extend ::Gitlab::Utils::Override
EpicAssignmentError = Class.new(::ArgumentError)
IterationAssignmentError = Class.new(StandardError)
class EpicAssignmentError < ::ArgumentError; end
def filter_epic(issue)
return unless epic_param_present?
......@@ -108,42 +107,6 @@ module EE
raise EpicAssignmentError, result[:message]
end
end
private
def validate_iteration_params!(iteration_params)
if iteration_params[:iteration_wildcard_id].present? && iteration_params[:iteration_cadence_id].blank?
raise IterationAssignmentError, 'iteration_cadence_id is required when iteration_wildcard_id is provided.'
end
if [iteration_params[:iteration_id], iteration_params[:iteration_wildcard_id]].all?(&:present?)
raise IterationAssignmentError, 'Incompatible arguments: iteration_id, iteration_wildcard_id.'
end
end
def find_iteration!(iteration_params, group)
validate_iteration_params!(iteration_params)
# converts params to keys the finder understands
finder_params = iteration_params.slice(:iteration_wildcard_id).merge(parent: group, include_ancestors: true)
finder_params[:id] = iteration_params[:iteration_id]
finder_params[:iteration_cadence_ids] = iteration_params[:iteration_cadence_id]
iteration = IterationsFinder.new(current_user, finder_params.compact).execute.first
return unless iteration && current_user.can?(:read_iteration, iteration)
iteration
end
def process_iteration_id
return unless project_group&.licensed_feature_available?(:iterations)
iteration_params = params.slice(:iteration_wildcard_id, :iteration_cadence_id, :iteration_id)
iteration = find_iteration!(iteration_params, project_group)
params[:iteration] = iteration if iteration
end
end
end
end
......@@ -5,13 +5,6 @@ module EE
module CreateService
extend ::Gitlab::Utils::Override
override :create
def create(issuable, skip_system_notes: false)
process_iteration_id
super
end
override :filter_params
def filter_params(issue)
filter_epic(issue)
......
......@@ -67,28 +67,6 @@ RSpec.describe IterationsFinder do
it 'returns iterations for groups' do
expect(subject).to contain_exactly(closed_iteration, started_group_iteration, upcoming_group_iteration)
end
context 'with filters' do
context 'by iteration_wildcard_id' do
let_it_be(:started_group_iteration2) { create(:current_iteration, :skip_future_date_validation, iterations_cadence: iteration_cadence1, group: iteration_cadence1.group, title: 'one test', start_date: 1.day.ago, due_date: Date.today) }
before do
params[:iteration_wildcard_id] = 'CURRENT'
end
it 'returns CURRENT iterations without ancestors' do
expect(subject).to contain_exactly(started_group_iteration, started_group_iteration2)
end
context 'when iteration_cadence_id is provided' do
it 'returns CURRENT iteration for the given cadence' do
params[:iteration_cadence_ids] = iteration_cadence1.id
expect(subject).to contain_exactly(started_group_iteration2)
end
end
end
end
end
context 'iterations for project with ancestors' do
......@@ -156,22 +134,6 @@ RSpec.describe IterationsFinder do
expect(subject).to contain_exactly(closed_iteration, started_group_iteration, upcoming_group_iteration)
end
context 'by iteration_wildcard_id' do
before do
params[:iteration_wildcard_id] = 'CURRENT'
end
it 'returns CURRENT iterations' do
expect(subject).to contain_exactly(root_group_iteration, started_group_iteration)
end
it 'returns CURRENT iteration for the specified cadence' do
params[:iteration_cadence_ids] = started_group_iteration.iterations_cadence.id
expect(subject).to contain_exactly(started_group_iteration)
end
end
context 'by timeframe' do
it 'returns iterations with start_date and due_date between timeframe' do
params.merge!(start_date: 1.day.ago, end_date: 3.days.from_now)
......
......@@ -7,8 +7,6 @@ RSpec.describe Mutations::Issues::Create do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:cadence1) { create(:iterations_cadence, group: group) }
let_it_be(:current_iteration) { create(:iteration, group: group, iterations_cadence: cadence1, start_date: 2.days.ago, due_date: 5.days.from_now) }
let_it_be(:user) { create(:user) }
let_it_be(:assignee1) { create(:user) }
let_it_be(:assignee2) { create(:user) }
......@@ -33,119 +31,29 @@ RSpec.describe Mutations::Issues::Create do
end
let(:mutation_params) do
inputs.merge(expected_attributes).merge(additional_attributes)
inputs.merge(expected_attributes)
end
let(:additional_attributes) { {} }
let(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
let(:mutated_issue) { resolved_mutation[:issue] }
before_all do
project.add_guest(assignee1)
project.add_guest(assignee2)
end
let(:mutated_issue) { subject[:issue] }
specify { expect(described_class).to require_graphql_authorizations(:create_issue) }
describe '#resolve' do
before do
project.add_guest(assignee1)
project.add_guest(assignee2)
stub_licensed_features(issuable_health_status: true)
stub_spam_services
end
subject(:resolved_mutation) { mutation.resolve(**mutation_params) }
subject { mutation.resolve(**mutation_params) }
context 'when user can create issues' do
before_all do
before do
group.add_developer(user)
end
context 'when iterations are available' do
let_it_be(:past_iteration) { create(:iteration, group: group, iterations_cadence: cadence1, start_date: 9.days.ago, due_date: 3.days.ago) }
let_it_be(:future_iteration) { create(:iteration, group: group, iterations_cadence: cadence1, start_date: 6.days.from_now, due_date: 9.days.from_now) }
before do
stub_licensed_features(iterations: true)
end
context 'when iteration_id is provided' do
let(:additional_attributes) { { iteration_id: past_iteration.to_global_id } }
it 'is successful, and assigns the current iteration to the issue' do
expect(resolved_mutation[:errors]).to be_empty
expect(mutated_issue).to have_attributes(iteration: past_iteration)
end
context 'when iteration_wildcard_id is provided' do
let(:additional_attributes) { { iteration_id: past_iteration.to_global_id, iteration_wildcard_id: 'CURRENT', iteration_cadence_id: cadence1.to_global_id } }
it 'raises a mutually exclusive argument error' do
expect { resolved_mutation }.to raise_error(
::Gitlab::Graphql::Errors::ArgumentError,
'Incompatible arguments: iterationId, iterationWildcardId.'
)
end
end
context 'when iteration cadences feature flag is disabled' do
before do
stub_feature_flags(iteration_cadences: false)
end
it 'is successful, and assigns the current iteration to the issue' do
expect(resolved_mutation[:errors]).to be_empty
expect(mutated_issue).to have_attributes(iteration: past_iteration)
end
end
end
context 'when iteration_wildcard_id is CURRENT' do
let(:additional_attributes) { { iteration_wildcard_id: 'CURRENT' } }
context 'when iteration_cadence_id is provided' do
let(:additional_attributes) { { iteration_wildcard_id: 'CURRENT', iteration_cadence_id: cadence1.to_global_id } }
it 'is successful, and assigns the current iteration to the issue' do
expect(resolved_mutation[:errors]).to be_empty
expect(mutated_issue).to have_attributes(iteration: current_iteration)
end
end
context 'when iteration_cadence_id is not provided' do
it 'always requires iteration cadence id when wildcard is provided' do
expect { resolved_mutation }.to raise_error(
::Gitlab::Graphql::Errors::ArgumentError,
'iterationCadenceId is required when iterationWildcardId is provided.'
)
end
end
end
end
context 'when iterations are not available' do
before do
stub_licensed_features(iterations: false)
end
context 'when iteration_wildcard_id is provided' do
let(:additional_attributes) { { iteration_wildcard_id: 'CURRENT' } }
it 'is successful, but it does not add the iteration' do
expect(resolved_mutation[:errors]).to be_empty
expect(mutated_issue).to have_attributes(iteration: nil)
end
end
context 'when iteration_id is provided' do
let(:additional_attributes) { { iteration_id: current_iteration.to_global_id } }
it 'is successful, but it does not add the iteration' do
expect(resolved_mutation[:errors]).to be_empty
expect(mutated_issue).to have_attributes(iteration: nil)
end
end
end
it 'creates issue with correct EE values' do
expect(mutated_issue).to have_attributes(expected_attributes)
expect(mutated_issue.assignees.pluck(:id)).to eq([assignee1.id, assignee2.id])
......@@ -165,7 +73,7 @@ RSpec.describe Mutations::Issues::Create do
end
it 'is successful, and assigns the issue to the epic' do
expect(resolved_mutation[:errors]).to be_empty
expect(subject[:errors]).to be_empty
expect(mutated_issue).to have_attributes(epic: epic)
end
......@@ -175,7 +83,7 @@ RSpec.describe Mutations::Issues::Create do
it 'is successful, but it does not add the epic' do
project.add_developer(user)
expect(resolved_mutation[:errors]).to be_empty
expect(subject[:errors]).to be_empty
expect(mutated_issue).not_to have_attributes(epic: epic)
end
end
......@@ -183,7 +91,7 @@ RSpec.describe Mutations::Issues::Create do
context 'epics are unavailable' do
it 'is unsuccessful' do
expect(resolved_mutation[:errors]).to contain_exactly("Couldn't find Epic")
expect(subject[:errors]).to contain_exactly("Couldn't find Epic")
end
it 'does not create an issue' do
......
......@@ -6,17 +6,13 @@ RSpec.describe 'Create an issue' do
include GraphqlHelpers
let_it_be(:current_user) { create(:user) }
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, namespace: group) }
let_it_be(:current_iteration) { create(:iteration, group: group, start_date: 2.days.ago, due_date: 10.days.from_now) }
let_it_be(:project) { create(:project) }
let(:input) do
{
'title' => 'new title',
'weight' => 2,
'healthStatus' => 'atRisk',
'iterationWildcardId' => 'CURRENT',
'iterationCadenceId' => current_iteration.iterations_cadence.to_global_id.to_s
'healthStatus' => 'atRisk'
}
end
......@@ -25,53 +21,14 @@ RSpec.describe 'Create an issue' do
let(:mutation_response) { graphql_mutation_response(:create_issue) }
before do
stub_licensed_features(issuable_health_status: true, iterations: true)
group.add_developer(current_user)
stub_licensed_features(issuable_health_status: true)
project.add_developer(current_user)
end
it 'creates the issue' do
post_graphql_mutation(mutation, current_user: current_user)
expect(response).to have_gitlab_http_status(:success)
expect(mutation_response['issue']).to include(input.except('iterationWildcardId', 'iterationCadenceId'))
expect(mutation_response['issue']).to include('iteration' => hash_including('id' => current_iteration.to_global_id.to_s))
end
context 'when iterationId is provided' do
let(:input) do
{
'title' => 'new title',
'weight' => 2,
'healthStatus' => 'atRisk',
'iterationId' => current_iteration.to_global_id.to_s
}
end
it 'creates the issue' do
post_graphql_mutation(mutation, current_user: current_user)
expect(response).to have_gitlab_http_status(:success)
expect(mutation_response['issue']).to include(input.except('iterationId'))
expect(mutation_response['issue']).to include('iteration' => hash_including('id' => current_iteration.to_global_id.to_s))
end
context 'when iterationId and iterationWildcardId are provided' do
let(:input) do
{
'title' => 'new title',
'weight' => 2,
'healthStatus' => 'atRisk',
'iterationId' => current_iteration.to_global_id.to_s,
'iterationWildcardId' => 'CURRENT',
'iterationCadenceId' => current_iteration.iterations_cadence.to_global_id.to_s
}
end
it 'returns a mutually exclusive argument error' do
post_graphql_mutation(mutation, current_user: current_user)
expect(graphql_errors).to contain_exactly(hash_including('message' => 'Incompatible arguments: iterationId, iterationWildcardId.'))
end
end
expect(mutation_response['issue']).to include(input)
end
end
......@@ -7,11 +7,8 @@ RSpec.describe Issues::CreateService do
let_it_be(:user) { create(:user) }
let_it_be_with_reload(:project) { create(:project, group: group) }
let(:base_params) { { title: 'Awesome issue', description: 'please fix', weight: 9 } }
let(:additional_params) { {} }
let(:params) { base_params.merge(additional_params) }
let(:params) { { title: 'Awesome issue', description: 'please fix', weight: 9 } }
let(:service) { described_class.new(project: project, current_user: user, params: params, spam_params: nil) }
let(:created_issue) { service.execute }
describe '#execute' do
context 'when current user cannot admin issues in the project' do
......@@ -20,8 +17,10 @@ RSpec.describe Issues::CreateService do
end
it 'filters out params that cannot be set without the :admin_issue permission' do
expect(created_issue).to be_persisted
expect(created_issue.weight).to be_nil
issue = service.execute
expect(issue).to be_persisted
expect(issue.weight).to be_nil
end
end
......@@ -32,8 +31,10 @@ RSpec.describe Issues::CreateService do
end
it 'sets permitted params correctly' do
expect(created_issue).to be_persisted
expect(created_issue.weight).to eq(9)
issue = service.execute
expect(issue).to be_persisted
expect(issue.weight).to eq(9)
end
context 'when epics are enabled' do
......@@ -57,9 +58,11 @@ RSpec.describe Issues::CreateService do
let(:params) { { title: 'New issue', description: "/epic #{epic.to_reference(project)}" } }
it 'adds an issue to the passed epic' do
expect(created_issue).to be_persisted
expect(created_issue.reload.epic).to eq(epic)
expect(created_issue.confidential).to eq(false)
issue = service.execute
expect(issue).to be_persisted
expect(issue.reload.epic).to eq(epic)
expect(issue.confidential).to eq(false)
end
end
......@@ -79,8 +82,10 @@ RSpec.describe Issues::CreateService do
end
it 'sets epic and milestone to issuable and update epic start and due date' do
expect(created_issue.milestone).to eq(milestone)
expect(created_issue.reload.epic).to eq(epic)
issue = service.execute
expect(issue.milestone).to eq(milestone)
expect(issue.reload.epic).to eq(epic)
expect(epic.reload.start_date).to eq(milestone.start_date)
expect(epic.due_date).to eq(milestone.due_date)
end
......@@ -101,82 +106,23 @@ RSpec.describe Issues::CreateService do
end
context 'when adding a public issue to confidential epic' do
let(:confidential_epic) { create(:epic, group: group, confidential: true) }
let(:params) { { title: 'confidential issue', epic_id: confidential_epic.id } }
it 'creates confidential child issue' do
expect(created_issue).to be_confidential
end
end
context 'when adding a confidential issue to public epic' do
let(:params) { { title: 'confidential issue', epic_id: epic.id, confidential: true } }
it 'creates a confidential child issue' do
expect(created_issue).to be_confidential
end
end
end
end
context 'when iterations are available' do
let_it_be(:iteration_cadence1) { create(:iterations_cadence, group: group) }
let_it_be(:iteration_cadence2) { create(:iterations_cadence, group: group) }
let_it_be(:current_iteration1) { create(:iteration, group: group, iterations_cadence: iteration_cadence1, start_date: 4.days.ago, due_date: 3.days.from_now) }
let_it_be(:current_iteration2) { create(:iteration, group: group, iterations_cadence: iteration_cadence2, start_date: 4.days.ago, due_date: 3.days.from_now) }
let_it_be(:future_iteration) { create(:iteration, group: group, iterations_cadence: iteration_cadence1, start_date: 6.days.from_now, due_date: 13.days.from_now) }
confidential_epic = create(:epic, group: group, confidential: true)
params = { title: 'confidential issue', epic_id: confidential_epic.id }
before do
stub_licensed_features(iterations: true)
end
context 'when iteration_id is provided' do
let(:additional_params) { { iteration_id: future_iteration.id } }
it 'is successful, and assigns the current iteration to the issue' do
expect(created_issue).to be_persisted
expect(created_issue).to have_attributes(iteration: future_iteration)
end
context 'when iteration_wildcard_id is provided' do
let(:additional_params) { { iteration_id: future_iteration.id, iteration_wildcard_id: 'CURRENT', iteration_cadence_id: iteration_cadence2.id } }
it 'raises a mutually exclusive argument error' do
expect { service.execute }.to raise_error(
::Issues::BaseService::IterationAssignmentError,
'Incompatible arguments: iteration_id, iteration_wildcard_id.'
)
end
end
context "when user can't read the given iteration" do
let(:additional_params) { { iteration_id: create(:iteration, group: create(:group, :private)).id } }
issue = described_class.new(project: project, current_user: user, params: params, spam_params: nil).execute
it 'is successful but does not assign the iteration' do
expect(created_issue).to be_persisted
expect(created_issue).to have_attributes(iteration: nil)
expect(issue.confidential).to eq(true)
end
end
end
context 'when iteration_wildcard_id is CURRENT' do
let(:additional_params) { { iteration_wildcard_id: 'CURRENT' } }
context 'when iteration_cadence_id is provided' do
let(:additional_params) { { iteration_wildcard_id: 'CURRENT', iteration_cadence_id: iteration_cadence2.id } }
context 'when adding a confidential issue to public epic' do
it 'creates a confidential child issue' do
params = { title: 'confidential issue', epic_id: epic.id, confidential: true }
it 'is successful, and assigns the current iteration to the issue' do
expect(created_issue).to be_persisted
expect(created_issue).to have_attributes(iteration: current_iteration2)
end
end
issue = described_class.new(project: project, current_user: user, params: params, spam_params: nil).execute
context 'when iteration_cadence_id is not provided' do
it 'always requires iteration cadence id when wildcard is provided' do
expect { service.execute }.to raise_error(
::Issues::BaseService::IterationAssignmentError,
'iteration_cadence_id is required when iteration_wildcard_id is provided.'
)
expect(issue.confidential).to eq(true)
end
end
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment