Extend project filter with replaced values and add spec

pull/10368/head
Oliver Günther 3 years ago
parent e5b05b9fa0
commit df220ed594
No known key found for this signature in database
GPG Key ID: A3A8BDAD7C0C552C
  1. 19
      app/models/queries/work_packages/filter/project_filter.rb
  2. 3
      app/seeders/demo_data/query_builder.rb
  3. 1
      app/seeders/demo_data/work_package_board_seeder.rb
  4. 6
      lib/api/v3/queries/query_representer.rb
  5. 8
      modules/calendar/spec/features/calendar_project_include_spec.rb
  6. 8
      modules/team_planner/spec/features/team_planner_project_include_spec.rb
  7. 14
      spec/features/work_packages/table/work_packages_table_project_include_spec.rb
  8. 6
      spec/features/work_packages/timeline/timeline_labels_spec.rb
  9. 15
      spec/lib/api/v3/queries/query_representer_parsing_spec.rb
  10. 20
      spec/models/queries/work_packages/filter/project_filter_spec.rb
  11. 150
      spec/models/query/results_project_filter_integration_spec.rb
  12. 8
      spec/services/principals/replace_references_service_call_integration_spec.rb

@ -59,8 +59,13 @@ class Queries::WorkPackages::Filter::ProjectFilter < Queries::WorkPackages::Filt
available_projects = visible_projects.index_by(&:id)
values
.flat_map { |project_id| expanded_subprojects(available_projects[project_id.to_i]) }
.flat_map { |project_id| available_projects[project_id.to_i] }
.compact
.uniq
end
def where
operator_strategy.sql_for_field(projects_and_descendants, self.class.model.table_name, :project_id)
end
private
@ -72,13 +77,17 @@ class Queries::WorkPackages::Filter::ProjectFilter < Queries::WorkPackages::Filt
##
# Depending on whether subprojects are included in the query,
# expand selected projects with its descendants
def expanded_subprojects(selected_project)
return if selected_project.nil?
def projects_and_descendants
value_objects
.inject(Set.new) { |project_set, project| project_set + expand_subprojects(project) }
.map(&:id)
end
def expand_subprojects(selected_project)
if context.include_subprojects?
[selected_project]
else
[selected_project].concat(selected_project.descendants.visible)
else
[selected_project]
end
end
end

@ -52,7 +52,8 @@ module DemoData
public: config.fetch(:public, true),
starred: config.fetch(:starred, false),
show_hierarchies: config.fetch(:hierarchy, false),
timeline_visible: config.fetch(:timeline, false)
timeline_visible: config.fetch(:timeline, false),
include_subprojects: true
}
end

@ -160,6 +160,7 @@ module DemoData
Query.new(project: project, user: admin).tap do |query|
# Make it public so that new members can see it too
query.public = true
query.include_subprojects = true
query.name = list[:name]

@ -259,11 +259,9 @@ module API
exec_context: :decorator,
getter: nil,
setter: ->(fragment:, **) {
next unless represented.new_record?
next if represented.persisted?
Hash(fragment).each do |wp_id, position|
represented.ordered_work_packages.build(work_package_id: wp_id, position: position)
end
represented.ordered_work_packages = fragment
}
property :starred,

@ -50,8 +50,8 @@ describe 'Calendar project include', type: :feature, js: true do
dropdown.expect_closed
work_package_view.expect_event task
work_package_view.expect_event sub_bug, present: false
work_package_view.expect_event sub_sub_bug, present: false
work_package_view.expect_event sub_bug, present: true
work_package_view.expect_event sub_sub_bug, present: true
work_package_view.expect_event other_task
work_package_view.expect_event other_other_task, present: false
@ -60,7 +60,7 @@ describe 'Calendar project include', type: :feature, js: true do
dropdown.click_button 'Apply'
dropdown.expect_count 2
work_package_view.expect_event sub_bug, present: false
work_package_view.expect_event sub_bug, present: true
work_package_view.expect_event sub_sub_bug
dropdown.toggle!
@ -74,7 +74,7 @@ describe 'Calendar project include', type: :feature, js: true do
page.refresh
work_package_view.expect_event task
work_package_view.expect_event sub_bug, present: false
work_package_view.expect_event sub_bug, present: true
work_package_view.expect_event sub_sub_bug
work_package_view.expect_event other_task
work_package_view.expect_event other_other_task

