mirror of
https://github.com/opf/openproject.git
synced 2026-06-14 03:30:14 +00:00
Add flat paths for meeting API
This commit is contained in:
@@ -36,17 +36,10 @@ module API
|
||||
get do
|
||||
items = @meeting.agenda_items.includes(:author, :presenter, :work_package, :meeting_section)
|
||||
MeetingAgendaItemCollectionRepresenter.new(items,
|
||||
self_link: api_v3_paths.meeting_agenda_items(@meeting.id),
|
||||
self_link: api_v3_paths.meeting_agenda_items(meeting_id: @meeting.id),
|
||||
current_user:)
|
||||
end
|
||||
|
||||
post(&::API::V3::Utilities::Endpoints::Create
|
||||
.new(model: MeetingAgendaItem,
|
||||
params_modifier: ->(params) {
|
||||
params.except(:meeting, :meeting_id).merge(meeting: @meeting)
|
||||
})
|
||||
.mount)
|
||||
|
||||
route_param :agenda_item_id, type: Integer, desc: "Agenda item ID" do
|
||||
after_validation do
|
||||
@meeting_agenda_item = @meeting.agenda_items.find(declared_params[:agenda_item_id])
|
||||
@@ -54,10 +47,6 @@ module API
|
||||
|
||||
get &::API::V3::Utilities::Endpoints::Show.new(model: MeetingAgendaItem).mount
|
||||
|
||||
patch &::API::V3::Utilities::Endpoints::Update.new(model: MeetingAgendaItem).mount
|
||||
|
||||
delete &::API::V3::Utilities::Endpoints::Delete.new(model: MeetingAgendaItem).mount
|
||||
|
||||
mount ::API::V3::MeetingOutcomes::OutcomesByAgendaItemAPI
|
||||
end
|
||||
end
|
||||
|
||||
@@ -42,8 +42,7 @@ module API
|
||||
{ outcomes: %i[author work_package] }
|
||||
]
|
||||
|
||||
self_link id_attribute: ->(*) { [represented.meeting_id, represented.id] },
|
||||
title_getter: ->(*) { represented.title }
|
||||
self_link title_getter: ->(*) { represented.title }
|
||||
|
||||
property :id
|
||||
|
||||
@@ -88,7 +87,7 @@ module API
|
||||
next if represented.meeting_section_id.nil?
|
||||
|
||||
{
|
||||
href: api_v3_paths.meeting_section(represented.meeting_id, represented.meeting_section_id),
|
||||
href: api_v3_paths.meeting_section(represented.meeting_section_id),
|
||||
title: represented.meeting_section&.title
|
||||
}
|
||||
}
|
||||
@@ -102,8 +101,7 @@ module API
|
||||
link: ->(*) {
|
||||
represented.outcomes.map do |outcome|
|
||||
{
|
||||
href: api_v3_paths
|
||||
.meeting_agenda_item_outcome(represented.meeting_id, represented.id, outcome.id),
|
||||
href: api_v3_paths.meeting_outcome(outcome.id),
|
||||
title: outcome.id.to_s
|
||||
}
|
||||
end
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# 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 MeetingAgendaItems
|
||||
class MeetingAgendaItemsAPI < ::API::OpenProjectAPI
|
||||
resources :meeting_agenda_items do
|
||||
post &::API::V3::Utilities::Endpoints::Create.new(model: MeetingAgendaItem).mount
|
||||
|
||||
route_param :id, type: Integer, desc: "Agenda item ID" do
|
||||
after_validation do
|
||||
@meeting_agenda_item = MeetingAgendaItem
|
||||
.joins(meeting: :project)
|
||||
.merge(Meeting.visible)
|
||||
.find(declared_params[:id])
|
||||
end
|
||||
|
||||
get &::API::V3::Utilities::Endpoints::Show.new(model: MeetingAgendaItem).mount
|
||||
|
||||
patch &::API::V3::Utilities::Endpoints::Update.new(model: MeetingAgendaItem).mount
|
||||
|
||||
delete &::API::V3::Utilities::Endpoints::Delete.new(model: MeetingAgendaItem).mount
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -39,10 +39,7 @@ module API
|
||||
|
||||
self.to_eager_load = [{ meeting_agenda_item: :meeting }, :author, :work_package]
|
||||
|
||||
self_link path: :meeting_agenda_item_outcome,
|
||||
id_attribute: ->(*) {
|
||||
[represented.meeting_agenda_item.meeting_id, represented.meeting_agenda_item_id, represented.id]
|
||||
},
|
||||
self_link path: :meeting_outcome,
|
||||
title_getter: ->(*) { represented.id.to_s }
|
||||
|
||||
property :id
|
||||
@@ -56,13 +53,16 @@ module API
|
||||
representer: ::API::V3::Users::UserRepresenter,
|
||||
skip_render: ->(*) { represented.author_id.nil? }
|
||||
|
||||
link :agendaItem do
|
||||
{
|
||||
href: api_v3_paths.meeting_agenda_item(represented.meeting_agenda_item.meeting_id,
|
||||
represented.meeting_agenda_item_id),
|
||||
title: represented.meeting_agenda_item.title
|
||||
}
|
||||
end
|
||||
associated_resource :meeting_agenda_item,
|
||||
as: :agendaItem,
|
||||
link: ->(*) {
|
||||
next if represented.meeting_agenda_item_id.nil?
|
||||
|
||||
{
|
||||
href: api_v3_paths.meeting_agenda_item(represented.meeting_agenda_item_id),
|
||||
title: represented.meeting_agenda_item.title
|
||||
}
|
||||
}
|
||||
|
||||
associated_visible_resource :work_package
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# 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 MeetingOutcomes
|
||||
class MeetingOutcomesAPI < ::API::OpenProjectAPI
|
||||
resources :meeting_outcomes do
|
||||
post &::API::V3::Utilities::Endpoints::Create.new(model: MeetingOutcome).mount
|
||||
|
||||
route_param :id, type: Integer, desc: "Outcome ID" do
|
||||
after_validation do
|
||||
@meeting_outcome = MeetingOutcome
|
||||
.joins(meeting_agenda_item: { meeting: :project })
|
||||
.merge(Meeting.visible)
|
||||
.find(declared_params[:id])
|
||||
end
|
||||
|
||||
get &::API::V3::Utilities::Endpoints::Show.new(model: MeetingOutcome).mount
|
||||
|
||||
patch &::API::V3::Utilities::Endpoints::Update.new(model: MeetingOutcome).mount
|
||||
|
||||
delete &::API::V3::Utilities::Endpoints::Delete.new(model: MeetingOutcome).mount
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -38,29 +38,17 @@ module API
|
||||
|
||||
MeetingOutcomeCollectionRepresenter.new(outcomes,
|
||||
self_link: api_v3_paths
|
||||
.meeting_agenda_item_outcomes(@meeting.id, @meeting_agenda_item.id),
|
||||
.meeting_agenda_item_outcomes(@meeting_agenda_item.id,
|
||||
meeting_id: @meeting.id),
|
||||
current_user:)
|
||||
end
|
||||
|
||||
post(&::API::V3::Utilities::Endpoints::Create
|
||||
.new(model: MeetingOutcome,
|
||||
params_modifier: ->(params) {
|
||||
params
|
||||
.except(:meeting_agenda_item, :meeting_agenda_item_id)
|
||||
.merge(meeting_agenda_item: @meeting_agenda_item)
|
||||
})
|
||||
.mount)
|
||||
|
||||
route_param :outcome_id, type: Integer, desc: "Outcome ID" do
|
||||
after_validation do
|
||||
@meeting_outcome = @meeting_agenda_item.outcomes.find(declared_params[:outcome_id])
|
||||
end
|
||||
|
||||
get &::API::V3::Utilities::Endpoints::Show.new(model: MeetingOutcome).mount
|
||||
|
||||
patch &::API::V3::Utilities::Endpoints::Update.new(model: MeetingOutcome).mount
|
||||
|
||||
delete &::API::V3::Utilities::Endpoints::Delete.new(model: MeetingOutcome).mount
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -38,8 +38,7 @@ module API
|
||||
|
||||
self.to_eager_load = [:meeting]
|
||||
|
||||
self_link id_attribute: ->(*) { [represented.meeting_id, represented.id] },
|
||||
title_getter: ->(*) { represented.title }
|
||||
self_link title_getter: ->(*) { represented.title }
|
||||
|
||||
property :id
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# 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 MeetingSections
|
||||
class MeetingSectionsAPI < ::API::OpenProjectAPI
|
||||
resources :meeting_sections do
|
||||
post &::API::V3::Utilities::Endpoints::Create.new(model: MeetingSection).mount
|
||||
|
||||
route_param :id, type: Integer, desc: "Section ID" do
|
||||
after_validation do
|
||||
@meeting_section = MeetingSection
|
||||
.joins(meeting: :project)
|
||||
.merge(Meeting.visible)
|
||||
.find(declared_params[:id])
|
||||
end
|
||||
|
||||
get &::API::V3::Utilities::Endpoints::Show.new(model: MeetingSection).mount
|
||||
|
||||
patch &::API::V3::Utilities::Endpoints::Update.new(model: MeetingSection).mount
|
||||
|
||||
delete &::API::V3::Utilities::Endpoints::Delete.new(model: MeetingSection).mount
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -36,27 +36,16 @@ module API
|
||||
get do
|
||||
sections = @meeting.sections
|
||||
MeetingSectionCollectionRepresenter.new(sections,
|
||||
self_link: api_v3_paths.meeting_sections(@meeting.id),
|
||||
self_link: api_v3_paths.meeting_sections(meeting_id: @meeting.id),
|
||||
current_user:)
|
||||
end
|
||||
|
||||
post(&::API::V3::Utilities::Endpoints::Create
|
||||
.new(model: MeetingSection,
|
||||
params_modifier: ->(params) {
|
||||
params.except(:meeting, :meeting_id).merge(meeting: @meeting)
|
||||
})
|
||||
.mount)
|
||||
|
||||
route_param :section_id, type: Integer, desc: "Section ID" do
|
||||
after_validation do
|
||||
@meeting_section = @meeting.sections.find(declared_params[:section_id])
|
||||
end
|
||||
|
||||
get &::API::V3::Utilities::Endpoints::Show.new(model: MeetingSection).mount
|
||||
|
||||
patch &::API::V3::Utilities::Endpoints::Update.new(model: MeetingSection).mount
|
||||
|
||||
delete &::API::V3::Utilities::Endpoints::Delete.new(model: MeetingSection).mount
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -76,13 +76,13 @@ module API
|
||||
|
||||
link :agendaItems do
|
||||
{
|
||||
href: api_v3_paths.meeting_agenda_items(represented.id)
|
||||
href: api_v3_paths.meeting_agenda_items(meeting_id: represented.id)
|
||||
}
|
||||
end
|
||||
|
||||
link :sections do
|
||||
{
|
||||
href: api_v3_paths.meeting_sections(represented.id)
|
||||
href: api_v3_paths.meeting_sections(meeting_id: represented.id)
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
@@ -58,6 +59,10 @@ module API
|
||||
mount ::API::V3::MeetingSections::SectionsByMeetingAPI
|
||||
end
|
||||
end
|
||||
|
||||
mount ::API::V3::MeetingAgendaItems::MeetingAgendaItemsAPI
|
||||
mount ::API::V3::MeetingSections::MeetingSectionsAPI
|
||||
mount ::API::V3::MeetingOutcomes::MeetingOutcomesAPI
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -241,28 +241,52 @@ module OpenProject::Meeting
|
||||
"#{root}/meetings/#{id}/form"
|
||||
end
|
||||
|
||||
add_api_path :meeting_agenda_items do |meeting_id|
|
||||
"#{meeting(meeting_id)}/agenda_items"
|
||||
add_api_path :meeting_agenda_items do |meeting_id: nil|
|
||||
if meeting_id
|
||||
"#{meeting(meeting_id)}/agenda_items"
|
||||
else
|
||||
"#{root}/meeting_agenda_items"
|
||||
end
|
||||
end
|
||||
|
||||
add_api_path :meeting_agenda_item do |meeting_id, id|
|
||||
"#{meeting(meeting_id)}/agenda_items/#{id}"
|
||||
add_api_path :meeting_agenda_item do |id, meeting_id: nil|
|
||||
if meeting_id
|
||||
"#{meeting(meeting_id)}/agenda_items/#{id}"
|
||||
else
|
||||
"#{root}/meeting_agenda_items/#{id}"
|
||||
end
|
||||
end
|
||||
|
||||
add_api_path :meeting_agenda_item_outcomes do |meeting_id, agenda_item_id|
|
||||
"#{meeting_agenda_item(meeting_id, agenda_item_id)}/outcomes"
|
||||
add_api_path :meeting_agenda_item_outcomes do |agenda_item_id, meeting_id: nil|
|
||||
"#{meeting_agenda_item(agenda_item_id, meeting_id:)}/outcomes"
|
||||
end
|
||||
|
||||
add_api_path :meeting_agenda_item_outcome do |meeting_id, agenda_item_id, id|
|
||||
"#{meeting_agenda_item_outcomes(meeting_id, agenda_item_id)}/#{id}"
|
||||
add_api_path :meeting_outcomes do
|
||||
"#{root}/meeting_outcomes"
|
||||
end
|
||||
|
||||
add_api_path :meeting_sections do |meeting_id|
|
||||
"#{meeting(meeting_id)}/sections"
|
||||
add_api_path :meeting_outcome do |id|
|
||||
"#{root}/meeting_outcomes/#{id}"
|
||||
end
|
||||
|
||||
add_api_path :meeting_section do |meeting_id, id|
|
||||
"#{meeting(meeting_id)}/sections/#{id}"
|
||||
add_api_path :meeting_agenda_item_outcome do |id, agenda_item_id:, meeting_id: nil|
|
||||
"#{meeting_agenda_item_outcomes(agenda_item_id, meeting_id:)}/#{id}"
|
||||
end
|
||||
|
||||
add_api_path :meeting_sections do |meeting_id: nil|
|
||||
if meeting_id
|
||||
"#{meeting(meeting_id)}/sections"
|
||||
else
|
||||
"#{root}/meeting_sections"
|
||||
end
|
||||
end
|
||||
|
||||
add_api_path :meeting_section do |id, meeting_id: nil|
|
||||
if meeting_id
|
||||
"#{meeting(meeting_id)}/sections/#{id}"
|
||||
else
|
||||
"#{root}/meeting_sections/#{id}"
|
||||
end
|
||||
end
|
||||
|
||||
add_api_path :recurring_meetings do
|
||||
|
||||
+128
-11
@@ -51,7 +51,7 @@ RSpec.describe "API v3 Meeting Agenda Items sub-resource", content_type: :json d
|
||||
end
|
||||
|
||||
describe "GET /api/v3/meetings/:meeting_id/agenda_items" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_items(meeting.id) }
|
||||
let(:path) { api_v3_paths.meeting_agenda_items(meeting_id: meeting.id) }
|
||||
|
||||
before { get path }
|
||||
|
||||
@@ -69,6 +69,18 @@ RSpec.describe "API v3 Meeting Agenda Items sub-resource", content_type: :json d
|
||||
expect(last_response.body)
|
||||
.to have_json_size(1)
|
||||
.at_path("_embedded/elements/0/_embedded/outcomes")
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(api_v3_paths.meeting_outcome(outcome.id).to_json)
|
||||
.at_path("_embedded/elements/0/_links/outcomes/0/href")
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(api_v3_paths.meeting_agenda_item(agenda_item.id).to_json)
|
||||
.at_path("_embedded/elements/0/_links/self/href")
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(api_v3_paths.meeting_section(section.id).to_json)
|
||||
.at_path("_embedded/elements/0/_links/section/href")
|
||||
end
|
||||
|
||||
context "without view_meetings permission" do
|
||||
@@ -80,11 +92,16 @@ RSpec.describe "API v3 Meeting Agenda Items sub-resource", content_type: :json d
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/v3/meetings/:meeting_id/agenda_items" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_items(meeting.id) }
|
||||
describe "POST /api/v3/meeting_agenda_items" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_items }
|
||||
let(:body) do
|
||||
{
|
||||
title: "New agenda item"
|
||||
title: "New agenda item",
|
||||
_links: {
|
||||
meeting: {
|
||||
href: api_v3_paths.meeting(meeting.id)
|
||||
}
|
||||
}
|
||||
}.to_json
|
||||
end
|
||||
|
||||
@@ -109,6 +126,44 @@ RSpec.describe "API v3 Meeting Agenda Items sub-resource", content_type: :json d
|
||||
.at_path("title")
|
||||
end
|
||||
|
||||
context "with a section href returned by the section collection" do
|
||||
let!(:target_section) { create(:meeting_section, meeting:) }
|
||||
let(:target_section_href) do
|
||||
get api_v3_paths.meeting_sections(meeting_id: meeting.id)
|
||||
|
||||
JSON
|
||||
.parse(last_response.body)
|
||||
.dig("_embedded", "elements")
|
||||
.find { |item| item["id"] == target_section.id }
|
||||
.dig("_links", "self", "href")
|
||||
end
|
||||
let(:body) do
|
||||
{
|
||||
title: "New agenda item in target section",
|
||||
_links: {
|
||||
meeting: {
|
||||
href: api_v3_paths.meeting(meeting.id)
|
||||
},
|
||||
section: {
|
||||
href: target_section_href
|
||||
}
|
||||
}
|
||||
}.to_json
|
||||
end
|
||||
|
||||
it "responds with 201" do
|
||||
expect(target_section_href).to eq(api_v3_paths.meeting_section(target_section.id))
|
||||
expect(response).to have_http_status(:created)
|
||||
end
|
||||
|
||||
it "creates the agenda item in that section" do
|
||||
response
|
||||
|
||||
expect(meeting.agenda_items.find_by(title: "New agenda item in target section").meeting_section)
|
||||
.to eq(target_section)
|
||||
end
|
||||
end
|
||||
|
||||
context "without manage_agendas permission" do
|
||||
let(:permissions) { %i[view_meetings] }
|
||||
|
||||
@@ -119,7 +174,7 @@ RSpec.describe "API v3 Meeting Agenda Items sub-resource", content_type: :json d
|
||||
end
|
||||
|
||||
describe "GET /api/v3/meetings/:meeting_id/agenda_items/:id" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(meeting.id, agenda_item.id) }
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(agenda_item.id, meeting_id: meeting.id) }
|
||||
|
||||
before { get path }
|
||||
|
||||
@@ -141,7 +196,7 @@ RSpec.describe "API v3 Meeting Agenda Items sub-resource", content_type: :json d
|
||||
|
||||
context "with an item from another meeting" do
|
||||
let(:other_meeting) { create(:meeting, project:, author: current_user) }
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(other_meeting.id, agenda_item.id) }
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(agenda_item.id, meeting_id: other_meeting.id) }
|
||||
|
||||
it "returns 404" do
|
||||
expect(last_response).to have_http_status(:not_found)
|
||||
@@ -155,7 +210,7 @@ RSpec.describe "API v3 Meeting Agenda Items sub-resource", content_type: :json d
|
||||
create(:wp_meeting_agenda_item, meeting:, meeting_section: section, work_package: private_work_package,
|
||||
author: current_user)
|
||||
end
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(meeting.id, wp_agenda_item.id) }
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(wp_agenda_item.id, meeting_id: meeting.id) }
|
||||
|
||||
it "returns 200" do
|
||||
expect(last_response).to have_http_status(:ok)
|
||||
@@ -173,8 +228,34 @@ RSpec.describe "API v3 Meeting Agenda Items sub-resource", content_type: :json d
|
||||
end
|
||||
end
|
||||
|
||||
describe "PATCH /api/v3/meetings/:meeting_id/agenda_items/:id" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(meeting.id, agenda_item.id) }
|
||||
describe "GET /api/v3/meeting_agenda_items/:id" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(agenda_item.id) }
|
||||
|
||||
before { get path }
|
||||
|
||||
it "returns 200 and the agenda item" do
|
||||
expect(last_response).to have_http_status(:ok)
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql("MeetingAgendaItem".to_json)
|
||||
.at_path("_type")
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(api_v3_paths.meeting_agenda_item(agenda_item.id).to_json)
|
||||
.at_path("_links/self/href")
|
||||
end
|
||||
|
||||
context "without view_meetings permission" do
|
||||
let(:permissions) { [] }
|
||||
|
||||
it "returns 404" do
|
||||
expect(last_response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "PATCH /api/v3/meeting_agenda_items/:id" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(agenda_item.id) }
|
||||
let(:body) do
|
||||
{
|
||||
title: "Updated title",
|
||||
@@ -193,6 +274,42 @@ RSpec.describe "API v3 Meeting Agenda Items sub-resource", content_type: :json d
|
||||
expect(agenda_item.reload.title).to eq("Updated title")
|
||||
end
|
||||
|
||||
context "with a section href returned by the agenda item collection" do
|
||||
let(:target_section) { create(:meeting_section, meeting:) }
|
||||
let!(:target_agenda_item) do
|
||||
create(:meeting_agenda_item, meeting:, meeting_section: target_section, author: current_user)
|
||||
end
|
||||
let(:target_section_href) do
|
||||
get api_v3_paths.meeting_agenda_items(meeting_id: meeting.id)
|
||||
|
||||
JSON
|
||||
.parse(last_response.body)
|
||||
.dig("_embedded", "elements")
|
||||
.find { |item| item["id"] == target_agenda_item.id }
|
||||
.dig("_links", "section", "href")
|
||||
end
|
||||
let(:body) do
|
||||
{
|
||||
lockVersion: agenda_item.lock_version,
|
||||
_links: {
|
||||
section: {
|
||||
href: target_section_href
|
||||
}
|
||||
}
|
||||
}.to_json
|
||||
end
|
||||
|
||||
it "responds with 200" do
|
||||
expect(target_section_href).to eq(api_v3_paths.meeting_section(target_section.id))
|
||||
expect(response).to have_http_status(:ok)
|
||||
end
|
||||
|
||||
it "moves the agenda item to that section" do
|
||||
response
|
||||
expect(agenda_item.reload.meeting_section).to eq(target_section)
|
||||
end
|
||||
end
|
||||
|
||||
context "without manage_agendas permission" do
|
||||
let(:permissions) { %i[view_meetings] }
|
||||
|
||||
@@ -202,8 +319,8 @@ RSpec.describe "API v3 Meeting Agenda Items sub-resource", content_type: :json d
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /api/v3/meetings/:meeting_id/agenda_items/:id" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(meeting.id, agenda_item.id) }
|
||||
describe "DELETE /api/v3/meeting_agenda_items/:id" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item(agenda_item.id) }
|
||||
|
||||
before { delete path }
|
||||
|
||||
|
||||
+68
-12
@@ -51,7 +51,7 @@ RSpec.describe "API v3 Meeting Outcomes sub-resource", content_type: :json do
|
||||
end
|
||||
|
||||
describe "GET /api/v3/meetings/:meeting_id/agenda_items/:agenda_item_id/outcomes" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item_outcomes(meeting.id, agenda_item.id) }
|
||||
let(:path) { api_v3_paths.meeting_agenda_item_outcomes(agenda_item.id, meeting_id: meeting.id) }
|
||||
|
||||
before { get path }
|
||||
|
||||
@@ -65,11 +65,19 @@ RSpec.describe "API v3 Meeting Outcomes sub-resource", content_type: :json do
|
||||
expect(last_response.body)
|
||||
.to have_json_size(1)
|
||||
.at_path("_embedded/elements")
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(api_v3_paths.meeting_outcome(outcome.id).to_json)
|
||||
.at_path("_embedded/elements/0/_links/self/href")
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(api_v3_paths.meeting_agenda_item(agenda_item.id).to_json)
|
||||
.at_path("_embedded/elements/0/_links/agendaItem/href")
|
||||
end
|
||||
|
||||
context "with an agenda item from another meeting" do
|
||||
let(:other_meeting) { create(:meeting, project:, author: current_user) }
|
||||
let(:path) { api_v3_paths.meeting_agenda_item_outcomes(other_meeting.id, agenda_item.id) }
|
||||
let(:path) { api_v3_paths.meeting_agenda_item_outcomes(agenda_item.id, meeting_id: other_meeting.id) }
|
||||
|
||||
it "returns 404" do
|
||||
expect(last_response).to have_http_status(:not_found)
|
||||
@@ -108,12 +116,17 @@ RSpec.describe "API v3 Meeting Outcomes sub-resource", content_type: :json do
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/v3/meetings/:meeting_id/agenda_items/:agenda_item_id/outcomes" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item_outcomes(meeting.id, agenda_item.id) }
|
||||
describe "POST /api/v3/meeting_outcomes" do
|
||||
let(:path) { api_v3_paths.meeting_outcomes }
|
||||
let(:body) do
|
||||
{
|
||||
kind: "information",
|
||||
notes: { raw: "Outcome created via API" }
|
||||
notes: { raw: "Outcome created via API" },
|
||||
_links: {
|
||||
agendaItem: {
|
||||
href: api_v3_paths.meeting_agenda_item(agenda_item.id)
|
||||
}
|
||||
}
|
||||
}.to_json
|
||||
end
|
||||
|
||||
@@ -153,6 +166,9 @@ RSpec.describe "API v3 Meeting Outcomes sub-resource", content_type: :json do
|
||||
{
|
||||
kind: "work_package",
|
||||
_links: {
|
||||
agendaItem: {
|
||||
href: api_v3_paths.meeting_agenda_item(agenda_item.id)
|
||||
},
|
||||
workPackage: {
|
||||
href: api_v3_paths.work_package(work_package.id)
|
||||
}
|
||||
@@ -182,6 +198,9 @@ RSpec.describe "API v3 Meeting Outcomes sub-resource", content_type: :json do
|
||||
{
|
||||
kind: "work_package",
|
||||
_links: {
|
||||
agendaItem: {
|
||||
href: api_v3_paths.meeting_agenda_item(agenda_item.id)
|
||||
},
|
||||
workPackage: {
|
||||
href: api_v3_paths.work_package(private_work_package.id)
|
||||
}
|
||||
@@ -197,7 +216,11 @@ RSpec.describe "API v3 Meeting Outcomes sub-resource", content_type: :json do
|
||||
end
|
||||
|
||||
describe "GET /api/v3/meetings/:meeting_id/agenda_items/:agenda_item_id/outcomes/:id" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item_outcome(meeting.id, agenda_item.id, outcome.id) }
|
||||
let(:path) do
|
||||
api_v3_paths.meeting_agenda_item_outcome(outcome.id,
|
||||
agenda_item_id: agenda_item.id,
|
||||
meeting_id: meeting.id)
|
||||
end
|
||||
|
||||
before { get path }
|
||||
|
||||
@@ -211,11 +234,19 @@ RSpec.describe "API v3 Meeting Outcomes sub-resource", content_type: :json do
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(outcome.id.to_json)
|
||||
.at_path("id")
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(api_v3_paths.meeting_outcome(outcome.id).to_json)
|
||||
.at_path("_links/self/href")
|
||||
end
|
||||
|
||||
context "with an outcome from another agenda item" do
|
||||
let(:other_agenda_item) { create(:meeting_agenda_item, meeting:, meeting_section: section, author: current_user) }
|
||||
let(:path) { api_v3_paths.meeting_agenda_item_outcome(meeting.id, other_agenda_item.id, outcome.id) }
|
||||
let(:path) do
|
||||
api_v3_paths.meeting_agenda_item_outcome(outcome.id,
|
||||
agenda_item_id: other_agenda_item.id,
|
||||
meeting_id: meeting.id)
|
||||
end
|
||||
|
||||
it "returns 404" do
|
||||
expect(last_response).to have_http_status(:not_found)
|
||||
@@ -242,13 +273,38 @@ RSpec.describe "API v3 Meeting Outcomes sub-resource", content_type: :json do
|
||||
.at_path("_links/workPackage/href")
|
||||
|
||||
expect(last_response.body).not_to have_json_path("_embedded/workPackage")
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "PATCH /api/v3/meetings/:meeting_id/agenda_items/:agenda_item_id/outcomes/:id" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item_outcome(meeting.id, agenda_item.id, outcome.id) }
|
||||
describe "GET /api/v3/meeting_outcomes/:id" do
|
||||
let(:path) { api_v3_paths.meeting_outcome(outcome.id) }
|
||||
|
||||
before { get path }
|
||||
|
||||
it "returns 200 and the outcome" do
|
||||
expect(last_response).to have_http_status(:ok)
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql("MeetingOutcome".to_json)
|
||||
.at_path("_type")
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(api_v3_paths.meeting_outcome(outcome.id).to_json)
|
||||
.at_path("_links/self/href")
|
||||
end
|
||||
|
||||
context "without view_meetings permission" do
|
||||
let(:permissions) { [] }
|
||||
|
||||
it "returns 404" do
|
||||
expect(last_response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "PATCH /api/v3/meeting_outcomes/:id" do
|
||||
let(:path) { api_v3_paths.meeting_outcome(outcome.id) }
|
||||
let(:body) do
|
||||
{
|
||||
notes: { raw: "Updated outcome" }
|
||||
@@ -271,8 +327,8 @@ RSpec.describe "API v3 Meeting Outcomes sub-resource", content_type: :json do
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /api/v3/meetings/:meeting_id/agenda_items/:agenda_item_id/outcomes/:id" do
|
||||
let(:path) { api_v3_paths.meeting_agenda_item_outcome(meeting.id, agenda_item.id, outcome.id) }
|
||||
describe "DELETE /api/v3/meeting_outcomes/:id" do
|
||||
let(:path) { api_v3_paths.meeting_outcome(outcome.id) }
|
||||
|
||||
before { delete path }
|
||||
|
||||
|
||||
+45
-10
@@ -49,7 +49,7 @@ RSpec.describe "API v3 Meeting Sections sub-resource", content_type: :json do
|
||||
end
|
||||
|
||||
describe "GET /api/v3/meetings/:meeting_id/sections" do
|
||||
let(:path) { api_v3_paths.meeting_sections(meeting.id) }
|
||||
let(:path) { api_v3_paths.meeting_sections(meeting_id: meeting.id) }
|
||||
|
||||
before { get path }
|
||||
|
||||
@@ -59,6 +59,10 @@ RSpec.describe "API v3 Meeting Sections sub-resource", content_type: :json do
|
||||
expect(last_response.body)
|
||||
.to be_json_eql("Collection".to_json)
|
||||
.at_path("_type")
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(api_v3_paths.meeting_section(section.id).to_json)
|
||||
.at_path("_embedded/elements/0/_links/self/href")
|
||||
end
|
||||
|
||||
context "without view_meetings permission" do
|
||||
@@ -70,11 +74,16 @@ RSpec.describe "API v3 Meeting Sections sub-resource", content_type: :json do
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/v3/meetings/:meeting_id/sections" do
|
||||
let(:path) { api_v3_paths.meeting_sections(meeting.id) }
|
||||
describe "POST /api/v3/meeting_sections" do
|
||||
let(:path) { api_v3_paths.meeting_sections }
|
||||
let(:body) do
|
||||
{
|
||||
title: "New Section"
|
||||
title: "New Section",
|
||||
_links: {
|
||||
meeting: {
|
||||
href: api_v3_paths.meeting(meeting.id)
|
||||
}
|
||||
}
|
||||
}.to_json
|
||||
end
|
||||
|
||||
@@ -109,7 +118,7 @@ RSpec.describe "API v3 Meeting Sections sub-resource", content_type: :json do
|
||||
end
|
||||
|
||||
describe "GET /api/v3/meetings/:meeting_id/sections/:id" do
|
||||
let(:path) { api_v3_paths.meeting_section(meeting.id, section.id) }
|
||||
let(:path) { api_v3_paths.meeting_section(section.id, meeting_id: meeting.id) }
|
||||
|
||||
before { get path }
|
||||
|
||||
@@ -127,7 +136,7 @@ RSpec.describe "API v3 Meeting Sections sub-resource", content_type: :json do
|
||||
|
||||
context "with a section from another meeting" do
|
||||
let(:other_meeting) { create(:meeting, project:, author: current_user) }
|
||||
let(:path) { api_v3_paths.meeting_section(other_meeting.id, section.id) }
|
||||
let(:path) { api_v3_paths.meeting_section(section.id, meeting_id: other_meeting.id) }
|
||||
|
||||
it "returns 404" do
|
||||
expect(last_response).to have_http_status(:not_found)
|
||||
@@ -135,8 +144,34 @@ RSpec.describe "API v3 Meeting Sections sub-resource", content_type: :json do
|
||||
end
|
||||
end
|
||||
|
||||
describe "PATCH /api/v3/meetings/:meeting_id/sections/:id" do
|
||||
let(:path) { api_v3_paths.meeting_section(meeting.id, section.id) }
|
||||
describe "GET /api/v3/meeting_sections/:id" do
|
||||
let(:path) { api_v3_paths.meeting_section(section.id) }
|
||||
|
||||
before { get path }
|
||||
|
||||
it "returns 200 and the section" do
|
||||
expect(last_response).to have_http_status(:ok)
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql("MeetingSection".to_json)
|
||||
.at_path("_type")
|
||||
|
||||
expect(last_response.body)
|
||||
.to be_json_eql(api_v3_paths.meeting_section(section.id).to_json)
|
||||
.at_path("_links/self/href")
|
||||
end
|
||||
|
||||
context "without view_meetings permission" do
|
||||
let(:permissions) { [] }
|
||||
|
||||
it "returns 404" do
|
||||
expect(last_response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "PATCH /api/v3/meeting_sections/:id" do
|
||||
let(:path) { api_v3_paths.meeting_section(section.id) }
|
||||
let(:body) do
|
||||
{
|
||||
title: "Updated Section Title"
|
||||
@@ -163,8 +198,8 @@ RSpec.describe "API v3 Meeting Sections sub-resource", content_type: :json do
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /api/v3/meetings/:meeting_id/sections/:id" do
|
||||
let(:path) { api_v3_paths.meeting_section(meeting.id, section.id) }
|
||||
describe "DELETE /api/v3/meeting_sections/:id" do
|
||||
let(:path) { api_v3_paths.meeting_section(section.id) }
|
||||
|
||||
before { delete path }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user