mirror of
https://github.com/opf/openproject.git
synced 2026-06-14 03:30:14 +00:00
Drop numeric pins on auxilary links
This commit is contained in:
@@ -106,7 +106,7 @@ module API
|
||||
next if represented.new_record?
|
||||
|
||||
{
|
||||
href: new_work_package_move_path(work_package_id: represented.id),
|
||||
href: new_work_package_move_path(represented),
|
||||
type: "text/html",
|
||||
title: "Move work package '#{represented.subject}'"
|
||||
}
|
||||
@@ -117,7 +117,7 @@ module API
|
||||
next if represented.new_record?
|
||||
|
||||
{
|
||||
href: copy_work_package_path(id: represented.id),
|
||||
href: work_package_path(represented, "copy"),
|
||||
type: "text/html",
|
||||
title: "Copy work package '#{represented.subject}'"
|
||||
}
|
||||
|
||||
@@ -100,18 +100,21 @@ RSpec.shared_examples_for "provides a single WP context menu" do
|
||||
context "with semantic identifiers enabled",
|
||||
with_flag: { semantic_work_package_ids: true },
|
||||
with_settings: { work_packages_identifier: "semantic" } do
|
||||
# The shared project is created classic-style (lowercase identifier), but
|
||||
# semantic mode requires the uppercase format. Rewrite it before any
|
||||
# example-scoped setup so work-package allocation and URL helpers both see
|
||||
# a valid semantic prefix. Specs that create their own project per example
|
||||
# should prefer the `:semantic` factory trait instead.
|
||||
around do |example|
|
||||
semantic_project_identifier = "PROJ#{project.id}".first(Projects::Identifier::SEMANTIC_IDENTIFIER_MAX_LENGTH)
|
||||
project.update_columns(identifier: semantic_project_identifier)
|
||||
example.run
|
||||
end
|
||||
|
||||
it "uses numeric parent_id in the URL and sets the parent correctly" do
|
||||
expect(Setting::WorkPackageIdentifier.semantic_mode_active?)
|
||||
.to be(true), "expected semantic mode to be active via with_settings + with_flag metadata"
|
||||
|
||||
# Consumers of this shared example use shared_let(:project), which evaluates
|
||||
# before per-example `with_settings:` activates semantic mode — so the project
|
||||
# was created via the classic-mode factory path with a lowercase slug. Force
|
||||
# an identifier that satisfies Projects::Identifier's semantic constraints
|
||||
# (uppercase, [A-Z][A-Z0-9_]*, max 10 chars). For specs that create their own
|
||||
# project per example, prefer the `:semantic` factory trait instead.
|
||||
semantic_project_identifier = "PROJ#{work_package.project.id}".first(Projects::Identifier::SEMANTIC_IDENTIFIER_MAX_LENGTH)
|
||||
work_package.project.update_columns(identifier: semantic_project_identifier)
|
||||
work_package.allocate_and_register_semantic_id if work_package.identifier.blank?
|
||||
|
||||
open_context_menu.call
|
||||
|
||||
@@ -1204,7 +1204,7 @@ RSpec.describe API::V3::WorkPackages::WorkPackageRepresenter do
|
||||
|
||||
it_behaves_like "has a titled action link" do
|
||||
let(:link) { "move" }
|
||||
let(:href) { "/work_packages/#{work_package.id}/move/new" }
|
||||
let(:href) { "/work_packages/#{work_package.display_id}/move/new" }
|
||||
let(:permission) { :move_work_packages }
|
||||
let(:title) { "Move work package '#{work_package.subject}'" }
|
||||
end
|
||||
@@ -1214,7 +1214,7 @@ RSpec.describe API::V3::WorkPackages::WorkPackageRepresenter do
|
||||
describe "copy" do
|
||||
it_behaves_like "has a titled action link" do
|
||||
let(:link) { "copy" }
|
||||
let(:href) { "/work_packages/#{work_package.id}/copy" }
|
||||
let(:href) { work_package_path(work_package, "copy") }
|
||||
let(:permission) { :add_work_packages }
|
||||
let(:title) { "Copy work package '#{work_package.subject}'" }
|
||||
end
|
||||
@@ -1226,7 +1226,7 @@ RSpec.describe API::V3::WorkPackages::WorkPackageRepresenter do
|
||||
|
||||
it_behaves_like "has a titled action link" do
|
||||
let(:link) { "copy" }
|
||||
let(:href) { "/work_packages/#{work_package.id}/copy" }
|
||||
let(:href) { "/work_packages/#{work_package.display_id}/copy" }
|
||||
let(:permission) { :add_work_packages }
|
||||
let(:title) { "Copy work package '#{work_package.subject}'" }
|
||||
end
|
||||
@@ -1261,33 +1261,32 @@ RSpec.describe API::V3::WorkPackages::WorkPackageRepresenter do
|
||||
end
|
||||
end
|
||||
|
||||
# The HAL surface must produce numeric URLs regardless of identifier
|
||||
# mode — external API consumers depend on stable, predictable IDs.
|
||||
# These specs guard against a future change that drops the explicit
|
||||
# `id:` kwargs (or model-positional pins) and silently lets URLs flip
|
||||
# to semantic identifiers via WorkPackage#to_param.
|
||||
# The HAL contract surface stays numeric in semantic mode so clients
|
||||
# can correlate work packages by comparing href strings (one
|
||||
# resource's `self` === another's `parent`, etc.). Auxiliary
|
||||
# endpoints (`pdf`, `generate_pdf`, `atom`) follow the same convention.
|
||||
context "with semantic identifier mode active",
|
||||
with_flag: { semantic_work_package_ids: true },
|
||||
with_settings: { work_packages_identifier: "semantic", feeds_enabled?: true } do
|
||||
let(:work_package) { build_stubbed(:work_package, identifier: "PROJ-7", project: workspace) }
|
||||
let(:permissions) { all_permissions + [:export_work_packages] }
|
||||
|
||||
it "self stays numeric" do
|
||||
it "self href stays numeric" do
|
||||
expect(subject).to be_json_eql("/api/v3/work_packages/#{work_package.id}".to_json)
|
||||
.at_path("_links/self/href")
|
||||
end
|
||||
|
||||
it "pdf stays numeric" do
|
||||
it "pdf href stays numeric" do
|
||||
expect(subject).to be_json_eql("/work_packages/#{work_package.id}.pdf".to_json)
|
||||
.at_path("_links/pdf/href")
|
||||
end
|
||||
|
||||
it "generate_pdf stays numeric" do
|
||||
it "generate_pdf href stays numeric" do
|
||||
expect(subject).to be_json_eql("/work_packages/#{work_package.id}/generate_pdf_dialog".to_json)
|
||||
.at_path("_links/generate_pdf/href")
|
||||
end
|
||||
|
||||
it "atom stays numeric" do
|
||||
it "atom href stays numeric" do
|
||||
expect(subject).to be_json_eql("/work_packages/#{work_package.id}.atom".to_json)
|
||||
.at_path("_links/atom/href")
|
||||
end
|
||||
|
||||
@@ -466,8 +466,9 @@ RSpec.describe WorkPackage::SemanticIdentifier do
|
||||
end
|
||||
end
|
||||
|
||||
context "when semantic mode is not active",
|
||||
with_flag: { semantic_work_package_ids: false } do
|
||||
context "when classic mode is active",
|
||||
with_flag: { semantic_work_package_ids: false },
|
||||
with_settings: { work_packages_identifier: "classic" } do
|
||||
it "returns the numeric id as a string" do
|
||||
expect(work_package.to_param).to eq(work_package.id.to_s)
|
||||
end
|
||||
@@ -475,10 +476,10 @@ RSpec.describe WorkPackage::SemanticIdentifier do
|
||||
it "makes work_package_path produce a numeric URL" do
|
||||
expect(work_package_path(work_package)).to end_with("/work_packages/#{work_package.id}")
|
||||
end
|
||||
end
|
||||
|
||||
it "returns nil for new (unsaved) records" do
|
||||
expect(WorkPackage.new.to_param).to be_nil
|
||||
it "returns nil for new (unsaved) records" do
|
||||
expect(WorkPackage.new.to_param).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -221,6 +221,13 @@ RSpec.describe "API v3 Work package resource",
|
||||
context "with a semantic identifier",
|
||||
with_flag: { semantic_work_package_ids: true },
|
||||
with_settings: { work_packages_identifier: "semantic" } do
|
||||
let(:project) { create(:project, :semantic) }
|
||||
let(:user) do
|
||||
create(:user, member_with_permissions: { project => %i[view_work_packages] })
|
||||
end
|
||||
let(:work_package) do
|
||||
create(:work_package, project:, description: "lorem ipsum")
|
||||
end
|
||||
let(:get_path) { api_v3_paths.work_package work_package.display_id }
|
||||
|
||||
before do
|
||||
|
||||
Reference in New Issue
Block a user