[#38833] BCF API Comments Service

- https://community.openproject.org/work_packages/38833
- added requests tests
- added check for expected body length
- added representer and api for bcf_comments
- added create and set attributes service for bcf_comments
- added migration for comment hierarchy
- added create and update service for journals
pull/9684/head
Eric Schubert 3 years ago
parent 23a8bef352
commit d6b87a2210
  1. 4
      .rubocop.yml
  2. 43
      app/contracts/journals/update_contract.rb
  3. 2
      app/contracts/work_packages/update_contract.rb
  4. 30
      app/services/journals/create_service.rb
  5. 33
      app/services/journals/set_attributes_service.rb
  6. 33
      app/services/journals/update_service.rb
  7. 6
      db/migrate/20210910092414_add_bcf_comment_hierarchy.rb
  8. 29
      lib/api/v3/activities/activities_api.rb
  9. 39
      lib/api/v3/activities/activity_payload_representer.rb
  10. 61
      modules/bim/app/contracts/bim/bcf/comments/create_contract.rb
  11. 54
      modules/bim/app/contracts/bim/bcf/comments/update_contract.rb
  12. 2
      modules/bim/app/contracts/bim/bcf/viewpoints/create_contract.rb
  13. 102
      modules/bim/app/controllers/bim/bcf/api/v2_1/comments/api.rb
  14. 2
      modules/bim/app/controllers/bim/bcf/api/v2_1/projects_api.rb
  15. 5
      modules/bim/app/controllers/bim/bcf/api/v2_1/topics_api.rb
  16. 34
      modules/bim/app/models/bim/bcf/comment.rb
  17. 4
      modules/bim/app/models/bim/bcf/non_existent_comment.rb
  18. 4
      modules/bim/app/models/bim/bcf/non_existent_viewpoint.rb
  19. 4
      modules/bim/app/representers/bim/bcf/api/v2_1/base_representer.rb
  20. 46
      modules/bim/app/representers/bim/bcf/api/v2_1/comments/authorization_representer.rb
  21. 88
      modules/bim/app/representers/bim/bcf/api/v2_1/comments/single_representer.rb
  22. 52
      modules/bim/app/services/bim/bcf/comments/create_service.rb
  23. 36
      modules/bim/app/services/bim/bcf/comments/set_attributes_service.rb
  24. 49
      modules/bim/app/services/bim/bcf/comments/update_service.rb
  25. 12
      modules/bim/spec/factories/bcf_comment_factory.rb
  26. 611
      modules/bim/spec/requests/api/bcf/v2_1/comments_api_spec.rb
  27. 1
      modules/bim/spec/requests/api/bcf/v2_1/projects_api_spec.rb
  28. 26
      modules/bim/spec/requests/api/bcf/v2_1/shared_responses.rb

@ -100,6 +100,10 @@ Naming/AccessorMethodName:
Naming/AsciiIdentifiers:
Enabled: false
Naming/ClassAndModuleCamelCase:
AllowedNames:
- V2_1
Naming/FileName:
Enabled: false

@ -0,0 +1,43 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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 Journals
class UpdateContract < BaseContract
attribute :notes
validate :user_allowed_to_edit
private
def user_allowed_to_edit
errors.add(:base, :error_unauthorized) unless model.editable_by?(user)
end
end
end

@ -28,8 +28,6 @@
# See COPYRIGHT and LICENSE files for more details.
#++
require 'work_packages/base_contract'
module WorkPackages
class UpdateContract < BaseContract
include UnchangedProject

@ -1,3 +1,33 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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.
#++
# Will create journals for a journable (e.g. WorkPackage and Meeting)
# As a journal is basically a copy of the current state of the database, consisting of the journable as well as its
# custom values and attachments, those entries are copied in the database.

@ -0,0 +1,33 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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 Journals
class SetAttributesService < ::BaseServices::SetAttributes; end
end

@ -0,0 +1,33 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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 Journals
class UpdateService < ::BaseServices::Update; end
end

@ -0,0 +1,6 @@
class AddBcfCommentHierarchy < ActiveRecord::Migration[6.1]
def change
add_column :bcf_comments, :reply_to, :bigint, default: nil, null: true
add_foreign_key :bcf_comments, :bcf_comments, column: :reply_to, on_delete: :nullify
end
end

@ -26,8 +26,6 @@
# See COPYRIGHT and LICENSE files for more details.
#++
require 'api/v3/activities/activity_representer'
module API
module V3
module Activities
@ -42,18 +40,6 @@ module API
end
end
helpers do
def save_activity(activity)
unless activity.save
fail ::API::Errors::ErrorBase.create_and_merge_errors(activity.errors)
end
end
def authorize_edit_own(activity)
authorize_by_with_raise activity.editable_by?(current_user)
end
end
get &::API::V3::Utilities::Endpoints::Show.new(model: ::Journal,
api_name: 'Activity',
instance_generator: ->(*) { @activity })
@ -63,14 +49,13 @@ module API
requires :comment, type: String
end
patch do
# TODO: Write a journal update notes service and mount default endpoint
authorize_edit_own(@activity)
@activity.notes = declared_params[:comment]
save_activity(@activity)
ActivityRepresenter.new(@activity, current_user: current_user)
end
patch &::API::V3::Utilities::Endpoints::Update.new(model: ::Journal,
api_name: 'Activity',
instance_generator: ->(*) { @activity },
params_modifier: ->(*) {
{ notes: declared_params[:comment] }
})
.mount
end
end
end

@ -0,0 +1,39 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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 Activities
class ActivityPayloadRepresenter < ::API::V3::Activities::ActivityRepresenter
include API::Utilities::PayloadRepresenter
end
end
end
end

@ -0,0 +1,61 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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 Bim::Bcf
module Comments
class CreateContract < BaseContract
attribute :journal
attribute :issue
attribute :viewpoint
attribute :reply_to
validate :user_allowed_to_create
validate :validate_journal
validate :validate_viewpoint_reference
validate :validate_reply_to_comment
private
def user_allowed_to_create
errors.add :base, :error_unauthorized unless @user.allowed_to?(:manage_bcf, model.issue.work_package.project)
end
def validate_journal
errors.add(:base, :invalid) if model.journal.journable != model.issue.work_package
end
def validate_viewpoint_reference
errors.add(:viewpoint, :does_not_exist) if model.viewpoint.is_a?(::Bim::Bcf::NonExistentViewpoint)
end
def validate_reply_to_comment
errors.add(:bcf_comment, :does_not_exist) if model.reply_to.is_a?(::Bim::Bcf::NonExistentComment)
end
end
end
end

@ -0,0 +1,54 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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 Bim::Bcf
module Comments
class UpdateContract < BaseContract
attribute :viewpoint
attribute :reply_to
validate :user_allowed_to_update
validate :validate_viewpoint_reference
validate :validate_reply_to_comment
private
def user_allowed_to_update
errors.add :base, :error_unauthorized unless @user.allowed_to?(:manage_bcf, model.issue.work_package.project)
end
def validate_viewpoint_reference
errors.add(:viewpoint, :does_not_exist) if model.viewpoint.is_a?(::Bim::Bcf::NonExistentViewpoint)
end
def validate_reply_to_comment
errors.add(:bcf_comment, :does_not_exist) if model.reply_to.is_a?(::Bim::Bcf::NonExistentComment)
end
end
end
end

@ -104,7 +104,7 @@ module Bim::Bcf
end
def validate_json_viewpoint_present
errors.add(:json_viewpoint, :blank) unless viewpoint.present?
errors.add(:json_viewpoint, :blank) if viewpoint.blank?
end
def validate_json_viewpoint_hash

@ -0,0 +1,102 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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 Bim::Bcf::API::V2_1
module Comments
class API < ::API::OpenProjectAPI
resources :comments do
helpers do
def all_comments
@issue.comments.includes(:journal, :issue, :viewpoint)
end
def transform_create_parameter(params)
viewpoint = if params[:viewpoint_guid] == nil
nil
else
@issue.viewpoints
.find_by(uuid: params[:viewpoint_guid]) || ::Bim::Bcf::NonExistentViewpoint.new
end
replied_comment = if params[:reply_to_comment_guid] == nil
nil
else
@issue.comments
.find_by(uuid: params[:reply_to_comment_guid]) || ::Bim::Bcf::NonExistentComment.new
end
{
issue: @issue,
viewpoint: viewpoint,
reply_to: replied_comment
}
end
def transform_update_parameter(params)
viewpoint = if params[:viewpoint_guid] == nil
nil
else
@issue.viewpoints
.find_by(uuid: params[:viewpoint_guid]) || ::Bim::Bcf::NonExistentViewpoint.new
end
replied_comment = if params[:reply_to_comment_guid] == nil
nil
else
@issue.comments
.find_by(uuid: params[:reply_to_comment_guid]) || ::Bim::Bcf::NonExistentComment.new
end
{
original_comment: @comment,
viewpoint: viewpoint,
reply_to: replied_comment
}
end
end
get &::Bim::Bcf::API::V2_1::Endpoints::Index.new(model: Bim::Bcf::Comment, scope: -> { all_comments }).mount
post &::Bim::Bcf::API::V2_1::Endpoints::Create
.new(model: Bim::Bcf::Comment,
params_modifier: ->(params) { transform_create_parameter(params).merge(params) })
.mount
route_param :comment_guid, regexp: /\A[a-f0-9\-]+\z/ do
after_validation do
@comment = all_comments.find_by!(uuid: params[:comment_guid])
end
get &::Bim::Bcf::API::V2_1::Endpoints::Show.new(model: Bim::Bcf::Comment).mount
put &::Bim::Bcf::API::V2_1::Endpoints::Update
.new(model: Bim::Bcf::Comment,
params_modifier: ->(params) { transform_update_parameter(params).merge(params) })
.mount
end
end
end
end
end

@ -28,7 +28,9 @@
# See COPYRIGHT and LICENSE files for more details.
#++
# rubocop:disable Naming/ClassAndModuleCamelCase
module Bim::Bcf::API::V2_1
# rubocop:enable Naming/ClassAndModuleCamelCase
class ProjectsAPI < ::API::OpenProjectAPI
resources :projects do
helpers do

@ -28,7 +28,9 @@
# See COPYRIGHT and LICENSE files for more details.
#++
# rubocop:disable Naming/ClassAndModuleCamelCase
module Bim::Bcf::API::V2_1
# rubocop:enable Naming/ClassAndModuleCamelCase
class TopicsAPI < ::API::OpenProjectAPI
resources :topics do
helpers do
@ -85,7 +87,7 @@ module Bim::Bcf::API::V2_1
route_param :topic_uuid, regexp: /\A[a-f0-9\-]+\z/ do
after_validation do
@issue = topics.find_by_uuid!(params[:topic_uuid])
@issue = topics.find_by!(uuid: params[:topic_uuid])
end
get &::Bim::Bcf::API::V2_1::Endpoints::Show
@ -108,6 +110,7 @@ module Bim::Bcf::API::V2_1
.mount
mount ::Bim::Bcf::API::V2_1::Viewpoints::API
mount ::Bim::Bcf::API::V2_1::Comments::API
end
end
end

@ -1,18 +1,50 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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 Bim::Bcf
class Comment < ActiveRecord::Base
self.table_name = :bcf_comments
include InitializeWithUuid
CREATE_ATTRIBUTES = %i[journal issue viewpoint reply_to].freeze
UPDATE_ATTRIBUTES = %i[viewpoint reply_to].freeze
belongs_to :journal
belongs_to :issue, foreign_key: :issue_id, class_name: "Bim::Bcf::Issue"
belongs_to :viewpoint, foreign_key: :viewpoint_id, class_name: "Bim::Bcf::Viewpoint", optional: true
belongs_to :reply_to, foreign_key: :reply_to, class_name: "Bim::Bcf::Comment", optional: true
validates_presence_of :uuid
validates_uniqueness_of :uuid, scope: [:issue_id]
def self.has_uuid?(uuid, issue_id)
where(uuid: uuid, issue_id: issue_id).exists?
exists?(uuid: uuid, issue_id: issue_id)
end
end
end

@ -0,0 +1,4 @@
module Bim::Bcf
class NonExistentComment < Comment
end
end

@ -0,0 +1,4 @@
module Bim::Bcf
class NonExistentViewpoint < Viewpoint
end
end

@ -33,5 +33,9 @@ module Bim::Bcf::API::V2_1
include Representable::JSON
defaults render_nil: true
def datetime_formatter
::API::V3::Utilities::DateTimeFormatter
end
end
end

@ -0,0 +1,46 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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.
#++
# rubocop:disable Naming/ClassAndModuleCamelCase
module Bim::Bcf::API::V2_1
# rubocop:enable Naming/ClassAndModuleCamelCase
class Comments::AuthorizationRepresenter < BaseRepresenter
property :comment_actions,
getter: ->(decorator:, **) {
if decorator.manage_bcf_allowed?
%w[update]
else
[]
end
}
def manage_bcf_allowed?
represented.user.allowed_to?(:manage_bcf, represented.model.project)
end
end
end

@ -0,0 +1,88 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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.
#++
# rubocop:disable Naming/ClassAndModuleCamelCase
module Bim::Bcf::API::V2_1
# rubocop:enable Naming/ClassAndModuleCamelCase
class Comments::SingleRepresenter < BaseRepresenter
include API::Decorators::DateProperty
property :uuid,
as: :guid
property :date,
getter: ->(represented:, decorator:, **) {
decorator.datetime_formatter.format_datetime(represented.journal.created_at, allow_nil: true)
}
property :author,
getter: ->(represented:, **) {
represented.journal.user.mail
}
property :comment,
getter: ->(represented:, **) {
represented.journal.notes
}
property :topic_guid,
getter: ->(represented:, **) {
represented.issue.uuid
}
# not required properties
property :viewpoint_guid,
getter: ->(represented:, **) {
represented.viewpoint&.uuid
}
property :reply_to_comment_guid,
getter: ->(represented:, **) {
represented.reply_to&.uuid
}
property :modified_date,
getter: ->(represented:, decorator:, **) {
decorator.datetime_formatter.format_datetime(represented.journal.updated_at, allow_nil: true)
}
# we do not store the author when editing a journal, hence the "modified author" is the same as the creator
property :modified_author,
getter: ->(represented:, **) {
represented.journal.user.mail
}
property :authorization,
getter: ->(represented:, **) {
contract = WorkPackages::UpdateContract.new(represented.issue.work_package, User.current)
Comments::AuthorizationRepresenter.new(contract)
}
end
end

@ -0,0 +1,52 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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 Bim::Bcf
module Comments
class CreateService < ::BaseServices::Create
private
def before_perform(params)
journal_call = create_journal(params[:issue].work_package,
params[:comment])
return journal_call if journal_call.failure?
input = { journal: journal_call.result }
.merge(params)
.slice(*::Bim::Bcf::Comment::CREATE_ATTRIBUTES)
super input
end
def create_journal(work_package, comment)
::Journals::CreateService.new(work_package, user).call(notes: comment)
end
end
end
end

@ -0,0 +1,36 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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 Bim::Bcf
module Comments
class SetAttributesService < ::BaseServices::SetAttributes
end
end
end

@ -0,0 +1,49 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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 Bim::Bcf
module Comments
class UpdateService < ::BaseServices::Update
private
def before_perform(params)
journal_call = update_journal(params[:original_comment].journal, params[:comment])
return journal_call if journal_call.failure?
super params.slice(*::Bim::Bcf::Comment::UPDATE_ATTRIBUTES)
end
def update_journal(journal, comment)
::Journals::UpdateService.new(user: user,
model: journal,
contract_class: ::EmptyContract)
.call(notes: comment)
end
end
end
end

@ -28,8 +28,16 @@
FactoryBot.define do
factory :bcf_comment, class: '::Bim::Bcf::Comment' do
after(:create) do |bcf_comment|
bcf_comment.journal = create(:work_package_journal)
transient do
author { nil }
end
after(:create) do |bcf_comment, evaluator|
bcf_comment.journal = if evaluator.author == nil
create(:work_package_journal)
else
create(:work_package_journal, user: evaluator.author)
end
bcf_comment.journal.update_attribute(:notes, 'Some BCF comment.')
bcf_comment.journal.save
bcf_comment.save

@ -0,0 +1,611 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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'
require_relative './shared_responses'
describe 'BCF 2.1 comments resource', type: :request, content_type: :json, with_mail: false do
include Rack::Test::Methods
include API::V3::Utilities::PathHelper
let(:project) do
FactoryBot.create(:project, enabled_module_names: %i[bim work_package_tracking])
end
let(:view_only_user) do
FactoryBot.create(:user,
member_in_project: project,
member_with_permissions: %i[view_linked_issues view_work_packages])
end
let(:edit_user) do
FactoryBot.create(:user,
member_in_project: project,
member_with_permissions: %i[view_linked_issues view_work_packages manage_bcf])
end
let(:user_without_permission) { FactoryBot.create(:user, member_in_project: project) }
let(:assignee) { FactoryBot.create(:user) }
let(:work_package) do
FactoryBot.create(:work_package, assigned_to: assignee, due_date: Date.today, project: project)
end
let(:bcf_issue) { FactoryBot.create(:bcf_issue_with_viewpoint, work_package: work_package) }
let(:viewpoint) { bcf_issue.viewpoints.first }
let(:bcf_comment) { FactoryBot.create(:bcf_comment, issue: bcf_issue, author: view_only_user) }
let(:bcf_answer) { FactoryBot.create(:bcf_comment, issue: bcf_issue, reply_to: bcf_comment, author: assignee) }
let(:bcf_comment_to_viewpoint) do
FactoryBot.create(:bcf_comment, issue: bcf_issue, viewpoint: viewpoint, author: edit_user)
end
subject(:response) { last_response }
describe 'GET /api/bcf/2.1/projects/:project_id/topics/:topic_guid/comments' do
let(:path) { "/api/bcf/2.1/projects/#{project.id}/topics/#{bcf_issue.uuid}/comments" }
let(:current_user) { view_only_user }
let(:comments) { bcf_comment }
before do
login_as(current_user)
comments
get path
end
it_behaves_like 'bcf api successful response' do
let(:comments) { [bcf_comment, bcf_answer, bcf_comment_to_viewpoint] }
let(:expected_body) do
[
{
guid: bcf_comment.uuid,
date: bcf_comment.journal.created_at,
author: view_only_user.mail,
comment: bcf_comment.journal.notes,
modified_date: bcf_comment.journal.updated_at,
modified_author: view_only_user.mail,
topic_guid: bcf_issue.uuid,
reply_to_comment_guid: nil,
viewpoint_guid: nil,
authorization: {
comment_actions: []
}
},
{
guid: bcf_answer.uuid,
date: bcf_answer.journal.created_at,
author: assignee.mail,
comment: bcf_answer.journal.notes,
modified_date: bcf_answer.journal.updated_at,
modified_author: assignee.mail,
topic_guid: bcf_issue.uuid,
reply_to_comment_guid: bcf_comment.uuid,
viewpoint_guid: nil,
authorization: {
comment_actions: []
}
},
{
guid: bcf_comment_to_viewpoint.uuid,
date: bcf_comment_to_viewpoint.journal.created_at,
author: edit_user.mail,
comment: bcf_comment_to_viewpoint.journal.notes,
modified_date: bcf_comment_to_viewpoint.journal.updated_at,
modified_author: edit_user.mail,
topic_guid: bcf_issue.uuid,
reply_to_comment_guid: nil,
viewpoint_guid: viewpoint.uuid,
authorization: {
comment_actions: []
}
}
]
end
end
context 'with edit comments permission' do
let(:current_user) { edit_user }
it_behaves_like 'bcf api successful response' do
let(:expected_body) do
[
{
guid: bcf_comment.uuid,
date: bcf_comment.journal.created_at,
author: view_only_user.mail,
comment: bcf_comment.journal.notes,
modified_date: bcf_comment.journal.updated_at,
modified_author: view_only_user.mail,
topic_guid: bcf_issue.uuid,
reply_to_comment_guid: nil,
viewpoint_guid: nil,
authorization: {
comment_actions: [
"update"
]
}
}
]
end
end
end
context 'without view permissions' do
let(:current_user) { user_without_permission }
it_behaves_like 'bcf api not allowed response'
end
end
describe 'POST /api/bcf/2.1/projects/:project_id/topics/:topic_guid/comments' do
let(:path) { "/api/bcf/2.1/projects/#{project.id}/topics/#{bcf_issue.uuid}/comments" }
let(:current_user) { edit_user }
let(:params) do
{
comment: "this is a new bcf comment"
}
end
before do
login_as(current_user)
post path, params.to_json
end
it_behaves_like 'bcf api successful response' do
let(:expected_status) { 201 }
let(:expected_body) do
comment = Bim::Bcf::Comment.last.reload
creation_date = comment&.journal&.created_at&.iso8601
{
guid: comment&.uuid,
date: creation_date,
author: edit_user.mail,
comment: "this is a new bcf comment",
modified_date: creation_date,
modified_author: edit_user.mail,
topic_guid: bcf_issue.uuid,
reply_to_comment_guid: nil,
viewpoint_guid: nil,
authorization: {
comment_actions: [
"update"
]
}
}
end
end
context 'if user has no permission to write comments' do
let(:current_user) { view_only_user }
it_behaves_like 'bcf api not allowed response'
end
context 'if request contains viewpoint guid' do
let(:params) do
{
comment: "this is a comment to a specific viewpoint",
viewpoint_guid: viewpoint.uuid
}
end
it_behaves_like 'bcf api successful response' do
let(:expected_status) { 201 }
let(:expected_body) do
comment = Bim::Bcf::Comment.last.reload
creation_date = comment&.journal&.created_at&.iso8601
{
guid: comment&.uuid,
date: creation_date,
author: edit_user.mail,
comment: "this is a comment to a specific viewpoint",
modified_date: creation_date,
modified_author: edit_user.mail,
topic_guid: bcf_issue.uuid,
reply_to_comment_guid: nil,
viewpoint_guid: viewpoint.uuid,
authorization: {
comment_actions: [
"update"
]
}
}
end
end
context 'if the viewpoint guid does not exist' do
let(:params) do
{
comment: "this is a comment to a specific viewpoint",
viewpoint_guid: "00000000-0000-0000-0000-000000000000"
}
end
it_behaves_like 'bcf api unprocessable response' do
let(:message) { 'Viewpoint does not exist.' }
end
end
end
context 'if request contains reply comment' do
let(:params) do
{
comment: "this is a reply comment to another comment",
reply_to_comment_guid: bcf_comment.uuid
}
end
it_behaves_like 'bcf api successful response' do
let(:expected_status) { 201 }
let(:expected_body) do
comment = Bim::Bcf::Comment.last.reload
creation_date = comment&.journal&.created_at&.iso8601
{
guid: comment&.uuid,
date: creation_date,
author: edit_user.mail,
comment: "this is a reply comment to another comment",
modified_date: creation_date,
modified_author: edit_user.mail,
topic_guid: bcf_issue.uuid,
reply_to_comment_guid: bcf_comment.uuid,
viewpoint_guid: nil,
authorization: {
comment_actions: [
"update"
]
}
}
end
end
context 'if the comment guid does not exist' do
let(:params) do
{
comment: "this is a reply comment to another comment",
reply_to_comment_guid: "00000000-0000-0000-0000-000000000000"
}
end
it_behaves_like 'bcf api unprocessable response' do
let(:message) { 'Bcf comment does not exist.' }
end
end
end
context 'if request contains reply comment and viewpoint reference' do
let(:params) do
{
comment: "this is a reply comment to another comment with a specific reference to a viewpoint",
reply_to_comment_guid: bcf_comment.uuid,
viewpoint_guid: viewpoint.uuid
}
end
it_behaves_like 'bcf api successful response' do
let(:expected_status) { 201 }
let(:expected_body) do
comment = Bim::Bcf::Comment.last.reload
creation_date = comment&.journal&.created_at&.iso8601
{
guid: comment&.uuid,
date: creation_date,
author: edit_user.mail,
comment: "this is a reply comment to another comment with a specific reference to a viewpoint",
modified_date: creation_date,
modified_author: edit_user.mail,
topic_guid: bcf_issue.uuid,
reply_to_comment_guid: bcf_comment.uuid,
viewpoint_guid: viewpoint.uuid,
authorization: {
comment_actions: [
"update"
]
}
}
end
end
context 'if the comment guid does not exist' do
let(:params) do
{
comment: "this is a reply comment to another comment",
reply_to_comment_guid: "00000000-0000-0000-0000-000000000000",
viewpoint_guid: viewpoint.uuid
}
end
it_behaves_like 'bcf api unprocessable response' do
let(:message) { 'Bcf comment does not exist.' }
end
end
context 'if the viewpoint guid does not exist' do
let(:params) do
{
comment: "this is a reply comment to another comment",
viewpoint_guid: "00000000-0000-0000-0000-000000000000",
reply_to_comment_guid: bcf_comment.uuid
}
end
it_behaves_like 'bcf api unprocessable response' do
let(:message) { 'Viewpoint does not exist.' }
end
end
context 'if the comment and viewpoint guid does not exist' do
let(:params) do
{
comment: "this is a reply comment to another comment",
reply_to_comment_guid: "00000000-0000-0000-0000-000000000000",
viewpoint_guid: "00000000-0000-0000-0000-000000000000"
}
end
it_behaves_like 'bcf api unprocessable response' do
let(:message) { 'Multiple field constraints have been violated. Viewpoint does not exist. Bcf comment does not exist.' }
end
end
end
end
describe 'PUT /api/bcf/2.1/projects/:project_id/topics/:topic_guid/comments' do
let(:path) { "/api/bcf/2.1/projects/#{project.id}/topics/#{bcf_issue.uuid}/comments" }
let(:current_user) { edit_user }
let(:params) { { comment: "This is a bad comment update ... " } }
before do
login_as(current_user)
put path, params.to_json
end
it_behaves_like 'bcf api method not allowed response'
end
describe 'GET /api/bcf/2.1/projects/:project_id/topics/:topic_guid/comments/:comment_guid' do
let(:path) { "/api/bcf/2.1/projects/#{project.id}/topics/#{bcf_issue.uuid}/comments/#{bcf_comment.uuid}" }
let(:current_user) { view_only_user }
let(:comments) { [bcf_comment, bcf_answer, bcf_comment_to_viewpoint] }
before do
login_as(current_user)
comments
get path
end
it_behaves_like 'bcf api successful response' do
let(:expected_body) do
{
guid: bcf_comment.uuid,
date: bcf_comment.journal.created_at,
author: view_only_user.mail,
comment: bcf_comment.journal.notes,
modified_date: bcf_comment.journal.updated_at,
modified_author: view_only_user.mail,
topic_guid: bcf_issue.uuid,
reply_to_comment_guid: nil,
viewpoint_guid: nil,
authorization: { comment_actions: [] }
}
end
end
context 'if user has editing permissions' do
let(:current_user) { edit_user }
it_behaves_like 'bcf api successful response' do
let(:expected_body) do
{
guid: bcf_comment.uuid,
date: bcf_comment.journal.created_at,
author: view_only_user.mail,
comment: bcf_comment.journal.notes,
modified_date: bcf_comment.journal.updated_at,
modified_author: view_only_user.mail,
topic_guid: bcf_issue.uuid,
reply_to_comment_guid: nil,
viewpoint_guid: nil,
authorization: {
comment_actions: [
"update"
]
}
}
end
end
end
context 'if comment id does not exist' do
let(:invalid_id) { "1337" }
let(:path) { "/api/bcf/2.1/projects/#{project.id}/topics/#{bcf_issue.uuid}/comments/#{invalid_id}" }
it_behaves_like 'bcf api not found response'
end
context 'without view permissions' do
let(:current_user) { user_without_permission }
it_behaves_like 'bcf api not allowed response'
end
end
describe 'PUT /api/bcf/2.1/projects/:project_id/topics/:topic_guid/comments/:comment_guid' do
let(:updated_comment) { bcf_comment }
let(:path) { "/api/bcf/2.1/projects/#{project.id}/topics/#{bcf_issue.uuid}/comments/#{updated_comment.uuid}" }
let(:current_user) { edit_user }
let(:params) { { comment: "Update comment to this elaborate text." } }
before do
login_as(current_user)
put path, params.to_json
end
it_behaves_like 'bcf api successful response' do
let(:expected_body) do
{
guid: updated_comment.uuid,
date: updated_comment.journal.created_at,
author: view_only_user.mail,
comment: "Update comment to this elaborate text.",
modified_date: updated_comment.journal.updated_at,
# we cannot store another author then the journal creator
modified_author: view_only_user.mail,
topic_guid: bcf_issue.uuid,
reply_to_comment_guid: nil,
viewpoint_guid: nil,
authorization: {
comment_actions: [
"update"
]
}
}
end
end
context 'if user has no edit permissions' do
let(:current_user) { view_only_user }
it_behaves_like 'bcf api not allowed response'
end
context 'if viewpoint reference and reply to is changed' do
let(:params) do
{
comment: "A new updated text",
viewpoint_guid: viewpoint.uuid,
reply_to_comment_guid: bcf_comment_to_viewpoint.uuid
}
end
it_behaves_like 'bcf api successful response' do
let(:expected_body) do
{
guid: updated_comment.uuid,
date: updated_comment.journal.created_at,
author: view_only_user.mail,
comment: "A new updated text",
modified_date: updated_comment.journal.updated_at,
# we cannot store another author then the journal creator
modified_author: view_only_user.mail,
topic_guid: bcf_issue.uuid,
reply_to_comment_guid: bcf_comment_to_viewpoint.uuid,
viewpoint_guid: viewpoint.uuid,
authorization: {
comment_actions: [
"update"
]
}
}
end
end
end
context 'if an invalid viewpoint guid is given' do
let(:params) do
{
comment: "A new updated text",
viewpoint_guid: "00000000-0000-0000-0000-000000000000"
}
end
it_behaves_like 'bcf api unprocessable response' do
let(:message) { 'Viewpoint does not exist.' }
end
end
context 'if an invalid comment guid is given' do
let(:params) do
{
comment: "A new updated text",
reply_to_comment_guid: "00000000-0000-0000-0000-000000000000"
}
end
it_behaves_like 'bcf api unprocessable response' do
let(:message) { 'Bcf comment does not exist.' }
end
end
context 'if the updated comment contains viewpoint reference and is a reply, but update does not set those attributes' do
let(:updated_comment) do
FactoryBot.create(:bcf_comment,
issue: bcf_issue,
viewpoint: viewpoint,
reply_to: bcf_comment,
author: edit_user)
end
let(:params) { { comment: "Only change the comment text and leave the reply and viewpoint guid empty." } }
it_behaves_like 'bcf api successful response' do
let(:expected_body) do
{
guid: updated_comment.uuid,
date: updated_comment.journal.created_at,
author: edit_user.mail,
comment: "Only change the comment text and leave the reply and viewpoint guid empty.",
modified_date: updated_comment.journal.updated_at,
# we cannot store another author then the journal creator
modified_author: edit_user.mail,
topic_guid: bcf_issue.uuid,
reply_to_comment_guid: nil,
viewpoint_guid: nil,
authorization: {
comment_actions: [
"update"
]
}
}
end
end
end
end
describe 'POST /api/bcf/2.1/projects/:project_id/topics/:topic_guid/comments/:comment_guid' do
let(:path) { "/api/bcf/2.1/projects/#{project.id}/topics/#{bcf_issue.uuid}/comments/#{bcf_comment.uuid}" }
let(:current_user) { edit_user }
let(:params) { { comment: "This is an invalid try to create a comment ..." } }
before do
login_as(current_user)
post path, params.to_json
end
it_behaves_like 'bcf api method not allowed response'
end
end

@ -48,6 +48,7 @@ describe 'BCF 2.1 projects resource', type: :request, content_type: :json do
end
let(:project) { FactoryBot.create(:project, enabled_module_names: [:bim]) }
subject(:response) { last_response }
describe 'GET /api/bcf/2.1/projects/:project_id' do

@ -28,12 +28,15 @@
shared_examples_for 'bcf api successful response' do
def expect_identical_without_time(subject, expected_body)
# Remove modified date
body = Array.wrap(JSON.parse(subject.body))
Array.wrap(expected_body).each_with_index do |expected_item, index|
expected = Array.wrap(expected_body)
expect(body.size).to eql(expected.size)
expected.each_with_index do |expected_item, index|
subject_body = body[index]
expected_item.stringify_keys!
# Remove date strings and compare separately
subject_modified_date = subject_body.delete('modified_date')&.to_time
expected_modified_date = expected_item.delete('modified_date')&.to_time
@ -43,6 +46,15 @@ shared_examples_for 'bcf api successful response' do
expect(subject_modified_date).to eql(expected_modified_date)
end
subject_created_date = subject_body.delete('date')&.to_time
expected_created_date = expected_item.delete('date')&.to_time
if expected_created_date
expect(subject_created_date).to be_within(10.seconds).of(expected_created_date)
else
expect(subject_created_date).to eql(expected_created_date)
end
expect(subject_body.to_json).to be_json_eql(expected_item.to_json)
end
end
@ -83,6 +95,16 @@ shared_examples_for 'bcf api not found response' do
end
end
shared_examples_for 'bcf api method not allowed response' do
let(:expect_405) { "405 Not Allowed" }
it 'responds 405 METHOD NOT ALLOWED', :aggregate_failures do
expect(subject.status).to eq 405
expect(subject.body).to eql(expect_405)
expect(subject.headers['Content-Type']).to eql 'application/json; charset=utf-8'
end
end
shared_examples_for 'bcf api not allowed response' do
let(:expect_403) do
{ message: 'You are not authorized to access this resource.' }

Loading…
Cancel
Save