Commit c5b72a34 authored by Sean McGivern's avatar Sean McGivern

Merge branch '213334-add-resource-state-events-pd' into 'master'

Track resource state events

See merge request gitlab-org/gitlab!29015
parents 5ea1d403 d2cc807b
......@@ -11,30 +11,44 @@ class EventCreateService
IllegalActionError = Class.new(StandardError)
def open_issue(issue, current_user)
create_resource_event(issue, current_user, :opened)
create_record_event(issue, current_user, Event::CREATED)
end
def close_issue(issue, current_user)
create_resource_event(issue, current_user, :closed)
create_record_event(issue, current_user, Event::CLOSED)
end
def reopen_issue(issue, current_user)
create_resource_event(issue, current_user, :reopened)
create_record_event(issue, current_user, Event::REOPENED)
end
def open_mr(merge_request, current_user)
create_resource_event(merge_request, current_user, :opened)
create_record_event(merge_request, current_user, Event::CREATED)
end
def close_mr(merge_request, current_user)
create_resource_event(merge_request, current_user, :closed)
create_record_event(merge_request, current_user, Event::CLOSED)
end
def reopen_mr(merge_request, current_user)
create_resource_event(merge_request, current_user, :reopened)
create_record_event(merge_request, current_user, Event::REOPENED)
end
def merge_mr(merge_request, current_user)
create_resource_event(merge_request, current_user, :merged)
create_record_event(merge_request, current_user, Event::MERGED)
end
......@@ -157,6 +171,18 @@ class EventCreateService
Event.create!(attributes)
end
def create_resource_event(issuable, current_user, status)
return unless state_change_tracking_enabled?(issuable)
ResourceEvents::ChangeStateService.new(resource: issuable, user: current_user)
.execute(status)
end
def state_change_tracking_enabled?(issuable)
issuable&.respond_to?(:resource_state_events) &&
::Feature.enabled?(:track_resource_state_change_events, issuable&.project)
end
end
EventCreateService.prepend_if_ee('EE::EventCreateService')
# frozen_string_literal: true
module ResourceEvents
class ChangeStateService
attr_reader :resource, :user
def initialize(user:, resource:)
@user, @resource = user, resource
end
def execute(state)
ResourceStateEvent.create(
user: user,
issue: issue,
merge_request: merge_request,
state: ResourceStateEvent.states[state],
created_at: Time.zone.now)
resource.expire_note_etag_cache
end
private
def issue
return unless resource.is_a?(Issue)
resource
end
def merge_request
return unless resource.is_a?(MergeRequest)
resource
end
end
end
......@@ -11,7 +11,8 @@ module ResourceEvents
SYNTHETIC_NOTE_BUILDER_SERVICES = [
SyntheticLabelNotesBuilderService,
SyntheticMilestoneNotesBuilderService
SyntheticMilestoneNotesBuilderService,
SyntheticStateNotesBuilderService
].freeze
attr_reader :resource, :current_user, :params
......@@ -23,7 +24,7 @@ module ResourceEvents
end
def execute(notes = [])
(notes + synthetic_notes).sort_by { |n| n.created_at }
(notes + synthetic_notes).sort_by(&:created_at)
end
private
......
# frozen_string_literal: true
module ResourceEvents
class SyntheticStateNotesBuilderService < BaseSyntheticNotesBuilderService
private
def synthetic_notes
state_change_events.map do |event|
StateNote.from_event(event, resource: resource, resource_parent: resource_parent)
end
end
def state_change_events
return [] unless resource.respond_to?(:resource_state_events)
events = resource.resource_state_events.includes(user: :status) # rubocop: disable CodeReuse/ActiveRecord
since_fetch_at(events)
end
end
end
......@@ -225,7 +225,12 @@ module SystemNotes
action = status == 'reopened' ? 'opened' : status
create_note(NoteSummary.new(noteable, project, author, body, action: action))
# A state event which results in a synthetic note will be
# created by EventCreateService if change event tracking
# is enabled.
unless state_change_tracking_enabled?
create_note(NoteSummary.new(noteable, project, author, body, action: action))
end
end
# Check if a cross reference to a noteable from a mentioner already exists
......@@ -318,6 +323,11 @@ module SystemNotes
def self.cross_reference?(note_text)
note_text =~ /\A#{cross_reference_note_prefix}/i
end
def state_change_tracking_enabled?
noteable.respond_to?(:resource_state_events) &&
::Feature.enabled?(:track_resource_state_change_events, noteable.project)
end
end
end
......
......@@ -65,16 +65,24 @@ describe Gitlab::Email::Handler::CreateNoteHandler do
end
end
context 'and current user can update noteable' do
before do
project.add_developer(user)
end
it 'does not raise an error' do
# One system note is created for the 'close' event
expect { receiver.execute }.to change { noteable.notes.count }.by(1)
expect(noteable.reload).to be_closed
[true, false].each do |state_tracking_enabled|
context "and current user can update noteable #{state_tracking_enabled ? 'enabled' : 'disabled'}" do
before do
stub_feature_flags(track_resource_state_change_events: state_tracking_enabled)
project.add_developer(user)
end
it 'does not raise an error' do
if state_tracking_enabled
expect { receiver.execute }.to change { noteable.resource_state_events.count }.by(1)
else
# One system note is created for the 'close' event
expect { receiver.execute }.to change { noteable.notes.count }.by(1)
end
expect(noteable.reload).to be_closed
end
end
end
end
......
......@@ -2157,7 +2157,34 @@ describe MergeRequest do
end
end
context 'when merging note is persisted, but no metrics or merge event exists' do
context 'when state event tracking is disabled' do
before do
stub_feature_flags(track_resource_state_change_events: false)
end
context 'when merging note is persisted, but no metrics or merge event exists' do
let(:user) { create(:user) }
let(:merge_request) { create(:merge_request, :merged) }
before do
merge_request.metrics.destroy!
SystemNoteService.change_status(merge_request,
merge_request.target_project,
user,
merge_request.state, nil)
end
it 'returns merging note creation date' do
expect(merge_request.reload.metrics).to be_nil
expect(merge_request.merge_event).to be_nil
expect(merge_request.notes.count).to eq(1)
expect(merge_request.merged_at).to eq(merge_request.notes.first.created_at)
end
end
end
context 'when state event tracking is enabled' do
let(:user) { create(:user) }
let(:merge_request) { create(:merge_request, :merged) }
......@@ -2170,11 +2197,8 @@ describe MergeRequest do
merge_request.state, nil)
end
it 'returns merging note creation date' do
expect(merge_request.reload.metrics).to be_nil
expect(merge_request.merge_event).to be_nil
expect(merge_request.notes.count).to eq(1)
expect(merge_request.merged_at).to eq(merge_request.notes.first.created_at)
it 'does not create a system note' do
expect(merge_request.notes).to be_empty
end
end
end
......
......@@ -13,6 +13,7 @@ describe EventCreateService do
it "creates new event" do
expect { service.open_issue(issue, issue.author) }.to change { Event.count }
expect { service.open_issue(issue, issue.author) }.to change { ResourceStateEvent.count }
end
end
......@@ -23,6 +24,7 @@ describe EventCreateService do
it "creates new event" do
expect { service.close_issue(issue, issue.author) }.to change { Event.count }
expect { service.close_issue(issue, issue.author) }.to change { ResourceStateEvent.count }
end
end
......@@ -33,6 +35,7 @@ describe EventCreateService do
it "creates new event" do
expect { service.reopen_issue(issue, issue.author) }.to change { Event.count }
expect { service.reopen_issue(issue, issue.author) }.to change { ResourceStateEvent.count }
end
end
end
......@@ -45,6 +48,7 @@ describe EventCreateService do
it "creates new event" do
expect { service.open_mr(merge_request, merge_request.author) }.to change { Event.count }
expect { service.open_mr(merge_request, merge_request.author) }.to change { ResourceStateEvent.count }
end
end
......@@ -55,6 +59,7 @@ describe EventCreateService do
it "creates new event" do
expect { service.close_mr(merge_request, merge_request.author) }.to change { Event.count }
expect { service.close_mr(merge_request, merge_request.author) }.to change { ResourceStateEvent.count }
end
end
......@@ -65,6 +70,7 @@ describe EventCreateService do
it "creates new event" do
expect { service.merge_mr(merge_request, merge_request.author) }.to change { Event.count }
expect { service.merge_mr(merge_request, merge_request.author) }.to change { ResourceStateEvent.count }
end
end
......@@ -75,6 +81,7 @@ describe EventCreateService do
it "creates new event" do
expect { service.reopen_mr(merge_request, merge_request.author) }.to change { Event.count }
expect { service.reopen_mr(merge_request, merge_request.author) }.to change { ResourceStateEvent.count }
end
end
end
......
......@@ -224,11 +224,26 @@ describe Issues::CloseService do
expect(email.subject).to include(issue.title)
end
it 'creates system note about issue reassign' do
close_issue
context 'when resource state events are disabled' do
before do
stub_feature_flags(track_resource_state_change_events: false)
end
it 'creates system note about the issue being closed' do
close_issue
note = issue.notes.last
expect(note.note).to include "closed"
end
end
note = issue.notes.last
expect(note.note).to include "closed"
context 'when resource state events are enabled' do
it 'creates resource state event about the issue being closed' do
close_issue
event = issue.resource_state_events.last
expect(event.state).to eq('closed')
end
end
it 'marks todos as done' do
......
......@@ -19,45 +19,54 @@ describe MergeRequests::CloseService do
describe '#execute' do
it_behaves_like 'cache counters invalidator'
context 'valid params' do
let(:service) { described_class.new(project, user, {}) }
[true, false].each do |state_tracking_enabled|
context "valid params with state_tracking #{state_tracking_enabled ? 'enabled' : 'disabled'}" do
let(:service) { described_class.new(project, user, {}) }
before do
allow(service).to receive(:execute_hooks)
before do
stub_feature_flags(track_resource_state_change_events: state_tracking_enabled)
perform_enqueued_jobs do
@merge_request = service.execute(merge_request)
allow(service).to receive(:execute_hooks)
perform_enqueued_jobs do
@merge_request = service.execute(merge_request)
end
end
end
it { expect(@merge_request).to be_valid }
it { expect(@merge_request).to be_closed }
it { expect(@merge_request).to be_valid }
it { expect(@merge_request).to be_closed }
it 'executes hooks with close action' do
expect(service).to have_received(:execute_hooks)
it 'executes hooks with close action' do
expect(service).to have_received(:execute_hooks)
.with(@merge_request, 'close')
end
end
it 'sends email to user2 about assign of new merge_request', :sidekiq_might_not_need_inline do
email = ActionMailer::Base.deliveries.last
expect(email.to.first).to eq(user2.email)
expect(email.subject).to include(merge_request.title)
end
it 'sends email to user2 about assign of new merge_request', :sidekiq_might_not_need_inline do
email = ActionMailer::Base.deliveries.last
expect(email.to.first).to eq(user2.email)
expect(email.subject).to include(merge_request.title)
end
it 'creates system note about merge_request reassign' do
note = @merge_request.notes.last
expect(note.note).to include 'closed'
end
it 'creates system note about merge_request reassign' do
if state_tracking_enabled
event = @merge_request.resource_state_events.last
expect(event.state).to eq('closed')
else
note = @merge_request.notes.last
expect(note.note).to include 'closed'
end
end
it 'marks todos as done' do
expect(todo.reload).to be_done
end
it 'marks todos as done' do
expect(todo.reload).to be_done
end
context 'when auto merge is enabled' do
let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
context 'when auto merge is enabled' do
let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
it 'cancels the auto merge' do
expect(@merge_request).not_to be_auto_merge_enabled
it 'cancels the auto merge' do
expect(@merge_request).not_to be_auto_merge_enabled
end
end
end
end
......
......@@ -21,65 +21,74 @@ describe MergeRequests::FfMergeService do
end
describe '#execute' do
context 'valid params' do
let(:service) { described_class.new(project, user, valid_merge_params) }
def execute_ff_merge
perform_enqueued_jobs do
service.execute(merge_request)
[true, false].each do |state_tracking_enabled|
context "valid params with state_tracking #{state_tracking_enabled ? 'enabled' : 'disabled'}" do
let(:service) { described_class.new(project, user, valid_merge_params) }
def execute_ff_merge
perform_enqueued_jobs do
service.execute(merge_request)
end
end
end
before do
allow(service).to receive(:execute_hooks)
end
before do
stub_feature_flags(track_resource_state_change_events: state_tracking_enabled)
it "does not create merge commit" do
execute_ff_merge
allow(service).to receive(:execute_hooks)
end
source_branch_sha = merge_request.source_project.repository.commit(merge_request.source_branch).sha
target_branch_sha = merge_request.target_project.repository.commit(merge_request.target_branch).sha
it "does not create merge commit" do
execute_ff_merge
expect(source_branch_sha).to eq(target_branch_sha)
end
source_branch_sha = merge_request.source_project.repository.commit(merge_request.source_branch).sha
target_branch_sha = merge_request.target_project.repository.commit(merge_request.target_branch).sha
it 'keeps the merge request valid' do
expect { execute_ff_merge }
.not_to change { merge_request.valid? }
end
expect(source_branch_sha).to eq(target_branch_sha)
end
it 'updates the merge request to merged' do
expect { execute_ff_merge }
.to change { merge_request.merged? }
.from(false)
.to(true)
end
it 'keeps the merge request valid' do
expect { execute_ff_merge }
.not_to change { merge_request.valid? }
end
it 'sends email to user2 about merge of new merge_request' do
execute_ff_merge
it 'updates the merge request to merged' do
expect { execute_ff_merge }
.to change { merge_request.merged? }
.from(false)
.to(true)
end
email = ActionMailer::Base.deliveries.last
expect(email.to.first).to eq(user2.email)
expect(email.subject).to include(merge_request.title)
end
it 'sends email to user2 about merge of new merge_request' do
execute_ff_merge
it 'creates system note about merge_request merge' do
execute_ff_merge
email = ActionMailer::Base.deliveries.last
expect(email.to.first).to eq(user2.email)
expect(email.subject).to include(merge_request.title)
end
note = merge_request.notes.last
expect(note.note).to include 'merged'
end
it 'creates system note about merge_request merge' do
execute_ff_merge
it 'does not update squash_commit_sha if it is not a squash' do
expect { execute_ff_merge }.not_to change { merge_request.squash_commit_sha }
end
if state_tracking_enabled
event = merge_request.resource_state_events.last
expect(event.state).to eq('merged')
else
note = merge_request.notes.last
expect(note.note).to include 'merged'
end
end
it 'updates squash_commit_sha if it is a squash' do
merge_request.update!(squash: true)
it 'does not update squash_commit_sha if it is not a squash' do
expect { execute_ff_merge }.not_to change { merge_request.squash_commit_sha }
end
expect { execute_ff_merge }
.to change { merge_request.squash_commit_sha }
.from(nil)
it 'updates squash_commit_sha if it is a squash' do
merge_request.update!(squash: true)
expect { execute_ff_merge }
.to change { merge_request.squash_commit_sha }
.from(nil)
end
end
end
......
......@@ -20,7 +20,11 @@ describe MergeRequests::MergeService do
end
context 'valid params' do
let(:state_tracking) { true }
before do
stub_feature_flags(track_resource_state_change_events: state_tracking)
allow(service).to receive(:execute_hooks)
perform_enqueued_jobs do
......@@ -42,9 +46,22 @@ describe MergeRequests::MergeService do
expect(email.subject).to include(merge_request.title)
end
it 'creates system note about merge_request merge' do
note = merge_request.notes.last
expect(note.note).to include 'merged'
context 'note creation' do
context 'when resource state event tracking is disabled' do
let(:state_tracking) { false }
it 'creates system note about merge_request merge' do
note = merge_request.notes.last
expect(note.note).to include 'merged'
end
end
context 'when resource state event tracking is enabled' do
it 'creates resource state event about merge_request merge' do
event = merge_request.resource_state_events.last
expect(event.state).to eq('merged')
end
end
end
context 'when squashing' do
......@@ -55,7 +72,7 @@ describe MergeRequests::MergeService do
end
let(:merge_request) do
# A merge reqeust with 5 commits
# A merge request with 5 commits
create(:merge_request, :simple,
author: user2,
assignees: [user2],
......
......@@ -362,76 +362,101 @@ describe MergeRequests::RefreshService do
end
end
context 'push to origin repo target branch', :sidekiq_might_not_need_inline do
context 'when all MRs to the target branch had diffs' do
[true, false].each do |state_tracking_enabled|
context "push to origin repo target branch with state tracking #{state_tracking_enabled ? 'enabled' : 'disabled'}", :sidekiq_might_not_need_inline do
before do
service.new(@project, @user).execute(@oldrev, @newrev, 'refs/heads/feature')
reload_mrs
stub_feature_flags(track_resource_state_change_events: state_tracking_enabled)
end
it 'updates the merge state' do
expect(@merge_request.notes.last.note).to include('merged')
expect(@merge_request).to be_merged
expect(@fork_merge_request).to be_merged
expect(@fork_merge_request.notes.last.note).to include('merged')
expect(@build_failed_todo).to be_done
expect(@fork_build_failed_todo).to be_done
context 'when all MRs to the target branch had diffs' do
before do
service.new(@project, @user).execute(@oldrev, @newrev, 'refs/heads/feature')
reload_mrs
end
it 'updates the merge state' do
expect(@merge_request).to be_merged
expect(@fork_merge_request).to be_merged
expect(@build_failed_todo).to be_done
expect(@fork_build_failed_todo).to be_done
if state_tracking_enabled
expect(@merge_request.resource_state_events.last.state).to eq('merged')
expect(@fork_merge_request.resource_state_events.last.state).to eq('merged')
else
expect(@merge_request.notes.last.note).to include('merged')
expect(@fork_merge_request.notes.last.note).to include('merged')
end
end
end
end
context 'when an MR to be closed was empty already' do
let!(:empty_fork_merge_request) do
create(:merge_request,
source_project: @fork_project,
source_branch: 'master',
target_branch: 'master',
target_project: @project)
context 'when an MR to be closed was empty already' do
let!(:empty_fork_merge_request) do
create(:merge_request,
source_project: @fork_project,
source_branch: 'master',
target_branch: 'master',
target_project: @project)
end
before do
# This spec already has a fake push, so pretend that we were targeting
# feature all along.
empty_fork_merge_request.update_columns(target_branch: 'feature')
service.new(@project, @user).execute(@oldrev, @newrev, 'refs/heads/feature')
reload_mrs
empty_fork_merge_request.reload
end
it 'only updates the non-empty MRs' do
expect(@merge_request).to be_merged
expect(@fork_merge_request).to be_merged
expect(empty_fork_merge_request).to be_open
expect(empty_fork_merge_request.merge_request_diff.state).to eq('empty')
expect(empty_fork_merge_request.notes).to be_empty
if state_tracking_enabled
expect(@merge_request.resource_state_events.last.state).to eq('merged')
expect(@fork_merge_request.resource_state_events.last.state).to eq('merged')
else
expect(@merge_request.notes.last.note).to include('merged')
expect(@fork_merge_request.notes.last.note).to include('merged')
end
end
end
end
context "manual merge of source branch #{state_tracking_enabled ? 'enabled' : 'disabled'}", :sidekiq_might_not_need_inline do
before do
# This spec already has a fake push, so pretend that we were targeting
# feature all along.
empty_fork_merge_request.update_columns(target_branch: 'feature')
stub_feature_flags(track_resource_state_change_events: state_tracking_enabled)
service.new(@project, @user).execute(@oldrev, @newrev, 'refs/heads/feature')
# Merge master -> feature branch
@project.repository.merge(@user, @merge_request.diff_head_sha, @merge_request, 'Test message')
commit = @project.repository.commit('feature')
service.new(@project, @user).execute(@oldrev, commit.id, 'refs/heads/feature')
reload_mrs
empty_fork_merge_request.reload
end
it 'only updates the non-empty MRs' do
expect(@merge_request).to be_merged
expect(@merge_request.notes.last.note).to include('merged')
it 'updates the merge state' do
if state_tracking_enabled
expect(@merge_request.resource_state_events.last.state).to eq('merged')
expect(@fork_merge_request.resource_state_events.last.state).to eq('merged')
else
expect(@merge_request.notes.last.note).to include('merged')
expect(@fork_merge_request.notes.last.note).to include('merged')
end
expect(@merge_request).to be_merged
expect(@merge_request.diffs.size).to be > 0
expect(@fork_merge_request).to be_merged
expect(@fork_merge_request.notes.last.note).to include('merged')
expect(empty_fork_merge_request).to be_open
expect(empty_fork_merge_request.merge_request_diff.state).to eq('empty')
expect(empty_fork_merge_request.notes).to be_empty
expect(@build_failed_todo).to be_done
expect(@fork_build_failed_todo).to be_done
end
end
end
context 'manual merge of source branch', :sidekiq_might_not_need_inline do
before do
# Merge master -> feature branch
@project.repository.merge(@user, @merge_request.diff_head_sha, @merge_request, 'Test message')
commit = @project.repository.commit('feature')
service.new(@project, @user).execute(@oldrev, commit.id, 'refs/heads/feature')
reload_mrs
end
it 'updates the merge state' do
expect(@merge_request.notes.last.note).to include('merged')
expect(@merge_request).to be_merged
expect(@merge_request.diffs.size).to be > 0
expect(@fork_merge_request).to be_merged
expect(@fork_merge_request.notes.last.note).to include('merged')
expect(@build_failed_todo).to be_done
expect(@fork_build_failed_todo).to be_done
end
end
context 'push to fork repo source branch', :sidekiq_might_not_need_inline do
let(:refresh_service) { service.new(@fork_project, @user) }
......@@ -583,20 +608,29 @@ describe MergeRequests::RefreshService do
end
end
context 'push to origin repo target branch after fork project was removed' do
before do
@fork_project.destroy
service.new(@project, @user).execute(@oldrev, @newrev, 'refs/heads/feature')
reload_mrs
end
[true, false].each do |state_tracking_enabled|
context "push to origin repo target branch after fork project was removed #{state_tracking_enabled ? 'enabled' : 'disabled'}" do
before do
stub_feature_flags(track_resource_state_change_events: state_tracking_enabled)
it 'updates the merge request state' do
expect(@merge_request.notes.last.note).to include('merged')
expect(@merge_request).to be_merged
expect(@fork_merge_request).to be_open
expect(@fork_merge_request.notes).to be_empty
expect(@build_failed_todo).to be_done
expect(@fork_build_failed_todo).to be_done
@fork_project.destroy
service.new(@project, @user).execute(@oldrev, @newrev, 'refs/heads/feature')
reload_mrs
end
it 'updates the merge request state' do
if state_tracking_enabled
expect(@merge_request.resource_state_events.last.state).to eq('merged')
else
expect(@merge_request.notes.last.note).to include('merged')
end
expect(@merge_request).to be_merged
expect(@fork_merge_request).to be_open
expect(@fork_merge_request.notes).to be_empty
expect(@build_failed_todo).to be_done
expect(@fork_build_failed_todo).to be_done
end
end
end
......
......@@ -20,8 +20,11 @@ describe MergeRequests::ReopenService do
context 'valid params' do
let(:service) { described_class.new(project, user, {}) }
let(:state_tracking) { true }
before do
stub_feature_flags(track_resource_state_change_events: state_tracking)
allow(service).to receive(:execute_hooks)
perform_enqueued_jobs do
......@@ -43,9 +46,22 @@ describe MergeRequests::ReopenService do
expect(email.subject).to include(merge_request.title)
end
it 'creates system note about merge_request reopen' do
note = merge_request.notes.last
expect(note.note).to include 'reopened'
context 'note creation' do
context 'when state event tracking is disabled' do
let(:state_tracking) { false }
it 'creates system note about merge_request reopen' do
note = merge_request.notes.last
expect(note.note).to include 'reopened'
end
end
context 'when state event tracking is enabled' do
it 'creates resource state event about merge_request reopen' do
event = merge_request.resource_state_events.last
expect(event.state).to eq('reopened')
end
end
end
end
......
# frozen_string_literal: true
require 'spec_helper'
describe ResourceEvents::ChangeStateService do
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
let(:issue) { create(:issue, project: project) }
let(:merge_request) { create(:merge_request, source_project: project) }
describe '#execute' do
context 'when resource is an issue' do
%w[opened reopened closed locked].each do |state|
it "creates the expected event if issue has #{state} state" do
described_class.new(user: user, resource: issue).execute(state)
event = issue.resource_state_events.last
expect(event.issue).to eq(issue)
expect(event.merge_request).to be_nil
expect(event.state).to eq(state)
end
end
end
context 'when resource is a merge request' do
%w[opened reopened closed locked merged].each do |state|
it "creates the expected event if merge request has #{state} state" do
described_class.new(user: user, resource: merge_request).execute(state)
event = merge_request.resource_state_events.last
expect(event.issue).to be_nil
expect(event.merge_request).to eq(merge_request)
expect(event.state).to eq(state)
end
end
end
end
end
......@@ -157,7 +157,18 @@ describe ::SystemNotes::IssuablesService do
describe '#change_status' do
subject { service.change_status(status, source) }
context 'when resource state event tracking is enabled' do
let(:status) { 'reopened' }
let(:source) { nil }
it { is_expected.to be_nil }
end
context 'with status reopened' do
before do
stub_feature_flags(track_resource_state_change_events: false)
end
let(:status) { 'reopened' }
let(:source) { nil }
......@@ -169,6 +180,10 @@ describe ::SystemNotes::IssuablesService do
end
context 'with a source' do
before do
stub_feature_flags(track_resource_state_change_events: false)
end
let(:status) { 'opened' }
let(:source) { double('commit', gfm_reference: 'commit 123456') }
......
......@@ -30,6 +30,8 @@ RSpec.shared_examples 'thread comments' do |resource_name|
click_button 'Comment & close issue'
wait_for_all_requests
expect(page).to have_content(comment)
expect(page).to have_content "@#{user.username} closed"
......
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