2019-04-03 19:10:21 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2015-05-01 03:16:19 +00:00
|
|
|
require 'spec_helper'
|
|
|
|
|
2020-06-24 15:08:50 +00:00
|
|
|
RSpec.describe SystemNoteService do
|
2017-07-07 15:43:37 +00:00
|
|
|
include Gitlab::Routing
|
2017-12-28 11:17:31 +00:00
|
|
|
include RepoHelpers
|
2018-05-22 16:37:35 +00:00
|
|
|
include AssetsHelpers
|
2020-05-13 18:08:47 +00:00
|
|
|
include DesignManagementTestHelpers
|
2016-11-09 21:55:21 +00:00
|
|
|
|
2020-01-10 09:07:49 +00:00
|
|
|
let_it_be(:group) { create(:group) }
|
|
|
|
let_it_be(:project) { create(:project, :repository, group: group) }
|
|
|
|
let_it_be(:author) { create(:user) }
|
2021-06-29 03:07:32 +00:00
|
|
|
|
2015-05-01 03:16:19 +00:00
|
|
|
let(:noteable) { create(:issue, project: project) }
|
2017-05-04 12:11:15 +00:00
|
|
|
let(:issue) { noteable }
|
2015-05-01 03:16:19 +00:00
|
|
|
|
2015-05-09 22:18:50 +00:00
|
|
|
describe '.add_commits' do
|
2019-10-03 12:06:00 +00:00
|
|
|
let(:new_commits) { double }
|
|
|
|
let(:old_commits) { double }
|
|
|
|
let(:oldrev) { double }
|
2015-05-01 03:16:19 +00:00
|
|
|
|
2019-10-03 12:06:00 +00:00
|
|
|
it 'calls CommitService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::CommitService) do |service|
|
|
|
|
expect(service).to receive(:add_commits).with(new_commits, old_commits, oldrev)
|
2016-09-30 01:51:33 +00:00
|
|
|
end
|
|
|
|
|
2019-10-03 12:06:00 +00:00
|
|
|
described_class.add_commits(noteable, project, author, new_commits, old_commits, oldrev)
|
2015-05-01 03:16:19 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-07-21 12:57:52 +00:00
|
|
|
describe '.tag_commit' do
|
2019-10-03 12:06:00 +00:00
|
|
|
let(:tag_name) { double }
|
2018-07-21 12:57:52 +00:00
|
|
|
|
2019-10-03 12:06:00 +00:00
|
|
|
it 'calls CommitService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::CommitService) do |service|
|
|
|
|
expect(service).to receive(:tag_commit).with(tag_name)
|
|
|
|
end
|
2018-07-23 20:16:00 +00:00
|
|
|
|
2019-10-03 12:06:00 +00:00
|
|
|
described_class.tag_commit(noteable, project, author, tag_name)
|
2018-07-21 12:57:52 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-05-09 22:18:50 +00:00
|
|
|
describe '.change_assignee' do
|
2019-10-08 15:06:04 +00:00
|
|
|
let(:assignee) { double }
|
2015-05-09 22:18:50 +00:00
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
|
|
|
expect(service).to receive(:change_assignee).with(assignee)
|
2015-05-09 22:18:50 +00:00
|
|
|
end
|
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
described_class.change_assignee(noteable, project, author, assignee)
|
2015-05-09 22:18:50 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-04-07 18:35:16 +00:00
|
|
|
describe '.change_issuable_assignees' do
|
2019-10-08 15:06:04 +00:00
|
|
|
let(:assignees) { [double, double] }
|
2019-08-27 11:00:34 +00:00
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
|
|
|
expect(service).to receive(:change_issuable_assignees).with(assignees)
|
2019-08-27 11:00:34 +00:00
|
|
|
end
|
2019-10-08 15:06:04 +00:00
|
|
|
|
|
|
|
described_class.change_issuable_assignees(noteable, project, author, assignees)
|
2019-08-27 11:00:34 +00:00
|
|
|
end
|
2017-05-04 12:11:15 +00:00
|
|
|
end
|
|
|
|
|
2020-09-24 09:09:35 +00:00
|
|
|
describe '.change_issuable_reviewers' do
|
|
|
|
let(:reviewers) { [double, double] }
|
|
|
|
|
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
|
|
|
expect(service).to receive(:change_issuable_reviewers).with(reviewers)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.change_issuable_reviewers(noteable, project, author, reviewers)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-02-11 15:14:00 +00:00
|
|
|
describe '.change_issuable_contacts' do
|
|
|
|
let(:added_count) { 5 }
|
|
|
|
let(:removed_count) { 3 }
|
|
|
|
|
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
|
|
|
expect(service).to receive(:change_issuable_contacts).with(added_count, removed_count)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.change_issuable_contacts(noteable, project, author, added_count, removed_count)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-01-24 12:09:01 +00:00
|
|
|
describe '.close_after_error_tracking_resolve' do
|
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
|
|
|
expect(service).to receive(:close_after_error_tracking_resolve)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.close_after_error_tracking_resolve(noteable, project, author)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-03-15 12:07:44 +00:00
|
|
|
describe '.relate_issuable' do
|
2020-08-21 00:10:44 +00:00
|
|
|
let(:noteable_ref) { double }
|
|
|
|
let(:noteable) { double }
|
|
|
|
|
|
|
|
before do
|
|
|
|
allow(noteable).to receive(:project).and_return(double)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
2022-03-15 12:07:44 +00:00
|
|
|
expect(service).to receive(:relate_issuable).with(noteable_ref)
|
2020-08-21 00:10:44 +00:00
|
|
|
end
|
|
|
|
|
2022-03-15 12:07:44 +00:00
|
|
|
described_class.relate_issuable(noteable, noteable_ref, double)
|
2020-08-21 00:10:44 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-03-04 18:20:01 +00:00
|
|
|
describe '.unrelate_issuable' do
|
2020-08-21 00:10:44 +00:00
|
|
|
let(:noteable_ref) { double }
|
|
|
|
let(:noteable) { double }
|
|
|
|
|
|
|
|
before do
|
|
|
|
allow(noteable).to receive(:project).and_return(double)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
2022-03-04 18:20:01 +00:00
|
|
|
expect(service).to receive(:unrelate_issuable).with(noteable_ref)
|
2020-08-21 00:10:44 +00:00
|
|
|
end
|
|
|
|
|
2022-03-04 18:20:01 +00:00
|
|
|
described_class.unrelate_issuable(noteable, noteable_ref, double)
|
2020-08-21 00:10:44 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-08-10 00:09:11 +00:00
|
|
|
describe '.change_start_date_or_due_date' do
|
|
|
|
let(:changed_dates) { double }
|
2018-09-09 18:08:21 +00:00
|
|
|
|
2020-01-17 18:08:41 +00:00
|
|
|
it 'calls TimeTrackingService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::TimeTrackingService) do |service|
|
2022-08-10 00:09:11 +00:00
|
|
|
expect(service).to receive(:change_start_date_or_due_date).with(changed_dates)
|
2018-09-09 18:08:21 +00:00
|
|
|
end
|
|
|
|
|
2022-08-10 00:09:11 +00:00
|
|
|
described_class.change_start_date_or_due_date(noteable, project, author, changed_dates)
|
2018-09-09 18:08:21 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-05-09 22:18:50 +00:00
|
|
|
describe '.change_status' do
|
2019-10-08 15:06:04 +00:00
|
|
|
let(:status) { double }
|
|
|
|
let(:source) { double }
|
2019-04-08 15:33:30 +00:00
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
|
|
|
expect(service).to receive(:change_status).with(status, source)
|
2017-04-04 10:36:58 +00:00
|
|
|
end
|
2019-04-08 15:33:30 +00:00
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
described_class.change_status(noteable, project, author, status, source)
|
2015-05-09 22:18:50 +00:00
|
|
|
end
|
|
|
|
end
|
2015-05-01 03:16:19 +00:00
|
|
|
|
2021-12-02 09:10:59 +00:00
|
|
|
describe '.request_attention' do
|
|
|
|
let(:user) { double }
|
|
|
|
|
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
|
|
|
expect(service).to receive(:request_attention).with(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.request_attention(noteable, project, author, user)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '.remove_attention_request' do
|
|
|
|
let(:user) { double }
|
|
|
|
|
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
|
|
|
expect(service).to receive(:remove_attention_request).with(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.remove_attention_request(noteable, project, author, user)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-02-17 13:56:13 +00:00
|
|
|
describe '.merge_when_pipeline_succeeds' do
|
2019-10-23 09:06:03 +00:00
|
|
|
it 'calls MergeRequestsService' do
|
|
|
|
sha = double
|
2015-11-18 10:17:41 +00:00
|
|
|
|
2019-10-23 09:06:03 +00:00
|
|
|
expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service|
|
|
|
|
expect(service).to receive(:merge_when_pipeline_succeeds).with(sha)
|
|
|
|
end
|
2015-11-18 10:17:41 +00:00
|
|
|
|
2019-10-23 09:06:03 +00:00
|
|
|
described_class.merge_when_pipeline_succeeds(noteable, project, author, sha)
|
2015-11-24 13:59:02 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-02-17 13:56:13 +00:00
|
|
|
describe '.cancel_merge_when_pipeline_succeeds' do
|
2019-10-23 09:06:03 +00:00
|
|
|
it 'calls MergeRequestsService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service|
|
|
|
|
expect(service).to receive(:cancel_merge_when_pipeline_succeeds)
|
|
|
|
end
|
2015-11-24 13:59:02 +00:00
|
|
|
|
2019-10-23 09:06:03 +00:00
|
|
|
described_class.cancel_merge_when_pipeline_succeeds(noteable, project, author)
|
2015-11-18 10:17:41 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-06-26 12:24:09 +00:00
|
|
|
describe '.abort_merge_when_pipeline_succeeds' do
|
2019-10-23 09:06:03 +00:00
|
|
|
it 'calls MergeRequestsService' do
|
|
|
|
reason = double
|
2019-06-26 12:24:09 +00:00
|
|
|
|
2019-10-23 09:06:03 +00:00
|
|
|
expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service|
|
|
|
|
expect(service).to receive(:abort_merge_when_pipeline_succeeds).with(reason)
|
|
|
|
end
|
2019-06-26 12:24:09 +00:00
|
|
|
|
2019-10-23 09:06:03 +00:00
|
|
|
described_class.abort_merge_when_pipeline_succeeds(noteable, project, author, reason)
|
2019-06-26 12:24:09 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-05-27 01:49:04 +00:00
|
|
|
describe '.change_title' do
|
2019-10-08 15:06:04 +00:00
|
|
|
let(:title) { double }
|
2015-05-27 01:49:04 +00:00
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
|
|
|
expect(service).to receive(:change_title).with(title)
|
2017-03-15 13:19:45 +00:00
|
|
|
end
|
2015-05-27 01:49:04 +00:00
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
described_class.change_title(noteable, project, author, title)
|
2015-05-27 01:49:04 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-04-28 23:54:37 +00:00
|
|
|
describe '.change_description' do
|
2019-10-08 15:06:04 +00:00
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
|
|
|
expect(service).to receive(:change_description)
|
2017-04-28 23:54:37 +00:00
|
|
|
end
|
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
described_class.change_description(noteable, project, author)
|
2017-04-28 23:54:37 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-05-18 17:56:13 +00:00
|
|
|
describe '.change_issue_confidentiality' do
|
2019-10-08 15:06:04 +00:00
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
|
|
|
expect(service).to receive(:change_issue_confidentiality)
|
2017-03-15 13:19:45 +00:00
|
|
|
end
|
2016-04-20 22:41:11 +00:00
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
described_class.change_issue_confidentiality(noteable, project, author)
|
2016-04-20 22:41:11 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-05-29 01:00:37 +00:00
|
|
|
describe '.change_branch' do
|
2019-10-23 09:06:03 +00:00
|
|
|
it 'calls MergeRequestsService' do
|
2021-02-17 09:09:36 +00:00
|
|
|
old_branch = double('old_branch')
|
|
|
|
new_branch = double('new_branch')
|
|
|
|
branch_type = double('branch_type')
|
|
|
|
event_type = double('event_type')
|
2015-05-29 01:00:37 +00:00
|
|
|
|
2019-10-23 09:06:03 +00:00
|
|
|
expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service|
|
2021-02-17 09:09:36 +00:00
|
|
|
expect(service).to receive(:change_branch).with(branch_type, event_type, old_branch, new_branch)
|
2015-05-29 01:00:37 +00:00
|
|
|
end
|
2019-10-23 09:06:03 +00:00
|
|
|
|
2021-02-17 09:09:36 +00:00
|
|
|
described_class.change_branch(noteable, project, author, branch_type, event_type, old_branch, new_branch)
|
2015-05-29 01:00:37 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-10-15 08:41:46 +00:00
|
|
|
describe '.change_branch_presence' do
|
2019-10-23 09:06:03 +00:00
|
|
|
it 'calls MergeRequestsService' do
|
|
|
|
presence = double
|
|
|
|
branch = double
|
|
|
|
branch_type = double
|
2015-10-15 08:41:46 +00:00
|
|
|
|
2019-10-23 09:06:03 +00:00
|
|
|
expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service|
|
|
|
|
expect(service).to receive(:change_branch_presence).with(branch_type, branch, presence)
|
2015-10-15 08:41:46 +00:00
|
|
|
end
|
2019-10-23 09:06:03 +00:00
|
|
|
|
|
|
|
described_class.change_branch_presence(noteable, project, author, branch_type, branch, presence)
|
2015-10-15 08:41:46 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-02-17 06:11:48 +00:00
|
|
|
describe '.new_issue_branch' do
|
2019-10-23 09:06:03 +00:00
|
|
|
it 'calls MergeRequestsService' do
|
|
|
|
branch = double
|
|
|
|
branch_project = double
|
2016-02-17 06:11:48 +00:00
|
|
|
|
2019-10-23 09:06:03 +00:00
|
|
|
expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service|
|
|
|
|
expect(service).to receive(:new_issue_branch).with(branch, branch_project: branch_project)
|
2019-06-28 22:08:26 +00:00
|
|
|
end
|
|
|
|
|
2019-10-23 09:06:03 +00:00
|
|
|
described_class.new_issue_branch(noteable, project, author, branch, branch_project: branch_project)
|
2016-02-17 06:11:48 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-10-19 07:16:58 +00:00
|
|
|
describe '.new_merge_request' do
|
2019-10-23 09:06:03 +00:00
|
|
|
it 'calls MergeRequestsService' do
|
|
|
|
merge_request = double
|
2018-10-19 07:16:58 +00:00
|
|
|
|
2019-10-23 09:06:03 +00:00
|
|
|
expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service|
|
|
|
|
expect(service).to receive(:new_merge_request).with(merge_request)
|
|
|
|
end
|
2018-10-19 07:16:58 +00:00
|
|
|
|
2019-10-23 09:06:03 +00:00
|
|
|
described_class.new_merge_request(noteable, project, author, merge_request)
|
2018-10-19 07:16:58 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-07-20 09:06:19 +00:00
|
|
|
describe '.zoom_link_added' do
|
2019-10-10 15:06:07 +00:00
|
|
|
it 'calls ZoomService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::ZoomService) do |service|
|
|
|
|
expect(service).to receive(:zoom_link_added)
|
|
|
|
end
|
2019-07-20 09:06:19 +00:00
|
|
|
|
2019-10-10 15:06:07 +00:00
|
|
|
described_class.zoom_link_added(noteable, project, author)
|
2019-07-20 09:06:19 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '.zoom_link_removed' do
|
2019-10-10 15:06:07 +00:00
|
|
|
it 'calls ZoomService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::ZoomService) do |service|
|
|
|
|
expect(service).to receive(:zoom_link_removed)
|
|
|
|
end
|
2019-07-20 09:06:19 +00:00
|
|
|
|
2019-10-10 15:06:07 +00:00
|
|
|
described_class.zoom_link_removed(noteable, project, author)
|
2019-07-20 09:06:19 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-05-09 22:18:50 +00:00
|
|
|
describe '.cross_reference' do
|
2021-11-23 12:14:32 +00:00
|
|
|
let(:mentioned_in) { double }
|
2015-05-01 03:16:19 +00:00
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
2021-11-23 12:14:32 +00:00
|
|
|
expect(service).to receive(:cross_reference).with(mentioned_in)
|
2015-05-09 22:18:50 +00:00
|
|
|
end
|
2017-03-15 13:19:45 +00:00
|
|
|
|
2021-11-23 12:14:32 +00:00
|
|
|
described_class.cross_reference(double, mentioned_in, double)
|
2015-05-01 03:16:19 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-05-11 03:51:49 +00:00
|
|
|
describe '.cross_reference_disallowed?' do
|
2021-11-23 12:14:32 +00:00
|
|
|
let(:mentioned_in) { double }
|
2015-05-11 03:51:49 +00:00
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
2021-11-23 12:14:32 +00:00
|
|
|
expect(service).to receive(:cross_reference_disallowed?).with(mentioned_in)
|
2015-05-11 03:51:49 +00:00
|
|
|
end
|
|
|
|
|
2021-11-23 12:14:32 +00:00
|
|
|
described_class.cross_reference_disallowed?(double, mentioned_in)
|
2015-06-14 15:41:11 +00:00
|
|
|
end
|
2015-05-11 03:51:49 +00:00
|
|
|
end
|
2015-05-01 03:16:19 +00:00
|
|
|
|
|
|
|
describe '.cross_reference_exists?' do
|
2021-11-23 12:14:32 +00:00
|
|
|
let(:mentioned_in) { double }
|
2016-02-04 17:36:16 +00:00
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
2021-11-23 12:14:32 +00:00
|
|
|
expect(service).to receive(:cross_reference_exists?).with(mentioned_in)
|
2016-02-04 17:36:16 +00:00
|
|
|
end
|
|
|
|
|
2021-11-23 12:14:32 +00:00
|
|
|
described_class.cross_reference_exists?(double, mentioned_in)
|
2016-02-04 17:36:16 +00:00
|
|
|
end
|
2015-05-01 03:16:19 +00:00
|
|
|
end
|
2015-12-17 22:08:14 +00:00
|
|
|
|
2016-02-16 10:47:00 +00:00
|
|
|
describe '.noteable_moved' do
|
2019-10-08 15:06:04 +00:00
|
|
|
let(:noteable_ref) { double }
|
|
|
|
let(:direction) { double }
|
2016-02-16 10:47:00 +00:00
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
|
|
|
expect(service).to receive(:noteable_moved).with(noteable_ref, direction)
|
2016-02-16 10:47:00 +00:00
|
|
|
end
|
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
described_class.noteable_moved(double, double, noteable_ref, double, direction: direction)
|
2020-12-03 21:09:35 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '.noteable_cloned' do
|
|
|
|
let(:noteable_ref) { double }
|
|
|
|
let(:direction) { double }
|
2022-07-21 09:09:01 +00:00
|
|
|
let(:created_at) { double }
|
2020-12-03 21:09:35 +00:00
|
|
|
|
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
2022-07-21 09:09:01 +00:00
|
|
|
expect(service).to receive(:noteable_cloned).with(noteable_ref, direction, created_at: created_at)
|
2020-12-03 21:09:35 +00:00
|
|
|
end
|
|
|
|
|
2022-07-21 09:09:01 +00:00
|
|
|
described_class.noteable_cloned(double, double, noteable_ref, double, direction: direction, created_at: created_at)
|
2016-02-15 14:14:57 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-04-03 19:10:21 +00:00
|
|
|
describe '.change_time_estimate' do
|
2020-01-17 18:08:41 +00:00
|
|
|
it 'calls TimeTrackingService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::TimeTrackingService) do |service|
|
|
|
|
expect(service).to receive(:change_time_estimate)
|
2019-06-11 10:40:01 +00:00
|
|
|
end
|
2019-04-03 19:10:21 +00:00
|
|
|
|
2020-01-17 18:08:41 +00:00
|
|
|
described_class.change_time_estimate(noteable, project, author)
|
2019-04-03 19:10:21 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-10-26 21:21:50 +00:00
|
|
|
describe '.discussion_continued_in_issue' do
|
2017-08-30 10:54:23 +00:00
|
|
|
let(:discussion) { create(:diff_note_on_merge_request, project: project).to_discussion }
|
2016-10-26 21:21:50 +00:00
|
|
|
let(:merge_request) { discussion.noteable }
|
|
|
|
let(:issue) { create(:issue, project: project) }
|
|
|
|
|
|
|
|
def reloaded_merge_request
|
|
|
|
MergeRequest.find(merge_request.id)
|
|
|
|
end
|
|
|
|
|
2017-03-15 13:19:45 +00:00
|
|
|
subject { described_class.discussion_continued_in_issue(discussion, project, author, issue) }
|
|
|
|
|
|
|
|
it_behaves_like 'a system note' do
|
|
|
|
let(:expected_noteable) { discussion.first_note.noteable }
|
|
|
|
let(:action) { 'discussion' }
|
2016-10-26 21:21:50 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'creates a new note in the discussion' do
|
|
|
|
# we need to completely rebuild the merge request object, or the `@discussions` on the merge request are not reloaded.
|
2017-03-15 13:19:45 +00:00
|
|
|
expect { subject }.to change { reloaded_merge_request.discussions.first.notes.size }.by(1)
|
2016-10-26 21:21:50 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'mentions the created issue in the system note' do
|
2017-03-15 13:19:45 +00:00
|
|
|
expect(subject.note).to include(issue.to_reference)
|
2016-10-26 21:21:50 +00:00
|
|
|
end
|
|
|
|
end
|
2016-12-23 05:44:02 +00:00
|
|
|
|
|
|
|
describe '.change_time_spent' do
|
2020-01-17 18:08:41 +00:00
|
|
|
it 'calls TimeTrackingService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::TimeTrackingService) do |service|
|
|
|
|
expect(service).to receive(:change_time_spent)
|
2016-12-23 05:44:02 +00:00
|
|
|
end
|
|
|
|
|
2020-01-17 18:08:41 +00:00
|
|
|
described_class.change_time_spent(noteable, project, author)
|
2016-12-23 05:44:02 +00:00
|
|
|
end
|
|
|
|
end
|
2016-12-15 20:48:26 +00:00
|
|
|
|
2022-07-27 15:09:42 +00:00
|
|
|
describe '.created_timelog' do
|
|
|
|
let(:issue) { create(:issue, project: project) }
|
2022-08-03 03:09:00 +00:00
|
|
|
let(:timelog) { create(:timelog, user: author, issue: issue, time_spent: 1800) }
|
2022-07-27 15:09:42 +00:00
|
|
|
|
|
|
|
it 'calls TimeTrackingService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::TimeTrackingService) do |service|
|
|
|
|
expect(service).to receive(:created_timelog)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.created_timelog(noteable, project, author, timelog)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-04-22 15:09:52 +00:00
|
|
|
describe '.remove_timelog' do
|
|
|
|
let(:issue) { create(:issue, project: project) }
|
2022-08-03 03:09:00 +00:00
|
|
|
let(:timelog) { create(:timelog, user: author, issue: issue, time_spent: 1800) }
|
2022-04-22 15:09:52 +00:00
|
|
|
|
|
|
|
it 'calls TimeTrackingService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::TimeTrackingService) do |service|
|
|
|
|
expect(service).to receive(:remove_timelog)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.remove_timelog(noteable, project, author, timelog)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-10-26 15:08:40 +00:00
|
|
|
describe '.handle_merge_request_draft' do
|
2019-10-23 09:06:03 +00:00
|
|
|
it 'calls MergeRequestsService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service|
|
2020-10-26 15:08:40 +00:00
|
|
|
expect(service).to receive(:handle_merge_request_draft)
|
2017-11-21 19:25:37 +00:00
|
|
|
end
|
2017-03-15 13:19:45 +00:00
|
|
|
|
2020-10-26 15:08:40 +00:00
|
|
|
described_class.handle_merge_request_draft(noteable, project, author)
|
2017-03-15 13:19:45 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-10-26 15:08:40 +00:00
|
|
|
describe '.add_merge_request_draft_from_commit' do
|
2019-10-23 09:06:03 +00:00
|
|
|
it 'calls MergeRequestsService' do
|
|
|
|
commit = double
|
2016-12-15 20:48:26 +00:00
|
|
|
|
2019-10-23 09:06:03 +00:00
|
|
|
expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service|
|
2020-10-26 15:08:40 +00:00
|
|
|
expect(service).to receive(:add_merge_request_draft_from_commit).with(commit)
|
2019-10-23 09:06:03 +00:00
|
|
|
end
|
2016-12-15 20:48:26 +00:00
|
|
|
|
2020-10-26 15:08:40 +00:00
|
|
|
described_class.add_merge_request_draft_from_commit(noteable, project, author, commit)
|
2016-12-15 20:48:26 +00:00
|
|
|
end
|
|
|
|
end
|
2017-03-15 13:19:45 +00:00
|
|
|
|
|
|
|
describe '.change_task_status' do
|
2019-10-08 15:06:04 +00:00
|
|
|
let(:new_task) { double }
|
2017-03-15 13:19:45 +00:00
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
|
|
|
expect(service).to receive(:change_task_status).with(new_task)
|
|
|
|
end
|
2017-03-15 13:19:45 +00:00
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
described_class.change_task_status(noteable, project, author, new_task)
|
2017-03-15 13:19:45 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '.resolve_all_discussions' do
|
2019-10-23 09:06:03 +00:00
|
|
|
it 'calls MergeRequestsService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service|
|
|
|
|
expect(service).to receive(:resolve_all_discussions)
|
|
|
|
end
|
2017-03-15 13:19:45 +00:00
|
|
|
|
2019-10-23 09:06:03 +00:00
|
|
|
described_class.resolve_all_discussions(noteable, project, author)
|
2017-03-15 13:19:45 +00:00
|
|
|
end
|
|
|
|
end
|
2017-05-21 20:38:33 +00:00
|
|
|
|
|
|
|
describe '.diff_discussion_outdated' do
|
2019-10-23 09:06:03 +00:00
|
|
|
it 'calls MergeRequestsService' do
|
|
|
|
discussion = double
|
|
|
|
change_position = double
|
2017-05-21 20:38:33 +00:00
|
|
|
|
2019-10-23 09:06:03 +00:00
|
|
|
expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service|
|
|
|
|
expect(service).to receive(:diff_discussion_outdated).with(discussion, change_position)
|
2019-07-05 11:03:47 +00:00
|
|
|
end
|
|
|
|
|
2019-10-23 09:06:03 +00:00
|
|
|
described_class.diff_discussion_outdated(discussion, project, author, change_position)
|
2017-05-21 20:38:33 +00:00
|
|
|
end
|
|
|
|
end
|
2017-03-30 01:39:06 +00:00
|
|
|
|
|
|
|
describe '.mark_duplicate_issue' do
|
2019-10-08 15:06:04 +00:00
|
|
|
let(:canonical_issue) { double }
|
2017-03-30 01:39:06 +00:00
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
|
|
|
expect(service).to receive(:mark_duplicate_issue).with(canonical_issue)
|
2017-03-30 01:39:06 +00:00
|
|
|
end
|
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
described_class.mark_duplicate_issue(noteable, project, author, canonical_issue)
|
2017-07-20 14:42:33 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '.mark_canonical_issue_of_duplicate' do
|
2019-10-08 15:06:04 +00:00
|
|
|
let(:duplicate_issue) { double }
|
2017-07-20 14:42:33 +00:00
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
|
|
|
expect(service).to receive(:mark_canonical_issue_of_duplicate).with(duplicate_issue)
|
2017-07-20 14:42:33 +00:00
|
|
|
end
|
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
described_class.mark_canonical_issue_of_duplicate(noteable, project, author, duplicate_issue)
|
2017-03-30 01:39:06 +00:00
|
|
|
end
|
|
|
|
end
|
2017-10-10 06:35:31 +00:00
|
|
|
|
|
|
|
describe '.discussion_lock' do
|
2019-10-08 15:06:04 +00:00
|
|
|
let(:issuable) { double }
|
2017-10-10 06:35:31 +00:00
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
before do
|
|
|
|
allow(issuable).to receive(:project).and_return(double)
|
2017-10-10 06:35:31 +00:00
|
|
|
end
|
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
|
|
|
expect(service).to receive(:discussion_lock)
|
2017-10-10 06:35:31 +00:00
|
|
|
end
|
|
|
|
|
2019-10-08 15:06:04 +00:00
|
|
|
described_class.discussion_lock(issuable, double)
|
2017-10-10 06:35:31 +00:00
|
|
|
end
|
|
|
|
end
|
2020-03-17 09:09:20 +00:00
|
|
|
|
|
|
|
describe '.auto_resolve_prometheus_alert' do
|
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
|
|
|
expect(service).to receive(:auto_resolve_prometheus_alert)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.auto_resolve_prometheus_alert(noteable, project, author)
|
|
|
|
end
|
|
|
|
end
|
2020-05-13 18:08:47 +00:00
|
|
|
|
|
|
|
describe '.design_version_added' do
|
|
|
|
let(:version) { create(:design_version) }
|
|
|
|
|
|
|
|
it 'calls DesignManagementService' do
|
|
|
|
expect_next_instance_of(SystemNotes::DesignManagementService) do |service|
|
|
|
|
expect(service).to receive(:design_version_added).with(version)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.design_version_added(version)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '.design_discussion_added' do
|
|
|
|
let(:discussion_note) { create(:diff_note_on_design) }
|
|
|
|
|
|
|
|
it 'calls DesignManagementService' do
|
|
|
|
expect_next_instance_of(SystemNotes::DesignManagementService) do |service|
|
|
|
|
expect(service).to receive(:design_discussion_added).with(discussion_note)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.design_discussion_added(discussion_note)
|
|
|
|
end
|
|
|
|
end
|
2020-07-03 09:08:53 +00:00
|
|
|
|
|
|
|
describe '.approve_mr' do
|
|
|
|
it 'calls MergeRequestsService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service|
|
|
|
|
expect(service).to receive(:approve_mr)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.approve_mr(noteable, author)
|
|
|
|
end
|
|
|
|
end
|
2020-07-07 12:09:16 +00:00
|
|
|
|
|
|
|
describe '.unapprove_mr' do
|
|
|
|
it 'calls MergeRequestsService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::MergeRequestsService) do |service|
|
|
|
|
expect(service).to receive(:unapprove_mr)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.unapprove_mr(noteable, author)
|
|
|
|
end
|
|
|
|
end
|
2020-07-09 03:09:01 +00:00
|
|
|
|
|
|
|
describe '.change_alert_status' do
|
|
|
|
let(:alert) { build(:alert_management_alert) }
|
|
|
|
|
2022-01-21 18:12:45 +00:00
|
|
|
context 'with status change reason' do
|
|
|
|
let(:reason) { 'reason for status change' }
|
|
|
|
|
|
|
|
it 'calls AlertManagementService' do
|
|
|
|
expect_next_instance_of(SystemNotes::AlertManagementService) do |service|
|
|
|
|
expect(service).to receive(:change_alert_status).with(reason)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.change_alert_status(alert, author, reason)
|
2020-07-09 03:09:01 +00:00
|
|
|
end
|
2022-01-21 18:12:45 +00:00
|
|
|
end
|
2020-07-09 03:09:01 +00:00
|
|
|
|
2022-01-21 18:12:45 +00:00
|
|
|
context 'without status change reason' do
|
|
|
|
it 'calls AlertManagementService' do
|
|
|
|
expect_next_instance_of(SystemNotes::AlertManagementService) do |service|
|
|
|
|
expect(service).to receive(:change_alert_status).with(nil)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.change_alert_status(alert, author)
|
|
|
|
end
|
2020-07-09 03:09:01 +00:00
|
|
|
end
|
|
|
|
end
|
2020-07-09 21:09:33 +00:00
|
|
|
|
|
|
|
describe '.new_alert_issue' do
|
2021-08-02 12:09:59 +00:00
|
|
|
let(:alert) { build(:alert_management_alert, :with_incident) }
|
2020-07-09 21:09:33 +00:00
|
|
|
|
|
|
|
it 'calls AlertManagementService' do
|
|
|
|
expect_next_instance_of(SystemNotes::AlertManagementService) do |service|
|
2020-07-23 09:09:18 +00:00
|
|
|
expect(service).to receive(:new_alert_issue).with(alert.issue)
|
2020-07-09 21:09:33 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
described_class.new_alert_issue(alert, alert.issue, author)
|
|
|
|
end
|
|
|
|
end
|
2020-08-27 18:10:29 +00:00
|
|
|
|
|
|
|
describe '.create_new_alert' do
|
|
|
|
let(:alert) { build(:alert_management_alert) }
|
|
|
|
let(:monitoring_tool) { 'Prometheus' }
|
|
|
|
|
|
|
|
it 'calls AlertManagementService' do
|
|
|
|
expect_next_instance_of(SystemNotes::AlertManagementService) do |service|
|
|
|
|
expect(service).to receive(:create_new_alert).with(monitoring_tool)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.create_new_alert(alert, monitoring_tool)
|
|
|
|
end
|
|
|
|
end
|
2020-09-21 21:09:27 +00:00
|
|
|
|
|
|
|
describe '.change_incident_severity' do
|
|
|
|
let(:incident) { build(:incident) }
|
|
|
|
|
|
|
|
it 'calls IncidentService' do
|
|
|
|
expect_next_instance_of(SystemNotes::IncidentService) do |service|
|
|
|
|
expect(service).to receive(:change_incident_severity)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.change_incident_severity(incident, author)
|
|
|
|
end
|
|
|
|
end
|
2021-02-23 18:10:40 +00:00
|
|
|
|
2022-01-21 18:12:45 +00:00
|
|
|
describe '.change_incident_status' do
|
|
|
|
let(:incident) { instance_double('Issue', project: project) }
|
|
|
|
|
|
|
|
context 'with status change reason' do
|
|
|
|
let(:reason) { 'reason for status change' }
|
|
|
|
|
|
|
|
it 'calls IncidentService' do
|
|
|
|
expect_next_instance_of(SystemNotes::IncidentService) do |service|
|
|
|
|
expect(service).to receive(:change_incident_status).with(reason)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.change_incident_status(incident, author, reason)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without status change reason' do
|
|
|
|
it 'calls IncidentService' do
|
|
|
|
expect_next_instance_of(SystemNotes::IncidentService) do |service|
|
|
|
|
expect(service).to receive(:change_incident_status).with(nil)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.change_incident_status(incident, author)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-02-23 18:10:40 +00:00
|
|
|
describe '.log_resolving_alert' do
|
|
|
|
let(:alert) { build(:alert_management_alert) }
|
|
|
|
let(:monitoring_tool) { 'Prometheus' }
|
|
|
|
|
|
|
|
it 'calls AlertManagementService' do
|
|
|
|
expect_next_instance_of(SystemNotes::AlertManagementService) do |service|
|
|
|
|
expect(service).to receive(:log_resolving_alert).with(monitoring_tool)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.log_resolving_alert(alert, monitoring_tool)
|
|
|
|
end
|
|
|
|
end
|
2021-08-19 18:10:32 +00:00
|
|
|
|
|
|
|
describe '.change_issue_type' do
|
|
|
|
let(:incident) { build(:incident) }
|
|
|
|
|
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
|
|
|
expect(service).to receive(:change_issue_type)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.change_issue_type(incident, author)
|
|
|
|
end
|
|
|
|
end
|
2022-05-11 12:09:03 +00:00
|
|
|
|
|
|
|
describe '.add_timeline_event' do
|
|
|
|
let(:timeline_event) { instance_double('IncidentManagement::TimelineEvent', incident: noteable, project: project) }
|
|
|
|
|
|
|
|
it 'calls IncidentsService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IncidentsService) do |service|
|
|
|
|
expect(service).to receive(:add_timeline_event).with(timeline_event)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.add_timeline_event(timeline_event)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '.edit_timeline_event' do
|
|
|
|
let(:timeline_event) { instance_double('IncidentManagement::TimelineEvent', incident: noteable, project: project) }
|
|
|
|
|
|
|
|
it 'calls IncidentsService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IncidentsService) do |service|
|
|
|
|
expect(service).to receive(:edit_timeline_event).with(timeline_event, author, was_changed: :occurred_at)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.edit_timeline_event(timeline_event, author, was_changed: :occurred_at)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '.delete_timeline_event' do
|
|
|
|
it 'calls IncidentsService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IncidentsService) do |service|
|
|
|
|
expect(service).to receive(:delete_timeline_event).with(author)
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.delete_timeline_event(noteable, author)
|
|
|
|
end
|
|
|
|
end
|
2022-07-20 15:08:38 +00:00
|
|
|
|
|
|
|
describe '.relate_work_item' do
|
|
|
|
let(:work_item) { double('work_item', issue_type: :task) }
|
|
|
|
let(:noteable) { double }
|
|
|
|
|
|
|
|
before do
|
|
|
|
allow(noteable).to receive(:project).and_return(double)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
|
|
|
expect(service).to receive(:hierarchy_changed).with(work_item, 'relate')
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.relate_work_item(noteable, work_item, double)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '.unrelate_wotk_item' do
|
|
|
|
let(:work_item) { double('work_item', issue_type: :task) }
|
|
|
|
let(:noteable) { double }
|
|
|
|
|
|
|
|
before do
|
|
|
|
allow(noteable).to receive(:project).and_return(double)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'calls IssuableService' do
|
|
|
|
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
|
|
|
|
expect(service).to receive(:hierarchy_changed).with(work_item, 'unrelate')
|
|
|
|
end
|
|
|
|
|
|
|
|
described_class.unrelate_work_item(noteable, work_item, double)
|
|
|
|
end
|
|
|
|
end
|
2015-05-01 03:16:19 +00:00
|
|
|
end
|