mirror of
https://github.com/opf/openproject.git
synced 2026-06-14 03:30:14 +00:00
Implements the GET /work_packages/:id/wiki_page_links endpoint (#22834)
* Introduce the PageLinkQuery * Update page link query and some copyright * Adds PageLinkCollectionRepresenter * Introduces the endpoint /work_packages/id/wiki_page_links * MetadaService tests, most of it is a work of fiction * Adds urns for page link type improve some tests * Removes mentions to view_wiki_page_links permissions * Adds a test for multiple providers and same identifiers --- Co-authored-by: Jan Sandbrink <j.sandbrink@openproject.com>
This commit is contained in:
@@ -58,4 +58,4 @@ 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.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
+1
-1
@@ -20,6 +20,6 @@ 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.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
See COPYRIGHT and LICENSE files for more details.
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#
|
||||
# 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.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# See COPYRIGHT and LICENSE files for more details.
|
||||
#++
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
# 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.
|
||||
#++
|
||||
|
||||
module Queries
|
||||
module Wikis
|
||||
module PageLinks
|
||||
module Filter
|
||||
class ProviderFilter < Filters::Base
|
||||
self.model = ::Wikis::PageLink
|
||||
|
||||
def type = :list
|
||||
|
||||
def human_name
|
||||
::Wikis::PageLink.human_attribute_name(name)
|
||||
end
|
||||
|
||||
def allowed_values
|
||||
::Wikis::Provider.enabled.pluck(:universal_identifier).map { |uid| [uid, uid] }
|
||||
end
|
||||
|
||||
def left_outer_joins = :provider
|
||||
|
||||
def where
|
||||
operator_strategy.sql_for_field(values, ::Wikis::Provider.table_name, "universal_identifier")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,48 @@
|
||||
# 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.
|
||||
#++
|
||||
|
||||
module Queries
|
||||
module Wikis
|
||||
module PageLinks
|
||||
class PageLinkQuery
|
||||
include BaseQuery
|
||||
include UnpersistedQuery
|
||||
|
||||
def self.model
|
||||
@model ||= ::Wikis::PageLink
|
||||
end
|
||||
|
||||
def default_scope
|
||||
::Wikis::PageLink.includes(:provider).all
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,74 @@
|
||||
# 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.
|
||||
#++
|
||||
|
||||
module Wikis
|
||||
class PageLinkMetadataService
|
||||
# @param page_links [ActiveRecord::Relation<Wikis::PageLink>]
|
||||
def initialize(page_links)
|
||||
@result = ServiceResult.success(errors: ActiveModel::Errors.new(self))
|
||||
@relation = page_links
|
||||
end
|
||||
|
||||
# @return [ServiceResult<ActiveRecord::Relation<Wikis::PageLink>]
|
||||
def call
|
||||
metadata = relation.group_by(&:provider).flat_map do |provider, page_links|
|
||||
build_inputs(page_links).filter_map do |input_data|
|
||||
provider.resolve("queries.page_info").call(input_data).value_or(nil)
|
||||
end
|
||||
end
|
||||
|
||||
@result.result = enrich_models(metadata)
|
||||
@result
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :relation
|
||||
|
||||
def build_inputs(page_links)
|
||||
page_links.filter_map do |page_link|
|
||||
Adapters::Input::PageInfo.build(identifier: page_link.identifier).value_or(nil)
|
||||
end
|
||||
end
|
||||
|
||||
def enrich_models(metadata)
|
||||
identifier_title_map = metadata.map { [it.identifier, it.title, it.provider.id] }
|
||||
variable_placeholders = Array.new(identifier_title_map.size, "(?,?,?)").join(",")
|
||||
join_string = <<~SQL.squish
|
||||
LEFT JOIN (VALUES #{variable_placeholders}) AS metadata(identifier, title, provider_id)
|
||||
ON metadata.identifier = wiki_page_links.identifier AND metadata.provider_id = wiki_page_links.provider_id
|
||||
SQL
|
||||
|
||||
join_expression = ActiveRecord::Base.sanitize_sql_array([join_string, *identifier_title_map.flatten])
|
||||
|
||||
relation.joins(join_expression).select("wiki_page_links.*, metadata.title as title")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -23,7 +23,7 @@
|
||||
#
|
||||
# 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.
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# See COPYRIGHT and LICENSE files for more details.
|
||||
#++
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
en:
|
||||
activerecord:
|
||||
attributes:
|
||||
wikis/page_link:
|
||||
provider: Wiki Provider
|
||||
wikis/xwiki_provider:
|
||||
authentication_method: Authentication method
|
||||
authentication_methods:
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
# 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.
|
||||
#++
|
||||
|
||||
module API
|
||||
module V3
|
||||
module PageLinks
|
||||
class PageLinkCollectionRepresenter < Decorators::OffsetPaginatedCollection
|
||||
def _type = "WikiPageLinkCollection"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -31,6 +31,14 @@
|
||||
module API
|
||||
module V3
|
||||
module PageLinks
|
||||
URN_INLINE_PAGE_LINK = "#{URN_PREFIX}wikiPageLinks:Inline".freeze
|
||||
URN_RELATION_PAGE_LINK = "#{URN_PREFIX}wikiPageLinks:Relation".freeze
|
||||
|
||||
URN_PAGE_LINK_TYPE = {
|
||||
"Wikis::RelationPageLink" => URN_RELATION_PAGE_LINK,
|
||||
"Wikis::InlinePageLink" => URN_INLINE_PAGE_LINK
|
||||
}.freeze
|
||||
|
||||
class PageLinkRepresenter < Decorators::Single
|
||||
include Decorators::LinkedResource
|
||||
include Decorators::DateProperty
|
||||
@@ -38,6 +46,7 @@ module API
|
||||
|
||||
property :id
|
||||
property :identifier
|
||||
property :wiki_page_link_type, exec_context: :decorator
|
||||
|
||||
date_time_property :created_at
|
||||
date_time_property :updated_at
|
||||
@@ -61,7 +70,9 @@ module API
|
||||
}
|
||||
end
|
||||
|
||||
associated_resource :provider, v3_path: :wiki_provider
|
||||
associated_resource :provider, v3_path: :wiki_provider, link: ->(*) {
|
||||
{ href: api_v3_paths.wiki_provider(represented.provider.universal_identifier), title: represented.provider.name }
|
||||
}
|
||||
|
||||
# TODO: Make this truly polymorphic - @mereghost 2026-04-13
|
||||
associated_resource :linkable,
|
||||
@@ -69,7 +80,9 @@ module API
|
||||
representer: ::API::V3::WorkPackages::WorkPackageRepresenter,
|
||||
skip_render: ->(*) { represented.linkable_id.nil? || represented.linkable_type != "WorkPackage" }
|
||||
|
||||
def _type = represented.class.name.demodulize
|
||||
def _type = "WikiPageLink"
|
||||
|
||||
def wiki_page_link_type = URN_PAGE_LINK_TYPE[represented.class.name]
|
||||
|
||||
private
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
# 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.
|
||||
#++
|
||||
|
||||
module API
|
||||
module V3
|
||||
module PageLinks
|
||||
class WorkPackageWikiPageLinksAPI < OpenProjectAPI
|
||||
helpers do
|
||||
def enrich_models_with_wiki_metadata(relation)
|
||||
Wikis::PageLinkMetadataService.new(relation).call
|
||||
end
|
||||
end
|
||||
|
||||
resources :wiki_page_links do
|
||||
get do
|
||||
query = ParamsToQueryService.new(
|
||||
::Wikis::PageLink,
|
||||
current_user,
|
||||
query_class: ::Queries::Wikis::PageLinks::PageLinkQuery
|
||||
).call(params)
|
||||
|
||||
unless query.valid?
|
||||
message = I18n.t("api_v3.errors.missing_or_malformed_parameter", parameter: "filters")
|
||||
raise ::API::Errors::InvalidQuery.new(message)
|
||||
end
|
||||
|
||||
relation = query.results.where(linkable: @work_package)
|
||||
|
||||
PageLinkCollectionRepresenter.new(
|
||||
enrich_models_with_wiki_metadata(relation).result,
|
||||
per_page: params[:pageSize],
|
||||
self_link: api_v3_paths.work_package_page_links(@work_package.id),
|
||||
current_user:
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -35,13 +35,13 @@ module API
|
||||
include Decorators::LinkedResource
|
||||
include Decorators::DateProperty
|
||||
|
||||
property :id
|
||||
property :universal_identifier
|
||||
property :name
|
||||
|
||||
date_time_property :created_at
|
||||
date_time_property :updated_at
|
||||
|
||||
self_link(path: :wiki_provider)
|
||||
self_link(path: :wiki_provider, id_attribute: :universal_identifier)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -60,6 +60,11 @@ module OpenProject::Wikis
|
||||
)
|
||||
|
||||
OpenProject::TextFormatting::Filters::PatternMatcherFilter.append_matcher ::Wikis::TextFormatting::WikiLinkMatcher
|
||||
|
||||
# Registering queries and filters
|
||||
::Queries::Register.register(::Queries::Wikis::PageLinks::PageLinkQuery) do
|
||||
filter ::Queries::Wikis::PageLinks::Filter::ProviderFilter
|
||||
end
|
||||
end
|
||||
|
||||
replace_principal_references "Wikis::PageLink" => %i[author_id]
|
||||
@@ -99,5 +104,10 @@ module OpenProject::Wikis
|
||||
|
||||
add_api_path(:wiki_page_link) { |page_link_id| "#{root}/wiki_page_links/#{page_link_id}" }
|
||||
add_api_path(:wiki_provider) { |provider_id| "#{root}/wiki_providers/#{provider_id}" }
|
||||
add_api_path(:work_package_page_links) { |work_package_id| "#{work_package(work_package_id)}/wiki_page_links" }
|
||||
|
||||
add_api_endpoint "API::V3::WorkPackages::WorkPackagesAPI", :id do
|
||||
mount ::API::V3::PageLinks::WorkPackageWikiPageLinksAPI
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -60,7 +60,7 @@ module API
|
||||
describe "provider" do
|
||||
it_behaves_like "has a titled link" do
|
||||
let(:link) { "provider" }
|
||||
let(:href) { "/api/v3/wiki_providers/#{represented.provider_id}" }
|
||||
let(:href) { "/api/v3/wiki_providers/#{represented.provider.universal_identifier}" }
|
||||
let(:title) { represented.provider.name }
|
||||
end
|
||||
end
|
||||
@@ -113,18 +113,34 @@ module API
|
||||
end
|
||||
|
||||
describe "properties" do
|
||||
describe "wiki_page_link_type" do
|
||||
context "when InlinePageLink" do
|
||||
let(:represented) { inline_page_link }
|
||||
|
||||
it_behaves_like "property", :wikiPageLinkType do
|
||||
let(:value) { URN_INLINE_PAGE_LINK }
|
||||
end
|
||||
end
|
||||
|
||||
context "when RelationPageLink" do
|
||||
it_behaves_like "property", :wikiPageLinkType do
|
||||
let(:value) { URN_RELATION_PAGE_LINK }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "_type" do
|
||||
context "when InlinePageLink" do
|
||||
let(:represented) { inline_page_link }
|
||||
|
||||
it_behaves_like "property", :_type do
|
||||
let(:value) { "InlinePageLink" }
|
||||
let(:value) { "WikiPageLink" }
|
||||
end
|
||||
end
|
||||
|
||||
context "when RelationPageLink" do
|
||||
it_behaves_like "property", :_type do
|
||||
let(:value) { "RelationPageLink" }
|
||||
let(:value) { "WikiPageLink" }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -48,13 +48,21 @@ module API
|
||||
describe "self" do
|
||||
it_behaves_like "has a titled link" do
|
||||
let(:link) { "self" }
|
||||
let(:href) { "/api/v3/wiki_providers/#{represented.id}" }
|
||||
let(:href) { "/api/v3/wiki_providers/#{represented.universal_identifier}" }
|
||||
let(:title) { represented.name }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "properties" do
|
||||
it_behaves_like "property", :name do
|
||||
let(:value) { represented.name }
|
||||
end
|
||||
|
||||
it_behaves_like "property", :universalIdentifier do
|
||||
let(:value) { represented.universal_identifier }
|
||||
end
|
||||
|
||||
it_behaves_like "datetime property", :createdAt do
|
||||
let(:value) { represented.created_at }
|
||||
end
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
# 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"
|
||||
require_module_spec_helper
|
||||
|
||||
RSpec.describe "API v3 wiki page links resource" do
|
||||
include API::V3::Utilities::PathHelper
|
||||
|
||||
let(:work_package) { create(:work_package) }
|
||||
let(:internal_wiki) { create(:internal_wiki_provider) }
|
||||
let(:xwiki_provider) { create(:xwiki_provider) }
|
||||
|
||||
let(:project) { work_package.project }
|
||||
|
||||
let(:user) { create(:user, member_with_permissions: { project => %i(view_work_packages) }) }
|
||||
|
||||
let(:relation_page_links) { create_list(:relation_wiki_page_link, 3, provider: xwiki_provider, linkable: work_package) }
|
||||
let(:inline_page_links) { create_list(:inline_wiki_page_link, 3, provider: internal_wiki, linkable: work_package) }
|
||||
|
||||
let(:unrelated_page_links) do
|
||||
create_list(:inline_wiki_page_link, 3, provider: internal_wiki, linkable: create(:work_package, project: project))
|
||||
end
|
||||
|
||||
before do
|
||||
login_as user
|
||||
stub_provider_queries
|
||||
unrelated_page_links
|
||||
end
|
||||
|
||||
describe "GET /api/v3/work_packages/:id/wiki_page_links" do
|
||||
let(:path) { api_v3_paths.work_package_page_links(work_package.id) }
|
||||
|
||||
context "with all preconditions met (happy path)" do
|
||||
before { get path }
|
||||
|
||||
it_behaves_like "API V3 collection response", 6, 6, "WikiPageLink", "WikiPageLinkCollection" do
|
||||
let(:elements) { Wikis::PageLink.where(linkable: work_package).order(id: :desc).all }
|
||||
end
|
||||
end
|
||||
|
||||
context "when filtered by provider" do
|
||||
let(:filter) { [{ provider: { operator: "=", values: [internal_wiki.universal_identifier] } }] }
|
||||
|
||||
before do
|
||||
get "#{path}?filters=#{CGI.escape(filter.to_json)}"
|
||||
end
|
||||
|
||||
it_behaves_like "API V3 collection response", 3, 3, "WikiPageLink", "WikiPageLinkCollection" do
|
||||
let(:elements) { Wikis::PageLink.where(linkable: work_package, provider: internal_wiki).order(id: :desc).all }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def stub_provider_queries
|
||||
internal_class = class_double(Wikis::Adapters::Providers::Internal::Queries::PageInfo)
|
||||
xwiki_class = class_double(Wikis::Adapters::Providers::XWiki::Queries::PageInfo)
|
||||
|
||||
internal_query = instance_double(Wikis::Adapters::Providers::Internal::Queries::PageInfo)
|
||||
xwiki_query = instance_double(Wikis::Adapters::Providers::XWiki::Queries::PageInfo)
|
||||
|
||||
Wikis::Adapters::Registry.stub("internal.queries.page_info", internal_class)
|
||||
Wikis::Adapters::Registry.stub("xwiki.queries.page_info", xwiki_class)
|
||||
|
||||
allow(internal_class).to receive(:new).and_return(internal_query)
|
||||
allow(xwiki_class).to receive(:new).and_return(xwiki_query)
|
||||
stub_query_calls(inline_page_links, internal_query)
|
||||
stub_query_calls(relation_page_links, xwiki_query)
|
||||
end
|
||||
|
||||
def stub_query_calls(links, query)
|
||||
links.each do |link|
|
||||
Wikis::Adapters::Input::PageInfo.build(identifier: link.identifier).bind do |input|
|
||||
allow(query).to receive(:call).with(input).and_return(Success(build_page_info(link)))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def build_page_info(link)
|
||||
Wikis::Adapters::Results::PageInfo.new(
|
||||
identifier: link.identifier, href: "valid_uri", title: "Title of #{link.identifier}", provider: link.provider
|
||||
)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,126 @@
|
||||
# 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"
|
||||
require_module_spec_helper
|
||||
|
||||
module Wikis
|
||||
RSpec.describe PageLinkMetadataService do
|
||||
let(:relation) { PageLink.limit(30) }
|
||||
let(:query_double) { instance_double(Adapters::Providers::Internal::Queries::PageInfo) }
|
||||
let(:query_class_double) { class_double(Adapters::Providers::Internal::Queries::PageInfo) }
|
||||
|
||||
shared_let(:provider) { create(:internal_wiki_provider) }
|
||||
shared_let(:page_links) { create_list(:relation_wiki_page_link, 3, provider:) }
|
||||
|
||||
subject(:service) { described_class.new(relation) }
|
||||
|
||||
before do
|
||||
allow(query_class_double).to receive(:new).with(model: provider).and_return(query_double)
|
||||
Adapters::Registry.stub("internal.queries.page_info", query_class_double)
|
||||
|
||||
build_inputs.each do |input|
|
||||
allow(query_double).to receive(:call).with(input).and_return(
|
||||
Success(
|
||||
Adapters::Results::PageInfo.new(title: "Wikis, now with more cheese! Part #{input.identifier}",
|
||||
identifier: input.identifier,
|
||||
href: "totally_valid_url",
|
||||
provider:)
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
it "returns a new relation" do
|
||||
service_result = service.call
|
||||
|
||||
expect(service_result).to be_success
|
||||
expect(service_result.errors).to be_empty
|
||||
expect(service_result.result).to be_an(ActiveRecord::Relation)
|
||||
end
|
||||
|
||||
it "adds the title attribute to the metadata association" do
|
||||
service_result = service.call
|
||||
expect(service_result).to be_success
|
||||
|
||||
page_links = service_result.result
|
||||
expect(page_links.first.title).to eq("Wikis, now with more cheese! Part #{page_links.first.identifier}")
|
||||
end
|
||||
|
||||
context "when page links have the same identifier but different providers" do
|
||||
shared_let(:xwiki_provider) { create(:xwiki_provider) }
|
||||
let(:new_page_links) do
|
||||
page_links.map do |pl|
|
||||
create(:relation_wiki_page_link, provider: xwiki_provider, identifier: pl.identifier)
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
new_double = instance_double(Adapters::Providers::Internal::Queries::PageInfo)
|
||||
allow(query_class_double).to receive(:new).with(model: xwiki_provider).and_return(new_double)
|
||||
Adapters::Registry.stub("xwiki.queries.page_info", query_class_double)
|
||||
|
||||
new_page_links.map do |pl|
|
||||
input = Adapters::Input::PageInfo.build(identifier: pl.identifier).value_or(nil)
|
||||
allow(new_double).to receive(:call).with(input).and_return(
|
||||
Success(
|
||||
Adapters::Results::PageInfo.new(title: "Wikis, now with more cheese! Part #{pl.id}",
|
||||
identifier: input.identifier,
|
||||
href: "totally_valid_url",
|
||||
provider: xwiki_provider)
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
it "maps the titles to the correct page link" do
|
||||
service_result = service.call
|
||||
|
||||
expect(service_result).to be_success
|
||||
page_links = service_result.result
|
||||
|
||||
page_links.find_each do |page_link|
|
||||
case page_link.provider_id
|
||||
when xwiki_provider.id
|
||||
expect(page_link.title).to eq("Wikis, now with more cheese! Part #{page_link.id}")
|
||||
else
|
||||
expect(page_link.title).to eq("Wikis, now with more cheese! Part #{page_link.identifier}")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def build_inputs(relation = page_links)
|
||||
relation.filter_map { Adapters::Input::PageInfo.build(identifier: it.identifier).value_or(nil) }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,43 @@
|
||||
# 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 "dry/container/stub"
|
||||
require "dry/monads"
|
||||
|
||||
RSpec.configure do |config|
|
||||
config.include Dry::Monads[:result]
|
||||
|
||||
config.prepend_before do
|
||||
Wikis::Adapters::Registry.enable_stubs!
|
||||
end
|
||||
config.append_after do
|
||||
Wikis::Adapters::Registry.unstub
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user