Skip to content

Commit d3267f4

Browse files
authored
chore(uve): Clean clientHost param when the value is the default (dotCMS#31418)
This pull request introduces several changes to the `DotEmaShellComponent` to handle client host URLs more robustly. The changes include adding new test cases and modifying the component's logic to sanitize and compare URLs correctly. Key changes: ### Test Cases Enhancements: * Added test cases to ensure the `clientHost` is not included in the location when it matches the base client host, differs from the base client host, or when sanitized URLs are compared. (`core-web/libs/portlets/edit-ema/portlet/src/lib/dot-ema-shell/dot-ema-shell.component.spec.ts`) ### Component Logic Update: * Updated the `$updateQueryParamsEffect` effect in `DotEmaShellComponent` to sanitize and compare URLs, ensuring the `clientHost` parameter is only included when necessary. (`core-web/libs/portlets/edit-ema/portlet/src/lib/dot-ema-shell/dot-ema-shell.component.ts`) ### Screenshots https://github.com/user-attachments/assets/dc8f917f-6864-45fb-bc73-5a8c6d22e74b
1 parent 7716efd commit d3267f4

File tree

4 files changed

+195
-31
lines changed

4 files changed

+195
-31
lines changed

core-web/libs/portlets/edit-ema/portlet/src/lib/dot-ema-shell/dot-ema-shell.component.spec.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,100 @@ describe('DotEmaShellComponent', () => {
588588
expect(spyUrlTree).toHaveBeenCalledWith([], { queryParams: userParams });
589589
expect(spyLocation).toHaveBeenCalledWith(expectURL.toString());
590590
});
591+
592+
it('should not include clientHost in location when it matches base client host', () => {
593+
const spyLocation = jest.spyOn(location, 'go');
594+
const baseClientHost = 'http://localhost:3000';
595+
const params = {
596+
...INITIAL_PAGE_PARAMS,
597+
clientHost: baseClientHost
598+
};
599+
600+
// Set up route with matching uveConfig.url
601+
overrideRouteSnashot(
602+
activatedRoute,
603+
SNAPSHOT_MOCK({
604+
queryParams: params,
605+
data: {
606+
uveConfig: {
607+
url: baseClientHost,
608+
options: BASIC_OPTIONS
609+
}
610+
}
611+
})
612+
);
613+
614+
store.loadPageAsset(params);
615+
spectator.detectChanges();
616+
617+
expect(spyLocation).toHaveBeenCalledWith(
618+
'/?language_id=1&url=index&variantName=DEFAULT&mode=EDIT_MODE'
619+
);
620+
});
621+
622+
it('should include clientHost in location when it differs from base client host', () => {
623+
const spyLocation = jest.spyOn(location, 'go');
624+
const baseClientHost = 'http://localhost:3000';
625+
const differentClientHost = 'http://localhost:4000';
626+
const params = {
627+
...INITIAL_PAGE_PARAMS,
628+
clientHost: differentClientHost
629+
};
630+
631+
// Set up route with different uveConfig.url
632+
overrideRouteSnashot(
633+
activatedRoute,
634+
SNAPSHOT_MOCK({
635+
queryParams: params,
636+
data: {
637+
uveConfig: {
638+
url: baseClientHost,
639+
options: {
640+
allowedDevURLs: [differentClientHost]
641+
}
642+
}
643+
}
644+
})
645+
);
646+
647+
store.loadPageAsset(params);
648+
spectator.detectChanges();
649+
650+
expect(spyLocation).toHaveBeenCalledWith(
651+
'/?language_id=1&url=index&variantName=DEFAULT&mode=EDIT_MODE&clientHost=http:%2F%2Flocalhost:4000'
652+
);
653+
});
654+
655+
it('should handle sanitized URLs in clientHost comparison', () => {
656+
const spyLocation = jest.spyOn(location, 'go');
657+
const baseClientHost = 'http://localhost:3000/';
658+
const params = {
659+
...INITIAL_PAGE_PARAMS,
660+
clientHost: 'http://localhost:3000' // No trailing slash
661+
};
662+
663+
// Set up route with uveConfig.url that has trailing slash
664+
overrideRouteSnashot(
665+
activatedRoute,
666+
SNAPSHOT_MOCK({
667+
queryParams: params,
668+
data: {
669+
uveConfig: {
670+
url: baseClientHost,
671+
options: BASIC_OPTIONS
672+
}
673+
}
674+
})
675+
);
676+
677+
store.loadPageAsset(params);
678+
spectator.detectChanges();
679+
680+
// Should treat these as the same URL and not include clientHost
681+
expect(spyLocation).toHaveBeenCalledWith(
682+
'/?language_id=1&url=index&variantName=DEFAULT&mode=EDIT_MODE'
683+
);
684+
});
591685
});
592686

