summaryrefslogtreecommitdiff
path: root/spec/support/shared_examples/services/boards/issues_move_service_shared_examples.rb
blob: 7d4fbeea0dc9075c54d1f94ac7c4d36a6b1fd632 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# frozen_string_literal: true

RSpec.shared_examples 'issues move service' do |group|
  shared_examples 'updating timestamps' do
    it 'updates updated_at' do
      expect {described_class.new(parent, user, params).execute(issue)}
        .to change {issue.reload.updated_at}
    end
  end

  context 'when moving an issue between lists' do
    let(:issue)  { create(:labeled_issue, project: project, labels: [bug, development]) }
    let(:params) { { board_id: board1.id, from_list_id: list1.id, to_list_id: list2.id } }

    it_behaves_like 'updating timestamps'

    it 'delegates the label changes to Issues::UpdateService' do
      service = double(:service)
      expect(Issues::UpdateService).to receive(:new).and_return(service)
      expect(service).to receive(:execute).with(issue).once

      described_class.new(parent, user, params).execute(issue)
    end

    it 'removes the label from the list it came from and adds the label of the list it goes to' do
      described_class.new(parent, user, params).execute(issue)

      expect(issue.reload.labels).to contain_exactly(bug, testing)
    end
  end

  context 'when moving to closed' do
    let!(:list3) { create(:list, board: board2, label: regression, position: 1) }

    let(:issue)  { create(:labeled_issue, project: project, labels: [bug, development, testing, regression]) }
    let(:params) { { board_id: board1.id, from_list_id: list2.id, to_list_id: closed.id } }

    it_behaves_like 'updating timestamps'

    it 'delegates the close proceedings to Issues::CloseService' do
      expect_any_instance_of(Issues::CloseService).to receive(:execute).with(issue).once

      described_class.new(parent, user, params).execute(issue)
    end

    it 'removes all list-labels from boards and close the issue' do
      described_class.new(parent, user, params).execute(issue)
      issue.reload

      expect(issue.labels).to contain_exactly(bug, regression)
      expect(issue).to be_closed
    end
  end

  context 'when moving to backlog' do
    let(:milestone) { create(:milestone, project: project) }
    let!(:backlog)  { create(:backlog_list, board: board1) }

    let(:issue)  { create(:labeled_issue, project: project, labels: [bug, development, testing, regression], milestone: milestone) }
    let(:params) { { board_id: board1.id, from_list_id: list2.id, to_list_id: backlog.id } }

    it_behaves_like 'updating timestamps'

    it 'keeps labels and milestone' do
      described_class.new(parent, user, params).execute(issue)
      issue.reload

      expect(issue.labels).to contain_exactly(bug, regression)
      expect(issue.milestone).to eq(milestone)
    end
  end

  context 'when moving from closed' do
    let(:issue)  { create(:labeled_issue, :closed, project: project, labels: [bug]) }
    let(:params) { { board_id: board1.id, from_list_id: closed.id, to_list_id: list2.id } }

    it_behaves_like 'updating timestamps'

    it 'delegates the re-open proceedings to Issues::ReopenService' do
      expect_any_instance_of(Issues::ReopenService).to receive(:execute).with(issue).once

      described_class.new(parent, user, params).execute(issue)
    end

    it 'adds the label of the list it goes to and reopen the issue' do
      described_class.new(parent, user, params).execute(issue)
      issue.reload

      expect(issue.labels).to contain_exactly(bug, testing)
      expect(issue).to be_opened
    end
  end

  context 'when moving to same list' do
    let(:assignee) { create(:user) }
    let(:params)   { { board_id: board1.id, from_list_id: list1.id, to_list_id: list1.id } }
    let(:issue1)   { create(:labeled_issue, project: project, labels: [bug, development]) }
    let(:issue2)   { create(:labeled_issue, project: project, labels: [bug, development]) }
    let(:issue) do
      create(:labeled_issue, project: project, labels: [bug, development], assignees: [assignee])
    end

    it 'returns false' do
      expect(described_class.new(parent, user, params).execute(issue)).to eq false
    end

    it 'keeps issues labels' do
      described_class.new(parent, user, params).execute(issue)

      expect(issue.reload.labels).to contain_exactly(bug, development)
    end

    it 'keeps issues assignees' do
      described_class.new(parent, user, params).execute(issue)

      expect(issue.reload.assignees).to contain_exactly(assignee)
    end

    it 'sorts issues' do
      reorder_issues(params, issues: [issue, issue1, issue2])

      described_class.new(parent, user, params).execute(issue)

      expect(issue.relative_position).to be_between(issue1.relative_position, issue2.relative_position)
    end

    it 'does not update updated_at' do
      reorder_issues(params, issues: [issue, issue1, issue2])

      updated_at = issue.updated_at
      updated_at1 = issue1.updated_at
      updated_at2 = issue2.updated_at

      travel_to(1.minute.from_now) do
        described_class.new(parent, user, params).execute(issue)
      end

      expect(issue.reload.updated_at.change(usec: 0)).to eq updated_at.change(usec: 0)
      expect(issue1.reload.updated_at.change(usec: 0)).to eq updated_at1.change(usec: 0)
      expect(issue2.reload.updated_at.change(usec: 0)).to eq updated_at2.change(usec: 0)
    end

    if group
      context 'when on a group board' do
        it 'sends the board_group_id parameter' do
          params.merge!(move_after_id: issue1.id, move_before_id: issue2.id)

          match_params = { move_between_ids: [issue1.id, issue2.id], board_group_id: parent.id }
          expect(Issues::UpdateService).to receive(:new).with(project: issue.project, current_user: user, params: match_params).and_return(double(execute: build(:issue)))

          described_class.new(parent, user, params).execute(issue)
        end
      end
    end

    def reorder_issues(params, issues: [])
      issues.each do |issue|
        issue.move_to_end && issue.save!
      end

      params.merge!(move_after_id: issues[1].id, move_before_id: issues[2].id)
    end
  end
end