From 55a6aada36cc22dae3acf7e4c7f2c59fcf742e1d Mon Sep 17 00:00:00 2001 From: milanmajchrak Date: Tue, 20 Oct 2026 10:10:54 +0200 Subject: [PATCH] CLARIN-DSpace v9: fix double encoding of CLARIN license names containing '+' Port of dtq-dev PR 1596 (commit c3c44fc451) to the v9 base, written for the 9.x spec. Co-Authored-By: Claude Fable 5.1 --- .../section-license.component.spec.ts | 18 ++++++++++++++++++ .../section-license.component.ts | 3 --- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/app/submission/sections/clarin-license-resource/section-license.component.spec.ts b/src/app/submission/sections/clarin-license-resource/section-license.component.spec.ts index 11ec651c5e5..423d1d32f25 100644 --- a/src/app/submission/sections/clarin-license-resource/section-license.component.spec.ts +++ b/src/app/submission/sections/clarin-license-resource/section-license.component.spec.ts @@ -196,6 +196,24 @@ describe('SubmissionSectionClarinLicenseComponent', () => { expect(app).toBeDefined(); })); + describe('findClarinLicenseByName', () => { + // the license name must be encoded exactly once in the byName query (RequestParam encodes it) + const expectEncodedName = async (app: SubmissionSectionClarinLicenseComponent, name: string, encoded: string) => { + mockClarinDataService.searchBy.and.returnValue(createSuccessfulRemoteDataObject$(createPaginatedList([]))); + await (app as any).findClarinLicenseByName(name); + const options = mockClarinDataService.searchBy.calls.mostRecent().args[1]; + expect(options.searchParams.map((p) => `${p.fieldName}=${p.fieldValue}`)).toEqual([`name=${encoded}`]); + }; + + it('should encode an ampersand and spaces in the license name', inject([SubmissionSectionClarinLicenseComponent], async (app: SubmissionSectionClarinLicenseComponent) => { + await expectEncodedName(app, 'Licence A & B', 'Licence%20A%20%26%20B'); + })); + + it('should encode a plus sign in the license name only once', inject([SubmissionSectionClarinLicenseComponent], async (app: SubmissionSectionClarinLicenseComponent) => { + await expectEncodedName(app, 'GNU GPL 2.0+', 'GNU%20GPL%202.0%2B'); + })); + }); + it('sendRequest should PATCH the submission object self link (route-aware, works for workflow items)', inject([SubmissionSectionClarinLicenseComponent], (app: SubmissionSectionClarinLicenseComponent) => { // Arrange: enable validation flow so sendRequest actually executes diff --git a/src/app/submission/sections/clarin-license-resource/section-license.component.ts b/src/app/submission/sections/clarin-license-resource/section-license.component.ts index ff206750bdc..cd99923fe01 100644 --- a/src/app/submission/sections/clarin-license-resource/section-license.component.ts +++ b/src/app/submission/sections/clarin-license-resource/section-license.component.ts @@ -457,9 +457,6 @@ export class SubmissionSectionClarinLicenseComponent extends SectionModelCompone * Get the license object from the API by the license name. */ private async findClarinLicenseByName(licenseName): Promise>> { - if (licenseName.includes('+')) { - licenseName = encodeURIComponent(licenseName); - } const options = { searchParams: [ new RequestParam('name', licenseName),