202 lines
6.7 KiB
Ruby
202 lines
6.7 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'spec_helper'
|
|
|
|
RSpec.describe Mutations::Issues::Update do
|
|
let_it_be(:project) { create(:project) }
|
|
let_it_be(:user) { create(:user) }
|
|
let_it_be(:project_label) { create(:label, project: project) }
|
|
let_it_be(:issue) { create(:issue, project: project, labels: [project_label]) }
|
|
let_it_be(:milestone) { create(:milestone, project: project) }
|
|
|
|
let(:expected_attributes) do
|
|
{
|
|
title: 'new title',
|
|
description: 'new description',
|
|
confidential: true,
|
|
due_date: Date.tomorrow,
|
|
discussion_locked: true,
|
|
milestone_id: milestone.id
|
|
}
|
|
end
|
|
|
|
let(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
|
|
let(:mutated_issue) { subject[:issue] }
|
|
|
|
specify { expect(described_class).to require_graphql_authorizations(:update_issue) }
|
|
|
|
describe '#resolve' do
|
|
let(:mutation_params) do
|
|
{
|
|
project_path: project.full_path,
|
|
iid: issue.iid
|
|
}.merge(expected_attributes)
|
|
end
|
|
|
|
subject { mutation.resolve(**mutation_params) }
|
|
|
|
before do
|
|
stub_spam_services
|
|
end
|
|
|
|
it_behaves_like 'permission level for issue mutation is correctly verified'
|
|
|
|
context 'when the user can update the issue' do
|
|
before do
|
|
project.add_developer(user)
|
|
end
|
|
|
|
context 'when all attributes except timeEstimate are provided' do
|
|
it 'updates issue with correct values' do
|
|
subject
|
|
|
|
expect(issue.reload).to have_attributes(expected_attributes)
|
|
end
|
|
end
|
|
|
|
context 'when iid does not exist' do
|
|
it 'raises resource not available error' do
|
|
mutation_params[:iid] = non_existing_record_iid
|
|
|
|
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
|
|
end
|
|
end
|
|
|
|
context 'when setting milestone to nil' do
|
|
let(:expected_attributes) { { milestone_id: nil } }
|
|
|
|
it 'changes the milestone corrrectly' do
|
|
issue.update_column(:milestone_id, milestone.id)
|
|
|
|
expect { subject }.to change { issue.reload.milestone }.from(milestone).to(nil)
|
|
end
|
|
end
|
|
|
|
context 'when changing state' do
|
|
let_it_be_with_refind(:issue) { create(:issue, project: project, state: :opened) }
|
|
|
|
it 'closes issue' do
|
|
mutation_params[:state_event] = 'close'
|
|
|
|
expect { subject }.to change { issue.reload.state }.from('opened').to('closed')
|
|
end
|
|
|
|
it 'reopens issue' do
|
|
issue.close
|
|
mutation_params[:state_event] = 'reopen'
|
|
|
|
expect { subject }.to change { issue.reload.state }.from('closed').to('opened')
|
|
end
|
|
end
|
|
|
|
context 'when changing labels' do
|
|
let_it_be(:label_1) { create(:label, project: project) }
|
|
let_it_be(:label_2) { create(:label, project: project) }
|
|
let_it_be(:external_label) { create(:label, project: create(:project)) }
|
|
|
|
it 'adds and removes labels correctly' do
|
|
mutation_params[:add_label_ids] = [label_1.id, label_2.id]
|
|
mutation_params[:remove_label_ids] = [project_label.id]
|
|
|
|
subject
|
|
|
|
expect(issue.reload.labels).to match_array([label_1, label_2])
|
|
end
|
|
|
|
it 'does not add label if label id is nil' do
|
|
mutation_params[:add_label_ids] = [nil, label_2.id]
|
|
|
|
subject
|
|
|
|
expect(issue.reload.labels).to match_array([project_label, label_2])
|
|
end
|
|
|
|
it 'does not add label if label is not found' do
|
|
mutation_params[:add_label_ids] = [external_label.id, label_2.id]
|
|
|
|
subject
|
|
|
|
expect(issue.reload.labels).to match_array([project_label, label_2])
|
|
end
|
|
|
|
it 'does not modify labels if label is already present' do
|
|
mutation_params[:add_label_ids] = [project_label.id]
|
|
|
|
expect(issue.reload.labels).to match_array([project_label])
|
|
end
|
|
|
|
it 'does not modify labels if label is addded and removed in the same request' do
|
|
mutation_params[:add_label_ids] = [label_1.id, label_2.id]
|
|
mutation_params[:remove_label_ids] = [label_1.id]
|
|
|
|
subject
|
|
|
|
expect(issue.reload.labels).to match_array([project_label, label_2])
|
|
end
|
|
|
|
context 'when setting labels with label_ids' do
|
|
it 'replaces existing labels with provided ones' do
|
|
expect(issue.reload.labels).to match_array([project_label])
|
|
|
|
mutation_params[:label_ids] = [label_1.id, label_2.id]
|
|
|
|
subject
|
|
|
|
expect(issue.reload.labels).to match_array([label_1, label_2])
|
|
end
|
|
|
|
it 'raises error when label_ids is combined with remove_label_ids' do
|
|
expect { mutation.ready?(label_ids: [label_1.id, label_2.id], remove_label_ids: [label_1.id]) }
|
|
.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'labelIds is mutually exclusive with any of addLabelIds or removeLabelIds')
|
|
end
|
|
|
|
it 'raises error when label_ids is combined with add_label_ids' do
|
|
expect { mutation.ready?(label_ids: [label_1.id, label_2.id], add_label_ids: [label_2.id]) }
|
|
.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'labelIds is mutually exclusive with any of addLabelIds or removeLabelIds')
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'when changing type' do
|
|
it 'changes the type of the issue' do
|
|
mutation_params[:issue_type] = 'incident'
|
|
|
|
expect { subject }.to change { issue.reload.issue_type }.from('issue').to('incident')
|
|
end
|
|
end
|
|
|
|
context 'when timeEstimate attribute is provided' do
|
|
let_it_be_with_refind(:issue) { create(:issue, project: project, time_estimate: 3600) }
|
|
|
|
let(:time_estimate) { '0' }
|
|
let(:expected_attributes) { { time_estimate: time_estimate } }
|
|
|
|
context 'when timeEstimate is invalid' do
|
|
let(:time_estimate) { '1e' }
|
|
|
|
it 'raises an argument error and changes are not applied' do
|
|
expect { mutation.ready?(time_estimate: time_estimate) }
|
|
.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'timeEstimate must be formatted correctly, for example `1h 30m`')
|
|
expect { subject }.not_to change { issue.reload.time_estimate }
|
|
end
|
|
end
|
|
|
|
context 'when timeEstimate is 0' do
|
|
let(:time_estimate) { '0' }
|
|
|
|
it 'resets the time estimate' do
|
|
expect { subject }.to change { issue.reload.time_estimate }.from(3600).to(0)
|
|
end
|
|
end
|
|
|
|
context 'when timeEstimate is a valid human readable time' do
|
|
let(:time_estimate) { '1h 30m' }
|
|
|
|
it 'updates the time estimate' do
|
|
expect { subject }.to change { issue.reload.time_estimate }.from(3600).to(5400)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|