summaryrefslogtreecommitdiff
path: root/spec/support/shared_examples/services/boards
diff options
context:
space:
mode:
Diffstat (limited to 'spec/support/shared_examples/services/boards')
-rw-r--r--spec/support/shared_examples/services/boards/boards_create_service.rb27
-rw-r--r--spec/support/shared_examples/services/boards/boards_list_service.rb29
-rw-r--r--spec/support/shared_examples/services/boards/issues_list_service.rb60
-rw-r--r--spec/support/shared_examples/services/boards/issues_move_service.rb87
-rw-r--r--spec/support/shared_examples/services/boards/lists_destroy_service.rb30
-rw-r--r--spec/support/shared_examples/services/boards/lists_list_service.rb23
-rw-r--r--spec/support/shared_examples/services/boards/lists_move_service.rb93
7 files changed, 349 insertions, 0 deletions
diff --git a/spec/support/shared_examples/services/boards/boards_create_service.rb b/spec/support/shared_examples/services/boards/boards_create_service.rb
new file mode 100644
index 00000000000..5bdc04f660f
--- /dev/null
+++ b/spec/support/shared_examples/services/boards/boards_create_service.rb
@@ -0,0 +1,27 @@
+shared_examples 'boards create service' do
+ context 'when parent does not have a board' do
+ it 'creates a new board' do
+ expect { service.execute }.to change(Board, :count).by(1)
+ end
+
+ it 'creates the default lists' do
+ board = service.execute
+
+ expect(board.lists.size).to eq 2
+ expect(board.lists.first).to be_backlog
+ expect(board.lists.last).to be_closed
+ end
+ end
+
+ context 'when parent has a board' do
+ before do
+ create(:board, parent: parent)
+ end
+
+ it 'does not create a new board' do
+ expect(service).to receive(:can_create_board?) { false }
+
+ expect { service.execute }.not_to change(parent.boards, :count)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/services/boards/boards_list_service.rb b/spec/support/shared_examples/services/boards/boards_list_service.rb
new file mode 100644
index 00000000000..e0d5a7c61f2
--- /dev/null
+++ b/spec/support/shared_examples/services/boards/boards_list_service.rb
@@ -0,0 +1,29 @@
+shared_examples 'boards list service' do
+ context 'when parent does not have a board' do
+ it 'creates a new parent board' do
+ expect { service.execute }.to change(parent.boards, :count).by(1)
+ end
+
+ it 'delegates the parent board creation to Boards::CreateService' do
+ expect_any_instance_of(Boards::CreateService).to receive(:execute).once
+
+ service.execute
+ end
+ end
+
+ context 'when parent has a board' do
+ before do
+ create(:board, parent: parent)
+ end
+
+ it 'does not create a new board' do
+ expect { service.execute }.not_to change(parent.boards, :count)
+ end
+ end
+
+ it 'returns parent boards' do
+ board = create(:board, parent: parent)
+
+ expect(service.execute).to eq [board]
+ end
+end
diff --git a/spec/support/shared_examples/services/boards/issues_list_service.rb b/spec/support/shared_examples/services/boards/issues_list_service.rb
new file mode 100644
index 00000000000..3e744323cea
--- /dev/null
+++ b/spec/support/shared_examples/services/boards/issues_list_service.rb
@@ -0,0 +1,60 @@
+shared_examples 'issues list service' do
+ it 'delegates search to IssuesFinder' do
+ params = { board_id: board.id, id: list1.id }
+
+ expect_any_instance_of(IssuesFinder).to receive(:execute).once.and_call_original
+
+ described_class.new(parent, user, params).execute
+ end
+
+ context 'issues are ordered by priority' do
+ it 'returns opened issues when list_id is missing' do
+ params = { board_id: board.id }
+
+ issues = described_class.new(parent, user, params).execute
+
+ expect(issues).to eq [opened_issue2, reopened_issue1, opened_issue1]
+ end
+
+ it 'returns opened issues when listing issues from Backlog' do
+ params = { board_id: board.id, id: backlog.id }
+
+ issues = described_class.new(parent, user, params).execute
+
+ expect(issues).to eq [opened_issue2, reopened_issue1, opened_issue1]
+ end
+
+ it 'returns closed issues when listing issues from Closed' do
+ params = { board_id: board.id, id: closed.id }
+
+ issues = described_class.new(parent, user, params).execute
+
+ expect(issues).to eq [closed_issue4, closed_issue2, closed_issue5, closed_issue3, closed_issue1]
+ end
+
+ it 'returns opened issues that have label list applied when listing issues from a label list' do
+ params = { board_id: board.id, id: list1.id }
+
+ issues = described_class.new(parent, user, params).execute
+
+ expect(issues).to eq [list1_issue3, list1_issue1, list1_issue2]
+ end
+ end
+
+ context 'with list that does not belong to the board' do
+ it 'raises an error' do
+ list = create(:list)
+ service = described_class.new(parent, user, board_id: board.id, id: list.id)
+
+ expect { service.execute }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+
+ context 'with invalid list id' do
+ it 'raises an error' do
+ service = described_class.new(parent, user, board_id: board.id, id: nil)
+
+ expect { service.execute }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/services/boards/issues_move_service.rb b/spec/support/shared_examples/services/boards/issues_move_service.rb
new file mode 100644
index 00000000000..4a4fbaa3a0e
--- /dev/null
+++ b/spec/support/shared_examples/services/boards/issues_move_service.rb
@@ -0,0 +1,87 @@
+shared_examples 'issues move service' do
+ 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 'delegates the label changes to Issues::UpdateService' do
+ expect_any_instance_of(Issues::UpdateService).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 '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)
+ expect(issue).to be_closed
+ 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 '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(:issue) { create(:labeled_issue, project: project, labels: [bug, development]) }
+ let(:issue1) { create(:labeled_issue, project: project, labels: [bug, development]) }
+ let(:issue2) { create(:labeled_issue, project: project, labels: [bug, development]) }
+ let(:params) { { board_id: board1.id, from_list_id: list1.id, to_list_id: list1.id } }
+
+ 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 'sorts issues' do
+ [issue, issue1, issue2].each do |issue|
+ issue.move_to_end && issue.save!
+ end
+
+ params.merge!(move_after_id: issue1.id, move_before_id: issue2.id)
+
+ described_class.new(parent, user, params).execute(issue)
+
+ expect(issue.relative_position).to be_between(issue1.relative_position, issue2.relative_position)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/services/boards/lists_destroy_service.rb b/spec/support/shared_examples/services/boards/lists_destroy_service.rb
new file mode 100644
index 00000000000..62b6ffe1836
--- /dev/null
+++ b/spec/support/shared_examples/services/boards/lists_destroy_service.rb
@@ -0,0 +1,30 @@
+shared_examples 'lists destroy service' do
+ context 'when list type is label' do
+ it 'removes list from board' do
+ list = create(:list, board: board)
+ service = described_class.new(parent, user)
+
+ expect { service.execute(list) }.to change(board.lists, :count).by(-1)
+ end
+
+ it 'decrements position of higher lists' do
+ development = create(:list, board: board, position: 0)
+ review = create(:list, board: board, position: 1)
+ staging = create(:list, board: board, position: 2)
+ closed = board.closed_list
+
+ described_class.new(parent, user).execute(development)
+
+ expect(review.reload.position).to eq 0
+ expect(staging.reload.position).to eq 1
+ expect(closed.reload.position).to be_nil
+ end
+ end
+
+ it 'does not remove list from board when list type is closed' do
+ list = board.closed_list
+ service = described_class.new(parent, user)
+
+ expect { service.execute(list) }.not_to change(board.lists, :count)
+ end
+end
diff --git a/spec/support/shared_examples/services/boards/lists_list_service.rb b/spec/support/shared_examples/services/boards/lists_list_service.rb
new file mode 100644
index 00000000000..0a8220111ab
--- /dev/null
+++ b/spec/support/shared_examples/services/boards/lists_list_service.rb
@@ -0,0 +1,23 @@
+shared_examples 'lists list service' do
+ context 'when the board has a backlog list' do
+ let!(:backlog_list) { create(:backlog_list, board: board) }
+
+ it 'does not create a backlog list' do
+ expect { service.execute(board) }.not_to change(board.lists, :count)
+ end
+
+ it "returns board's lists" do
+ expect(service.execute(board)).to eq [backlog_list, list, board.closed_list]
+ end
+ end
+
+ context 'when the board does not have a backlog list' do
+ it 'creates a backlog list' do
+ expect { service.execute(board) }.to change(board.lists, :count).by(1)
+ end
+
+ it "returns board's lists" do
+ expect(service.execute(board)).to eq [board.backlog_list, list, board.closed_list]
+ end
+ end
+end
diff --git a/spec/support/shared_examples/services/boards/lists_move_service.rb b/spec/support/shared_examples/services/boards/lists_move_service.rb
new file mode 100644
index 00000000000..07c98cb29b7
--- /dev/null
+++ b/spec/support/shared_examples/services/boards/lists_move_service.rb
@@ -0,0 +1,93 @@
+shared_examples 'lists move service' do
+ let!(:planning) { create(:list, board: board, position: 0) }
+ let!(:development) { create(:list, board: board, position: 1) }
+ let!(:review) { create(:list, board: board, position: 2) }
+ let!(:staging) { create(:list, board: board, position: 3) }
+ let!(:closed) { create(:closed_list, board: board) }
+
+ context 'when list type is set to label' do
+ it 'keeps position of lists when new position is nil' do
+ service = described_class.new(parent, user, position: nil)
+
+ service.execute(planning)
+
+ expect(current_list_positions).to eq [0, 1, 2, 3]
+ end
+
+ it 'keeps position of lists when new positon is equal to old position' do
+ service = described_class.new(parent, user, position: planning.position)
+
+ service.execute(planning)
+
+ expect(current_list_positions).to eq [0, 1, 2, 3]
+ end
+
+ it 'keeps position of lists when new positon is negative' do
+ service = described_class.new(parent, user, position: -1)
+
+ service.execute(planning)
+
+ expect(current_list_positions).to eq [0, 1, 2, 3]
+ end
+
+ it 'keeps position of lists when new positon is equal to number of labels lists' do
+ service = described_class.new(parent, user, position: board.lists.label.size)
+
+ service.execute(planning)
+
+ expect(current_list_positions).to eq [0, 1, 2, 3]
+ end
+
+ it 'keeps position of lists when new positon is greater than number of labels lists' do
+ service = described_class.new(parent, user, position: board.lists.label.size + 1)
+
+ service.execute(planning)
+
+ expect(current_list_positions).to eq [0, 1, 2, 3]
+ end
+
+ it 'increments position of intermediate lists when new positon is equal to first position' do
+ service = described_class.new(parent, user, position: 0)
+
+ service.execute(staging)
+
+ expect(current_list_positions).to eq [1, 2, 3, 0]
+ end
+
+ it 'decrements position of intermediate lists when new positon is equal to last position' do
+ service = described_class.new(parent, user, position: board.lists.label.last.position)
+
+ service.execute(planning)
+
+ expect(current_list_positions).to eq [3, 0, 1, 2]
+ end
+
+ it 'decrements position of intermediate lists when new position is greater than old position' do
+ service = described_class.new(parent, user, position: 2)
+
+ service.execute(planning)
+
+ expect(current_list_positions).to eq [2, 0, 1, 3]
+ end
+
+ it 'increments position of intermediate lists when new position is lower than old position' do
+ service = described_class.new(parent, user, position: 1)
+
+ service.execute(staging)
+
+ expect(current_list_positions).to eq [0, 2, 3, 1]
+ end
+ end
+
+ it 'keeps position of lists when list type is closed' do
+ service = described_class.new(parent, user, position: 2)
+
+ service.execute(closed)
+
+ expect(current_list_positions).to eq [0, 1, 2, 3]
+ end
+
+ def current_list_positions
+ [planning, development, review, staging].map { |list| list.reload.position }
+ end
+end