@ -76,8 +76,8 @@ describe 'Team planner project include', type: :feature, js: true do
work_package_view.within_lane(user) do
work_package_view.expect_event task
work_package_view.expect_event sub_bug, present: false
work_package_view.expect_event sub_sub_bug, present: false
work_package_view.expect_event sub_bug, present: true
work_package_view.expect_event sub_sub_bug, present: true
end
work_package_view.within_lane(other_user) do
@ -92,7 +92,7 @@ describe 'Team planner project include', type: :feature, js: true do
work_package_view.within_lane(user) do
work_package_view.expect_event task
work_package_view.expect_event sub_bug, present: false
work_package_view.expect_event sub_bug, present: true
work_package_view.expect_event sub_sub_bug
end
@ -115,7 +115,7 @@ describe 'Team planner project include', type: :feature, js: true do
work_package_view.within_lane(user) do
work_package_view.expect_event task
work_package_view.expect_event sub_bug, present: false
work_package_view.expect_event sub_bug, present: true
work_package_view.expect_event sub_sub_bug
end
end

@ -45,29 +45,27 @@ describe 'Calendar project include', type: :feature, js: true do
dropdown.click_button 'Apply'
dropdown.expect_closed
work_package_view.expect_work_package_listed(task, other_task)
work_package_view.ensure_work_package_not_listed!(sub_bug, sub_sub_bug, other_other_task)
work_package_view.expect_work_package_listed(task, other_task, sub_bug, sub_sub_bug)
work_package_view.ensure_work_package_not_listed!(other_other_task)
dropdown.toggle!
dropdown.toggle_checkbox(sub_sub_project.id)
dropdown.click_button 'Apply'
dropdown.expect_count 2
work_package_view.expect_work_package_listed(task, other_task, sub_sub_bug)
work_package_view.ensure_work_package_not_listed!(sub_bug, other_other_task)
work_package_view.expect_work_package_listed(task, other_task, sub_sub_bug, sub_bug)
work_package_view.ensure_work_package_not_listed!(other_other_task)
dropdown.toggle!
dropdown.toggle_checkbox(other_project.id)
dropdown.click_button 'Apply'
dropdown.expect_count 3
work_package_view.expect_work_package_listed(task, other_task, sub_sub_bug, other_other_task)
work_package_view.ensure_work_package_not_listed!(sub_bug)
work_package_view.expect_work_package_listed(task, other_task, sub_sub_bug, sub_bug, other_other_task)
page.refresh
work_package_view.expect_work_package_listed(task, other_task, sub_sub_bug, other_other_task)
work_package_view.ensure_work_package_not_listed!(sub_bug)
work_package_view.expect_work_package_listed(task, other_task, sub_bug, sub_sub_bug, other_other_task)
end
end
end

@ -135,9 +135,9 @@ RSpec.feature 'Work package timeline labels',
# Check the query
query = Query.last
expect(query.timeline_labels).to eq 'left' => 'assignee',
'right' => 'type',
'farRight' => 'status'
expect(query.timeline_labels).to eq left: 'assignee',
right: 'type',
farRight: 'status'
# Revisit page
wp_timeline.visit_query query

@ -31,7 +31,7 @@ require 'spec_helper'
describe ::API::V3::Queries::QueryRepresenter, 'parsing' do
include ::API::V3::Utilities::PathHelper
let(:query) { build_stubbed(:query, project: project) }
let(:query) { ::API::ParserStruct.new }
let(:project) { build_stubbed(:project) }
let(:user) { build_stubbed(:user) }
let(:representer) do
@ -82,10 +82,7 @@ describe ::API::V3::Queries::QueryRepresenter, 'parsing' do
end
it 'unsets group_by' do
expect(query).to be_grouped
expect(query.group_by).to eq('project')
expect(subject).not_to be_grouped
end
end
@ -115,20 +112,20 @@ describe ::API::V3::Queries::QueryRepresenter, 'parsing' do
end
before do
allow(query).to receive(:new_record?).and_return(new_record)
allow(query).to receive(:persisted?).and_return(persisted)
end
context 'if query is new' do
let(:new_record) { true }
let(:persisted) { nil }
it 'sets ordered_work_packages' do
order = subject.ordered_work_packages.map { |el| [el.work_package_id, el.position] }
expect(order).to match_array [[50, 0], [38, 1234], [102, 81234123]]
order = subject.ordered_work_packages
expect(order).to eq({ '50' => 0, '38' => 1234, '102' => 81234123 })
end
end
context 'if query is not new' do
let(:new_record) { false }
let(:persisted) { true }
it 'sets ordered_work_packages' do
allow(query)

