diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/components/dot-uve-toolbar/dot-uve-toolbar.component.html b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/components/dot-uve-toolbar/dot-uve-toolbar.component.html
index 835d9a334eab..34b3e7ca45e3 100644
--- a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/components/dot-uve-toolbar/dot-uve-toolbar.component.html
+++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/components/dot-uve-toolbar/dot-uve-toolbar.component.html
@@ -16,10 +16,14 @@
[cdkCopyToClipboard]="$toolbar().editor.copyUrl"
data-testId="uve-toolbar-copy-url" />
-
+ class="p-button-text"
+ target="_blank"
+ data-testId="uve-toolbar-api-link"
+ [href]="$apiURL()">
} @else if ($toolbar().preview) {
PREVIEW MODE CONTENT
diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/components/dot-uve-toolbar/dot-uve-toolbar.component.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/components/dot-uve-toolbar/dot-uve-toolbar.component.spec.ts
index a87708cecd5f..70b5c8518936 100644
--- a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/components/dot-uve-toolbar/dot-uve-toolbar.component.spec.ts
+++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/components/dot-uve-toolbar/dot-uve-toolbar.component.spec.ts
@@ -37,6 +37,8 @@ import {
import { DotEmaBookmarksComponent } from '../dot-ema-bookmarks/dot-ema-bookmarks.component';
import { DotEmaRunningExperimentComponent } from '../dot-ema-running-experiment/dot-ema-running-experiment.component';
+const $apiURL = '/api/v1/page/json/123-xyz-567-xxl?host_id=123-xyz-567-xxl&language_id=1';
+
describe('DotUveToolbarComponent', () => {
let spectator: Spectator;
let messageService: MessageService;
@@ -125,6 +127,7 @@ describe('DotUveToolbarComponent', () => {
setSocialMedia: jest.fn(),
pageParams: signal(params),
pageAPIResponse: signal(MOCK_RESPONSE_VTL),
+ $apiURL: signal($apiURL),
reloadCurrentPage: jest.fn(),
loadPageAsset: jest.fn()
};
@@ -187,8 +190,8 @@ describe('DotUveToolbarComponent', () => {
});
});
- it('should have api link button', () => {
- expect(spectator.query(byTestId('uve-toolbar-api-link'))).toBeTruthy();
+ it('should have not experiments button if experiment is not running', () => {
+ expect(spectator.query(byTestId('uve-toolbar-running-experiment'))).toBeFalsy();
});
it('should have language selector', () => {
@@ -202,6 +205,17 @@ describe('DotUveToolbarComponent', () => {
it('should have workflows button', () => {
expect(spectator.query(byTestId('uve-toolbar-workflow-actions'))).toBeTruthy();
});
+
+ describe('API URL', () => {
+ it('should have api link button', () => {
+ expect(spectator.query(byTestId('uve-toolbar-api-link'))).toBeTruthy();
+ });
+
+ it('should have api link button with correct href', () => {
+ const btn = spectator.query(byTestId('uve-toolbar-api-link'));
+ expect(btn.getAttribute('href')).toBe($apiURL);
+ });
+ });
});
describe('State changes', () => {
diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/components/dot-uve-toolbar/dot-uve-toolbar.component.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/components/dot-uve-toolbar/dot-uve-toolbar.component.ts
index 5e3869e11e1e..0e8495d4a3f9 100644
--- a/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/components/dot-uve-toolbar/dot-uve-toolbar.component.ts
+++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/edit-ema-editor/components/dot-uve-toolbar/dot-uve-toolbar.component.ts
@@ -33,6 +33,7 @@ export class DotUveToolbarComponent {
readonly #dotMessageService = inject(DotMessageService);
readonly $toolbar = this.#store.$uveToolbar;
+ readonly $apiURL = this.#store.$apiURL;
togglePreviewMode(preview: boolean) {
this.#store.togglePreviewMode(preview);
diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/editor/toolbar/withUVEToolbar.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/editor/toolbar/withUVEToolbar.spec.ts
new file mode 100644
index 000000000000..6a3b044ff152
--- /dev/null
+++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/editor/toolbar/withUVEToolbar.spec.ts
@@ -0,0 +1,83 @@
+import { describe } from '@jest/globals';
+import { createServiceFactory, mockProvider, SpectatorService } from '@ngneat/spectator/jest';
+import { signalStore, withState } from '@ngrx/signals';
+import { of } from 'rxjs';
+
+import { ActivatedRoute, Router } from '@angular/router';
+
+import { withUVEToolbar } from './withUVEToolbar';
+
+import { DotPageApiService } from '../../../../services/dot-page-api.service';
+import { UVE_STATUS } from '../../../../shared/enums';
+import { MOCK_RESPONSE_HEADLESS } from '../../../../shared/mocks';
+import { UVEState } from '../../../models';
+
+const pageParams = {
+ url: 'test-url',
+ language_id: '1',
+ 'com.dotmarketing.persona.id': 'dot:persona',
+ variantName: 'DEFAULT',
+ clientHost: 'http://localhost:3000'
+};
+
+const initialState: UVEState = {
+ isEnterprise: true,
+ languages: [],
+ pageAPIResponse: MOCK_RESPONSE_HEADLESS,
+ currentUser: null,
+ experiment: null,
+ errorCode: null,
+ pageParams,
+ status: UVE_STATUS.LOADED,
+ isTraditionalPage: false,
+ canEditPage: true,
+ pageIsLocked: true,
+ isClientReady: false
+};
+
+export const uveStoreMock = signalStore(withState(initialState), withUVEToolbar());
+
+describe('withEditor', () => {
+ let spectator: SpectatorService>;
+ let store: InstanceType;
+
+ const createService = createServiceFactory({
+ service: uveStoreMock,
+ providers: [
+ mockProvider(Router),
+ mockProvider(ActivatedRoute),
+ mockProvider(Router),
+ mockProvider(ActivatedRoute),
+ {
+ provide: DotPageApiService,
+ useValue: {
+ get() {
+ return of(MOCK_RESPONSE_HEADLESS);
+ },
+ getClientPage() {
+ return of(MOCK_RESPONSE_HEADLESS);
+ },
+ save: jest.fn()
+ }
+ }
+ ]
+ });
+
+ beforeEach(() => {
+ spectator = createService();
+ store = spectator.service;
+ });
+
+ describe('Computed', () => {
+ it('should return the right API URL', () => {
+ const params = { ...pageParams };
+ // Delete the url from the params to test the function
+ delete params.url;
+
+ const queryParams = new URLSearchParams(params).toString();
+ const expectURL = `/api/v1/page/json/test-url?${queryParams}`;
+
+ expect(store.$apiURL()).toBe(expectURL);
+ });
+ });
+});
diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/editor/toolbar/withUVEToolbar.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/editor/toolbar/withUVEToolbar.ts
index ce67a7ae9ffb..047bb34bdbec 100644
--- a/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/editor/toolbar/withUVEToolbar.ts
+++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/store/features/editor/toolbar/withUVEToolbar.ts
@@ -116,6 +116,15 @@ export function withUVEToolbar() {
unlockButton: shouldShowUnlock ? unlockButton : null,
showInfoDisplay: shouldShowInfoDisplay
};
+ }),
+ $apiURL: computed(() => {
+ const pageParams = store.pageParams();
+ const url = sanitizeURL(pageParams?.url);
+ const params = createPageApiUrlWithQueryParams(url, pageParams);
+ const pageType = store.isTraditionalPage() ? 'render' : 'json';
+ const pageAPI = `/api/v1/page/${pageType}/${params}`;
+
+ return pageAPI;
})
})),
withMethods((store) => ({