split up work package by project resource specs

pull/10088/head
ulferts 3 years ago
parent bd819530c5
commit cf1a7addc5
No known key found for this signature in database
GPG Key ID: A205708DE1284017
  1. 179
      spec/requests/api/v3/work_packages/by_project_create_resource_spec.rb
  2. 287
      spec/requests/api/v3/work_packages/by_project_index_resource_spec.rb
  3. 2
      spec/requests/api/v3/work_packages/index_resource_spec.rb
  4. 430
      spec/requests/api/v3/work_packages/work_packages_by_project_resource_spec.rb

@ -0,0 +1,179 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
require 'spec_helper'
require 'rack/test'
describe API::V3::WorkPackages::WorkPackagesByProjectAPI, type: :request, content_type: :json do
include Rack::Test::Methods
include API::V3::Utilities::PathHelper
let(:role) { create(:role, permissions: permissions) }
let(:project) { create(:project_with_types, public: false) }
let(:path) { api_v3_paths.work_packages_by_project project.id }
let(:permissions) { %i[add_work_packages view_project] }
let(:status) { build(:status, is_default: true) }
let(:priority) { build(:priority, is_default: true) }
let(:other_user) { nil }
let(:parameters) do
{
subject: 'new work packages',
_links: {
type: {
href: api_v3_paths.type(project.types.first.id)
}
}
}
end
current_user do
create(:user, member_in_project: project, member_through_role: role)
end
before do
status.save!
priority.save!
other_user
perform_enqueued_jobs do
post path, parameters.to_json
end
end
describe 'notifications' do
let(:other_user) { create(:user, member_in_project: project, member_with_permissions: %i(view_work_packages)) }
it 'creates a notification' do
expect(Notification.where(recipient: other_user, resource: WorkPackage.last))
.to exist
end
context 'without notifications' do
let(:path) { "#{api_v3_paths.work_packages_by_project(project.id)}?notify=false" }
it 'creates no notification' do
expect(Notification)
.not_to exist
end
end
context 'with notifications' do
let(:path) { "#{api_v3_paths.work_packages_by_project(project.id)}?notify=true" }
it 'creates a notification' do
expect(Notification.where(recipient: other_user, resource: WorkPackage.last))
.to exist
end
end
end
it 'returns Created(201)' do
expect(last_response.status).to eq(201)
end
it 'creates a work package' do
expect(WorkPackage.all.count).to eq(1)
end
it 'uses the given parameters' do
expect(WorkPackage.first.subject).to eq(parameters[:subject])
end
context 'without permissions' do
let(:current_user) { create(:user) }
it 'hides the endpoint' do
expect(last_response.status).to eq(404)
end
end
context 'with view_project permission' do
# Note that this just removes the add_work_packages permission
# view_project is actually provided by being a member of the project
let(:permissions) { [:view_project] }
it 'points out the missing permission' do
expect(last_response.status).to eq(403)
end
end
context 'with empty parameters' do
let(:parameters) { {} }
it_behaves_like 'constraint violation' do
let(:message) { "Subject can't be blank" }
end
it 'does not create a work package' do
expect(WorkPackage.all.count).to eq(0)
end
end
context 'with bogus parameters' do
let(:parameters) do
{
bogus: 'bogus',
_links: {
type: {
href: api_v3_paths.type(project.types.first.id)
}
}
}
end
it_behaves_like 'constraint violation' do
let(:message) { "Subject can't be blank" }
end
it 'does not create a work package' do
expect(WorkPackage.all.count).to eq(0)
end
end
context 'with an invalid value' do
let(:parameters) do
{
subject: nil,
_links: {
type: {
href: api_v3_paths.type(project.types.first.id)
}
}
}
end
it_behaves_like 'constraint violation' do
let(:message) { "Subject can't be blank" }
end
it 'does not create a work package' do
expect(WorkPackage.all.count).to eq(0)
end
end
end