@ -106,13 +106,29 @@ describe Queries::WorkPackages::Filter::ProjectFilter, type: :model do
end
describe '#value_objects' do
let(:selected) { visible_projects.first }
let(:visible_descendants) { [] }
let(:descendants) { double('Project', visible: visible_descendants) } # rubocop:disable RSpec/VerifiedDoubles
before do
instance.values = [visible_projects.first.id.to_s]
allow(selected).to receive(:descendants).and_return(descendants)
instance.values = [selected.id.to_s]
end
it 'returns an array of projects' do
expect(instance.value_objects)
.to match_array([visible_projects.first])
.to match_array([selected])
end
context 'with a visible child' do
let(:child) { build_stubbed(:project, parent: selected, id: 2134) }
let(:visible_descendants) { [child] }
it 'still only returns the parent object' do
expect(instance.value_objects)
.to match_array([selected])
end
end
end
end

@ -0,0 +1,150 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2022 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'
describe ::Query::Results, 'Project filter integration', type: :model, with_mail: false do
let(:query) do
build(:query,
user: user,
project: parent_project).tap do |q|
q.filters.clear
end
end
let(:query_results) do
described_class.new query
end
shared_let(:parent_project) { create :project }
shared_let(:child_project) { create :project, parent: parent_project }
shared_let(:second_parent_project) { create :project }
shared_let(:second_child_project) { create :project, parent: second_parent_project }
shared_let(:user) do
create(:user,
firstname: 'user',
lastname: '1',
member_in_projects: [parent_project, child_project, second_parent_project, second_child_project],
member_with_permissions: [:view_work_packages])
end
shared_let(:parent_wp) { create :work_package, project: parent_project }
shared_let(:child_wp) { create :work_package, project: child_project }
shared_let(:second_parent_wp) { create :work_package, project: second_parent_project }
shared_let(:second_child_wp) { create :work_package, project: second_child_project }
before do
login_as user
end
describe 'both parent projects selected' do
before do
query.add_filter 'project_id', '=', [parent_project.id, second_parent_project.id]
end
context 'when subprojects included', with_settings: { display_subprojects_work_packages: true } do
it 'shows the sub work packages' do
expect(query_results.work_packages).to match_array [parent_wp, child_wp, second_parent_wp, second_child_wp]
end
end
context 'when subprojects not included', with_settings: { display_subprojects_work_packages: false } do
it 'does not show the sub work packages' do
expect(query_results.work_packages).to match_array [parent_wp, second_parent_wp]
end
end
context 'when subprojects explicitly disabled' do
before do
query.include_subprojects = false
end
it 'does not show the sub work packages' do
expect(query_results.work_packages).to match_array [parent_wp, second_parent_wp]
end
end
end
describe 'one parent projects selected' do
before do
query.add_filter 'project_id', '=', [second_parent_project.id]
end
context 'when subprojects included', with_settings: { display_subprojects_work_packages: true } do
it 'shows the sub work packages' do
expect(query_results.work_packages).to match_array [second_parent_wp, second_child_wp]
end
end
context 'when subprojects not included', with_settings: { display_subprojects_work_packages: false } do
it 'does not show the sub work packages' do
expect(query_results.work_packages).to match_array [second_parent_wp]
end
end
context 'when subprojects explicitly disabled' do
before do
query.include_subprojects = false
end
it 'does not show the sub work packages' do
expect(query_results.work_packages).to match_array [second_parent_wp]
end
end
end
describe 'one parent and one other child selected' do
before do
query.add_filter 'project_id', '=', [child_project.id, second_parent_project.id]
end
context 'when subprojects included', with_settings: { display_subprojects_work_packages: true } do
it 'shows the sub work packages' do
expect(query_results.work_packages).to match_array [child_wp, second_parent_wp, second_child_wp]
end
end
context 'when subprojects not included', with_settings: { display_subprojects_work_packages: false } do
it 'does not show the sub work packages' do
expect(query_results.work_packages).to match_array [child_wp, second_parent_wp]
end
end
context 'when subprojects explicitly disabled' do
before do
query.include_subprojects = false
end
it 'does not show the sub work packages' do
expect(query_results.work_packages).to match_array [child_wp, second_parent_wp]
end
end
end
end

@ -380,7 +380,13 @@ describe Principals::ReplaceReferencesService, '#call', type: :model do
context 'with Query' do
it_behaves_like 'rewritten record',
:query,
:user_id
:user_id do
let(:attributes) do
{
include_subprojects: true
}
end
end
end
context 'with CostQuery' do

Loading…
Cancel
Save