593687
describe('ClientHost', () => {

core-web/libs/portlets/edit-ema/portlet/src/lib/dot-ema-shell/dot-ema-shell.component.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import {
3939
checkClientHostAccess,
4040
getAllowedPageParams,
4141
getTargetUrl,
42+
normalizeQueryParams,
4243
sanitizeURL,
4344
shouldNavigate
4445
} from '../utils';
@@ -102,7 +103,14 @@ export class DotEmaShellComponent implements OnInit {
102103
*/
103104
readonly $updateQueryParamsEffect = effect(() => {
104105
const params = this.uveStore.$friendlyParams();
105-
this.#updateLocation(params);
106+
107+
const { data } = this.#activatedRoute.snapshot;
108+
109+
const baseClientHost = data?.uveConfig?.url;
110+
111+
const cleanedParams = normalizeQueryParams(params, baseClientHost);
112+
113+
this.#updateLocation(cleanedParams);
106114
});
107115

108116
ngOnInit(): void {

core-web/libs/portlets/edit-ema/portlet/src/lib/utils/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,9 +277,10 @@ export function getFullPageURL({
277277
*
278278
* @export
279279
* @param {Object} params - The raw query parameters to be processed.
280+
* @param {string} baseClientHost - The base client host to be used to compare with the clientHost query param.
280281
* @return {Object} A cleaned and formatted version of the query parameters.
281282
*/
282-
export function normalizeQueryParams(params) {
283+
export function normalizeQueryParams(params, baseClientHost?: string) {
283284
const queryParams = { ...params };
284285

285286
if (queryParams[PERSONA_KEY] === DEFAULT_PERSONA.identifier) {
@@ -291,6 +292,10 @@ export function normalizeQueryParams(params) {
291292
delete queryParams[PERSONA_KEY];
292293
}
293294

295+
if (baseClientHost && sanitizeURL(baseClientHost) === sanitizeURL(params.clientHost)) {
296+
delete queryParams.clientHost;
297+
}
298+
294299
return queryParams;
295300
}
296301

core-web/libs/portlets/edit-ema/portlet/src/lib/utils/utils.spec.ts

Lines changed: 86 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -879,50 +879,107 @@ describe('utils functions', () => {
879879
});
880880

881881
describe('normalizeQueryParams', () => {
882-
it('should remove PERSONA_KEY if it equals DEFAULT_PERSONA.identifier', () => {
883-
const params = {
884-
[PERSONA_KEY]: DEFAULT_PERSONA.identifier,
885-
someOtherKey: 'someValue'
886-
};
882+
describe('persona handling', () => {
883+
it('should remove PERSONA_KEY if it equals DEFAULT_PERSONA.identifier', () => {
884+
const params = {
885+
[PERSONA_KEY]: DEFAULT_PERSONA.identifier,
886+
someOtherKey: 'someValue'
887+
};
888+
889+
const result = normalizeQueryParams(params);
890+
891+
expect(result).toEqual({
892+
someOtherKey: 'someValue'
893+
});
894+
});
887895

888-
const result = normalizeQueryParams(params);
896+
it('should rename PERSONA_KEY to personaId if not default', () => {
897+
const params = {
898+
[PERSONA_KEY]: 'customPersonaId',
899+
anotherKey: 'anotherValue'
900+
};
889901

890-
expect(result).toEqual({
891-
someOtherKey: 'someValue'
902+
const result = normalizeQueryParams(params);
903+
904+
expect(result).toEqual({
905+
personaId: 'customPersonaId',
906+
anotherKey: 'anotherValue'
907+
});
892908
});
893909
});
894910

895-
it('should rename PERSONA_KEY to personaId if it is present and not default', () => {
896-
const params = {
897-
[PERSONA_KEY]: 'customPersonaId',
898-
anotherKey: 'anotherValue'
899-
};
911+
describe('clientHost handling', () => {
912+
it('should remove clientHost when it matches baseClientHost exactly', () => {
913+
const params = {
914+
clientHost: 'http://example.com',
915+
someKey: 'someValue'
916+
};
900917

901-
const result = normalizeQueryParams(params);
918+
const result = normalizeQueryParams(params, 'http://example.com');
902919

903-
expect(result).toEqual({
904-
personaId: 'customPersonaId',
905-
anotherKey: 'anotherValue'
920+
expect(result).toEqual({
921+
someKey: 'someValue'
922+
});
906923
});
907-
});
908924

909-
it('should not modify params if PERSONA_KEY is absent', () => {
910-
const params = {
911-
someKey: 'someValue',
912-
anotherKey: 'anotherValue'
913-
};
925+
it('should remove clientHost when it matches baseClientHost with trailing slash', () => {
926+
const params = {
927+
clientHost: 'http://example.com/',
928+
someKey: 'someValue'
929+
};
930+
931+
const result = normalizeQueryParams(params, 'http://example.com');
914932

915-
const result = normalizeQueryParams(params);
933+
expect(result).toEqual({
934+
someKey: 'someValue'
935+
});
936+
});
916937

917-
expect(result).toEqual(params);
938+
it('should keep clientHost if it differs from baseClientHost', () => {
939+
const params = {
940+
clientHost: 'http://example.com',
941+
someKey: 'someValue'
942+
};
943+
944+
const result = normalizeQueryParams(params, 'http://different.com');
945+
946+
expect(result).toEqual({
947+
clientHost: 'http://example.com',
948+
someKey: 'someValue'
949+
});
950+
});
951+
952+
it('should keep clientHost if baseClientHost is not provided', () => {
953+
const params = {
954+
clientHost: 'http://example.com',
955+
someKey: 'someValue'
956+
};
957+
958+
const result = normalizeQueryParams(params);
959+
960+
expect(result).toEqual(params);
961+
});
918962
});
919963

920-
it('should handle empty params object', () => {
921-
const params = {};
964+
describe('edge cases', () => {
965+
it('should handle empty params object', () => {
966+
const params = {};
967+
968+
const result = normalizeQueryParams(params);
969+
970+
expect(result).toEqual({});
971+
});
972+
973+
it('should handle params with no special keys', () => {
974+
const params = {
975+
someKey: 'someValue',
976+
anotherKey: 'anotherValue'
977+
};
922978

923-
const result = normalizeQueryParams(params);
979+
const result = normalizeQueryParams(params);
924980

925-
expect(result).toEqual({});
981+
expect(result).toEqual(params);
982+
});
926983
});
927984
});
928985
});

0 commit comments

Comments
 (0)