summaryrefslogtreecommitdiff
path: root/spec/services/boards
diff options
context:
space:
mode:
Diffstat (limited to 'spec/services/boards')
-rw-r--r--spec/services/boards/create_service_spec.rb35
-rw-r--r--spec/services/boards/issues/list_service_spec.rb73
-rw-r--r--spec/services/boards/issues/move_service_spec.rb140
-rw-r--r--spec/services/boards/lists/create_service_spec.rb54
-rw-r--r--spec/services/boards/lists/destroy_service_spec.rb47
-rw-r--r--spec/services/boards/lists/generate_service_spec.rb40
-rw-r--r--spec/services/boards/lists/move_service_spec.rb110
7 files changed, 499 insertions, 0 deletions
diff --git a/spec/services/boards/create_service_spec.rb b/spec/services/boards/create_service_spec.rb
new file mode 100644
index 00000000000..a1a4dd4c57c
--- /dev/null
+++ b/spec/services/boards/create_service_spec.rb
@@ -0,0 +1,35 @@
+require 'spec_helper'
+
+describe Boards::CreateService, services: true do
+ describe '#execute' do
+ subject(:service) { described_class.new(project, double) }
+
+ context 'when project does not have a board' do
+ let(:project) { create(:empty_project, board: nil) }
+
+ it 'creates a new board' do
+ expect { service.execute }.to change(Board, :count).by(1)
+ end
+
+ it 'creates default lists' do
+ service.execute
+
+ expect(project.board.lists.size).to eq 2
+ expect(project.board.lists.first).to be_backlog
+ expect(project.board.lists.last).to be_done
+ end
+ end
+
+ context 'when project has a board' do
+ let!(:project) { create(:project_with_board) }
+
+ it 'does not create a new board' do
+ expect { service.execute }.not_to change(Board, :count)
+ end
+
+ it 'does not create board lists' do
+ expect { service.execute }.not_to change(project.board.lists, :count)
+ end
+ end
+ end
+end
diff --git a/spec/services/boards/issues/list_service_spec.rb b/spec/services/boards/issues/list_service_spec.rb
new file mode 100644
index 00000000000..f7f45983d26
--- /dev/null
+++ b/spec/services/boards/issues/list_service_spec.rb
@@ -0,0 +1,73 @@
+require 'spec_helper'
+
+describe Boards::Issues::ListService, services: true do
+ describe '#execute' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project_with_board) }
+ let(:board) { project.board }
+
+ let(:bug) { create(:label, project: project, name: 'Bug') }
+ let(:development) { create(:label, project: project, name: 'Development') }
+ let(:testing) { create(:label, project: project, name: 'Testing') }
+ let(:p1) { create(:label, title: 'P1', project: project, priority: 1) }
+ let(:p2) { create(:label, title: 'P2', project: project, priority: 2) }
+ let(:p3) { create(:label, title: 'P3', project: project, priority: 3) }
+
+ let!(:backlog) { create(:backlog_list, board: board) }
+ let!(:list1) { create(:list, board: board, label: development, position: 0) }
+ let!(:list2) { create(:list, board: board, label: testing, position: 1) }
+ let!(:done) { create(:done_list, board: board) }
+
+ let!(:opened_issue1) { create(:labeled_issue, project: project, labels: [bug]) }
+ let!(:opened_issue2) { create(:labeled_issue, project: project, labels: [p2]) }
+ let!(:reopened_issue1) { create(:issue, :reopened, project: project) }
+
+ let!(:list1_issue1) { create(:labeled_issue, project: project, labels: [p2, development]) }
+ let!(:list1_issue2) { create(:labeled_issue, project: project, labels: [development]) }
+ let!(:list1_issue3) { create(:labeled_issue, project: project, labels: [development, p1]) }
+ let!(:list2_issue1) { create(:labeled_issue, project: project, labels: [testing]) }
+
+ let!(:closed_issue1) { create(:labeled_issue, :closed, project: project, labels: [bug]) }
+ let!(:closed_issue2) { create(:labeled_issue, :closed, project: project, labels: [p3]) }
+ let!(:closed_issue3) { create(:issue, :closed, project: project) }
+ let!(:closed_issue4) { create(:labeled_issue, :closed, project: project, labels: [p1]) }
+
+ before do
+ project.team << [user, :developer]
+ end
+
+ it 'delegates search to IssuesFinder' do
+ params = { id: list1.id }
+
+ expect_any_instance_of(IssuesFinder).to receive(:execute).once.and_call_original
+
+ described_class.new(project, user, params).execute
+ end
+
+ context 'sets default order to priority' do
+ it 'returns opened issues when listing issues from Backlog' do
+ params = { id: backlog.id }
+
+ issues = described_class.new(project, user, params).execute
+
+ expect(issues).to eq [opened_issue2, reopened_issue1, opened_issue1]
+ end
+
+ it 'returns closed issues when listing issues from Done' do
+ params = { id: done.id }
+
+ issues = described_class.new(project, user, params).execute
+
+ expect(issues).to eq [closed_issue4, closed_issue2, closed_issue3, closed_issue1]
+ end
+
+ it 'returns opened issues that have label list applied when listing issues from a label list' do
+ params = { id: list1.id }
+
+ issues = described_class.new(project, user, params).execute
+
+ expect(issues).to eq [list1_issue3, list1_issue1, list1_issue2]
+ end
+ end
+ end
+end
diff --git a/spec/services/boards/issues/move_service_spec.rb b/spec/services/boards/issues/move_service_spec.rb
new file mode 100644
index 00000000000..0122159cab8
--- /dev/null
+++ b/spec/services/boards/issues/move_service_spec.rb
@@ -0,0 +1,140 @@
+require 'spec_helper'
+
+describe Boards::Issues::MoveService, services: true do
+ describe '#execute' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project_with_board) }
+ let(:board) { project.board }
+
+ let(:bug) { create(:label, project: project, name: 'Bug') }
+ let(:development) { create(:label, project: project, name: 'Development') }
+ let(:testing) { create(:label, project: project, name: 'Testing') }
+
+ let!(:backlog) { create(:backlog_list, board: board) }
+ let!(:list1) { create(:list, board: board, label: development, position: 0) }
+ let!(:list2) { create(:list, board: board, label: testing, position: 1) }
+ let!(:done) { create(:done_list, board: board) }
+
+ before do
+ project.team << [user, :developer]
+ end
+
+ context 'when moving from backlog' do
+ it 'adds the label of the list it goes to' do
+ issue = create(:labeled_issue, project: project, labels: [bug])
+ params = { from_list_id: backlog.id, to_list_id: list1.id }
+
+ described_class.new(project, user, params).execute(issue)
+
+ expect(issue.reload.labels).to contain_exactly(bug, development)
+ end
+ end
+
+ context 'when moving to backlog' do
+ it 'removes all list-labels' do
+ issue = create(:labeled_issue, project: project, labels: [bug, development, testing])
+ params = { from_list_id: list1.id, to_list_id: backlog.id }
+
+ described_class.new(project, user, params).execute(issue)
+
+ expect(issue.reload.labels).to contain_exactly(bug)
+ end
+ end
+
+ context 'when moving from backlog to done' do
+ it 'closes the issue' do
+ issue = create(:labeled_issue, project: project, labels: [bug])
+ params = { from_list_id: backlog.id, to_list_id: done.id }
+
+ described_class.new(project, user, params).execute(issue)
+ issue.reload
+
+ expect(issue.labels).to contain_exactly(bug)
+ expect(issue).to be_closed
+ end
+ end
+
+ context 'when moving an issue between lists' do
+ let(:issue) { create(:labeled_issue, project: project, labels: [bug, development]) }
+ let(:params) { { 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(project, 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(project, user, params).execute(issue)
+
+ expect(issue.reload.labels).to contain_exactly(bug, testing)
+ end
+ end
+
+ context 'when moving to done' do
+ let(:issue) { create(:labeled_issue, project: project, labels: [bug, development, testing]) }
+ let(:params) { { from_list_id: list2.id, to_list_id: done.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(project, user, params).execute(issue)
+ end
+
+ it 'removes all list-labels and close the issue' do
+ described_class.new(project, user, params).execute(issue)
+ issue.reload
+
+ expect(issue.labels).to contain_exactly(bug)
+ expect(issue).to be_closed
+ end
+ end
+
+ context 'when moving from done' do
+ let(:issue) { create(:labeled_issue, :closed, project: project, labels: [bug]) }
+ let(:params) { { from_list_id: done.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(project, user, params).execute(issue)
+ end
+
+ it 'adds the label of the list it goes to and reopen the issue' do
+ described_class.new(project, user, params).execute(issue)
+ issue.reload
+
+ expect(issue.labels).to contain_exactly(bug, testing)
+ expect(issue).to be_reopened
+ end
+ end
+
+ context 'when moving from done to backlog' do
+ it 'reopens the issue' do
+ issue = create(:labeled_issue, :closed, project: project, labels: [bug])
+ params = { from_list_id: done.id, to_list_id: backlog.id }
+
+ described_class.new(project, user, params).execute(issue)
+ issue.reload
+
+ expect(issue.labels).to contain_exactly(bug)
+ expect(issue).to be_reopened
+ end
+ end
+
+ context 'when moving to same list' do
+ let(:issue) { create(:labeled_issue, project: project, labels: [bug, development]) }
+ let(:params) { { from_list_id: list1.id, to_list_id: list1.id } }
+
+ it 'returns false' do
+ expect(described_class.new(project, user, params).execute(issue)).to eq false
+ end
+
+ it 'keeps issues labels' do
+ described_class.new(project, user, params).execute(issue)
+
+ expect(issue.reload.labels).to contain_exactly(bug, development)
+ end
+ end
+ end
+end
diff --git a/spec/services/boards/lists/create_service_spec.rb b/spec/services/boards/lists/create_service_spec.rb
new file mode 100644
index 00000000000..5e7e145065e
--- /dev/null
+++ b/spec/services/boards/lists/create_service_spec.rb
@@ -0,0 +1,54 @@
+require 'spec_helper'
+
+describe Boards::Lists::CreateService, services: true do
+ describe '#execute' do
+ let(:project) { create(:project_with_board) }
+ let(:board) { project.board }
+ let(:user) { create(:user) }
+ let(:label) { create(:label, name: 'in-progress') }
+
+ subject(:service) { described_class.new(project, user, label_id: label.id) }
+
+ context 'when board lists is empty' do
+ it 'creates a new list at beginning of the list' do
+ list = service.execute
+
+ expect(list.position).to eq 0
+ end
+ end
+
+ context 'when board lists has only a backlog list' do
+ it 'creates a new list at beginning of the list' do
+ create(:backlog_list, board: board)
+
+ list = service.execute
+
+ expect(list.position).to eq 0
+ end
+ end
+
+ context 'when board lists has only labels lists' do
+ it 'creates a new list at end of the lists' do
+ create(:list, board: board, position: 0)
+ create(:list, board: board, position: 1)
+
+ list = service.execute
+
+ expect(list.position).to eq 2
+ end
+ end
+
+ context 'when board lists has backlog, label and done lists' do
+ it 'creates a new list at end of the label lists' do
+ create(:backlog_list, board: board)
+ create(:done_list, board: board)
+ list1 = create(:list, board: board, position: 0)
+
+ list2 = service.execute
+
+ expect(list1.reload.position).to eq 0
+ expect(list2.reload.position).to eq 1
+ end
+ end
+ end
+end
diff --git a/spec/services/boards/lists/destroy_service_spec.rb b/spec/services/boards/lists/destroy_service_spec.rb
new file mode 100644
index 00000000000..6eff445feee
--- /dev/null
+++ b/spec/services/boards/lists/destroy_service_spec.rb
@@ -0,0 +1,47 @@
+require 'spec_helper'
+
+describe Boards::Lists::DestroyService, services: true do
+ describe '#execute' do
+ let(:project) { create(:project_with_board) }
+ let(:board) { project.board }
+ let(:user) { create(:user) }
+
+ context 'when list type is label' do
+ it 'removes list from board' do
+ list = create(:list, board: board)
+ service = described_class.new(project, user)
+
+ expect { service.execute(list) }.to change(board.lists, :count).by(-1)
+ end
+
+ it 'decrements position of higher lists' do
+ backlog = create(:backlog_list, board: board)
+ development = create(:list, board: board, position: 0)
+ review = create(:list, board: board, position: 1)
+ staging = create(:list, board: board, position: 2)
+ done = create(:done_list, board: board)
+
+ described_class.new(project, user).execute(development)
+
+ expect(backlog.reload.position).to be_nil
+ expect(review.reload.position).to eq 0
+ expect(staging.reload.position).to eq 1
+ expect(done.reload.position).to be_nil
+ end
+ end
+
+ it 'does not remove list from board when list type is backlog' do
+ list = create(:backlog_list, board: board)
+ service = described_class.new(project, user)
+
+ expect { service.execute(list) }.not_to change(board.lists, :count)
+ end
+
+ it 'does not remove list from board when list type is done' do
+ list = create(:done_list, board: board)
+ service = described_class.new(project, user)
+
+ expect { service.execute(list) }.not_to change(board.lists, :count)
+ end
+ end
+end
diff --git a/spec/services/boards/lists/generate_service_spec.rb b/spec/services/boards/lists/generate_service_spec.rb
new file mode 100644
index 00000000000..9fd39122737
--- /dev/null
+++ b/spec/services/boards/lists/generate_service_spec.rb
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+describe Boards::Lists::GenerateService, services: true do
+ describe '#execute' do
+ let(:project) { create(:project_with_board) }
+ let(:board) { project.board }
+ let(:user) { create(:user) }
+
+ subject(:service) { described_class.new(project, user) }
+
+ context 'when board lists is empty' do
+ it 'creates the default lists' do
+ expect { service.execute }.to change(board.lists, :count).by(4)
+ end
+ end
+
+ context 'when board lists is not empty' do
+ it 'does not creates the default lists' do
+ create(:list, board: board)
+
+ expect { service.execute }.not_to change(board.lists, :count)
+ end
+ end
+
+ context 'when project labels does not contains any list label' do
+ it 'creates labels' do
+ expect { service.execute }.to change(project.labels, :count).by(4)
+ end
+ end
+
+ context 'when project labels contains some of list label' do
+ it 'creates the missing labels' do
+ create(:label, project: project, name: 'Development')
+ create(:label, project: project, name: 'Ready')
+
+ expect { service.execute }.to change(project.labels, :count).by(2)
+ end
+ end
+ end
+end
diff --git a/spec/services/boards/lists/move_service_spec.rb b/spec/services/boards/lists/move_service_spec.rb
new file mode 100644
index 00000000000..3e9b7d07fc6
--- /dev/null
+++ b/spec/services/boards/lists/move_service_spec.rb
@@ -0,0 +1,110 @@
+require 'spec_helper'
+
+describe Boards::Lists::MoveService, services: true do
+ describe '#execute' do
+ let(:project) { create(:project_with_board) }
+ let(:board) { project.board }
+ let(:user) { create(:user) }
+
+ let!(:backlog) { create(:backlog_list, board: board) }
+ 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!(:done) { create(:done_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(project, 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(project, 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(project, 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(project, 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(project, 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(project, 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(project, 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(project, 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(project, 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 backlog' do
+ service = described_class.new(project, user, position: 2)
+
+ service.execute(backlog)
+
+ expect(current_list_positions).to eq [0, 1, 2, 3]
+ end
+
+ it 'keeps position of lists when list type is done' do
+ service = described_class.new(project, user, position: 2)
+
+ service.execute(done)
+
+ expect(current_list_positions).to eq [0, 1, 2, 3]
+ end
+ end
+
+ def current_list_positions
+ [planning, development, review, staging].map { |list| list.reload.position }
+ end
+end