@ -0,0 +1,287 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
require 'spec_helper'
require 'rack/test'
describe API::V3::WorkPackages::WorkPackagesByProjectAPI, type: :request, content_type: :json do
include Rack::Test::Methods
include API::V3::Utilities::PathHelper
let(:role) { create(:role, permissions: permissions) }
let(:permissions) { [:view_work_packages] }
let(:project) { create(:project_with_types, public: false) }
let(:path) { api_v3_paths.work_packages_by_project project.id }
let(:work_packages) { [] }
current_user do
create(:user, member_in_project: project, member_through_role: role)
end
subject { last_response }
before do
work_packages.each(&:save!)
get path
end
it 'succeeds' do
expect(subject.status).to eq 200
end
context 'when not allowed to see the project' do
let(:current_user) { build(:user) }
it 'fails with HTTP Not Found' do
expect(subject.status).to eq 404
end
end
context 'when not allowed to see work packages' do
let(:permissions) { [:view_project] }
it 'fails with HTTP Not Found' do
expect(subject.status).to eq 403
end
end
describe 'advanced query options' do
let(:base_path) { api_v3_paths.work_packages_by_project project.id }
let(:query) { {} }
let(:path) { "#{base_path}?#{query.to_query}" }
describe 'sorting' do
let(:query) { { sortBy: '[["id", "desc"]]' } }
let(:work_packages) { create_list(:work_package, 2, project: project) }
it 'returns both elements' do
expect(subject.body).to be_json_eql(2).at_path('count')
expect(subject.body).to be_json_eql(2).at_path('total')
end
it 'returns work packages in the expected order' do
first_wp = work_packages.first
last_wp = work_packages.last
expect(subject.body).to be_json_eql(last_wp.id).at_path('_embedded/elements/0/id')
expect(subject.body).to be_json_eql(first_wp.id).at_path('_embedded/elements/1/id')
end
end
describe 'filtering' do
let(:query) do
{
filters: [
{
priority: {
operator: '=',
values: [priority1.id.to_s]
}
}
].to_json
}
end
let(:priority1) { create(:priority, name: 'Prio A') }
let(:priority2) { create(:priority, name: 'Prio B') }
let(:work_packages) do
[
create(:work_package, project: project, priority: priority1),
create(:work_package, project: project, priority: priority2)
]
end
it 'returns only one element' do
expect(subject.body).to be_json_eql(1).at_path('count')
expect(subject.body).to be_json_eql(1).at_path('total')
end
it 'returns the matching element' do
expected_id = work_packages.first.id
expect(subject.body).to be_json_eql(expected_id).at_path('_embedded/elements/0/id')
end
end
describe 'grouping' do
let(:query) { { groupBy: 'priority' } }
let(:priority1) { build(:priority, name: 'Prio A', position: 2) }
let(:priority2) { build(:priority, name: 'Prio B', position: 1) }
let(:work_packages) do
[
create(:work_package,
project: project,
priority: priority1,
estimated_hours: 1),
create(:work_package,
project: project,
priority: priority2,
estimated_hours: 2),
create(:work_package,
project: project,
priority: priority1,
estimated_hours: 3)
]
end
let(:expected_group1) do
{
_links: {
valueLink: [{
href: api_v3_paths.priority(priority1.id)
}],
groupBy: {
href: api_v3_paths.query_group_by('priority'),
title: 'Priority'
}
},
value: priority1.name,
count: 2
}
end
let(:expected_group2) do
{
_links: {
valueLink: [{
href: api_v3_paths.priority(priority2.id)
}],
groupBy: {
href: api_v3_paths.query_group_by('priority'),
title: 'Priority'
}
},
value: priority2.name,
count: 1
}
end
it 'returns all elements' do
expect(subject.body).to be_json_eql(3).at_path('count')
expect(subject.body).to be_json_eql(3).at_path('total')
end
it 'returns work packages ordered by priority' do
prio1_path = api_v3_paths.priority(priority1.id)
prio2_path = api_v3_paths.priority(priority2.id)
expect(subject.body).to(be_json_eql(prio2_path.to_json)
.at_path('_embedded/elements/0/_links/priority/href'))
expect(subject.body).to(be_json_eql(prio1_path.to_json)
.at_path('_embedded/elements/1/_links/priority/href'))
expect(subject.body).to(be_json_eql(prio1_path.to_json)
.at_path('_embedded/elements/2/_links/priority/href'))
end
it 'contains group elements' do
expect(subject.body).to include_json(expected_group1.to_json).at_path('groups')
expect(subject.body).to include_json(expected_group2.to_json).at_path('groups')
end
context 'when displaying sums' do
let(:query) { { groupBy: 'priority', showSums: 'true' } }
let(:expected_group1) do
{
_links: {
valueLink: [{
href: api_v3_paths.priority(priority1.id)
}],
groupBy: {
href: api_v3_paths.query_group_by('priority'),
title: 'Priority'
}
},
value: priority1.name,
count: 2,
sums: {
estimatedTime: 'PT4H',
laborCosts: "0.00 EUR",
materialCosts: "0.00 EUR",
overallCosts: "0.00 EUR",
remainingTime: nil,
storyPoints: nil
}
}
end
let(:expected_group2) do
{
_links: {
valueLink: [{
href: api_v3_paths.priority(priority2.id)
}],
groupBy: {
href: api_v3_paths.query_group_by('priority'),
title: 'Priority'
}
},
value: priority2.name,
count: 1,
sums: {
estimatedTime: 'PT2H',
laborCosts: "0.00 EUR",
materialCosts: "0.00 EUR",
overallCosts: "0.00 EUR",
remainingTime: nil,
storyPoints: nil
}
}
end
it 'contains extended group elements' do
expect(subject.body).to include_json(expected_group1.to_json).at_path('groups')
expect(subject.body).to include_json(expected_group2.to_json).at_path('groups')
end
end
end
describe 'displaying sums' do
let(:query) { { showSums: 'true' } }
let(:work_packages) do
[
create(:work_package, project: project, estimated_hours: 1),
create(:work_package, project: project, estimated_hours: 2)
]
end
it 'returns both elements' do
expect(subject.body).to be_json_eql(2).at_path('count')
expect(subject.body).to be_json_eql(2).at_path('total')
end
it 'contains the sum element' do
expected = {
estimatedTime: 'PT3H',
laborCosts: "0.00 EUR",
materialCosts: "0.00 EUR",
overallCosts: "0.00 EUR",
remainingTime: nil,
storyPoints: nil
}
expect(subject.body).to be_json_eql(expected.to_json).at_path('totalSums')
end
end
end
end

