diff options
Diffstat (limited to 'spec/services/boards')
-rw-r--r-- | spec/services/boards/create_service_spec.rb | 35 | ||||
-rw-r--r-- | spec/services/boards/issues/list_service_spec.rb | 73 | ||||
-rw-r--r-- | spec/services/boards/issues/move_service_spec.rb | 140 | ||||
-rw-r--r-- | spec/services/boards/lists/create_service_spec.rb | 54 | ||||
-rw-r--r-- | spec/services/boards/lists/destroy_service_spec.rb | 47 | ||||
-rw-r--r-- | spec/services/boards/lists/generate_service_spec.rb | 40 | ||||
-rw-r--r-- | spec/services/boards/lists/move_service_spec.rb | 110 |
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 |