summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean McGivern <sean@mcgivern.me.uk>2016-10-13 14:21:14 +0000
committerSean McGivern <sean@mcgivern.me.uk>2016-10-13 14:21:14 +0000
commit11e93ad59d6209bf9805a6f7053719e8052cc508 (patch)
tree0770038bcfb327e45381e8f45ba6629c02a09f12
parent36dafbbb02201ad36ca7e59f699cbf727494129e (diff)
parent25c82c6faf067a82e99bad590357ad57618475d9 (diff)
downloadgitlab-ce-11e93ad59d6209bf9805a6f7053719e8052cc508.tar.gz
Merge branch 'feature/issues-board' into 'master'
Refactoring Issues Board ## What does this MR do? This MR aims to minimize conflicts between the CE issues board feature with EE multiple boards feature. ## Are there points in the code the reviewer needs to double check? ## Why was this MR needed? To avoid a lot of conflicts with EE multiple boards feature. ## Screenshots (if relevant) ## Does this MR meet the acceptance criteria? - [ ] ~~[CHANGELOG](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG) entry added~~ - [ ] ~~[Documentation created/updated](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/doc_styleguide.md)~~ - [x] API support added - Tests - [X] Added for this feature/bug - [ ] All builds are passing - [x] Conform by the [merge request performance guides](http://docs.gitlab.com/ce/development/merge_request_performance_guidelines.html) - [X] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#style-guides) - [ ] Branch has no merge conflicts with `master` (if you do - rebase it please) - [x] [Squashed related commits together](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits) ## What are the relevant issue numbers? https://gitlab.com/gitlab-org/gitlab-ee/issues/929 https://gitlab.com/gitlab-org/gitlab-ee/issues/1084 See merge request !6727
-rw-r--r--app/assets/javascripts/boards/boards_bundle.js.es63
-rw-r--r--app/assets/javascripts/boards/services/board_service.js.es610
-rw-r--r--app/assets/javascripts/dispatcher.js1
-rw-r--r--app/assets/javascripts/labels_select.js4
-rw-r--r--app/assets/javascripts/milestone_select.js2
-rw-r--r--app/assets/javascripts/users_select.js2
-rw-r--r--app/controllers/projects/board_lists_controller.rb65
-rw-r--r--app/controllers/projects/boards/issues_controller.rb9
-rw-r--r--app/controllers/projects/boards/lists_controller.rb18
-rw-r--r--app/controllers/projects/boards_controller.rb28
-rw-r--r--app/helpers/boards_helper.rb12
-rw-r--r--app/models/project.rb10
-rw-r--r--app/services/boards/base_service.rb5
-rw-r--r--app/services/boards/create_service.rb17
-rw-r--r--app/services/boards/issues/create_service.rb17
-rw-r--r--app/services/boards/issues/list_service.rb6
-rw-r--r--app/services/boards/issues/move_service.rb8
-rw-r--r--app/services/boards/list_service.rb14
-rw-r--r--app/services/boards/lists/create_service.rb12
-rw-r--r--app/services/boards/lists/destroy_service.rb6
-rw-r--r--app/services/boards/lists/generate_service.rb10
-rw-r--r--app/services/boards/lists/list_service.rb9
-rw-r--r--app/services/boards/lists/move_service.rb5
-rw-r--r--app/views/layouts/nav/_project.html.haml2
-rw-r--r--app/views/projects/boards/index.html.haml16
-rw-r--r--app/views/projects/boards/show.html.haml5
-rw-r--r--app/views/projects/issues/_head.html.haml2
-rw-r--r--config/routes/project.rb2
-rw-r--r--lib/api/boards.rb31
-rw-r--r--spec/controllers/projects/boards/issues_controller_spec.rb66
-rw-r--r--spec/controllers/projects/boards/lists_controller_spec.rb61
-rw-r--r--spec/controllers/projects/boards_controller_spec.rb84
-rw-r--r--spec/factories/boards.rb5
-rw-r--r--spec/factories/projects.rb8
-rw-r--r--spec/features/boards/boards_spec.rb21
-rw-r--r--spec/features/boards/keyboard_shortcut_spec.rb4
-rw-r--r--spec/features/boards/new_issue_spec.rb7
-rw-r--r--spec/fixtures/api/schemas/board.json11
-rw-r--r--spec/fixtures/api/schemas/boards.json4
-rw-r--r--spec/javascripts/boards/boards_store_spec.js.es62
-rw-r--r--spec/javascripts/boards/issue_spec.js.es62
-rw-r--r--spec/javascripts/boards/list_spec.js.es62
-rw-r--r--spec/javascripts/boards/mock_data.js.es68
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml2
-rw-r--r--spec/models/project_spec.rb11
-rw-r--r--spec/services/boards/create_service_spec.rb22
-rw-r--r--spec/services/boards/issues/create_service_spec.rb12
-rw-r--r--spec/services/boards/issues/list_service_spec.rb33
-rw-r--r--spec/services/boards/issues/move_service_spec.rb36
-rw-r--r--spec/services/boards/list_service_spec.rb37
-rw-r--r--spec/services/boards/lists/create_service_spec.rb14
-rw-r--r--spec/services/boards/lists/destroy_service_spec.rb12
-rw-r--r--spec/services/boards/lists/generate_service_spec.rb12
-rw-r--r--spec/services/boards/lists/list_service_spec.rb16
-rw-r--r--spec/services/boards/lists/move_service_spec.rb8
55 files changed, 528 insertions, 303 deletions
diff --git a/app/assets/javascripts/boards/boards_bundle.js.es6 b/app/assets/javascripts/boards/boards_bundle.js.es6
index 91c12570e09..d4f8f4b9420 100644
--- a/app/assets/javascripts/boards/boards_bundle.js.es6
+++ b/app/assets/javascripts/boards/boards_bundle.js.es6
@@ -28,12 +28,13 @@ $(() => {
state: Store.state,
loading: true,
endpoint: $boardApp.dataset.endpoint,
+ boardId: $boardApp.dataset.boardId,
disabled: $boardApp.dataset.disabled === 'true',
issueLinkBase: $boardApp.dataset.issueLinkBase
},
init: Store.create.bind(Store),
created () {
- gl.boardService = new BoardService(this.endpoint);
+ gl.boardService = new BoardService(this.endpoint, this.boardId);
},
ready () {
Store.disabled = this.disabled;
diff --git a/app/assets/javascripts/boards/services/board_service.js.es6 b/app/assets/javascripts/boards/services/board_service.js.es6
index 2b825c3949f..b9c91cbf31e 100644
--- a/app/assets/javascripts/boards/services/board_service.js.es6
+++ b/app/assets/javascripts/boards/services/board_service.js.es6
@@ -1,15 +1,15 @@
class BoardService {
- constructor (root) {
+ constructor (root, boardId) {
Vue.http.options.root = root;
- this.lists = Vue.resource(`${root}/lists{/id}`, {}, {
+ this.lists = Vue.resource(`${root}/${boardId}/lists{/id}`, {}, {
generate: {
method: 'POST',
- url: `${root}/lists/generate.json`
+ url: `${root}/${boardId}/lists/generate.json`
}
});
- this.issue = Vue.resource(`${root}/issues{/id}`, {});
- this.issues = Vue.resource(`${root}/lists{/id}/issues`, {});
+ this.issue = Vue.resource(`${root}/${boardId}/issues{/id}`, {});
+ this.issues = Vue.resource(`${root}/${boardId}/lists{/id}/issues`, {});
Vue.http.interceptors.push((request, next) => {
request.headers['X-CSRF-Token'] = $.rails.csrfToken();
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index adff73af79c..f3ef13ce20e 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -21,6 +21,7 @@
shortcut_handler = null;
switch (page) {
case 'projects:boards:show':
+ case 'projects:boards:index':
shortcut_handler = new ShortcutsNavigation();
break;
case 'projects:merge_requests:index':
diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js
index e356872624a..f1e719937c7 100644
--- a/app/assets/javascripts/labels_select.js
+++ b/app/assets/javascripts/labels_select.js
@@ -292,7 +292,7 @@
return;
}
- if (page === 'projects:boards:show') {
+ if ($('html').hasClass('issue-boards-page')) {
return;
}
if ($dropdown.hasClass('js-multiselect')) {
@@ -334,7 +334,7 @@
page = $('body').data('page');
isIssueIndex = page === 'projects:issues:index';
isMRIndex = page === 'projects:merge_requests:index';
- if (page === 'projects:boards:show') {
+ if ($('html').hasClass('issue-boards-page')) {
if (label.isAny) {
gl.issueBoards.BoardsStore.state.filters['label_name'] = [];
}
diff --git a/app/assets/javascripts/milestone_select.js b/app/assets/javascripts/milestone_select.js
index 26cc6eb0e96..cee42633c79 100644
--- a/app/assets/javascripts/milestone_select.js
+++ b/app/assets/javascripts/milestone_select.js
@@ -110,7 +110,7 @@
e.preventDefault();
return;
}
- if (page === 'projects:boards:show') {
+ if ($('html').hasClass('issue-boards-page')) {
gl.issueBoards.BoardsStore.state.filters[$dropdown.data('field-name')] = selected.name;
gl.issueBoards.BoardsStore.updateFiltersUrl();
e.preventDefault();
diff --git a/app/assets/javascripts/users_select.js b/app/assets/javascripts/users_select.js
index d966277a8b2..6aa0e1cd2b6 100644
--- a/app/assets/javascripts/users_select.js
+++ b/app/assets/javascripts/users_select.js
@@ -160,7 +160,7 @@
selectedId = user.id;
return;
}
- if (page === 'projects:boards:show') {
+ if ($('html').hasClass('issue-boards-page')) {
selectedId = user.id;
gl.issueBoards.BoardsStore.state.filters[$dropdown.data('field-name')] = user.id;
gl.issueBoards.BoardsStore.updateFiltersUrl();
diff --git a/app/controllers/projects/board_lists_controller.rb b/app/controllers/projects/board_lists_controller.rb
deleted file mode 100644
index 3cfb08d5822..00000000000
--- a/app/controllers/projects/board_lists_controller.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-class Projects::BoardListsController < Projects::ApplicationController
- respond_to :json
-
- before_action :authorize_admin_list!
-
- rescue_from ActiveRecord::RecordNotFound, with: :record_not_found
-
- def create
- list = Boards::Lists::CreateService.new(project, current_user, list_params).execute
-
- if list.valid?
- render json: list.as_json(only: [:id, :list_type, :position], methods: [:title], include: { label: { only: [:id, :title, :description, :color, :priority] } })
- else
- render json: list.errors, status: :unprocessable_entity
- end
- end
-
- def update
- service = Boards::Lists::MoveService.new(project, current_user, move_params)
-
- if service.execute
- head :ok
- else
- head :unprocessable_entity
- end
- end
-
- def destroy
- service = Boards::Lists::DestroyService.new(project, current_user, params)
-
- if service.execute
- head :ok
- else
- head :unprocessable_entity
- end
- end
-
- def generate
- service = Boards::Lists::GenerateService.new(project, current_user)
-
- if service.execute
- render json: project.board.lists.label.as_json(only: [:id, :list_type, :position], methods: [:title], include: { label: { only: [:id, :title, :description, :color, :priority] } })
- else
- head :unprocessable_entity
- end
- end
-
- private
-
- def authorize_admin_list!
- return render_403 unless can?(current_user, :admin_list, project)
- end
-
- def list_params
- params.require(:list).permit(:label_id)
- end
-
- def move_params
- params.require(:list).permit(:position).merge(id: params[:id])
- end
-
- def record_not_found(exception)
- render json: { error: exception.message }, status: :not_found
- end
-end
diff --git a/app/controllers/projects/boards/issues_controller.rb b/app/controllers/projects/boards/issues_controller.rb
index 095af6c35eb..71eb56aed0b 100644
--- a/app/controllers/projects/boards/issues_controller.rb
+++ b/app/controllers/projects/boards/issues_controller.rb
@@ -16,9 +16,8 @@ module Projects
end
def create
- list = project.board.lists.find(params[:list_id])
service = ::Boards::Issues::CreateService.new(project, current_user, issue_params)
- issue = service.execute(list)
+ issue = service.execute
if issue.valid?
render json: serialize_as_json(issue)
@@ -60,15 +59,15 @@ module Projects
end
def filter_params
- params.merge(id: params[:list_id])
+ params.merge(board_id: params[:board_id], id: params[:list_id])
end
def move_params
- params.permit(:id, :from_list_id, :to_list_id)
+ params.permit(:board_id, :id, :from_list_id, :to_list_id)
end
def issue_params
- params.require(:issue).permit(:title).merge(request: request)
+ params.require(:issue).permit(:title).merge(board_id: params[:board_id], list_id: params[:list_id], request: request)
end
def serialize_as_json(resource)
diff --git a/app/controllers/projects/boards/lists_controller.rb b/app/controllers/projects/boards/lists_controller.rb
index b995f586737..76ae41319c4 100644
--- a/app/controllers/projects/boards/lists_controller.rb
+++ b/app/controllers/projects/boards/lists_controller.rb
@@ -5,11 +5,11 @@ module Projects
before_action :authorize_read_list!, only: [:index]
def index
- render json: serialize_as_json(project.board.lists)
+ render json: serialize_as_json(board.lists)
end
def create
- list = ::Boards::Lists::CreateService.new(project, current_user, list_params).execute
+ list = ::Boards::Lists::CreateService.new(project, current_user, list_params).execute(board)
if list.valid?
render json: serialize_as_json(list)
@@ -19,7 +19,7 @@ module Projects
end
def update
- list = project.board.lists.movable.find(params[:id])
+ list = board.lists.movable.find(params[:id])
service = ::Boards::Lists::MoveService.new(project, current_user, move_params)
if service.execute(list)
@@ -30,8 +30,8 @@ module Projects
end
def destroy
- list = project.board.lists.destroyable.find(params[:id])
- service = ::Boards::Lists::DestroyService.new(project, current_user, params)
+ list = board.lists.destroyable.find(params[:id])
+ service = ::Boards::Lists::DestroyService.new(project, current_user)
if service.execute(list)
head :ok
@@ -43,8 +43,8 @@ module Projects
def generate
service = ::Boards::Lists::GenerateService.new(project, current_user)
- if service.execute
- render json: serialize_as_json(project.board.lists.movable)
+ if service.execute(board)
+ render json: serialize_as_json(board.lists.movable)
else
head :unprocessable_entity
end
@@ -60,6 +60,10 @@ module Projects
return render_403 unless can?(current_user, :read_list, project)
end
+ def board
+ @board ||= project.boards.find(params[:board_id])
+ end
+
def list_params
params.require(:list).permit(:label_id)
end
diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb
index 0035633b774..808affa4f98 100644
--- a/app/controllers/projects/boards_controller.rb
+++ b/app/controllers/projects/boards_controller.rb
@@ -1,12 +1,28 @@
class Projects::BoardsController < Projects::ApplicationController
include IssuableCollections
-
- respond_to :html
- before_action :authorize_read_board!, only: [:show]
+ before_action :authorize_read_board!, only: [:index, :show]
+
+ def index
+ @boards = ::Boards::ListService.new(project, current_user).execute
+
+ respond_to do |format|
+ format.html
+ format.json do
+ render json: serialize_as_json(@boards)
+ end
+ end
+ end
def show
- ::Boards::CreateService.new(project, current_user).execute
+ @board = project.boards.find(params[:id])
+
+ respond_to do |format|
+ format.html
+ format.json do
+ render json: serialize_as_json(@board)
+ end
+ end
end
private
@@ -14,4 +30,8 @@ class Projects::BoardsController < Projects::ApplicationController
def authorize_read_board!
return access_denied! unless can?(current_user, :read_board, project)
end
+
+ def serialize_as_json(resource)
+ resource.as_json(only: [:id])
+ end
end
diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb
new file mode 100644
index 00000000000..b7247ffa8b2
--- /dev/null
+++ b/app/helpers/boards_helper.rb
@@ -0,0 +1,12 @@
+module BoardsHelper
+ def board_data
+ board = @board || @boards.first
+
+ {
+ endpoint: namespace_project_boards_path(@project.namespace, @project),
+ board_id: board.id,
+ disabled: !can?(current_user, :admin_list, @project),
+ issue_link_base: namespace_project_issues_path(@project.namespace, @project)
+ }
+ end
+end
diff --git a/app/models/project.rb b/app/models/project.rb
index 74d54e69648..758927edd5c 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -16,6 +16,9 @@ class Project < ActiveRecord::Base
extend Gitlab::ConfigHelper
+ class BoardLimitExceeded < StandardError; end
+
+ NUMBER_OF_PERMITTED_BOARDS = 1
UNKNOWN_IMPORT_URL = 'http://unknown.git'
cache_markdown_field :description, pipeline: :description
@@ -65,8 +68,7 @@ class Project < ActiveRecord::Base
belongs_to :namespace
has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event', foreign_key: 'project_id'
-
- has_one :board, dependent: :destroy
+ has_many :boards, before_add: :validate_board_limit, dependent: :destroy
# Project services
has_many :services
@@ -1339,4 +1341,8 @@ class Project < ActiveRecord::Base
shared_projects.any?
end
+
+ def validate_board_limit(board)
+ raise BoardLimitExceeded, 'Number of permitted boards exceeded' if boards.size >= NUMBER_OF_PERMITTED_BOARDS
+ end
end
diff --git a/app/services/boards/base_service.rb b/app/services/boards/base_service.rb
deleted file mode 100644
index b2069ca825a..00000000000
--- a/app/services/boards/base_service.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-module Boards
- class BaseService < ::BaseService
- delegate :board, to: :project
- end
-end
diff --git a/app/services/boards/create_service.rb b/app/services/boards/create_service.rb
index 072a0749285..9bdd7b6f0cf 100644
--- a/app/services/boards/create_service.rb
+++ b/app/services/boards/create_service.rb
@@ -1,16 +1,21 @@
module Boards
- class CreateService < Boards::BaseService
+ class CreateService < BaseService
def execute
- create_board! unless project.board.present?
- project.board
+ if project.boards.empty?
+ create_board!
+ else
+ project.boards.first
+ end
end
private
def create_board!
- project.create_board
- project.board.lists.create(list_type: :backlog)
- project.board.lists.create(list_type: :done)
+ board = project.boards.create
+ board.lists.create(list_type: :backlog)
+ board.lists.create(list_type: :done)
+
+ board
end
end
end
diff --git a/app/services/boards/issues/create_service.rb b/app/services/boards/issues/create_service.rb
index 3701afd441f..c0d7ff5b585 100644
--- a/app/services/boards/issues/create_service.rb
+++ b/app/services/boards/issues/create_service.rb
@@ -1,14 +1,21 @@
module Boards
module Issues
- class CreateService < Boards::BaseService
- def execute(list)
- params.merge!(label_ids: [list.label_id])
- create_issue
+ class CreateService < BaseService
+ def execute
+ create_issue(params.merge(label_ids: [list.label_id]))
end
private
- def create_issue
+ def board
+ @board ||= project.boards.find(params.delete(:board_id))
+ end
+
+ def list
+ @list ||= board.lists.find(params.delete(:list_id))
+ end
+
+ def create_issue(params)
::Issues::CreateService.new(project, current_user, params).execute
end
end
diff --git a/app/services/boards/issues/list_service.rb b/app/services/boards/issues/list_service.rb
index 435a8c6e681..fd4a462c7b2 100644
--- a/app/services/boards/issues/list_service.rb
+++ b/app/services/boards/issues/list_service.rb
@@ -1,6 +1,6 @@
module Boards
module Issues
- class ListService < Boards::BaseService
+ class ListService < BaseService
def execute
issues = IssuesFinder.new(current_user, filter_params).execute
issues = without_board_labels(issues) unless list.movable?
@@ -10,6 +10,10 @@ module Boards
private
+ def board
+ @board ||= project.boards.find(params[:board_id])
+ end
+
def list
@list ||= board.lists.find(params[:id])
end
diff --git a/app/services/boards/issues/move_service.rb b/app/services/boards/issues/move_service.rb
index 84dc3f70e76..96554a92a02 100644
--- a/app/services/boards/issues/move_service.rb
+++ b/app/services/boards/issues/move_service.rb
@@ -1,6 +1,6 @@
module Boards
module Issues
- class MoveService < Boards::BaseService
+ class MoveService < BaseService
def execute(issue)
return false unless can?(current_user, :update_issue, issue)
return false unless valid_move?
@@ -10,6 +10,10 @@ module Boards
private
+ def board
+ @board ||= project.boards.find(params[:board_id])
+ end
+
def valid_move?
moving_from_list.present? && moving_to_list.present? &&
moving_from_list != moving_to_list
@@ -49,7 +53,7 @@ module Boards
if moving_to_list.movable?
moving_from_list.label_id
else
- board.lists.movable.pluck(:label_id)
+ project.boards.joins(:lists).merge(List.movable).pluck(:label_id)
end
Array(label_ids).compact
diff --git a/app/services/boards/list_service.rb b/app/services/boards/list_service.rb
new file mode 100644
index 00000000000..84f1fc3a4e2
--- /dev/null
+++ b/app/services/boards/list_service.rb
@@ -0,0 +1,14 @@
+module Boards
+ class ListService < BaseService
+ def execute
+ create_board! if project.boards.empty?
+ project.boards
+ end
+
+ private
+
+ def create_board!
+ Boards::CreateService.new(project, current_user).execute
+ end
+ end
+end
diff --git a/app/services/boards/lists/create_service.rb b/app/services/boards/lists/create_service.rb
index b1887820bd4..abc7aeece39 100644
--- a/app/services/boards/lists/create_service.rb
+++ b/app/services/boards/lists/create_service.rb
@@ -1,23 +1,23 @@
module Boards
module Lists
- class CreateService < Boards::BaseService
- def execute
+ class CreateService < BaseService
+ def execute(board)
List.transaction do
label = project.labels.find(params[:label_id])
- position = next_position
+ position = next_position(board)
- create_list(label, position)
+ create_list(board, label, position)
end
end
private
- def next_position
+ def next_position(board)
max_position = board.lists.movable.maximum(:position)
max_position.nil? ? 0 : max_position.succ
end
- def create_list(label, position)
+ def create_list(board, label, position)
board.lists.create(label: label, list_type: :label, position: position)
end
end
diff --git a/app/services/boards/lists/destroy_service.rb b/app/services/boards/lists/destroy_service.rb
index 25da3bfb56d..f986e05944c 100644
--- a/app/services/boards/lists/destroy_service.rb
+++ b/app/services/boards/lists/destroy_service.rb
@@ -1,9 +1,11 @@
module Boards
module Lists
- class DestroyService < Boards::BaseService
+ class DestroyService < BaseService
def execute(list)
return false unless list.destroyable?
+ @board = list.board
+
list.with_lock do
decrement_higher_lists(list)
remove_list(list)
@@ -12,6 +14,8 @@ module Boards
private
+ attr_reader :board
+
def decrement_higher_lists(list)
board.lists.movable.where('position > ?', list.position)
.update_all('position = position - 1')
diff --git a/app/services/boards/lists/generate_service.rb b/app/services/boards/lists/generate_service.rb
index 830e386c98b..d8048f1c67e 100644
--- a/app/services/boards/lists/generate_service.rb
+++ b/app/services/boards/lists/generate_service.rb
@@ -1,11 +1,11 @@
module Boards
module Lists
- class GenerateService < Boards::BaseService
- def execute
+ class GenerateService < BaseService
+ def execute(board)
return false unless board.lists.movable.empty?
List.transaction do
- label_params.each { |params| create_list(params) }
+ label_params.each { |params| create_list(board, params) }
end
true
@@ -13,9 +13,9 @@ module Boards
private
- def create_list(params)
+ def create_list(board, params)
label = find_or_create_label(params)
- Lists::CreateService.new(project, current_user, label_id: label.id).execute
+ Lists::CreateService.new(project, current_user, label_id: label.id).execute(board)
end
def find_or_create_label(params)
diff --git a/app/services/boards/lists/list_service.rb b/app/services/boards/lists/list_service.rb
new file mode 100644
index 00000000000..c579ed4c869
--- /dev/null
+++ b/app/services/boards/lists/list_service.rb
@@ -0,0 +1,9 @@
+module Boards
+ module Lists
+ class ListService < BaseService
+ def execute(board)
+ board.lists
+ end
+ end
+ end
+end
diff --git a/app/services/boards/lists/move_service.rb b/app/services/boards/lists/move_service.rb
index 020ff69f4a7..f2a68865f7b 100644
--- a/app/services/boards/lists/move_service.rb
+++ b/app/services/boards/lists/move_service.rb
@@ -1,7 +1,8 @@
module Boards
module Lists
- class MoveService < Boards::BaseService
+ class MoveService < BaseService
def execute(list)
+ @board = list.board
@old_position = list.position
@new_position = params[:position]
@@ -16,7 +17,7 @@ module Boards
private
- attr_reader :old_position, :new_position
+ attr_reader :board, :old_position, :new_position
def valid_move?
new_position.present? && new_position != old_position &&
diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml
index e44a2bfed9d..99a58bbb676 100644
--- a/app/views/layouts/nav/_project.html.haml
+++ b/app/views/layouts/nav/_project.html.haml
@@ -116,4 +116,4 @@
-# Shortcut to issue boards
%li.hidden
- = link_to 'Issue Boards', namespace_project_board_path(@project.namespace, @project), title: 'Issue Boards', class: 'shortcuts-issue-boards'
+ = link_to 'Issue Boards', namespace_project_boards_path(@project.namespace, @project), title: 'Issue Boards', class: 'shortcuts-issue-boards'
diff --git a/app/views/projects/boards/index.html.haml b/app/views/projects/boards/index.html.haml
new file mode 100644
index 00000000000..885f8e34b55
--- /dev/null
+++ b/app/views/projects/boards/index.html.haml
@@ -0,0 +1,16 @@
+- @no_container = true
+- @content_class = "issue-boards-content"
+- page_title "Boards"
+
+- content_for :page_specific_javascripts do
+ = page_specific_javascript_tag('boards/boards_bundle.js')
+ = page_specific_javascript_tag('boards/test_utils/simulate_drag.js') if Rails.env.test?
+
+= render "projects/issues/head"
+
+= render 'shared/issuable/filter', type: :boards
+
+.boards-list#board-app{ "v-cloak" => true, data: board_data }
+ .boards-app-loading.text-center{ "v-if" => "loading" }
+ = icon("spinner spin")
+ = render "projects/boards/components/board"
diff --git a/app/views/projects/boards/show.html.haml b/app/views/projects/boards/show.html.haml
index edbbd3f3d2a..885f8e34b55 100644
--- a/app/views/projects/boards/show.html.haml
+++ b/app/views/projects/boards/show.html.haml
@@ -10,10 +10,7 @@
= render 'shared/issuable/filter', type: :boards
-.boards-list#board-app{ "v-cloak" => true,
- "data-endpoint" => "#{namespace_project_board_path(@project.namespace, @project)}",
- "data-disabled" => "#{!can?(current_user, :admin_list, @project)}",
- "data-issue-link-base" => "#{namespace_project_issues_path(@project.namespace, @project)}" }
+.boards-list#board-app{ "v-cloak" => true, data: board_data }
.boards-app-loading.text-center{ "v-if" => "loading" }
= icon("spinner spin")
= render "projects/boards/components/board"
diff --git a/app/views/projects/issues/_head.html.haml b/app/views/projects/issues/_head.html.haml
index 509b01c548a..4825820c4d9 100644
--- a/app/views/projects/issues/_head.html.haml
+++ b/app/views/projects/issues/_head.html.haml
@@ -10,7 +10,7 @@
Issues
= nav_link(controller: :boards) do
- = link_to namespace_project_board_path(@project.namespace, @project), title: 'Board' do
+ = link_to namespace_project_boards_path(@project.namespace, @project), title: 'Board' do
%span
Board
diff --git a/config/routes/project.rb b/config/routes/project.rb
index dd0e84b1475..f9d58f5d5b2 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -417,7 +417,7 @@ resources :namespaces, path: '/', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only:
end
end
- resource :board, only: [:show] do
+ resources :boards, only: [:index, :show] do
scope module: :boards do
resources :issues, only: [:update]
diff --git a/lib/api/boards.rb b/lib/api/boards.rb
index 4d5d144a02e..9b71d335128 100644
--- a/lib/api/boards.rb
+++ b/lib/api/boards.rb
@@ -7,13 +7,14 @@ module API
# Get the project board
get ':id/boards' do
authorize!(:read_board, user_project)
- present [user_project.board], with: Entities::Board
+ present user_project.boards, with: Entities::Board
end
segment ':id/boards/:board_id' do
helpers do
def project_board
- board = user_project.board
+ board = user_project.boards.first
+
if params[:board_id].to_i == board.id
board
else
@@ -55,8 +56,10 @@ module API
authorize!(:admin_list, user_project)
- list = ::Boards::Lists::CreateService.new(user_project, current_user,
- { label_id: params[:label_id] }).execute
+ service = ::Boards::Lists::CreateService.new(user_project, current_user,
+ { label_id: params[:label_id] })
+
+ list = service.execute(project_board)
if list.valid?
present list, with: Entities::List
@@ -78,10 +81,10 @@ module API
authorize!(:admin_list, user_project)
- moved = ::Boards::Lists::MoveService.new(user_project, current_user,
- { position: params[:position].to_i }).execute(list)
+ service = ::Boards::Lists::MoveService.new(user_project, current_user,
+ { position: params[:position].to_i })
- if moved
+ if service.execute(list)
present list, with: Entities::List
else
render_api_error!({ error: "List could not be moved!" }, 400)
@@ -97,16 +100,16 @@ module API
# Example Request:
# DELETE /projects/:id/boards/:board_id/lists/:list_id
delete "/lists/:list_id" do
- list = board_lists.find_by(id: params[:list_id])
-
authorize!(:admin_list, user_project)
- if list
- destroyed_list = ::Boards::Lists::DestroyService.new(
- user_project, current_user).execute(list)
- present destroyed_list, with: Entities::List
+ list = board_lists.find(params[:list_id])
+
+ service = ::Boards::Lists::DestroyService.new(user_project, current_user)
+
+ if service.execute(list)
+ present list, with: Entities::List
else
- not_found!('List')
+ render_api_error!({ error: 'List could not be deleted!' }, 400)
end
end
end
diff --git a/spec/controllers/projects/boards/issues_controller_spec.rb b/spec/controllers/projects/boards/issues_controller_spec.rb
index 566658b508d..da59642f24d 100644
--- a/spec/controllers/projects/boards/issues_controller_spec.rb
+++ b/spec/controllers/projects/boards/issues_controller_spec.rb
@@ -1,15 +1,16 @@
require 'spec_helper'
describe Projects::Boards::IssuesController do
- let(:project) { create(:project_with_board) }
+ let(:project) { create(:empty_project) }
+ let(:board) { create(:board, project: project) }
let(:user) { create(:user) }
let(:guest) { create(:user) }
let(:planning) { create(:label, project: project, name: 'Planning') }
let(:development) { create(:label, project: project, name: 'Development') }
- let!(:list1) { create(:list, board: project.board, label: planning, position: 0) }
- let!(:list2) { create(:list, board: project.board, label: development, position: 1) }
+ let!(:list1) { create(:list, board: board, label: planning, position: 0) }
+ let!(:list2) { create(:list, board: board, label: development, position: 1) }
before do
project.team << [user, :master]
@@ -24,7 +25,7 @@ describe Projects::Boards::IssuesController do
create(:labeled_issue, project: project, labels: [development])
create(:labeled_issue, project: project, labels: [development], assignee: johndoe)
- list_issues user: user, list_id: list2
+ list_issues user: user, board: board, list: list2
parsed_response = JSON.parse(response.body)
@@ -33,9 +34,17 @@ describe Projects::Boards::IssuesController do
end
end
+ context 'with invalid board id' do
+ it 'returns a not found 404 response' do
+ list_issues user: user, board: 999, list: list2
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
context 'with invalid list id' do
it 'returns a not found 404 response' do
- list_issues user: user, list_id: 999
+ list_issues user: user, board: board, list: 999
expect(response).to have_http_status(404)
end
@@ -47,32 +56,33 @@ describe Projects::Boards::IssuesController do
allow(Ability).to receive(:allowed?).with(user, :read_issue, project).and_return(false)
end
- it 'returns a successful 403 response' do
- list_issues user: user, list_id: list2
+ it 'returns a forbidden 403 response' do
+ list_issues user: user, board: board, list: list2
expect(response).to have_http_status(403)
end
end
- def list_issues(user:, list_id:)
+ def list_issues(user:, board:, list:)
sign_in(user)
get :index, namespace_id: project.namespace.to_param,
project_id: project.to_param,
- list_id: list_id.to_param
+ board_id: board.to_param,
+ list_id: list.to_param
end
end
describe 'POST create' do
context 'with valid params' do
it 'returns a successful 200 response' do
- create_issue user: user, list: list1, title: 'New issue'
+ create_issue user: user, board: board, list: list1, title: 'New issue'
expect(response).to have_http_status(200)
end
it 'returns the created issue' do
- create_issue user: user, list: list1, title: 'New issue'
+ create_issue user: user, board: board, list: list1, title: 'New issue'
expect(response).to match_response_schema('issue')
end
@@ -81,7 +91,7 @@ describe Projects::Boards::IssuesController do
context 'with invalid params' do
context 'when title is nil' do
it 'returns an unprocessable entity 422 response' do
- create_issue user: user, list: list1, title: nil
+ create_issue user: user, board: board, list: list1, title: nil
expect(response).to have_http_status(422)
end
@@ -91,7 +101,7 @@ describe Projects::Boards::IssuesController do
it 'returns a not found 404 response' do
list = create(:list)
- create_issue user: user, list: list, title: 'New issue'
+ create_issue user: user, board: board, list: list, title: 'New issue'
expect(response).to have_http_status(404)
end
@@ -100,17 +110,18 @@ describe Projects::Boards::IssuesController do
context 'with unauthorized user' do
it 'returns a forbidden 403 response' do
- create_issue user: guest, list: list1, title: 'New issue'
+ create_issue user: guest, board: board, list: list1, title: 'New issue'
expect(response).to have_http_status(403)
end
end
- def create_issue(user:, list:, title:)
+ def create_issue(user:, board:, list:, title:)
sign_in(user)
post :create, namespace_id: project.namespace.to_param,
project_id: project.to_param,
+ board_id: board.to_param,
list_id: list.to_param,
issue: { title: title },
format: :json
@@ -122,13 +133,13 @@ describe Projects::Boards::IssuesController do
context 'with valid params' do
it 'returns a successful 200 response' do
- move user: user, issue: issue, from_list_id: list1.id, to_list_id: list2.id
+ move user: user, board: board, issue: issue, from_list_id: list1.id, to_list_id: list2.id
expect(response).to have_http_status(200)
end
it 'moves issue to the desired list' do
- move user: user, issue: issue, from_list_id: list1.id, to_list_id: list2.id
+ move user: user, board: board, issue: issue, from_list_id: list1.id, to_list_id: list2.id
expect(issue.reload.labels).to contain_exactly(development)
end
@@ -136,31 +147,44 @@ describe Projects::Boards::IssuesController do
context 'with invalid params' do
it 'returns a unprocessable entity 422 response for invalid lists' do
- move user: user, issue: issue, from_list_id: nil, to_list_id: nil
+ move user: user, board: board, issue: issue, from_list_id: nil, to_list_id: nil
expect(response).to have_http_status(422)
end
+ it 'returns a not found 404 response for invalid board id' do
+ move user: user, board: 999, issue: issue, from_list_id: list1.id, to_list_id: list2.id
+
+ expect(response).to have_http_status(404)
+ end
+
it 'returns a not found 404 response for invalid issue id' do
- move user: user, issue: 999, from_list_id: list1.id, to_list_id: list2.id
+ move user: user, board: board, issue: 999, from_list_id: list1.id, to_list_id: list2.id
expect(response).to have_http_status(404)
end
end
context 'with unauthorized user' do
+ let(:guest) { create(:user) }
+
+ before do
+ project.team << [guest, :guest]
+ end
+
it 'returns a forbidden 403 response' do
- move user: guest, issue: issue, from_list_id: list1.id, to_list_id: list2.id
+ move user: guest, board: board, issue: issue, from_list_id: list1.id, to_list_id: list2.id
expect(response).to have_http_status(403)
end
end
- def move(user:, issue:, from_list_id:, to_list_id:)
+ def move(user:, board:, issue:, from_list_id:, to_list_id:)
sign_in(user)
patch :update, namespace_id: project.namespace.to_param,
project_id: project.to_param,
+ board_id: board.to_param,
id: issue.to_param,
from_list_id: from_list_id,
to_list_id: to_list_id,
diff --git a/spec/controllers/projects/boards/lists_controller_spec.rb b/spec/controllers/projects/boards/lists_controller_spec.rb
index 709006a3601..34d6119429d 100644
--- a/spec/controllers/projects/boards/lists_controller_spec.rb
+++ b/spec/controllers/projects/boards/lists_controller_spec.rb
@@ -1,8 +1,8 @@
require 'spec_helper'
describe Projects::Boards::ListsController do
- let(:project) { create(:project_with_board) }
- let(:board) { project.board }
+ let(:project) { create(:empty_project) }
+ let(:board) { create(:board, project: project) }
let(:user) { create(:user) }
let(:guest) { create(:user) }
@@ -13,7 +13,7 @@ describe Projects::Boards::ListsController do
describe 'GET index' do
it 'returns a successful 200 response' do
- read_board_list user: user
+ read_board_list user: user, board: board
expect(response).to have_http_status(200)
expect(response.content_type).to eq 'application/json'
@@ -22,7 +22,7 @@ describe Projects::Boards::ListsController do
it 'returns a list of board lists' do
create(:list, board: board)
- read_board_list user: user
+ read_board_list user: user, board: board
parsed_response = JSON.parse(response.body)
@@ -37,17 +37,18 @@ describe Projects::Boards::ListsController do
end
it 'returns a forbidden 403 response' do
- read_board_list user: user
+ read_board_list user: user, board: board
expect(response).to have_http_status(403)
end
end
- def read_board_list(user:)
+ def read_board_list(user:, board:)
sign_in(user)
get :index, namespace_id: project.namespace.to_param,
project_id: project.to_param,
+ board_id: board.to_param,
format: :json
end
end
@@ -57,13 +58,13 @@ describe Projects::Boards::ListsController do
let(:label) { create(:label, project: project, name: 'Development') }
it 'returns a successful 200 response' do
- create_board_list user: user, label_id: label.id
+ create_board_list user: user, board: board, label_id: label.id
expect(response).to have_http_status(200)
end
it 'returns the created list' do
- create_board_list user: user, label_id: label.id
+ create_board_list user: user, board: board, label_id: label.id
expect(response).to match_response_schema('list')
end
@@ -72,7 +73,7 @@ describe Projects::Boards::ListsController do
context 'with invalid params' do
context 'when label is nil' do
it 'returns a not found 404 response' do
- create_board_list user: user, label_id: nil
+ create_board_list user: user, board: board, label_id: nil
expect(response).to have_http_status(404)
end
@@ -82,7 +83,7 @@ describe Projects::Boards::ListsController do
it 'returns a not found 404 response' do
label = create(:label, name: 'Development')
- create_board_list user: user, label_id: label.id
+ create_board_list user: user, board: board, label_id: label.id
expect(response).to have_http_status(404)
end
@@ -93,17 +94,18 @@ describe Projects::Boards::ListsController do
it 'returns a forbidden 403 response' do
label = create(:label, project: project, name: 'Development')
- create_board_list user: guest, label_id: label.id
+ create_board_list user: guest, board: board, label_id: label.id
expect(response).to have_http_status(403)
end
end
- def create_board_list(user:, label_id:)
+ def create_board_list(user:, board:, label_id:)
sign_in(user)
post :create, namespace_id: project.namespace.to_param,
project_id: project.to_param,
+ board_id: board.to_param,
list: { label_id: label_id },
format: :json
end
@@ -115,13 +117,13 @@ describe Projects::Boards::ListsController do
context 'with valid position' do
it 'returns a successful 200 response' do
- move user: user, list: planning, position: 1
+ move user: user, board: board, list: planning, position: 1
expect(response).to have_http_status(200)
end
it 'moves the list to the desired position' do
- move user: user, list: planning, position: 1
+ move user: user, board: board, list: planning, position: 1
expect(planning.reload.position).to eq 1
end
@@ -129,7 +131,7 @@ describe Projects::Boards::ListsController do
context 'with invalid position' do
it 'returns an unprocessable entity 422 response' do
- move user: user, list: planning, position: 6
+ move user: user, board: board, list: planning, position: 6
expect(response).to have_http_status(422)
end
@@ -137,7 +139,7 @@ describe Projects::Boards::ListsController do
context 'with invalid list id' do
it 'returns a not found 404 response' do
- move user: user, list: 999, position: 1
+ move user: user, board: board, list: 999, position: 1
expect(response).to have_http_status(404)
end
@@ -145,17 +147,18 @@ describe Projects::Boards::ListsController do
context 'with unauthorized user' do
it 'returns a forbidden 403 response' do
- move user: guest, list: planning, position: 6
+ move user: guest, board: board, list: planning, position: 6
expect(response).to have_http_status(403)
end
end
- def move(user:, list:, position:)
+ def move(user:, board:, list:, position:)
sign_in(user)
patch :update, namespace_id: project.namespace.to_param,
project_id: project.to_param,
+ board_id: board.to_param,
id: list.to_param,
list: { position: position },
format: :json
@@ -167,19 +170,19 @@ describe Projects::Boards::ListsController do
context 'with valid list id' do
it 'returns a successful 200 response' do
- remove_board_list user: user, list: planning
+ remove_board_list user: user, board: board, list: planning
expect(response).to have_http_status(200)
end
it 'removes list from board' do
- expect { remove_board_list user: user, list: planning }.to change(board.lists, :size).by(-1)
+ expect { remove_board_list user: user, board: board, list: planning }.to change(board.lists, :size).by(-1)
end
end
context 'with invalid list id' do
it 'returns a not found 404 response' do
- remove_board_list user: user, list: 999
+ remove_board_list user: user, board: board, list: 999
expect(response).to have_http_status(404)
end
@@ -187,17 +190,18 @@ describe Projects::Boards::ListsController do
context 'with unauthorized user' do
it 'returns a forbidden 403 response' do
- remove_board_list user: guest, list: planning
+ remove_board_list user: guest, board: board, list: planning
expect(response).to have_http_status(403)
end
end
- def remove_board_list(user:, list:)
+ def remove_board_list(user:, board:, list:)
sign_in(user)
delete :destroy, namespace_id: project.namespace.to_param,
project_id: project.to_param,
+ board_id: board.to_param,
id: list.to_param,
format: :json
end
@@ -206,13 +210,13 @@ describe Projects::Boards::ListsController do
describe 'POST generate' do
context 'when board lists is empty' do
it 'returns a successful 200 response' do
- generate_default_board_lists user: user
+ generate_default_lists user: user, board: board
expect(response).to have_http_status(200)
end
it 'returns the defaults lists' do
- generate_default_board_lists user: user
+ generate_default_lists user: user, board: board
expect(response).to match_response_schema('lists')
end
@@ -222,7 +226,7 @@ describe Projects::Boards::ListsController do
it 'returns an unprocessable entity 422 response' do
create(:list, board: board)
- generate_default_board_lists user: user
+ generate_default_lists user: user, board: board
expect(response).to have_http_status(422)
end
@@ -230,17 +234,18 @@ describe Projects::Boards::ListsController do
context 'with unauthorized user' do
it 'returns a forbidden 403 response' do
- generate_default_board_lists user: guest
+ generate_default_lists user: guest, board: board
expect(response).to have_http_status(403)
end
end
- def generate_default_board_lists(user:)
+ def generate_default_lists(user:, board:)
sign_in(user)
post :generate, namespace_id: project.namespace.to_param,
project_id: project.to_param,
+ board_id: board.to_param,
format: :json
end
end
diff --git a/spec/controllers/projects/boards_controller_spec.rb b/spec/controllers/projects/boards_controller_spec.rb
index 6f6e608e1f3..cc19035740e 100644
--- a/spec/controllers/projects/boards_controller_spec.rb
+++ b/spec/controllers/projects/boards_controller_spec.rb
@@ -9,16 +9,71 @@ describe Projects::BoardsController do
sign_in(user)
end
+ describe 'GET index' do
+ it 'creates a new project board when project does not have one' do
+ expect { list_boards }.to change(project.boards, :count).by(1)
+ end
+
+ context 'when format is HTML' do
+ it 'renders template' do
+ list_boards
+
+ expect(response).to render_template :index
+ expect(response.content_type).to eq 'text/html'
+ end
+ end
+
+ context 'when format is JSON' do
+ it 'returns a list of project boards' do
+ create_list(:board, 2, project: project)
+
+ list_boards format: :json
+
+ parsed_response = JSON.parse(response.body)
+
+ expect(response).to match_response_schema('boards')
+ expect(parsed_response.length).to eq 2
+ end
+ end
+
+ context 'with unauthorized user' do
+ before do
+ allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(true)
+ allow(Ability).to receive(:allowed?).with(user, :read_board, project).and_return(false)
+ end
+
+ it 'returns a not found 404 response' do
+ list_boards
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ def list_boards(format: :html)
+ get :index, namespace_id: project.namespace.to_param,
+ project_id: project.to_param,
+ format: format
+ end
+ end
+
describe 'GET show' do
- it 'creates a new board when project does not have one' do
- expect { read_board }.to change(Board, :count).by(1)
+ let!(:board) { create(:board, project: project) }
+
+ context 'when format is HTML' do
+ it 'renders template' do
+ read_board board: board
+
+ expect(response).to render_template :show
+ expect(response.content_type).to eq 'text/html'
+ end
end
- it 'renders HTML template' do
- read_board
+ context 'when format is JSON' do
+ it 'returns project board' do
+ read_board board: board, format: :json
- expect(response).to render_template :show
- expect(response.content_type).to eq 'text/html'
+ expect(response).to match_response_schema('board')
+ end
end
context 'with unauthorized user' do
@@ -27,16 +82,27 @@ describe Projects::BoardsController do
allow(Ability).to receive(:allowed?).with(user, :read_board, project).and_return(false)
end
- it 'returns a successful 404 response' do
- read_board
+ it 'returns a not found 404 response' do
+ read_board board: board
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context 'when board does not belong to project' do
+ it 'returns a not found 404 response' do
+ another_board = create(:board)
+
+ read_board board: another_board
expect(response).to have_http_status(404)
end
end
- def read_board(format: :html)
+ def read_board(board:, format: :html)
get :show, namespace_id: project.namespace.to_param,
project_id: project.to_param,
+ id: board.to_param,
format: format
end
end
diff --git a/spec/factories/boards.rb b/spec/factories/boards.rb
index 35c4a0b6f08..ec46146d9b5 100644
--- a/spec/factories/boards.rb
+++ b/spec/factories/boards.rb
@@ -1,5 +1,10 @@
FactoryGirl.define do
factory :board do
project factory: :empty_project
+
+ after(:create) do |board|
+ board.lists.create(list_type: :backlog)
+ board.lists.create(list_type: :done)
+ end
end
end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 331172445e4..719ef17f57e 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -124,12 +124,4 @@ FactoryGirl.define do
)
end
end
-
- factory :project_with_board, parent: :empty_project do
- after(:create) do |project|
- project.create_board
- project.board.lists.create(list_type: :backlog)
- project.board.lists.create(list_type: :done)
- end
- end
end
diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb
index 470e2bdbb9b..0fb1608a0a3 100644
--- a/spec/features/boards/boards_spec.rb
+++ b/spec/features/boards/boards_spec.rb
@@ -4,7 +4,8 @@ describe 'Issue Boards', feature: true, js: true do
include WaitForAjax
include WaitForVueResource
- let(:project) { create(:project_with_board, :public) }
+ let(:project) { create(:empty_project, :public) }
+ let(:board) { create(:board, project: project) }
let(:user) { create(:user) }
let!(:user2) { create(:user) }
@@ -17,7 +18,7 @@ describe 'Issue Boards', feature: true, js: true do
context 'no lists' do
before do
- visit namespace_project_board_path(project.namespace, project)
+ visit namespace_project_board_path(project.namespace, project, board)
wait_for_vue_resource
expect(page).to have_selector('.board', count: 3)
end
@@ -60,8 +61,8 @@ describe 'Issue Boards', feature: true, js: true do
let!(:done) { create(:label, project: project, name: 'Done') }
let!(:accepting) { create(:label, project: project, name: 'Accepting Merge Requests') }
- let!(:list1) { create(:list, board: project.board, label: planning, position: 0) }
- let!(:list2) { create(:list, board: project.board, label: development, position: 1) }
+ let!(:list1) { create(:list, board: board, label: planning, position: 0) }
+ let!(:list2) { create(:list, board: board, label: development, position: 1) }
let!(:confidential_issue) { create(:issue, :confidential, project: project, author: user) }
let!(:issue1) { create(:issue, project: project, assignee: user) }
@@ -75,7 +76,7 @@ describe 'Issue Boards', feature: true, js: true do
let!(:issue9) { create(:labeled_issue, project: project, labels: [testing, bug, accepting]) }
before do
- visit namespace_project_board_path(project.namespace, project)
+ visit namespace_project_board_path(project.namespace, project, board)
wait_for_vue_resource
@@ -169,7 +170,7 @@ describe 'Issue Boards', feature: true, js: true do
create(:issue, project: project)
end
- visit namespace_project_board_path(project.namespace, project)
+ visit namespace_project_board_path(project.namespace, project, board)
wait_for_vue_resource
page.within(find('.board', match: :first)) do
@@ -468,7 +469,7 @@ describe 'Issue Boards', feature: true, js: true do
it 'removes filtered labels' do
wait_for_vue_resource
-
+
page.within '.labels-filter' do
click_button('Label')
wait_for_ajax
@@ -603,7 +604,7 @@ describe 'Issue Boards', feature: true, js: true do
context 'keyboard shortcuts' do
before do
- visit namespace_project_board_path(project.namespace, project)
+ visit namespace_project_board_path(project.namespace, project, board)
wait_for_vue_resource
end
@@ -616,7 +617,7 @@ describe 'Issue Boards', feature: true, js: true do
context 'signed out user' do
before do
logout
- visit namespace_project_board_path(project.namespace, project)
+ visit namespace_project_board_path(project.namespace, project, board)
wait_for_vue_resource
end
@@ -632,7 +633,7 @@ describe 'Issue Boards', feature: true, js: true do
project.team << [user_guest, :guest]
logout
login_as(user_guest)
- visit namespace_project_board_path(project.namespace, project)
+ visit namespace_project_board_path(project.namespace, project, board)
wait_for_vue_resource
end
diff --git a/spec/features/boards/keyboard_shortcut_spec.rb b/spec/features/boards/keyboard_shortcut_spec.rb
index 7ef68e9eb8d..a5fc766401f 100644
--- a/spec/features/boards/keyboard_shortcut_spec.rb
+++ b/spec/features/boards/keyboard_shortcut_spec.rb
@@ -6,9 +6,7 @@ describe 'Issue Boards shortcut', feature: true, js: true do
let(:project) { create(:empty_project) }
before do
- project.create_board
- project.board.lists.create(list_type: :backlog)
- project.board.lists.create(list_type: :done)
+ create(:board, project: project)
login_as :admin
diff --git a/spec/features/boards/new_issue_spec.rb b/spec/features/boards/new_issue_spec.rb
index c046e6b8d79..67d6da5f39a 100644
--- a/spec/features/boards/new_issue_spec.rb
+++ b/spec/features/boards/new_issue_spec.rb
@@ -4,7 +4,8 @@ describe 'Issue Boards new issue', feature: true, js: true do
include WaitForAjax
include WaitForVueResource
- let(:project) { create(:project_with_board, :public) }
+ let(:project) { create(:empty_project, :public) }
+ let(:board) { create(:board, project: project) }
let(:user) { create(:user) }
context 'authorized user' do
@@ -13,7 +14,7 @@ describe 'Issue Boards new issue', feature: true, js: true do
login_as(user)
- visit namespace_project_board_path(project.namespace, project)
+ visit namespace_project_board_path(project.namespace, project, board)
wait_for_vue_resource
expect(page).to have_selector('.board', count: 3)
@@ -69,7 +70,7 @@ describe 'Issue Boards new issue', feature: true, js: true do
context 'unauthorized user' do
before do
- visit namespace_project_board_path(project.namespace, project)
+ visit namespace_project_board_path(project.namespace, project, board)
wait_for_vue_resource
end
diff --git a/spec/fixtures/api/schemas/board.json b/spec/fixtures/api/schemas/board.json
new file mode 100644
index 00000000000..03aca4a3cc0
--- /dev/null
+++ b/spec/fixtures/api/schemas/board.json
@@ -0,0 +1,11 @@
+{
+ "type": "object",
+ "required" : [
+ "id"
+ ],
+ "properties" : {
+ "id": { "type": "integer" },
+ "name": { "type": "string" }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/boards.json b/spec/fixtures/api/schemas/boards.json
new file mode 100644
index 00000000000..117564ef77a
--- /dev/null
+++ b/spec/fixtures/api/schemas/boards.json
@@ -0,0 +1,4 @@
+{
+ "type": "array",
+ "items": { "$ref": "board.json" }
+}
diff --git a/spec/javascripts/boards/boards_store_spec.js.es6 b/spec/javascripts/boards/boards_store_spec.js.es6
index 078e4b00023..15c305ce321 100644
--- a/spec/javascripts/boards/boards_store_spec.js.es6
+++ b/spec/javascripts/boards/boards_store_spec.js.es6
@@ -14,7 +14,7 @@
(() => {
beforeEach(() => {
- gl.boardService = new BoardService('/test/issue-boards/board');
+ gl.boardService = new BoardService('/test/issue-boards/board', '1');
gl.issueBoards.BoardsStore.create();
$.cookie('issue_board_welcome_hidden', 'false');
diff --git a/spec/javascripts/boards/issue_spec.js.es6 b/spec/javascripts/boards/issue_spec.js.es6
index 3569d1b98bd..328c6f82ab5 100644
--- a/spec/javascripts/boards/issue_spec.js.es6
+++ b/spec/javascripts/boards/issue_spec.js.es6
@@ -16,7 +16,7 @@ describe('Issue model', () => {
let issue;
beforeEach(() => {
- gl.boardService = new BoardService('/test/issue-boards/board');
+ gl.boardService = new BoardService('/test/issue-boards/board', '1');
gl.issueBoards.BoardsStore.create();
issue = new ListIssue({
diff --git a/spec/javascripts/boards/list_spec.js.es6 b/spec/javascripts/boards/list_spec.js.es6
index 1688b996162..ec78d82e919 100644
--- a/spec/javascripts/boards/list_spec.js.es6
+++ b/spec/javascripts/boards/list_spec.js.es6
@@ -16,7 +16,7 @@ describe('List model', () => {
let list;
beforeEach(() => {
- gl.boardService = new BoardService('/test/issue-boards/board');
+ gl.boardService = new BoardService('/test/issue-boards/board', '1');
gl.issueBoards.BoardsStore.create();
list = new List(listObj);
diff --git a/spec/javascripts/boards/mock_data.js.es6 b/spec/javascripts/boards/mock_data.js.es6
index f3797ed44d4..052455f2ca6 100644
--- a/spec/javascripts/boards/mock_data.js.es6
+++ b/spec/javascripts/boards/mock_data.js.es6
@@ -26,7 +26,7 @@ const listObjDuplicate = {
const BoardsMockData = {
'GET': {
- '/test/issue-boards/board/lists{/id}/issues': {
+ '/test/issue-boards/board/1/lists{/id}/issues': {
issues: [{
title: 'Testing',
iid: 1,
@@ -37,13 +37,13 @@ const BoardsMockData = {
}
},
'POST': {
- '/test/issue-boards/board/lists{/id}': listObj
+ '/test/issue-boards/board/1/lists{/id}': listObj
},
'PUT': {
- '/test/issue-boards/board/lists{/id}': {}
+ '/test/issue-boards/board/1/lists{/id}': {}
},
'DELETE': {
- '/test/issue-boards/board/lists{/id}': {}
+ '/test/issue-boards/board/1/lists{/id}': {}
}
};
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 006569254a6..5d5836e9bee 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -118,7 +118,7 @@ project:
- creator
- group
- namespace
-- board
+- boards
- last_event
- services
- campfire_service
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index dae546a0cdc..308a00db9cd 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -24,7 +24,7 @@ describe Project, models: true do
it { is_expected.to have_one(:slack_service).dependent(:destroy) }
it { is_expected.to have_one(:pushover_service).dependent(:destroy) }
it { is_expected.to have_one(:asana_service).dependent(:destroy) }
- it { is_expected.to have_one(:board).dependent(:destroy) }
+ it { is_expected.to have_many(:boards).dependent(:destroy) }
it { is_expected.to have_one(:campfire_service).dependent(:destroy) }
it { is_expected.to have_one(:drone_ci_service).dependent(:destroy) }
it { is_expected.to have_one(:emails_on_push_service).dependent(:destroy) }
@@ -94,6 +94,15 @@ describe Project, models: true do
end
end
end
+
+ describe '#boards' do
+ it 'raises an error when attempting to add more than one board to the project' do
+ subject.boards.build
+
+ expect { subject.boards.build }.to raise_error(Project::BoardLimitExceeded, 'Number of permitted boards exceeded')
+ expect(subject.boards.size).to eq 1
+ end
+ end
end
describe 'modules' do
diff --git a/spec/services/boards/create_service_spec.rb b/spec/services/boards/create_service_spec.rb
index a1a4dd4c57c..fde807cc410 100644
--- a/spec/services/boards/create_service_spec.rb
+++ b/spec/services/boards/create_service_spec.rb
@@ -2,33 +2,31 @@ require 'spec_helper'
describe Boards::CreateService, services: true do
describe '#execute' do
+ let(:project) { create(:empty_project) }
+
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
+ board = 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
+ expect(board.lists.size).to eq 2
+ expect(board.lists.first).to be_backlog
+ expect(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)
+ before do
+ create(:board, project: project)
end
- it 'does not create board lists' do
- expect { service.execute }.not_to change(project.board.lists, :count)
+ it 'does not create a new board' do
+ expect { service.execute }.not_to change(project.boards, :count)
end
end
end
diff --git a/spec/services/boards/issues/create_service_spec.rb b/spec/services/boards/issues/create_service_spec.rb
index 33e10e79f6d..360ee398f77 100644
--- a/spec/services/boards/issues/create_service_spec.rb
+++ b/spec/services/boards/issues/create_service_spec.rb
@@ -2,13 +2,13 @@ require 'spec_helper'
describe Boards::Issues::CreateService, services: true do
describe '#execute' do
- let(:project) { create(:project_with_board) }
- let(:board) { project.board }
+ let(:project) { create(:empty_project) }
+ let(:board) { create(:board, project: project) }
let(:user) { create(:user) }
let(:label) { create(:label, project: project, name: 'in-progress') }
let!(:list) { create(:list, board: board, label: label, position: 0) }
- subject(:service) { described_class.new(project, user, title: 'New issue') }
+ subject(:service) { described_class.new(project, user, board_id: board.id, list_id: list.id, title: 'New issue') }
before do
project.team << [user, :developer]
@@ -17,15 +17,15 @@ describe Boards::Issues::CreateService, services: true do
it 'delegates the create proceedings to Issues::CreateService' do
expect_any_instance_of(Issues::CreateService).to receive(:execute).once
- service.execute(list)
+ service.execute
end
it 'creates a new issue' do
- expect { service.execute(list) }.to change(project.issues, :count).by(1)
+ expect { service.execute }.to change(project.issues, :count).by(1)
end
it 'adds the label of the list to the issue' do
- issue = service.execute(list)
+ issue = service.execute
expect(issue.labels).to eq [label]
end
diff --git a/spec/services/boards/issues/list_service_spec.rb b/spec/services/boards/issues/list_service_spec.rb
index 5b9f454fd2d..7c206cf3ce7 100644
--- a/spec/services/boards/issues/list_service_spec.rb
+++ b/spec/services/boards/issues/list_service_spec.rb
@@ -3,8 +3,8 @@ 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(:project) { create(:empty_project) }
+ let(:board) { create(:board, project: project) }
let(:bug) { create(:label, project: project, name: 'Bug') }
let(:development) { create(:label, project: project, name: 'Development') }
@@ -13,10 +13,10 @@ describe Boards::Issues::ListService, services: true do
let(:p2) { create(:label, title: 'P2', project: project, priority: 2) }
let(:p3) { create(:label, title: 'P3', project: project, priority: 3) }
- let!(:backlog) { project.board.backlog_list }
+ 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) { project.board.done_list }
+ 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]) }
@@ -37,7 +37,7 @@ describe Boards::Issues::ListService, services: true do
end
it 'delegates search to IssuesFinder' do
- params = { id: list1.id }
+ params = { board_id: board.id, id: list1.id }
expect_any_instance_of(IssuesFinder).to receive(:execute).once.and_call_original
@@ -46,7 +46,7 @@ describe Boards::Issues::ListService, services: true do
context 'sets default order to priority' do
it 'returns opened issues when listing issues from Backlog' do
- params = { id: backlog.id }
+ params = { board_id: board.id, id: backlog.id }
issues = described_class.new(project, user, params).execute
@@ -54,7 +54,7 @@ describe Boards::Issues::ListService, services: true do
end
it 'returns closed issues when listing issues from Done' do
- params = { id: done.id }
+ params = { board_id: board.id, id: done.id }
issues = described_class.new(project, user, params).execute
@@ -62,12 +62,29 @@ describe Boards::Issues::ListService, services: true do
end
it 'returns opened issues that have label list applied when listing issues from a label list' do
- params = { id: list1.id }
+ params = { board_id: board.id, id: list1.id }
issues = described_class.new(project, 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(project, 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(project, user, board_id: board.id, id: nil)
+
+ expect { service.execute }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
end
end
diff --git a/spec/services/boards/issues/move_service_spec.rb b/spec/services/boards/issues/move_service_spec.rb
index 180f1b08631..c43b2aec490 100644
--- a/spec/services/boards/issues/move_service_spec.rb
+++ b/spec/services/boards/issues/move_service_spec.rb
@@ -3,17 +3,17 @@ 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(:project) { create(:empty_project) }
+ let(:board1) { create(:board, project: project) }
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) { project.board.backlog_list }
- let!(:list1) { create(:list, board: board, label: development, position: 0) }
- let!(:list2) { create(:list, board: board, label: testing, position: 1) }
- let!(:done) { project.board.done_list }
+ let!(:backlog) { create(:backlog_list, board: board1) }
+ let!(:list1) { create(:list, board: board1, label: development, position: 0) }
+ let!(:list2) { create(:list, board: board1, label: testing, position: 1) }
+ let!(:done) { create(:done_list, board: board1) }
before do
project.team << [user, :developer]
@@ -22,7 +22,7 @@ describe Boards::Issues::MoveService, services: true do
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 }
+ params = { board_id: board1.id, from_list_id: backlog.id, to_list_id: list1.id }
described_class.new(project, user, params).execute(issue)
@@ -33,7 +33,7 @@ describe Boards::Issues::MoveService, services: true do
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 }
+ params = { board_id: board1.id, from_list_id: list1.id, to_list_id: backlog.id }
described_class.new(project, user, params).execute(issue)
@@ -44,7 +44,7 @@ describe Boards::Issues::MoveService, services: true do
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 }
+ params = { board_id: board1.id, from_list_id: backlog.id, to_list_id: done.id }
described_class.new(project, user, params).execute(issue)
issue.reload
@@ -56,7 +56,7 @@ describe Boards::Issues::MoveService, services: true do
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 } }
+ 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
@@ -72,8 +72,12 @@ describe Boards::Issues::MoveService, services: true do
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 } }
+ let(:board2) { create(:board, project: project) }
+ let(:regression) { create(:label, project: project, name: 'Regression') }
+ 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: done.id } }
it 'delegates the close proceedings to Issues::CloseService' do
expect_any_instance_of(Issues::CloseService).to receive(:execute).with(issue).once
@@ -81,7 +85,7 @@ describe Boards::Issues::MoveService, services: true do
described_class.new(project, user, params).execute(issue)
end
- it 'removes all list-labels and close the issue' do
+ it 'removes all list-labels from project boards and close the issue' do
described_class.new(project, user, params).execute(issue)
issue.reload
@@ -92,7 +96,7 @@ describe Boards::Issues::MoveService, services: true do
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 } }
+ let(:params) { { board_id: board1.id, 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
@@ -112,7 +116,7 @@ describe Boards::Issues::MoveService, services: true do
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 }
+ params = { board_id: board1.id, from_list_id: done.id, to_list_id: backlog.id }
described_class.new(project, user, params).execute(issue)
issue.reload
@@ -124,7 +128,7 @@ describe Boards::Issues::MoveService, services: true do
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 } }
+ let(:params) { { board_id: board1.id, 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
diff --git a/spec/services/boards/list_service_spec.rb b/spec/services/boards/list_service_spec.rb
new file mode 100644
index 00000000000..dff33e4bcbb
--- /dev/null
+++ b/spec/services/boards/list_service_spec.rb
@@ -0,0 +1,37 @@
+require 'spec_helper'
+
+describe Boards::ListService, services: true do
+ describe '#execute' do
+ let(:project) { create(:empty_project) }
+
+ subject(:service) { described_class.new(project, double) }
+
+ context 'when project does not have a board' do
+ it 'creates a new project board' do
+ expect { service.execute }.to change(project.boards, :count).by(1)
+ end
+
+ it 'delegates the project board creation to Boards::CreateService' do
+ expect_any_instance_of(Boards::CreateService).to receive(:execute).once
+
+ service.execute
+ end
+ end
+
+ context 'when project has a board' do
+ before do
+ create(:board, project: project)
+ end
+
+ it 'does not create a new board' do
+ expect { service.execute }.not_to change(project.boards, :count)
+ end
+ end
+
+ it 'returns project boards' do
+ board = create(:board, project: project)
+
+ expect(service.execute).to match_array [board]
+ end
+ end
+end
diff --git a/spec/services/boards/lists/create_service_spec.rb b/spec/services/boards/lists/create_service_spec.rb
index bff9c1fd1fe..e7806add916 100644
--- a/spec/services/boards/lists/create_service_spec.rb
+++ b/spec/services/boards/lists/create_service_spec.rb
@@ -2,8 +2,8 @@ require 'spec_helper'
describe Boards::Lists::CreateService, services: true do
describe '#execute' do
- let(:project) { create(:project_with_board) }
- let(:board) { project.board }
+ let(:project) { create(:empty_project) }
+ let(:board) { create(:board, project: project) }
let(:user) { create(:user) }
let(:label) { create(:label, project: project, name: 'in-progress') }
@@ -11,7 +11,7 @@ describe Boards::Lists::CreateService, services: true do
context 'when board lists is empty' do
it 'creates a new list at beginning of the list' do
- list = service.execute
+ list = service.execute(board)
expect(list.position).to eq 0
end
@@ -19,7 +19,7 @@ describe Boards::Lists::CreateService, services: true do
context 'when board lists has backlog, and done lists' do
it 'creates a new list at beginning of the list' do
- list = service.execute
+ list = service.execute(board)
expect(list.position).to eq 0
end
@@ -30,7 +30,7 @@ describe Boards::Lists::CreateService, services: true do
create(:list, board: board, position: 0)
create(:list, board: board, position: 1)
- list = service.execute
+ list = service.execute(board)
expect(list.position).to eq 2
end
@@ -40,7 +40,7 @@ describe Boards::Lists::CreateService, services: true do
it 'creates a new list at end of the label lists' do
list1 = create(:list, board: board, position: 0)
- list2 = service.execute
+ list2 = service.execute(board)
expect(list1.reload.position).to eq 0
expect(list2.reload.position).to eq 1
@@ -52,7 +52,7 @@ describe Boards::Lists::CreateService, services: true do
label = create(:label, name: 'in-development')
service = described_class.new(project, user, label_id: label.id)
- expect { service.execute }.to raise_error(ActiveRecord::RecordNotFound)
+ expect { service.execute(board) }.to raise_error(ActiveRecord::RecordNotFound)
end
end
end
diff --git a/spec/services/boards/lists/destroy_service_spec.rb b/spec/services/boards/lists/destroy_service_spec.rb
index 474c4512471..628caf03476 100644
--- a/spec/services/boards/lists/destroy_service_spec.rb
+++ b/spec/services/boards/lists/destroy_service_spec.rb
@@ -2,8 +2,8 @@ require 'spec_helper'
describe Boards::Lists::DestroyService, services: true do
describe '#execute' do
- let(:project) { create(:project_with_board) }
- let(:board) { project.board }
+ let(:project) { create(:empty_project) }
+ let(:board) { create(:board, project: project) }
let(:user) { create(:user) }
context 'when list type is label' do
@@ -15,11 +15,11 @@ describe Boards::Lists::DestroyService, services: true do
end
it 'decrements position of higher lists' do
- backlog = project.board.backlog_list
+ backlog = board.backlog_list
development = create(:list, board: board, position: 0)
review = create(:list, board: board, position: 1)
staging = create(:list, board: board, position: 2)
- done = project.board.done_list
+ done = board.done_list
described_class.new(project, user).execute(development)
@@ -31,14 +31,14 @@ describe Boards::Lists::DestroyService, services: true do
end
it 'does not remove list from board when list type is backlog' do
- list = project.board.backlog_list
+ list = board.backlog_list
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 = project.board.done_list
+ list = board.done_list
service = described_class.new(project, user)
expect { service.execute(list) }.not_to change(board.lists, :count)
diff --git a/spec/services/boards/lists/generate_service_spec.rb b/spec/services/boards/lists/generate_service_spec.rb
index 4171e4d816c..8b2f5e81338 100644
--- a/spec/services/boards/lists/generate_service_spec.rb
+++ b/spec/services/boards/lists/generate_service_spec.rb
@@ -2,15 +2,15 @@ require 'spec_helper'
describe Boards::Lists::GenerateService, services: true do
describe '#execute' do
- let(:project) { create(:project_with_board) }
- let(:board) { project.board }
+ let(:project) { create(:empty_project) }
+ let(:board) { create(:board, project: project) }
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(2)
+ expect { service.execute(board) }.to change(board.lists, :count).by(2)
end
end
@@ -18,13 +18,13 @@ describe Boards::Lists::GenerateService, services: true do
it 'does not creates the default lists' do
create(:list, board: board)
- expect { service.execute }.not_to change(board.lists, :count)
+ expect { service.execute(board) }.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(2)
+ expect { service.execute(board) }.to change(project.labels, :count).by(2)
end
end
@@ -32,7 +32,7 @@ describe Boards::Lists::GenerateService, services: true do
it 'creates the missing labels' do
create(:label, project: project, name: 'Doing')
- expect { service.execute }.to change(project.labels, :count).by(1)
+ expect { service.execute(board) }.to change(project.labels, :count).by(1)
end
end
end
diff --git a/spec/services/boards/lists/list_service_spec.rb b/spec/services/boards/lists/list_service_spec.rb
new file mode 100644
index 00000000000..334cee3f06d
--- /dev/null
+++ b/spec/services/boards/lists/list_service_spec.rb
@@ -0,0 +1,16 @@
+require 'spec_helper'
+
+describe Boards::Lists::ListService, services: true do
+ describe '#execute' do
+ it "returns board's lists" do
+ project = create(:empty_project)
+ board = create(:board, project: project)
+ label = create(:label, project: project)
+ list = create(:list, board: board, label: label)
+
+ service = described_class.new(project, double)
+
+ expect(service.execute(board)).to eq [board.backlog_list, list, board.done_list]
+ end
+ end
+end
diff --git a/spec/services/boards/lists/move_service_spec.rb b/spec/services/boards/lists/move_service_spec.rb
index 102ed67449d..63fa0bb8c5f 100644
--- a/spec/services/boards/lists/move_service_spec.rb
+++ b/spec/services/boards/lists/move_service_spec.rb
@@ -2,16 +2,16 @@ require 'spec_helper'
describe Boards::Lists::MoveService, services: true do
describe '#execute' do
- let(:project) { create(:project_with_board) }
- let(:board) { project.board }
+ let(:project) { create(:empty_project) }
+ let(:board) { create(:board, project: project) }
let(:user) { create(:user) }
- let!(:backlog) { project.board.backlog_list }
+ 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) { project.board.done_list }
+ 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