@ -69,7 +69,7 @@ describe 'API v3 Work package resource',
expect(subject.body).to be_json_eql(1.to_json).at_path('total')
end
it 'embedds the work package schemas' do
it 'embeds the work package schemas' do
expect(subject.body)
.to be_json_eql(api_v3_paths.work_package_schema(project.id, work_package.type.id).to_json)
.at_path('_embedded/schemas/_embedded/elements/0/_links/self/href')

@ -1,430 +0,0 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
require 'spec_helper'
require 'rack/test'
describe API::V3::WorkPackages::WorkPackagesByProjectAPI, type: :request, content_type: :json do
include Rack::Test::Methods
include API::V3::Utilities::PathHelper
let(:current_user) do
FactoryBot.create(:user, member_in_project: project, member_through_role: role)
end
let(:role) { FactoryBot.create(:role, permissions: permissions) }
let(:permissions) { [:view_work_packages] }
let(:project) { FactoryBot.create(:project_with_types, public: false) }
let(:path) { api_v3_paths.work_packages_by_project project.id }
before do
allow(User).to receive(:current).and_return current_user
end
describe '#get' do
let(:work_packages) { [] }
subject { last_response }
before do
work_packages.each(&:save!)
get path
end
it 'succeeds' do
expect(subject.status).to eql 200
end
context 'not allowed to see the project' do
let(:current_user) { FactoryBot.build(:user) }
it 'fails with HTTP Not Found' do
expect(subject.status).to eql 404
end
end
context 'not allowed to see work packages' do
let(:permissions) { [:view_project] }
it 'fails with HTTP Not Found' do
expect(subject.status).to eql 403
end
end
describe 'advanced query options' do
let(:base_path) { api_v3_paths.work_packages_by_project project.id }
let(:query) { {} }
let(:path) { "#{base_path}?#{query.to_query}" }
describe 'sorting' do
let(:query) { { sortBy: '[["id", "desc"]]' } }
let(:work_packages) { FactoryBot.create_list(:work_package, 2, project: project) }
it 'returns both elements' do
expect(subject.body).to be_json_eql(2).at_path('count')
expect(subject.body).to be_json_eql(2).at_path('total')
end
it 'returns work packages in the expected order' do
first_wp = work_packages.first
last_wp = work_packages.last
expect(subject.body).to be_json_eql(last_wp.id).at_path('_embedded/elements/0/id')
expect(subject.body).to be_json_eql(first_wp.id).at_path('_embedded/elements/1/id')
end
end
describe 'filtering' do
let(:query) do
{
filters: [
{
priority: {
operator: '=',
values: [priority1.id.to_s]
}
}
].to_json
}
end
let(:priority1) { FactoryBot.create(:priority, name: 'Prio A') }
let(:priority2) { FactoryBot.create(:priority, name: 'Prio B') }
let(:work_packages) do
[
FactoryBot.create(:work_package, project: project, priority: priority1),
FactoryBot.create(:work_package, project: project, priority: priority2)
]
end
it 'returns only one element' do
expect(subject.body).to be_json_eql(1).at_path('count')
expect(subject.body).to be_json_eql(1).at_path('total')
end
it 'returns the matching element' do
expected_id = work_packages.first.id
expect(subject.body).to be_json_eql(expected_id).at_path('_embedded/elements/0/id')
end
end
describe 'grouping' do
let(:query) { { groupBy: 'priority' } }
let(:priority1) { FactoryBot.build(:priority, name: 'Prio A', position: 2) }
let(:priority2) { FactoryBot.build(:priority, name: 'Prio B', position: 1) }
let(:work_packages) do
[
FactoryBot.create(:work_package,
project: project,
priority: priority1,
estimated_hours: 1),
FactoryBot.create(:work_package,
project: project,
priority: priority2,
estimated_hours: 2),
FactoryBot.create(:work_package,
project: project,
priority: priority1,
estimated_hours: 3)
]
end
let(:expected_group1) do
{
_links: {
valueLink: [{
href: api_v3_paths.priority(priority1.id)
}],
groupBy: {
href: api_v3_paths.query_group_by('priority'),
title: 'Priority'
}
},
value: priority1.name,
count: 2
}
end
let(:expected_group2) do
{
_links: {
valueLink: [{
href: api_v3_paths.priority(priority2.id)
}],
groupBy: {
href: api_v3_paths.query_group_by('priority'),
title: 'Priority'
}
},
value: priority2.name,
count: 1
}
end
it 'returns all elements' do
expect(subject.body).to be_json_eql(3).at_path('count')
expect(subject.body).to be_json_eql(3).at_path('total')
end
it 'returns work packages ordered by priority' do
prio1_path = api_v3_paths.priority(priority1.id)
prio2_path = api_v3_paths.priority(priority2.id)
expect(subject.body).to(be_json_eql(prio2_path.to_json)
.at_path('_embedded/elements/0/_links/priority/href'))
expect(subject.body).to(be_json_eql(prio1_path.to_json)
.at_path('_embedded/elements/1/_links/priority/href'))
expect(subject.body).to(be_json_eql(prio1_path.to_json)
.at_path('_embedded/elements/2/_links/priority/href'))
end
it 'contains group elements' do
expect(subject.body).to include_json(expected_group1.to_json).at_path('groups')
expect(subject.body).to include_json(expected_group2.to_json).at_path('groups')
end
context 'displaying sums' do
let(:query) { { groupBy: 'priority', showSums: 'true' } }
let(:expected_group1) do
{
_links: {
valueLink: [{
href: api_v3_paths.priority(priority1.id)
}],
groupBy: {
href: api_v3_paths.query_group_by('priority'),
title: 'Priority'
}
},
value: priority1.name,
count: 2,
sums: {
estimatedTime: 'PT4H',
laborCosts: "0.00 EUR",
materialCosts: "0.00 EUR",
overallCosts: "0.00 EUR",
remainingTime: nil,
storyPoints: nil
}
}
end
let(:expected_group2) do
{
_links: {
valueLink: [{
href: api_v3_paths.priority(priority2.id)
}],
groupBy: {
href: api_v3_paths.query_group_by('priority'),
title: 'Priority'
}
},
value: priority2.name,
count: 1,
sums: {
estimatedTime: 'PT2H',
laborCosts: "0.00 EUR",
materialCosts: "0.00 EUR",
overallCosts: "0.00 EUR",
remainingTime: nil,
storyPoints: nil
}
}
end
it 'contains extended group elements' do
expect(subject.body).to include_json(expected_group1.to_json).at_path('groups')
expect(subject.body).to include_json(expected_group2.to_json).at_path('groups')
end
end
end
describe 'displaying sums' do
let(:query) { { showSums: 'true' } }
let(:work_packages) do
[
FactoryBot.create(:work_package, project: project, estimated_hours: 1),
FactoryBot.create(:work_package, project: project, estimated_hours: 2)
]
end
it 'returns both elements' do
expect(subject.body).to be_json_eql(2).at_path('count')
expect(subject.body).to be_json_eql(2).at_path('total')
end
it 'contains the sum element' do
expected = {
estimatedTime: 'PT3H',
laborCosts: "0.00 EUR",
materialCosts: "0.00 EUR",
overallCosts: "0.00 EUR",
remainingTime: nil,
storyPoints: nil
}
expect(subject.body).to be_json_eql(expected.to_json).at_path('totalSums')
end
end
end
end
describe '#post' do
let(:permissions) { %i[add_work_packages view_project] }
let(:status) { FactoryBot.build(:status, is_default: true) }
let(:priority) { FactoryBot.build(:priority, is_default: true) }
let(:other_user) { nil }
let(:parameters) do
{
subject: 'new work packages',
_links: {
type: {
href: api_v3_paths.type(project.types.first.id)
}
}
}
end
before do
status.save!
priority.save!
other_user
perform_enqueued_jobs do
post path, parameters.to_json
end
end
describe 'notifications' do
let(:other_user) { FactoryBot.create(:user, member_in_project: project, member_with_permissions: %i(view_work_packages)) }
it 'creates a notification' do
expect(Notification.where(recipient: other_user, resource: WorkPackage.last))
.to exist
end
context 'without notifications' do
let(:path) { "#{api_v3_paths.work_packages_by_project(project.id)}?notify=false" }
it 'creates no notification' do
expect(Notification)
.not_to exist
end
end
context 'with notifications' do
let(:path) { "#{api_v3_paths.work_packages_by_project(project.id)}?notify=true" }
it 'creates a notification' do
expect(Notification.where(recipient: other_user, resource: WorkPackage.last))
.to exist
end
end
end
it 'should return Created(201)' do
expect(last_response.status).to eq(201)
end
it 'should create a work package' do
expect(WorkPackage.all.count).to eq(1)
end
it 'should use the given parameters' do
expect(WorkPackage.first.subject).to eq(parameters[:subject])
end
context 'no permissions' do
let(:current_user) { FactoryBot.create(:user) }
it 'should hide the endpoint' do
expect(last_response.status).to eq(404)
end
end
context 'view_project permission' do
# Note that this just removes the add_work_packages permission
# view_project is actually provided by being a member of the project
let(:permissions) { [:view_project] }
it 'should point out the missing permission' do
expect(last_response.status).to eq(403)
end
end
context 'empty parameters' do
let(:parameters) { {} }
it_behaves_like 'constraint violation' do
let(:message) { "Subject can't be blank" }
end
it 'should not create a work package' do
expect(WorkPackage.all.count).to eq(0)
end
end
context 'bogus parameters' do
let(:parameters) do
{
bogus: 'bogus',
_links: {
type: {
href: api_v3_paths.type(project.types.first.id)
}
}
}
end
it_behaves_like 'constraint violation' do
let(:message) { "Subject can't be blank" }
end
it 'should not create a work package' do
expect(WorkPackage.all.count).to eq(0)
end
end
context 'invalid value' do
let(:parameters) do
{
subject: nil,
_links: {
type: {
href: api_v3_paths.type(project.types.first.id)
}
}
}
end
it_behaves_like 'constraint violation' do
let(:message) { "Subject can't be blank" }
end
it 'should not create a work package' do
expect(WorkPackage.all.count).to eq(0)
end
end
end
end
Loading…
Cancel
Save