mirror of
https://github.com/opf/openproject.git
synced 2026-06-14 03:30:14 +00:00
655756631f
* Create a FullView::CopyComponent for WorkPackages which is routed from rails * Remove angular splitCopy route and component as it was overwritten by the angular fullCopy route for quite some time already and nobody complained. So we decided to remove the splitCopy completely * Create FullView::CreateComponent for WorkPackages which is now routed from rails instead of Angular * First draft of implementing the FullView route for WorkPackages from rails * Pass correct tab from the URL to the FullView::ShowComponent * Do a hard reload to "create" route when we are not routed from Angular * Adapt routing spec to new WorkPackage routes and to some fine-tuning with the WP routes * Show correct tab in WP Full view and change URL when clicking a tab entry * Adapt to new rails based routing * Fix some routes and redirects * Make sure, the split screen stil renders correctly * Remove back button from WP full view * Fix routing issues * Start fixing specs * Attempt to override the browser history to be able to use browser back * Use helper function to build new WP url string * Adapt spec that now partially renders backend toasts * Remove ability to move to fullscreen Theoretically, we can re-add it by posting to some form endpoint, but not worth it for the first iteration * Disable cache-control on angular routed pages, so back links work * Fix double click to fullscreen * Adapt navigation and title setting * Let WP breadcrumb to a hard reload instead of Angular transition * Redirect when the WP route is incomplete (this is the attempt to re-implement an angular functionality) * Navigate with Turbo when double clicking a card * Adapt onboarding tour to new hard reload when switching to WP full view * Fix some specs * Fix more tests * Hide Overview tab on FullView * Correct check for incomplete routes * Do a hard refresh when coming from slpit screen to full view * Fix notification navigation * Adapt attachment spec as the tab switch cannot be done anymore while dragging * Fix more tests * Please rubocop and fix more tests * Attempt to fix navigation_spec * Add debian_base for pullpreview --------- Co-authored-by: Oliver Günther <mail@oliverguenther.de>
374 lines
12 KiB
Ruby
374 lines
12 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
#-- copyright
|
|
# OpenProject is an open source project management software.
|
|
# Copyright (C) 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"
|
|
|
|
RSpec.describe WorkPackagesController do
|
|
before do
|
|
login_as current_user
|
|
end
|
|
|
|
let(:project) { create(:project, identifier: "test_project", public: false) }
|
|
let(:other_project) { build_stubbed(:project) }
|
|
let(:stub_project) { build_stubbed(:project, identifier: "test_project", public: false) }
|
|
let(:type) { build_stubbed(:type) }
|
|
let(:stub_work_package) do
|
|
build_stubbed(:work_package,
|
|
id: 1337,
|
|
type:,
|
|
project: stub_project)
|
|
end
|
|
|
|
let(:current_user) { create(:user) }
|
|
|
|
def self.requires_permission_in_project(&)
|
|
describe "w/o the permission to see the project/work_package" do
|
|
before do
|
|
allow(controller).to receive(:work_package).and_return(nil)
|
|
|
|
call_action
|
|
end
|
|
|
|
it "renders a 404" do
|
|
expect(response.response_code).to be === 404
|
|
end
|
|
end
|
|
|
|
describe "with the permission to see the project " \
|
|
"with having the necessary permissions" do
|
|
before do
|
|
expect(WorkPackage).to receive_message_chain("visible.find_by").and_return(stub_work_package)
|
|
mock_permissions_for(current_user) do |mock|
|
|
mock.allow_in_project :view_work_packages, project: stub_work_package.project
|
|
end
|
|
end
|
|
|
|
instance_eval(&)
|
|
end
|
|
end
|
|
|
|
def self.requires_export_permission(&)
|
|
describe "with the export permission " \
|
|
"without a project" do
|
|
let(:project) { nil }
|
|
let(:other_project) { build_stubbed(:project) }
|
|
|
|
before do
|
|
mock_permissions_for(current_user) do |mock|
|
|
mock.allow_in_project :export_work_packages, project: other_project
|
|
end
|
|
end
|
|
|
|
instance_eval(&)
|
|
end
|
|
|
|
describe "with the export permission " \
|
|
"with a project" do
|
|
before do
|
|
params[:project_id] = project.id
|
|
|
|
mock_permissions_for(current_user) do |mock|
|
|
mock.allow_in_project :export_work_packages, project:
|
|
end
|
|
end
|
|
|
|
instance_eval(&)
|
|
end
|
|
|
|
describe "w/o the export permission" do
|
|
let(:project) { nil }
|
|
|
|
before do
|
|
mock_permissions_for(current_user, &:forbid_everything)
|
|
|
|
call_action
|
|
end
|
|
|
|
it "renders a 403" do
|
|
expect(response.response_code).to eq(403)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "index" do
|
|
let(:query) { build_stubbed(:query).tap(&:add_default_filter) }
|
|
let(:work_packages) { double("work packages").as_null_object }
|
|
let(:results) { double("results").as_null_object }
|
|
|
|
describe "with valid query" do
|
|
before do
|
|
mock_permissions_for(current_user) do |mock|
|
|
mock.allow_in_project :view_work_packages, project: other_project
|
|
mock.allow_in_project(:view_work_packages, project:) if project
|
|
end
|
|
|
|
allow(controller).to receive(:retrieve_query).and_return(query)
|
|
end
|
|
|
|
describe "html" do
|
|
let(:call_action) { get("index", params: { project_id: project.id }) }
|
|
|
|
before do
|
|
call_action
|
|
end
|
|
|
|
describe "without a project, but with view_work_packages permission on any project" do
|
|
let(:project) { nil }
|
|
let(:call_action) { get("index") }
|
|
|
|
it "renders the index template" do
|
|
expect(response).to render_template("work_packages/index")
|
|
end
|
|
end
|
|
|
|
context "with a project" do
|
|
it "renders the index template" do
|
|
expect(response).to render_template("work_packages/index")
|
|
end
|
|
end
|
|
end
|
|
|
|
shared_examples_for "export of mime_type" do
|
|
let(:export_storage) { build_stubbed(:work_packages_export) }
|
|
let(:call_action) { get("index", params: params.merge(format: mime_type)) }
|
|
|
|
requires_export_permission do
|
|
before do
|
|
service_instance = double("service_instance")
|
|
|
|
allow(WorkPackages::Exports::ScheduleService)
|
|
.to receive(:new)
|
|
.with(user: current_user)
|
|
.and_return(service_instance)
|
|
|
|
allow(service_instance)
|
|
.to receive(:call)
|
|
.with(query:, mime_type: mime_type.to_sym, params: anything)
|
|
.and_return(ServiceResult.failure(result: "uuid of the export job"))
|
|
end
|
|
|
|
it "redirects to the job status" do
|
|
call_action
|
|
expect(response).to redirect_to job_status_path("uuid of the export job")
|
|
end
|
|
|
|
context "with json accept" do
|
|
it "fulfills the defined should_receives" do
|
|
request.headers["Accept"] = "application/json"
|
|
call_action
|
|
expect(response.body).to eq({ job_id: "uuid of the export job" }.to_json)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "csv" do
|
|
let(:params) { {} }
|
|
let(:mime_type) { "csv" }
|
|
|
|
it_behaves_like "export of mime_type"
|
|
end
|
|
|
|
describe "pdf" do
|
|
let(:params) { {} }
|
|
let(:mime_type) { "pdf" }
|
|
|
|
it_behaves_like "export of mime_type"
|
|
end
|
|
|
|
describe "atom" do
|
|
let(:params) { {} }
|
|
let(:call_action) { get("index", params: params.merge(format: "atom")) }
|
|
|
|
requires_export_permission do
|
|
before do
|
|
# Note: Stubs for methods used to build up the json query results.
|
|
# TODO RS: Clearly this isn't testing anything, but it all needs to be moved to an API controller anyway.
|
|
allow(query).to receive(:results).and_return(results)
|
|
allow(results).to receive_message_chain(:work_packages, :page, :per_page).and_return(work_packages)
|
|
|
|
expect(controller).to receive(:render_feed).with(work_packages, anything) do |*_args|
|
|
# We need to render something because otherwise
|
|
# the controller will and it will not find a suitable template
|
|
controller.render plain: "success"
|
|
end
|
|
end
|
|
|
|
it "fulfills the defined should_receives" do
|
|
call_action
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "with invalid query" do
|
|
describe "pdf" do
|
|
let(:call_action) { get("index", params: params.merge(format: "pdf")) }
|
|
let(:params) { { query_id: "hokusbogus" } }
|
|
|
|
context "when a non-existent query has been previously selected" do
|
|
before do
|
|
mock_permissions_for(current_user, &:allow_everything)
|
|
|
|
allow(controller)
|
|
.to receive(:retrieve_query)
|
|
.and_raise(ActiveRecord::RecordNotFound)
|
|
|
|
call_action
|
|
end
|
|
|
|
it "renders a 404" do
|
|
expect(response.response_code).to be 404
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "index with a broken project reference" do
|
|
before do
|
|
get("index", params: { project_id: "project_that_doesnt_exist" })
|
|
end
|
|
|
|
it { is_expected.to respond_with :not_found }
|
|
end
|
|
|
|
describe "show.html" do
|
|
let(:call_action) { get("show", params: { id: "1337" }) }
|
|
|
|
requires_permission_in_project do
|
|
it "redirects to the full url" do
|
|
call_action
|
|
|
|
expect(response).to redirect_to("/projects/test_project/work_packages/1337/activity")
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "show.pdf" do
|
|
let(:call_action) { get("show", params: { format: "pdf", id: "1337" }) }
|
|
let(:exporter) { WorkPackage::PDFExport::WorkPackageToPdf }
|
|
let(:exporter_instance) { instance_double(exporter) }
|
|
|
|
before do
|
|
allow(exporter).to receive(:new).and_return(exporter_instance)
|
|
end
|
|
|
|
requires_permission_in_project do
|
|
it "respond with a pdf" do
|
|
pdf_data = "foobar"
|
|
time = DateTime.new(2023, 6, 30, 23, 59)
|
|
allow(DateTime).to receive(:now).and_return(time)
|
|
expected_name = [stub_work_package.project.identifier, "##{stub_work_package.id}",
|
|
stub_work_package.subject, "2023-06-30_23-59"].join("_").tr(" ", "-")
|
|
expected_type = "application/pdf"
|
|
pdf_result = double("pdf_result",
|
|
error?: false,
|
|
content: pdf_data,
|
|
title: expected_name,
|
|
mime_type: expected_type)
|
|
|
|
allow(exporter_instance).to receive(:export!).and_return(pdf_result)
|
|
expect(controller).to receive(:send_data).with(pdf_data,
|
|
type: expected_type,
|
|
filename: expected_name) do |*_args|
|
|
# We need to render something because otherwise
|
|
# the controller will and it will not find a suitable template
|
|
controller.render plain: "success"
|
|
end
|
|
call_action
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "show.atom" do
|
|
let(:call_action) { get("show", params: { format: "atom", id: "1337" }) }
|
|
|
|
requires_permission_in_project do
|
|
it "render the journal/index template" do
|
|
call_action
|
|
expect(response).to render_template("journals/index")
|
|
end
|
|
end
|
|
|
|
context "when there are internal comments" do
|
|
render_views
|
|
|
|
let(:admin) { create(:admin) }
|
|
let(:project) do
|
|
create(:project, identifier: "test_project", public: false, enabled_internal_comments: true)
|
|
end
|
|
|
|
before do
|
|
work_package = create(:work_package, id: 5173, project:)
|
|
create(:work_package_journal,
|
|
journable: work_package,
|
|
user: admin,
|
|
notes: "internal comment",
|
|
internal: true,
|
|
version: 2)
|
|
end
|
|
|
|
context "and the user does not have permission to see such comments" do
|
|
it "does not include internal comments" do
|
|
get("show", params: { format: "atom", id: 5173 })
|
|
expect(response.body).not_to include("internal comment")
|
|
end
|
|
end
|
|
|
|
context "and the user has permission to see such comments" do
|
|
before do
|
|
login_as admin
|
|
end
|
|
|
|
it "includes internal comments" do
|
|
get("show", params: { format: "atom", id: 5173 })
|
|
expect(response.body).to include("internal comment")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "redirect deep link", with_settings: { login_required?: true } do
|
|
let(:current_user) { User.anonymous }
|
|
let(:params) do
|
|
{ project_id: project.id }
|
|
end
|
|
|
|
it "redirects to collection with query" do
|
|
get "index", params: params.merge(query_id: 123, query_props: "foo")
|
|
expect(response).to be_redirect
|
|
|
|
location = "/projects/#{project.id}/work_packages?query_id=123&query_props=foo"
|
|
expect(response.location).to end_with(CGI.escape(location))
|
|
end
|
|
end
|
|
end
|