parent
a51e4408c1
commit
3881b47e26
@ -0,0 +1,75 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module Queries::WorkPackages::Filter::FilterForWpMixin |
||||
def type |
||||
:list |
||||
end |
||||
|
||||
def allowed_values |
||||
raise NotImplementedError, 'There would be too many candidates' |
||||
end |
||||
|
||||
def value_objects |
||||
scope.find(values) |
||||
end |
||||
|
||||
def allowed_objects |
||||
raise NotImplementedError, 'There would be too many candidates' |
||||
end |
||||
|
||||
def available? |
||||
scope.exists? |
||||
end |
||||
|
||||
def ar_object_filter? |
||||
true |
||||
end |
||||
|
||||
def allowed_values_subset |
||||
scope.where(id: values).pluck(:id).map(&:to_s) |
||||
end |
||||
|
||||
private |
||||
|
||||
def scope |
||||
if context.project |
||||
WorkPackage |
||||
.visible |
||||
.for_projects(context.project.self_and_descendants) |
||||
else |
||||
WorkPackage.visible |
||||
end |
||||
end |
||||
|
||||
def type_strategy |
||||
@type_strategy ||= Queries::Filters::Strategies::HugeList.new(self) |
||||
end |
||||
end |
@ -0,0 +1,47 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
require_relative './filter_for_wp_mixing' |
||||
|
||||
class Queries::WorkPackages::Filter::ParentFilter < |
||||
Queries::WorkPackages::Filter::WorkPackageFilter |
||||
|
||||
include ::Queries::WorkPackages::Filter::FilterForWpMixin |
||||
|
||||
def includes |
||||
:parent_relation |
||||
end |
||||
|
||||
def where |
||||
operator_strategy.sql_for_field(values, |
||||
Relation.table_name, |
||||
'from_id') |
||||
end |
||||
end |
@ -0,0 +1,59 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module API |
||||
module V3 |
||||
module Queries |
||||
module Schemas |
||||
class ByWorkPackageFilterDependencyRepresenter < |
||||
FilterDependencyRepresenter |
||||
|
||||
def json_cache_key |
||||
super + (filter.project.present? ? [filter.project.id] : []) |
||||
end |
||||
|
||||
def href_callback |
||||
if filter.project |
||||
api_v3_paths.work_packages_by_project(filter.project.id) |
||||
else |
||||
api_v3_paths.work_packages |
||||
end |
||||
end |
||||
|
||||
private |
||||
|
||||
def type |
||||
'[]WorkPackage' |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,39 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
module API |
||||
module V3 |
||||
module Queries |
||||
module Schemas |
||||
class ParentFilterDependencyRepresenter < ByWorkPackageFilterDependencyRepresenter; end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,133 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
require 'spec_helper' |
||||
|
||||
describe ::API::V3::Queries::Schemas::ParentFilterDependencyRepresenter, clear_cache: true do |
||||
include ::API::V3::Utilities::PathHelper |
||||
|
||||
let(:project) { FactoryGirl.build_stubbed(:project) } |
||||
let(:query) { FactoryGirl.build_stubbed(:query, project: project) } |
||||
let(:filter) { Queries::WorkPackages::Filter::ParentFilter.create!(context: query) } |
||||
let(:form_embedded) { false } |
||||
|
||||
let(:instance) do |
||||
described_class.new(filter, |
||||
operator, |
||||
form_embedded: form_embedded) |
||||
end |
||||
|
||||
subject(:generated) { instance.to_json } |
||||
|
||||
context 'generation' do |
||||
context 'properties' do |
||||
describe 'values' do |
||||
context 'within project' do |
||||
let(:path) { 'values' } |
||||
let(:type) { '[]WorkPackage' } |
||||
let(:href) { api_v3_paths.work_packages_by_project(project.id) } |
||||
|
||||
context "for operator 'Queries::Operators::Equals'" do |
||||
let(:operator) { Queries::Operators::Equals } |
||||
|
||||
it_behaves_like 'filter dependency with allowed link' |
||||
end |
||||
|
||||
context "for operator 'Queries::Operators::NotEquals'" do |
||||
let(:operator) { Queries::Operators::NotEquals } |
||||
|
||||
it_behaves_like 'filter dependency with allowed link' |
||||
end |
||||
end |
||||
|
||||
context 'outside of a project' do |
||||
let(:project) { nil } |
||||
let(:path) { 'values' } |
||||
let(:type) { '[]WorkPackage' } |
||||
let(:href) { api_v3_paths.work_packages } |
||||
|
||||
context "for operator 'Queries::Operators::Equals'" do |
||||
let(:operator) { Queries::Operators::Equals } |
||||
|
||||
it_behaves_like 'filter dependency with allowed link' |
||||
end |
||||
|
||||
context "for operator 'Queries::Operators::NotEquals'" do |
||||
let(:operator) { Queries::Operators::NotEquals } |
||||
|
||||
it_behaves_like 'filter dependency with allowed link' |
||||
end |
||||
end |
||||
end |
||||
end |
||||
|
||||
describe 'caching' do |
||||
let(:operator) { Queries::Operators::Equals } |
||||
let(:other_project) { FactoryGirl.build_stubbed(:project) } |
||||
|
||||
before do |
||||
# fill the cache |
||||
instance.to_json |
||||
end |
||||
|
||||
it 'is cached' do |
||||
expect(instance) |
||||
.not_to receive(:to_hash) |
||||
|
||||
instance.to_json |
||||
end |
||||
|
||||
it 'busts the cache on a different operator' do |
||||
instance.send(:operator=, Queries::Operators::NotEquals) |
||||
|
||||
expect(instance) |
||||
.to receive(:to_hash) |
||||
|
||||
instance.to_json |
||||
end |
||||
|
||||
it 'busts the cache on a different project' do |
||||
query.project = other_project |
||||
|
||||
expect(instance) |
||||
.to receive(:to_hash) |
||||
|
||||
instance.to_json |
||||
end |
||||
|
||||
it 'busts the cache on changes to the locale' do |
||||
expect(instance) |
||||
.to receive(:to_hash) |
||||
|
||||
I18n.with_locale(:de) do |
||||
instance.to_json |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,259 @@ |
||||
#-- encoding: UTF-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF) |
||||
# |
||||
# 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-2017 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 docs/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
require 'spec_helper' |
||||
|
||||
describe Queries::WorkPackages::Filter::ParentFilter, type: :model do |
||||
let(:project) { FactoryGirl.build_stubbed(:project) } |
||||
let(:query) do |
||||
FactoryGirl.build_stubbed(:query, project: project) |
||||
end |
||||
|
||||
it_behaves_like 'basic query filter' do |
||||
let(:class_key) { :parent } |
||||
let(:type) { :list } |
||||
|
||||
before do |
||||
instance.context = query |
||||
end |
||||
|
||||
describe '#available?' do |
||||
context 'within a project' do |
||||
it 'is true if any work package exists and is visible' do |
||||
allow(WorkPackage) |
||||
.to receive_message_chain(:visible, :for_projects, :exists?) |
||||
.with(no_args) |
||||
.with(project) |
||||
.with(no_args) |
||||
.and_return true |
||||
|
||||
expect(instance).to be_available |
||||
end |
||||
|
||||
it 'is false if no work package exists/ is visible' do |
||||
allow(WorkPackage) |
||||
.to receive_message_chain(:visible, :for_projects, :exists?) |
||||
.with(no_args) |
||||
.with(project) |
||||
.with(no_args) |
||||
.and_return false |
||||
|
||||
expect(instance).not_to be_available |
||||
end |
||||
end |
||||
|
||||
context 'outside of a project' do |
||||
let(:project) { nil } |
||||
|
||||
it 'is true if any work package exists and is visible' do |
||||
allow(WorkPackage) |
||||
.to receive_message_chain(:visible, :exists?) |
||||
.with(no_args) |
||||
.and_return true |
||||
|
||||
expect(instance).to be_available |
||||
end |
||||
|
||||
it 'is false if no work package exists/ is visible' do |
||||
allow(WorkPackage) |
||||
.to receive_message_chain(:visible, :exists?) |
||||
.with(no_args) |
||||
.and_return false |
||||
|
||||
expect(instance).not_to be_available |
||||
end |
||||
end |
||||
end |
||||
|
||||
describe '#ar_object_filter?' do |
||||
it 'is true' do |
||||
expect(instance).to be_ar_object_filter |
||||
end |
||||
end |
||||
|
||||
describe '#allowed_values' do |
||||
it 'raises an error' do |
||||
expect { instance.allowed_values }.to raise_error NotImplementedError |
||||
end |
||||
end |
||||
|
||||
describe '#value_object' do |
||||
let(:visible_wp) { FactoryGirl.build_stubbed(:work_package) } |
||||
|
||||
it 'returns the work package for the values' do |
||||
allow(WorkPackage) |
||||
.to receive_message_chain(:visible, :for_projects, :find) |
||||
.with(no_args) |
||||
.with(project) |
||||
.with(instance.values) |
||||
.and_return([visible_wp]) |
||||
|
||||
expect(instance.value_objects) |
||||
.to match_array [visible_wp] |
||||
end |
||||
end |
||||
|
||||
describe '#allowed_objects' do |
||||
it 'raises an error' do |
||||
expect { instance.allowed_objects }.to raise_error NotImplementedError |
||||
end |
||||
end |
||||
|
||||
describe '#valid_values!' do |
||||
let(:visible_wp) { FactoryGirl.build_stubbed(:work_package) } |
||||
let(:invisible_wp) { FactoryGirl.build_stubbed(:work_package) } |
||||
|
||||
context 'within a project' do |
||||
it 'removes all non existing/non visible ids' do |
||||
instance.values = [visible_wp.id.to_s, invisible_wp.id.to_s, '999999'] |
||||
|
||||
allow(WorkPackage) |
||||
.to receive_message_chain(:visible, :for_projects, :where, :pluck) |
||||
.with(no_args) |
||||
.with(project) |
||||
.with(id: instance.values) |
||||
.with(:id) |
||||
.and_return([visible_wp.id]) |
||||
|
||||
instance.valid_values! |
||||
|
||||
expect(instance.values) |
||||
.to match_array [visible_wp.id.to_s] |
||||
end |
||||
end |
||||
|
||||
context 'outside of a project' do |
||||
let(:project) { nil } |
||||
|
||||
it 'removes all non existing/non visible ids' do |
||||
instance.values = [visible_wp.id.to_s, invisible_wp.id.to_s, '999999'] |
||||
|
||||
allow(WorkPackage) |
||||
.to receive_message_chain(:visible, :where, :pluck) |
||||
.with(no_args) |
||||
.with(id: instance.values) |
||||
.with(:id) |
||||
.and_return([visible_wp.id]) |
||||
|
||||
instance.valid_values! |
||||
|
||||
expect(instance.values) |
||||
.to match_array [visible_wp.id.to_s] |
||||
end |
||||
end |
||||
end |
||||
|
||||
describe '#validate' do |
||||
let(:visible_wp) { FactoryGirl.build_stubbed(:work_package) } |
||||
let(:invisible_wp) { FactoryGirl.build_stubbed(:work_package) } |
||||
|
||||
context 'within a project' do |
||||
it 'is valid if only visible wps are values' do |
||||
instance.values = [visible_wp.id.to_s] |
||||
|
||||
allow(WorkPackage) |
||||
.to receive_message_chain(:visible, :for_projects, :where, :pluck) |
||||
.with(no_args) |
||||
.with(project) |
||||
.with(id: instance.values) |
||||
.with(:id) |
||||
.and_return([visible_wp.id]) |
||||
|
||||
expect(instance).to be_valid |
||||
end |
||||
|
||||
it 'is invalid if invisible wps are values' do |
||||
instance.values = [invisible_wp.id.to_s, visible_wp.id.to_s] |
||||
|
||||
allow(WorkPackage) |
||||
.to receive_message_chain(:visible, :for_projects, :where, :pluck) |
||||
.with(no_args) |
||||
.with(project) |
||||
.with(id: instance.values) |
||||
.with(:id) |
||||
.and_return([visible_wp.id]) |
||||
|
||||
expect(instance).not_to be_valid |
||||
end |
||||
end |
||||
|
||||
context 'outside of a project' do |
||||
let(:project) { nil } |
||||
|
||||
it 'is valid if only visible wps are values' do |
||||
instance.values = [visible_wp.id.to_s] |
||||
|
||||
allow(WorkPackage) |
||||
.to receive_message_chain(:visible, :where, :pluck) |
||||
.with(no_args) |
||||
.with(id: instance.values) |
||||
.with(:id) |
||||
.and_return([visible_wp.id]) |
||||
|
||||
expect(instance).to be_valid |
||||
end |
||||
|
||||
it 'is invalid if invisible wps are values' do |
||||
instance.values = [invisible_wp.id.to_s, visible_wp.id.to_s] |
||||
|
||||
allow(WorkPackage) |
||||
.to receive_message_chain(:visible, :where, :pluck) |
||||
.with(no_args) |
||||
.with(id: instance.values) |
||||
.with(:id) |
||||
.and_return([visible_wp.id]) |
||||
|
||||
expect(instance).not_to be_valid |
||||
end |
||||
end |
||||
end |
||||
|
||||
describe '#where and #includes' do |
||||
let(:parent) { FactoryGirl.create(:work_package) } |
||||
let(:visible_wp) { FactoryGirl.create(:work_package, parent: parent) } |
||||
|
||||
before do |
||||
visible_wp |
||||
instance.values = [parent.id.to_s] |
||||
instance.operator = '=' |
||||
end |
||||
|
||||
it 'filters' do |
||||
scope = WorkPackage |
||||
.references(instance.includes) |
||||
.includes(instance.includes) |
||||
.where(instance.where) |
||||
|
||||
expect(scope) |
||||
.to match_array [visible_wp] |
||||
end |
||||
end |
||||
end |
||||
end |
Loading…
Reference in new issue