diff --git a/.mvn/maven-build-cache-config.xml b/.mvn/maven-build-cache-config.xml index 77e235f74b92..6aed72f588ae 100644 --- a/.mvn/maven-build-cache-config.xml +++ b/.mvn/maven-build-cache-config.xml @@ -12,7 +12,7 @@ https://maven.apache.org/extensions/maven-build-cache-extension/maven-build-cach xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/BUILD-CACHE-CONFIG/1.0.0 https://maven.apache.org/xsd/build-cache-config-1.0.0.xsd"> - true + false SHA-256 true diff --git a/bom/application/pom.xml b/bom/application/pom.xml index 312d8f280d6e..1eae80e3ca5f 100644 --- a/bom/application/pom.xml +++ b/bom/application/pom.xml @@ -1433,6 +1433,13 @@ + + com.dotcms + tomcat-redis-session-manager + 1.3 + provided + + org.apache.tomcat diff --git a/bom/logging/pom.xml b/bom/logging/pom.xml index 333f10810332..fb2d98a93f0a 100644 --- a/bom/logging/pom.xml +++ b/bom/logging/pom.xml @@ -15,8 +15,8 @@ false bom - 2.20.0 - 2.0.7 + 2.23.1 + 2.0.9 @@ -27,30 +27,42 @@ Do not include incompatible artifacts e.g. --> org.apache.logging.log4j - log4j-core + log4j-api ${log4j.version} compile org.apache.logging.log4j - log4j-1.2-api + log4j-iostreams + ${log4j.version} + + + org.apache.logging.log4j + log4j-core ${log4j.version} compile + + + org.apache.logging.log4j + log4j-1.2-api + ${log4j.version} + runtime + org.apache.logging.log4j log4j-jcl ${log4j.version} - compile + runtime org.apache.logging.log4j log4j-slf4j2-impl ${log4j.version} - compile + runtime org.slf4j @@ -61,16 +73,16 @@ org.apache.logging.log4j - log4j-web + log4j-appserver ${log4j.version} - compile + runtime com.lmax disruptor 3.3.4 - compile + runtime diff --git a/core-web/apps/dotcms-ui/src/app/view/components/dot-toolbar/components/dot-toolbar-user/dot-toolbar-user.component.html b/core-web/apps/dotcms-ui/src/app/view/components/dot-toolbar/components/dot-toolbar-user/dot-toolbar-user.component.html index 2dccb506e84d..b24f439fa98d 100644 --- a/core-web/apps/dotcms-ui/src/app/view/components/dot-toolbar/components/dot-toolbar-user/dot-toolbar-user.component.html +++ b/core-web/apps/dotcms-ui/src/app/view/components/dot-toolbar/components/dot-toolbar-user/dot-toolbar-user.component.html @@ -1,11 +1,9 @@ - -
+@if (vm$ | async; as vm) { + @if ($showMask()) { +
+ } @@ -13,16 +11,17 @@ [model]="vm.items" [popup]="true" #menu + (onHide)="hideMask()" appendTo="body" styleClass="toolbar-user__menu"> - + @if (vm.showMyAccount) { + + } - -
+ @if (vm.showLoginAs) { + + } +} diff --git a/core-web/apps/dotcms-ui/src/app/view/components/dot-toolbar/components/dot-toolbar-user/dot-toolbar-user.component.spec.ts b/core-web/apps/dotcms-ui/src/app/view/components/dot-toolbar/components/dot-toolbar-user/dot-toolbar-user.component.spec.ts index 6cff7ad5b8eb..8a4b430b1e81 100644 --- a/core-web/apps/dotcms-ui/src/app/view/components/dot-toolbar/components/dot-toolbar-user/dot-toolbar-user.component.spec.ts +++ b/core-web/apps/dotcms-ui/src/app/view/components/dot-toolbar/components/dot-toolbar-user/dot-toolbar-user.component.spec.ts @@ -221,4 +221,17 @@ describe('DotToolbarUserComponent', () => { fixture.detectChanges(); expect(de.query(By.css('[data-testid="dot-mask"]'))).toBeFalsy(); }); + + it('should hide mask when menu hide', () => { + fixture.detectChanges(); + const avatarComponent = de.query(By.css('[data-testid="avatar"]')).nativeElement; + avatarComponent.click(); + + const menu = de.query(By.css('p-menu')); + menu.triggerEventHandler('onHide', {}); + + fixture.detectChanges(); + + expect(de.query(By.css('[data-testId="dot-mask"]'))).toBeNull(); + }); }); diff --git a/core-web/apps/dotcms-ui/src/app/view/components/dot-toolbar/components/dot-toolbar-user/dot-toolbar-user.component.ts b/core-web/apps/dotcms-ui/src/app/view/components/dot-toolbar/components/dot-toolbar-user/dot-toolbar-user.component.ts index aa120f3e0c6c..80ea2238cfc2 100644 --- a/core-web/apps/dotcms-ui/src/app/view/components/dot-toolbar/components/dot-toolbar-user/dot-toolbar-user.component.ts +++ b/core-web/apps/dotcms-ui/src/app/view/components/dot-toolbar/components/dot-toolbar-user/dot-toolbar-user.component.ts @@ -1,11 +1,11 @@ -import { AsyncPipe, NgIf } from '@angular/common'; +import { AsyncPipe } from '@angular/common'; import { ChangeDetectionStrategy, Component, OnInit, - ViewChild, inject, - signal + signal, + viewChild } from '@angular/core'; import { AvatarModule } from 'primeng/avatar'; @@ -33,23 +33,26 @@ import { DotMyAccountModule } from '../dot-my-account/dot-my-account.module'; DotMyAccountModule, DotSafeHtmlPipe, MenuModule, - AsyncPipe, - NgIf + AsyncPipe ] }) export class DotToolbarUserComponent implements OnInit { - readonly #store = inject(DotToolbarUserStore); + readonly store = inject(DotToolbarUserStore); - vm$ = this.#store.vm$; - @ViewChild('menu') menu: Menu; - showMask = signal(false); + vm$ = this.store.vm$; + $menu = viewChild('menu'); + $showMask = signal(false); ngOnInit(): void { - this.#store.init(); + this.store.init(); } - toogleMenu(event: CustomEvent): void { - this.menu.toggle(event); - this.showMask.update((value) => !value); + toggleMenu(event: Event): void { + this.$menu().toggle(event); + this.$showMask.update((value) => !value); + } + + hideMask(): void { + this.$showMask.update(() => false); } } diff --git a/core-web/apps/dotcms-ui/src/assets/seo/page-tools.json b/core-web/apps/dotcms-ui/src/assets/seo/page-tools.json index 33ec10494d94..cb809628fb00 100644 --- a/core-web/apps/dotcms-ui/src/assets/seo/page-tools.json +++ b/core-web/apps/dotcms-ui/src/assets/seo/page-tools.json @@ -12,7 +12,7 @@ "title": "Mozilla Observatory", "description": "The Mozilla Observatory has helped hundreds of thousands of websites by teaching developers, system administrators, and security professionals how to configure their sites safely and securely. ", "tags": ["Security", "Best Practices"], - "runnableLink": "https://developer.mozilla.org/en-US/observatory/analyze?host={requestHostName}" + "runnableLink": "https://developer.mozilla.org/en-US/observatory/analyze?host={domainName}" }, { "icon": "assets/seo/security-headers.png", diff --git a/core-web/libs/block-editor/src/lib/components/dot-editor-count-bar/dot-editor-count-bar.component.scss b/core-web/libs/block-editor/src/lib/components/dot-editor-count-bar/dot-editor-count-bar.component.scss index 5b6bdce8b16f..6772dd4da96d 100644 --- a/core-web/libs/block-editor/src/lib/components/dot-editor-count-bar/dot-editor-count-bar.component.scss +++ b/core-web/libs/block-editor/src/lib/components/dot-editor-count-bar/dot-editor-count-bar.component.scss @@ -7,7 +7,7 @@ color: $color-palette-gray-500; margin-top: 1rem; gap: 0.65rem; - font-size: $dot-editor-size; + font-size: $font-size-md; .error-message { color: $error; diff --git a/core-web/libs/block-editor/src/lib/extensions/bubble-link-form/bubble-link-form.component.scss b/core-web/libs/block-editor/src/lib/extensions/bubble-link-form/bubble-link-form.component.scss index 010bac910415..bd7f94c166dd 100644 --- a/core-web/libs/block-editor/src/lib/extensions/bubble-link-form/bubble-link-form.component.scss +++ b/core-web/libs/block-editor/src/lib/extensions/bubble-link-form/bubble-link-form.component.scss @@ -38,7 +38,7 @@ .url-container { cursor: pointer; white-space: nowrap; - font-size: $dot-editor-size; + font-size: $font-size-md; width: 100%; word-wrap: normal; display: flex; @@ -52,7 +52,7 @@ display: flex; gap: 0.2 * $dot-editor-size; min-width: 100%; - font-size: $dot-editor-size; + font-size: $font-size-md; .checkbox-container { cursor: pointer; diff --git a/core-web/libs/block-editor/src/lib/shared/components/suggestions/suggestions.component.scss b/core-web/libs/block-editor/src/lib/shared/components/suggestions/suggestions.component.scss index 99fcf541e0b6..3470ed5c6572 100644 --- a/core-web/libs/block-editor/src/lib/shared/components/suggestions/suggestions.component.scss +++ b/core-web/libs/block-editor/src/lib/shared/components/suggestions/suggestions.component.scss @@ -11,7 +11,7 @@ h3 { text-transform: uppercase; - font-size: $dot-editor-size; + font-size: $font-size-md; margin: (0.5 * $dot-editor-size) $dot-editor-size; color: #999999; } diff --git a/core-web/libs/dotcms-scss/jsp/scss/dotcms.scss b/core-web/libs/dotcms-scss/jsp/scss/dotcms.scss index 414f14b6014a..dc4488c237a9 100644 --- a/core-web/libs/dotcms-scss/jsp/scss/dotcms.scss +++ b/core-web/libs/dotcms-scss/jsp/scss/dotcms.scss @@ -77,6 +77,7 @@ legend, input, button, textarea, +select, p, blockquote, th, diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/store/dot-ema-dialog.store.spec.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/store/dot-ema-dialog.store.spec.ts index 576b77f1d6a5..ac6346b6ed3e 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/store/dot-ema-dialog.store.spec.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/store/dot-ema-dialog.store.spec.ts @@ -245,40 +245,82 @@ describe('DotEmaDialogStoreService', () => { }); }); - it('should update the state to show dialog for a translation', () => { - spectator.service.translatePage({ - page: { - inode: '123', - liveInode: '1234', - stInode: '12345', - live: true, - title: 'test' - } as DotPage, - newLanguage: 2 - }); + describe('Dialog for translation', () => { + it('should update the state to show dialog for a translation', () => { + spectator.service.translatePage({ + page: { + inode: '123', + liveInode: '1234', + stInode: '12345', + live: true, + title: 'test' + } as DotPage, + newLanguage: 2 + }); - const queryParams = new URLSearchParams({ - p_p_id: 'content', - p_p_action: '1', - p_p_state: 'maximized', - angularCurrentPortlet: 'edit-page', - _content_sibbling: '1234', - _content_cmd: 'edit', - p_p_mode: 'view', - _content_sibblingStructure: '1234', - _content_struts_action: '/ext/contentlet/edit_contentlet', - inode: '', - lang: '2', - populateaccept: 'true', - reuseLastLang: 'true' + const queryParams = new URLSearchParams({ + p_p_id: 'content', + p_p_action: '1', + p_p_state: 'maximized', + angularCurrentPortlet: 'edit-page', + _content_sibbling: '123', + _content_cmd: 'edit', + p_p_mode: 'view', + _content_sibblingStructure: '123', + _content_struts_action: '/ext/contentlet/edit_contentlet', + inode: '', + lang: '2', + populateaccept: 'true', + reuseLastLang: 'true' + }); + + spectator.service.dialogState$.subscribe((state) => { + expect(state).toEqual({ + url: LAYOUT_URL + '?' + queryParams.toString(), + status: DialogStatus.LOADING, + header: 'test', + type: 'content' + }); + }); }); - spectator.service.dialogState$.subscribe((state) => { - expect(state).toEqual({ - url: LAYOUT_URL + '?' + queryParams.toString(), - status: DialogStatus.LOADING, - header: 'test', - type: 'content' + it('should update the state to show dialog for a translation with working inode', () => { + spectator.service.translatePage({ + page: { + inode: '123', + liveInode: '1234', + stInode: '12345', + live: true, + title: 'test', + working: true, + workingInode: '56789' + } as DotPage, + newLanguage: 2 + }); + + const queryParams = new URLSearchParams({ + p_p_id: 'content', + p_p_action: '1', + p_p_state: 'maximized', + angularCurrentPortlet: 'edit-page', + _content_sibbling: '56789', + _content_cmd: 'edit', + p_p_mode: 'view', + _content_sibblingStructure: '56789', + _content_struts_action: '/ext/contentlet/edit_contentlet', + inode: '', + lang: '2', + populateaccept: 'true', + reuseLastLang: 'true' + }); + + spectator.service.dialogState$.subscribe((state) => { + expect(state).toEqual({ + url: LAYOUT_URL + '?' + queryParams.toString(), + status: DialogStatus.LOADING, + header: 'test', + type: 'content' + }); }); }); }); diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/store/dot-ema-dialog.store.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/store/dot-ema-dialog.store.ts index 3faedddb2f67..c1e27ac6602c 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/store/dot-ema-dialog.store.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/components/dot-ema-dialog/store/dot-ema-dialog.store.ts @@ -309,20 +309,17 @@ export class DotEmaDialogStore extends ComponentStore { } private createTranslatePageUrl(page: DotPage, newLanguage: number | string) { - const isLive = page.live; - const pageLiveInode = page.liveInode; - const iNode = page.inode; - const stInode = page.stInode; - + const { working, workingInode, inode } = page; + const pageInode = working ? workingInode : inode; const queryParams = new URLSearchParams({ p_p_id: 'content', p_p_action: '1', p_p_state: 'maximized', angularCurrentPortlet: 'edit-page', - _content_sibbling: isLive ? pageLiveInode : iNode, + _content_sibbling: pageInode, _content_cmd: 'edit', p_p_mode: 'view', - _content_sibblingStructure: isLive ? pageLiveInode : stInode, + _content_sibblingStructure: pageInode, _content_struts_action: '/ext/contentlet/edit_contentlet', inode: '', lang: newLanguage.toString(), diff --git a/core-web/libs/portlets/edit-ema/portlet/src/lib/shared/models.ts b/core-web/libs/portlets/edit-ema/portlet/src/lib/shared/models.ts index 88dd9a1d30de..e3c3f194e1f8 100644 --- a/core-web/libs/portlets/edit-ema/portlet/src/lib/shared/models.ts +++ b/core-web/libs/portlets/edit-ema/portlet/src/lib/shared/models.ts @@ -179,6 +179,8 @@ export interface DotPage { live: boolean; liveInode?: string; stInode?: string; + working?: boolean; + workingInode?: string; } export interface DotDeviceWithIcon extends DotDevice { diff --git a/core-web/libs/portlets/edit-ema/ui/src/lib/dot-page-tools-seo/dot-page-tools-seo.component.spec.ts b/core-web/libs/portlets/edit-ema/ui/src/lib/dot-page-tools-seo/dot-page-tools-seo.component.spec.ts index 726540501555..f086ecab478d 100644 --- a/core-web/libs/portlets/edit-ema/ui/src/lib/dot-page-tools-seo/dot-page-tools-seo.component.spec.ts +++ b/core-web/libs/portlets/edit-ema/ui/src/lib/dot-page-tools-seo/dot-page-tools-seo.component.spec.ts @@ -43,7 +43,7 @@ describe('DotPageToolsSeoComponent', () => { beforeEach(() => { pageToolUrlParamsTest = { currentUrl: '/blogTest', - requestHostName: 'localhost', + requestHostName: 'http://localhost', siteId: '123', languageId: 1 }; diff --git a/core-web/libs/sdk/angular/package.json b/core-web/libs/sdk/angular/package.json index 49dd4ea45040..477fcedcdf0d 100644 --- a/core-web/libs/sdk/angular/package.json +++ b/core-web/libs/sdk/angular/package.json @@ -1,11 +1,11 @@ { "name": "@dotcms/angular", - "version": "0.0.1-alpha.31", + "version": "0.0.1-alpha.32", "peerDependencies": { "@angular/common": "^17.1.0", "@angular/core": "^17.1.0", "@angular/router": "^17.1.0", - "@dotcms/client": "0.0.1-alpha.31", + "@dotcms/client": "0.0.1-alpha.32", "@tinymce/tinymce-angular": "^8.0.0", "rxjs": "^7.8.0" }, diff --git a/core-web/libs/sdk/client/README.md b/core-web/libs/sdk/client/README.md index 8d4801e35e8b..d90d233b5111 100644 --- a/core-web/libs/sdk/client/README.md +++ b/core-web/libs/sdk/client/README.md @@ -26,11 +26,23 @@ yarn add @dotcms/client ## Usage -First, initialize the client with your DotCMS instance details. +`@dotcms/client` supports both ES modules and CommonJS. You can import it using either syntax: + +### ES Modules ```javascript import { dotcmsClient } from '@dotcms/client'; +``` + +### CommonJS + +```javascript +const { dotcmsClient } = require('@dotcms/client'); +``` +First, initialize the client with your DotCMS instance details. + +```javascript const client = dotcmsClient.init({ dotcmsUrl: 'https://your-dotcms-instance.com', authToken: 'your-auth-token', @@ -107,4 +119,4 @@ Always refer to the official [DotCMS documentation](https://www.dotcms.com/docs/ | Videos | [Helpful Videos](http://dotcms.com/videos/) | | Forums/Listserv | [via Google Groups](https://groups.google.com/forum/#!forum/dotCMS) | | Twitter | @dotCMS | -| Main Site | [dotCMS.com](https://dotcms.com/) | +| Main Site | [dotCMS.com](https://dotcms.com/) | \ No newline at end of file diff --git a/core-web/libs/sdk/client/package.json b/core-web/libs/sdk/client/package.json index 9a8c56e50ee7..3c049aa9e858 100644 --- a/core-web/libs/sdk/client/package.json +++ b/core-web/libs/sdk/client/package.json @@ -1,7 +1,6 @@ { "name": "@dotcms/client", - "version": "0.0.1-alpha.31", - "type": "module", + "version": "0.0.1-alpha.32", "description": "Official JavaScript library for interacting with DotCMS REST APIs.", "repository": { "type": "git", diff --git a/core-web/libs/sdk/client/project.json b/core-web/libs/sdk/client/project.json index 1286a369b1f6..b2a7f198c96b 100644 --- a/core-web/libs/sdk/client/project.json +++ b/core-web/libs/sdk/client/project.json @@ -5,13 +5,16 @@ "projectType": "library", "targets": { "build": { - "executor": "@nrwl/js:tsc", + "executor": "@nx/rollup:rollup", "outputs": ["{options.outputPath}"], "options": { + "format": ["esm", "cjs"], + "compiler": "tsc", + "generateExportsField": true, + "assets": [{ "input": ".", "output": ".", "glob": "*.md" }], "outputPath": "dist/libs/sdk/client", "main": "libs/sdk/client/src/index.ts", - "tsConfig": "libs/sdk/client/tsconfig.lib.json", - "assets": ["libs/sdk/client/*.md"] + "tsConfig": "libs/sdk/client/tsconfig.lib.json" } }, "build:js": { @@ -34,7 +37,7 @@ "publish": { "executor": "nx:run-commands", "options": { - "command": "node tools/scripts/publish.mjs sdk-js-client {args.ver} {args.tag}" + "command": "node tools/scripts/publish.mjs sdk-client {args.ver} {args.tag}" }, "dependsOn": ["build"] }, diff --git a/core-web/libs/sdk/client/src/index.ts b/core-web/libs/sdk/client/src/index.ts index 5c720d05e47d..919b1f1f6981 100644 --- a/core-web/libs/sdk/client/src/index.ts +++ b/core-web/libs/sdk/client/src/index.ts @@ -1,6 +1,30 @@ -export * from './lib/client/sdk-js-client'; -export * from './lib/editor/sdk-editor'; -export * from './lib/editor/models/editor.model'; -export * from './lib/editor/models/client.model'; -export * from './lib/query-builder/sdk-query-builder'; -export * from './lib/utils'; +import { ClientConfig, DotCmsClient } from './lib/client/sdk-js-client'; +import { CUSTOMER_ACTIONS, postMessageToEditor } from './lib/editor/models/client.model'; +import { + CustomClientParams, + DotCMSPageEditorConfig, + EditorConfig +} from './lib/editor/models/editor.model'; +import { + destroyEditor, + initEditor, + isInsideEditor, + updateNavigation +} from './lib/editor/sdk-editor'; +import { getPageRequestParams, graphqlToPageEntity } from './lib/utils'; + +export { + graphqlToPageEntity, + getPageRequestParams, + isInsideEditor, + DotCmsClient, + DotCMSPageEditorConfig, + CUSTOMER_ACTIONS, + CustomClientParams, + postMessageToEditor, + EditorConfig, + initEditor, + updateNavigation, + destroyEditor, + ClientConfig +}; diff --git a/core-web/libs/sdk/client/tsconfig.lib.json b/core-web/libs/sdk/client/tsconfig.lib.json index 163d90724090..2f77580986dc 100644 --- a/core-web/libs/sdk/client/tsconfig.lib.json +++ b/core-web/libs/sdk/client/tsconfig.lib.json @@ -3,7 +3,10 @@ "compilerOptions": { "outDir": "../../../dist/out-tsc", "declaration": true, - "types": ["node"] + "types": [""], + "target": "es2020", + "module": "es2020", + "moduleResolution": "node" }, "include": ["src/**/*.ts"], "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] diff --git a/core-web/libs/sdk/experiments/package.json b/core-web/libs/sdk/experiments/package.json index e2429154a078..2eed7e32c417 100644 --- a/core-web/libs/sdk/experiments/package.json +++ b/core-web/libs/sdk/experiments/package.json @@ -1,6 +1,6 @@ { "name": "@dotcms/experiments", - "version": "0.0.1-alpha.31", + "version": "0.0.1-alpha.32", "description": "Official JavaScript library to use Experiments with DotCMS.", "repository": { "type": "git", @@ -25,6 +25,6 @@ "peerDependencies": { "react": ">=18", "react-dom": ">=18", - "@dotcms/client": "0.0.1-alpha.31" + "@dotcms/client": "0.0.1-alpha.32" } } diff --git a/core-web/libs/sdk/react/package.json b/core-web/libs/sdk/react/package.json index 64ce599625a9..598add55b570 100644 --- a/core-web/libs/sdk/react/package.json +++ b/core-web/libs/sdk/react/package.json @@ -1,10 +1,10 @@ { "name": "@dotcms/react", - "version": "0.0.1-alpha.31", + "version": "0.0.1-alpha.32", "peerDependencies": { "react": ">=18", "react-dom": ">=18", - "@dotcms/client": "0.0.1-alpha.31" + "@dotcms/client": "0.0.1-alpha.32" }, "description": "Official React Components library to render a dotCMS page.", "repository": { diff --git a/core-web/libs/ui/src/lib/components/dot-asset-search/components/dot-asset-card/dot-asset-card.component.scss b/core-web/libs/ui/src/lib/components/dot-asset-search/components/dot-asset-card/dot-asset-card.component.scss index c17788c3ee61..aa8fcfebf904 100644 --- a/core-web/libs/ui/src/lib/components/dot-asset-search/components/dot-asset-card/dot-asset-card.component.scss +++ b/core-web/libs/ui/src/lib/components/dot-asset-search/components/dot-asset-card/dot-asset-card.component.scss @@ -47,7 +47,7 @@ .p-card-title { flex-grow: 1; h2 { - font-size: $dot-editor-size; + font-size: $font-size-md; line-height: 140%; margin: 0; overflow: hidden; diff --git a/core-web/libs/utils-testing/src/lib/dot-page-tools.mock.ts b/core-web/libs/utils-testing/src/lib/dot-page-tools.mock.ts index b595d8a2a60c..e7b5b5519017 100644 --- a/core-web/libs/utils-testing/src/lib/dot-page-tools.mock.ts +++ b/core-web/libs/utils-testing/src/lib/dot-page-tools.mock.ts @@ -9,7 +9,7 @@ export const mockPageTools: DotPageTools = { 'The WAVE® evaluation suite helps educate authors on how to make their web content more accessible to individuals with disabilities. WAVE can identify many accessibility and Web Content Accessibility Guideline (WCAG) errors, but also facilitates human evaluation of web content.', tags: ['Accessibility', 'WCAG'], runnableLink: - 'https://wave.webaim.org/report#/localhost/blogTest?host_id=123?language_id=1' + 'https://wave.webaim.org/report#/http://localhost/blogTest?host_id=123?language_id=1' }, { icon: 'assets/seo/mozilla.png', @@ -17,7 +17,7 @@ export const mockPageTools: DotPageTools = { description: 'The Mozilla Observatory has helped hundreds of thousands of websites by teaching developers, system administrators, and security professionals how to configure their sites safely and securely. ', tags: ['Security', 'Best Practices'], - runnableLink: 'https://observatory.mozilla.org/analyze/localhost' + runnableLink: 'https://developer.mozilla.org/en-US/observatory/analyze?host=localhost' }, { icon: 'assets/seo/security-headers.png', @@ -26,7 +26,7 @@ export const mockPageTools: DotPageTools = { 'This tool is designed to help you better deploy and understand modern security features that are available for your website. It will provide a simple to understand grading system for how well your site follows best practices, as well as suggestions for how to make improvement.', tags: ['Securty', 'Best Practices'], runnableLink: - 'https://securityheaders.com/?q=localhost/blogTest&host_id=123&language_id=1&followRedirects=on' + 'https://securityheaders.com/?q=http://localhost/blogTest&host_id=123&language_id=1&followRedirects=on' } ] }; diff --git a/core-web/libs/utils/src/lib/dot-utils.spec.ts b/core-web/libs/utils/src/lib/dot-utils.spec.ts index 0f7163ffd650..2fb5b6f1d1e9 100644 --- a/core-web/libs/utils/src/lib/dot-utils.spec.ts +++ b/core-web/libs/utils/src/lib/dot-utils.spec.ts @@ -130,13 +130,13 @@ describe('Dot Utils', () => { 'https://wave.webaim.org/report#/{requestHostName}{currentUrl}{urlSearchParams}'; const params: DotPageToolUrlParams = { currentUrl: '', - requestHostName: 'my-site', + requestHostName: 'https://my-site.com', siteId: '', languageId: 1 }; expect(getRunnableLink(url, params)).toEqual( - 'https://wave.webaim.org/report#/my-site?language_id=1' + 'https://wave.webaim.org/report#/https://my-site.com?language_id=1' ); }); @@ -145,28 +145,27 @@ describe('Dot Utils', () => { 'https://wave.webaim.org/report#/{requestHostName}{currentUrl}{urlSearchParams}'; const params: DotPageToolUrlParams = { currentUrl: '/current-page', - requestHostName: 'my-site', + requestHostName: 'https://my-site.com', siteId: '50a79decd9e21702cb2f52fc4935a52b', languageId: 1 }; expect(getRunnableLink(url, params)).toEqual( - 'https://wave.webaim.org/report#/my-site/current-page?host_id=50a79decd9e21702cb2f52fc4935a52b&language_id=1' + 'https://wave.webaim.org/report#/https://my-site.com/current-page?host_id=50a79decd9e21702cb2f52fc4935a52b&language_id=1' ); }); it('should replace {requestHostName} and append query parameters in Mozilla Observatory URL', () => { - const url = - 'https://developer.mozilla.org/en-US/observatory/analyze?host={requestHostName}'; + const url = 'https://developer.mozilla.org/en-US/observatory/analyze?host={domainName}'; const params: DotPageToolUrlParams = { currentUrl: '', - requestHostName: 'my-site', + requestHostName: 'http://my-site.com:80', siteId: '50a79decd9e21702cb2f52fc4935a52b', languageId: 1 }; expect(getRunnableLink(url, params)).toEqual( - 'https://developer.mozilla.org/en-US/observatory/analyze?host=my-site' + 'https://developer.mozilla.org/en-US/observatory/analyze?host=my-site.com' ); }); @@ -175,13 +174,13 @@ describe('Dot Utils', () => { 'https://securityheaders.com/?q={requestHostName}{currentUrl}{urlSearchParams}&followRedirects=on'; const params: DotPageToolUrlParams = { currentUrl: '/current-page', - requestHostName: 'my-site', + requestHostName: 'https://my-site.com', siteId: '50a79decd9e21702cb2f52fc4935a52b', languageId: 1 }; expect(getRunnableLink(url, params)).toEqual( - 'https://securityheaders.com/?q=my-site/current-page?host_id=50a79decd9e21702cb2f52fc4935a52b&language_id=1&followRedirects=on' + 'https://securityheaders.com/?q=https://my-site.com/current-page?host_id=50a79decd9e21702cb2f52fc4935a52b&language_id=1&followRedirects=on' ); }); @@ -200,12 +199,14 @@ describe('Dot Utils', () => { const url = 'https://example.com/{requestHostName}/page'; const params: DotPageToolUrlParams = { currentUrl: '', - requestHostName: 'my-site', + requestHostName: 'https://my-site.com', siteId: '', languageId: 1 }; - expect(getRunnableLink(url, params)).toEqual('https://example.com/my-site/page'); + expect(getRunnableLink(url, params)).toEqual( + 'https://example.com/https://my-site.com/page' + ); }); it('should replace {currentUrl} with the actual currentUrl', () => { @@ -238,13 +239,13 @@ describe('Dot Utils', () => { const url = 'https://example.com/{requestHostName}{currentUrl}{urlSearchParams}'; const params: DotPageToolUrlParams = { currentUrl: '/current-page', - requestHostName: 'my-site', + requestHostName: 'https://my-site.com', siteId: '123', languageId: 456 }; expect(getRunnableLink(url, params)).toEqual( - 'https://example.com/my-site/current-page?host_id=123&language_id=456' + 'https://example.com/https://my-site.com/current-page?host_id=123&language_id=456' ); }); @@ -295,5 +296,75 @@ describe('Dot Utils', () => { expect(getRunnableLink(url, params)).toEqual('https://example.com/'); }); + + it('should and respect https protocol and port in requestHostName', () => { + const url = 'https://example.com/{requestHostName}{currentUrl}{urlSearchParams}'; + const params: DotPageToolUrlParams = { + currentUrl: '/current-page', + requestHostName: 'https://my-site.com:4200', + siteId: '123', + languageId: 456 + }; + + expect(getRunnableLink(url, params)).toEqual( + 'https://example.com/https://my-site.com:4200/current-page?host_id=123&language_id=456' + ); + }); + + it('should and respect http protocol and port in requestHostName', () => { + const url = 'https://example.com/{requestHostName}{currentUrl}{urlSearchParams}'; + const params: DotPageToolUrlParams = { + currentUrl: '/current-page', + requestHostName: 'http://my-site.com:4200', + siteId: '123', + languageId: 456 + }; + + expect(getRunnableLink(url, params)).toEqual( + 'https://example.com/http://my-site.com:4200/current-page?host_id=123&language_id=456' + ); + }); + + it('should remove port and protocol in domainName', () => { + const url = 'https://example.com/{domainName}{currentUrl}{urlSearchParams}'; + const params: DotPageToolUrlParams = { + currentUrl: '/current-page', + requestHostName: 'https://my-site.com:4200', + siteId: '123', + languageId: 456 + }; + + expect(getRunnableLink(url, params)).toEqual( + 'https://example.com/my-site.com/current-page?host_id=123&language_id=456' + ); + }); + + it('should remove port in requestHostName given https protocol and 443 port ', () => { + const url = 'https://example.com/{requestHostName}{currentUrl}{urlSearchParams}'; + const params: DotPageToolUrlParams = { + currentUrl: '/current-page', + requestHostName: 'https://my-site.com:443', + siteId: '123', + languageId: 456 + }; + + expect(getRunnableLink(url, params)).toEqual( + 'https://example.com/https://my-site.com/current-page?host_id=123&language_id=456' + ); + }); + + it('should remove port in requestHostName given http protocol and 80 port ', () => { + const url = 'https://example.com/{requestHostName}{currentUrl}{urlSearchParams}'; + const params: DotPageToolUrlParams = { + currentUrl: '/current-page', + requestHostName: 'http://my-site.com:80', + siteId: '123', + languageId: 456 + }; + + expect(getRunnableLink(url, params)).toEqual( + 'https://example.com/http://my-site.com/current-page?host_id=123&language_id=456' + ); + }); }); }); diff --git a/core-web/libs/utils/src/lib/dot-utils.ts b/core-web/libs/utils/src/lib/dot-utils.ts index 27918942f6f1..1db28810f97d 100644 --- a/core-web/libs/utils/src/lib/dot-utils.ts +++ b/core-web/libs/utils/src/lib/dot-utils.ts @@ -70,8 +70,10 @@ export function getRunnableLink(url: string, currentPageUrlParams: DotPageToolUr if (languageId) pageParams.append('language_id', String(languageId)); // Replace placeholders in the base URL with actual values and append query parameters if they exist + const requestHostUrl = requestHostName ? new URL(requestHostName) : null; const finalUrl = url - .replace(/{requestHostName}/g, requestHostName ?? '') + .replace(/{requestHostName}/g, requestHostUrl ? requestHostUrl.origin : '') + .replace(/{domainName}/g, requestHostUrl ? requestHostUrl.hostname : '') .replace(/{currentUrl}/g, currentUrl ?? '') .replace(/{urlSearchParams}/g, pageParams.toString() ? `?${pageParams.toString()}` : ''); diff --git a/core-web/tools/scripts/publish.mjs b/core-web/tools/scripts/publish.mjs index ba40aaa8e9c7..f2eeb6a7d686 100644 --- a/core-web/tools/scripts/publish.mjs +++ b/core-web/tools/scripts/publish.mjs @@ -56,4 +56,4 @@ try { } // Execute "npm publish" to publish -execSync(`npm publish --access public --tag ${tag}`); +execSync(`npm publish --access public --tag ${tag} --dry-run`); diff --git a/dotCMS/pom.xml b/dotCMS/pom.xml index 143d68ffaf9d..f7fa0c97edfd 100644 --- a/dotCMS/pom.xml +++ b/dotCMS/pom.xml @@ -15,8 +15,6 @@ 2.29.0 ${project.basedir}/src/main/java ${project.basedir}/src/test/java - 2.36.0 - 1.16 0.14.1 1.10.6 ${basedir}/target/dist @@ -27,6 +25,8 @@ true dotserver/tomcat-${tomcat.version} ${assembly-directory}/${tomcat-dist-folder}/lib + ${assembly-directory}/${tomcat-dist-folder}/log4j2/lib + ${assembly-directory}/${tomcat-dist-folder}/session-manager/lib ${project.basedir}/src/main/resources/container/tomcat9 ${assembly-directory}/${tomcat-dist-folder}/webapps/ROOT ${project.build.directory}/${project.build.finalName}-war.war @@ -63,10 +63,6 @@ felix/core/undeployed felix/system/undeployed - 1.3 - 2.11.1 - 1.7.36 - 4.4.6 ${project.build.directory}/tomcat-run-data/${context.name} false @@ -88,6 +84,11 @@ zip provided + + com.dotcms + tomcat-redis-session-manager + provided + com.dotcms.plugins dotcms-system-bundles @@ -1351,21 +1352,30 @@ org.apache.logging.log4j log4j-jcl + runtime - + org.apache.logging.log4j - log4j-slf4j2-impl + log4j-jcl + runtime - + org.slf4j + slf4j-api + compile + + + org.apache.logging.log4j - log4j-web + log4j-appserver + provided com.lmax disruptor + runtime @@ -1402,6 +1412,12 @@ + + org.apache.tomcat + tomcat-catalina + ${tomcat.version} + provided + @@ -1535,37 +1551,69 @@ - com.dotcms - tomcat-redis-session-manager - ${tomcat.redis-session-manager.version} + org.apache.logging.log4j + log4j-api jar - true - ${tomcat-lib-folder} + false + ${tomcat-log4j-lib-folder} - org.apache.commons - commons-pool2 - ${commons-pool2.version} + org.apache.logging.log4j + log4j-core jar - true - ${tomcat-lib-folder} + false + ${tomcat-log4j-lib-folder} + + + org.apache.logging.log4j + log4j-appserver + jar + false + ${tomcat-log4j-lib-folder} + + + org.apache.logging.log4j + log4j-slf4j2-impl + jar + false + ${tomcat-log4j-lib-folder} org.slf4j slf4j-api - ${org.slfj4.version} + jar + false + ${tomcat-log4j-lib-folder} + + + com.dotcms + tomcat-redis-session-manager jar true - ${tomcat-lib-folder} + ${session-manager-lib-folder} + + + org.apache.commons + commons-pool2 + jar + true + ${session-manager-lib-folder} redis.clients jedis - ${jedis.version} jar true - ${tomcat-lib-folder} + ${session-manager-lib-folder} + + + + com.lmax + disruptor + true + ${tomcat-log4j-lib-folder} + @@ -1913,12 +1961,6 @@ ${tomcat9-overrides}/bin/setenv.sh bin - ${tomcat9-overrides}/conf/server.xml conf diff --git a/dotCMS/src/enterprise/java/com/dotcms/enterprise/publishing/remote/handler/ContentHandler.java b/dotCMS/src/enterprise/java/com/dotcms/enterprise/publishing/remote/handler/ContentHandler.java index 5719dbde4a24..3a4ffa980339 100644 --- a/dotCMS/src/enterprise/java/com/dotcms/enterprise/publishing/remote/handler/ContentHandler.java +++ b/dotCMS/src/enterprise/java/com/dotcms/enterprise/publishing/remote/handler/ContentHandler.java @@ -114,10 +114,12 @@ import com.dotmarketing.util.PushPublishLogger.PushPublishHandler; import com.dotmarketing.util.UUIDUtil; import com.dotmarketing.util.UtilMethods; +import com.google.common.annotations.VisibleForTesting; import com.liferay.portal.model.User; import com.liferay.util.FileUtil; import com.thoughtworks.xstream.XStream; import io.vavr.Lazy; +import io.vavr.control.Try; import org.apache.commons.lang3.tuple.Pair; import java.io.File; @@ -1049,32 +1051,48 @@ private String getUniqueMatchErrorMsg(final List uniqueFields, final Stri matchedContent.getInode(), fieldsInfo.toString()); } - /** - * Associates a list of tags coming from the bundle to the specified local content. - * - * @param content - The {@link Contentlet} that will have the updated tags from the bundle. - * @param tagsFromSender - The list of {@link Tag} objects coming from the sender, - * @throws DotDataException Tags could not be read or saved to the data source. - */ - private void relateTagsToContent(Contentlet content, Map> tagsFromSender) throws DotDataException { - if(tagsFromSender!=null) { - for (Map.Entry> fieldTags : tagsFromSender.entrySet()) { - String fieldVarName = fieldTags.getKey(); + /** + * Associates a list of tags coming from the bundle to the specified local content. + * + * @param content - The {@link Contentlet} that will have the updated tags from the bundle. + * @param tagsFromSender - The list of {@link Tag} objects coming from the sender, + * @throws DotDataException Tags could not be read or saved to the data source. + */ + @VisibleForTesting + void relateTagsToContent(Contentlet content, Map> tagsFromSender) throws DotDataException { + if(tagsFromSender==null || tagsFromSender.isEmpty()) { + return; + } - for (Tag remoteTag : fieldTags.getValue()) { - Tag localTag = tagAPI.getTagByNameAndHost(remoteTag.getTagName(), remoteTag.getHostId()); + for (Map.Entry> fieldTags : tagsFromSender.entrySet()) { + String fieldVarName = fieldTags.getKey(); - // if there is NO local tag, save the one coming from remote, otherwise use local - if (localTag == null || Strings.isNullOrEmpty(localTag.getTagId())) { - localTag = tagAPI.saveTag(remoteTag.getTagName(), remoteTag.getUserId(), remoteTag.getHostId()); - } + for (Tag remoteTag : fieldTags.getValue()) { + Tag localTag = tagAPI.getTagByNameAndHost(remoteTag.getTagName(), remoteTag.getHostId()); - TagInode localTagInode = tagAPI.getTagInode(localTag.getTagId(), content.getInode(), fieldVarName); + String localUserId = Try.of(()->APILocator.getUserAPI().loadUserById(remoteTag.getUserId()).getUserId()).getOrElse(APILocator.systemUser().getUserId()); - // avoid relating tags twice - if(localTagInode==null || !Strings.isNullOrEmpty(localTagInode.getTagId())) { - tagAPI.addContentletTagInode(localTag, content.getInode(), fieldVarName); - } + Host tagSite = Try.of(()->APILocator.getHostAPI().find(remoteTag.getHostId(), APILocator.systemUser(), false)).getOrNull(); + Host contentSite = Try.of(()->APILocator.getHostAPI().find(content.getIdentifier(), APILocator.systemUser(), false)).getOrNull(); + + final String localSiteId = UtilMethods.isSet(()->tagSite.getTagStorage()) + ? tagSite.getTagStorage() + : UtilMethods.isSet(()->contentSite.getTagStorage()) + ? contentSite.getTagStorage() + : Host.SYSTEM_HOST; + + + + // if there is NO local tag, save the one coming from remote, otherwise use local + if (localTag == null || Strings.isNullOrEmpty(localTag.getTagId())) { + localTag = tagAPI.saveTag(remoteTag.getTagName(), localUserId, localSiteId); + } + + TagInode localTagInode = tagAPI.getTagInode(localTag.getTagId(), content.getInode(), fieldVarName); + + // avoid relating tags twice + if(UtilMethods.isEmpty(()->localTagInode.getTagId())) { + tagAPI.addContentletTagInode(localTag, content.getInode(), fieldVarName); } } } diff --git a/dotCMS/src/enterprise/java/com/dotcms/enterprise/publishing/remote/handler/ContentTypeHandler.java b/dotCMS/src/enterprise/java/com/dotcms/enterprise/publishing/remote/handler/ContentTypeHandler.java index f582bb5beeca..4c1ab2516dba 100644 --- a/dotCMS/src/enterprise/java/com/dotcms/enterprise/publishing/remote/handler/ContentTypeHandler.java +++ b/dotCMS/src/enterprise/java/com/dotcms/enterprise/publishing/remote/handler/ContentTypeHandler.java @@ -45,6 +45,11 @@ package com.dotcms.enterprise.publishing.remote.handler; +import com.dotcms.api.system.event.message.MessageSeverity; +import com.dotcms.api.system.event.message.MessageType; +import com.dotcms.api.system.event.message.SystemMessageEventUtil; +import com.dotcms.api.system.event.message.builder.SystemMessage; +import com.dotcms.api.system.event.message.builder.SystemMessageBuilder; import com.dotcms.business.WrapInTransaction; import com.dotcms.contenttype.business.ContentTypeAPI; import com.dotcms.contenttype.business.FieldAPI; @@ -54,7 +59,7 @@ import com.dotcms.contenttype.model.field.RelationshipField; import com.dotcms.contenttype.model.field.RelationshipFieldBuilder; import com.dotcms.contenttype.model.type.ContentType; -import com.dotcms.contenttype.transform.contenttype.StructureTransformer; +import com.dotcms.contenttype.model.type.ContentTypeBuilder; import com.dotcms.enterprise.LicenseUtil; import com.dotcms.enterprise.license.LicenseLevel; import com.dotcms.enterprise.publishing.remote.bundler.ContentTypeBundler; @@ -64,7 +69,6 @@ import com.dotcms.publishing.DotPublishingException; import com.dotcms.publishing.PublisherConfig; import com.dotcms.publishing.PublisherConfig.Operation; -import com.dotcms.repackage.com.google.common.collect.ImmutableList; import com.dotcms.workflow.helper.SystemActionMappingsHandlerMerger; import com.dotmarketing.beans.Host; import com.dotmarketing.business.APILocator; @@ -72,13 +76,13 @@ import com.dotmarketing.business.PermissionAPI; import com.dotmarketing.business.UserAPI; import com.dotmarketing.exception.DotDataException; +import com.dotmarketing.exception.DotRuntimeException; import com.dotmarketing.exception.DotSecurityException; import com.dotmarketing.portlets.contentlet.business.HostAPI; import com.dotmarketing.portlets.folders.business.FolderAPI; import com.dotmarketing.portlets.folders.model.Folder; import com.dotmarketing.portlets.workflows.business.WorkflowAPI; import com.dotmarketing.portlets.workflows.model.SystemActionWorkflowActionMapping; -import com.dotmarketing.portlets.workflows.model.WorkflowScheme; import com.dotmarketing.util.Logger; import com.dotmarketing.util.PushPublishLogger; import com.dotmarketing.util.PushPublishLogger.PushPublishAction; @@ -86,12 +90,10 @@ import com.dotmarketing.util.UtilMethods; import com.liferay.portal.model.User; import com.liferay.util.FileUtil; +import io.vavr.control.Try; import java.io.File; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; /** @@ -139,7 +141,7 @@ public String getName() { public void handle(final File bundleFolder) throws Exception { if(LicenseUtil.getLevel() < LicenseLevel.PROFESSIONAL.level) { - throw new RuntimeException("need an enterprise pro license to run this"); + throw new DotRuntimeException("need an enterprise pro license to run this"); } final Collection contentTypes = FileUtil.listFilesRecursively @@ -152,65 +154,66 @@ private void handleContentTypes(final Collection contentTypes) throws DotP if(LicenseUtil.getLevel() < LicenseLevel.PROFESSIONAL.level) { - throw new RuntimeException("need an enterprise pro license to run this"); + throw new DotRuntimeException("need an enterprise pro license to run this"); } File workingOn = null; ContentType contentType = null; try { //Handle folders for(final File contentTypeFile: contentTypes) { - workingOn = contentTypeFile; - if(contentTypeFile.isDirectory()) { - - continue; + if(contentTypeFile.isDirectory()) { + continue; } + workingOn = contentTypeFile; + final ContentTypeWrapper contentTypeWrapper = BundlerUtil .jsonToObject(contentTypeFile, ContentTypeWrapper.class); - contentType = contentTypeWrapper.getContentType(); + if(UtilMethods.isEmpty(()->contentTypeWrapper.getContentType().inode())){ + continue; + } + + contentType = contentTypeWrapper.getContentType(); + final List fields = contentTypeWrapper.getFields(); final List fieldVariables = contentTypeWrapper.getFieldVariables(); - ContentType localContentType = null; - try { - localContentType = typeAPI.find(contentType.inode()); - } catch (final NotFoundInDbException e) { - // The Content Type doesn't exist in the receiving instance. Just move on - localContentType = null; - } - final boolean localExists = localContentType != null && UtilMethods.isSet(localContentType.inode()); + final Optional inodeType = Try.of(()->typeAPI.find(contentTypeWrapper.getContentType().inode())).toJavaOptional(); + final Optional variableType = Try.of(()->typeAPI.find(contentTypeWrapper.getContentType().variable())).toJavaOptional(); + + if(inodeType.isPresent() && variableType.isPresent() && ! inodeType.get().inode().equals(variableType.get().inode())){ + throw new DotPublishingException("ContentType:" + contentType.variable() + " exists but does not have the same inode. Expecting: " + contentType.inode() + " and got:" + variableType.get().inode() + "\n\t\tPlease delete one of the types or run the integrity checker before continuing."); + } + + + final ContentType localContentType = inodeType.orElse(variableType.orElse((null))); - if(contentTypeWrapper.getOperation().equals(Operation.UNPUBLISH)) { - // delete operation - if(localExists) { - String contentTypeInode = localContentType.inode(); - if(contentType.fixed()){ - PushPublishLogger.error(getClass(), PushPublishHandler.CONTENT_TYPE, PushPublishAction.UNPUBLISH, - localContentType.id(), localContentType.inode(), localContentType.name(), config.getId(), - "Type is Fixed", null); - continue; - } + if(contentTypeWrapper.getOperation().equals(Operation.UNPUBLISH)) { this.deleteContentType(localContentType); - } - } else { + continue; + } + + // create/update the structure + ContentType updatedContentType = this.saveOrUpdateContentType(contentTypeWrapper, contentType, fields, + fieldVariables, localContentType); - // create/update the structure - localContentType = this.saveOrUpdateContentType(contentTypeWrapper, contentType, fields, - fieldVariables, localContentType, localExists); - } //And finally verify it this content type was the default type of an already added folder - this.verifyPendingFolders(localContentType); + this.verifyPendingFolders(updatedContentType); } } catch (final Exception e) { + Logger.error(this.getClass(), "Error on Content Type: "+ workingOn); + Logger.error(this.getClass(), e.getMessage(), e); + final String errorMsg = String.format("An error occurred when processing Content Type in '%s' with ID '%s': %s", - workingOn, (null == contentType ? "(empty)" : contentType.name()), (null == contentType ? "(empty)" : - contentType.id()), e.getMessage()); - Logger.error(this.getClass(), errorMsg, e); + (null == contentType ? "(empty)" : contentType.variable()), + (null == contentType ? "(empty)" : contentType.id()), + e.getMessage()); + throw new DotPublishingException(errorMsg, e); } } @@ -248,13 +251,21 @@ private void verifyPendingFolders(final ContentType localContentType) throws Dot } } - private void deleteContentType(final ContentType localContentType) throws DotSecurityException, DotDataException { + private void deleteContentType(final ContentType localContentType) { + if(UtilMethods.isEmpty(()->localContentType.inode())){ + return; + } try { - + if(localContentType.fixed()){ + PushPublishLogger.error(getClass(), PushPublishHandler.CONTENT_TYPE, PushPublishAction.UNPUBLISH, + localContentType.id(), localContentType.inode(), localContentType.name(), config.getId(), + "Type is Fixed", null); + return; + } typeAPI.delete(localContentType); PushPublishLogger.log(getClass(), PushPublishHandler.CONTENT_TYPE, PushPublishAction.UNPUBLISH, localContentType.id(), localContentType.inode(), localContentType.name(), config.getId()); - } catch(DotStateException ex) { + } catch(DotStateException | DotSecurityException | DotDataException ex) { PushPublishLogger.error(getClass(), PushPublishHandler.CONTENT_TYPE, PushPublishAction.UNPUBLISH, localContentType.id(), localContentType.inode(), localContentType.name(), config.getId(), null, ex); @@ -279,29 +290,38 @@ private void deleteContentType(final ContentType localContentType) throws DotSec * @throws DotSecurityException The dotCMS user accessing the APIs doesn't have the required permissions to do so. */ private ContentType saveOrUpdateContentType(final ContentTypeWrapper contentTypeWrapper, - final ContentType contentType, + final ContentType contentTypeIn, final List fields, final List fieldVariables, - ContentType localContentType, - final boolean localExists) throws DotDataException, DotSecurityException { - final Host site = this.siteAPI.find(contentType.host(), APILocator.getUserAPI().getSystemUser(), false); - if (null == site || !UtilMethods.isSet(site.getIdentifier())) { - throw new NotFoundInDbException(String.format("Content Type '%s' [%s] is pointing to an invalid Site ID: " + - "'%s'. Make sure that the ID of the Site in the sender is the same as the receiver.", contentType - .name(), contentType.id(), contentType.host())); - } - final List deferredFields = fields.stream() + final ContentType localContentType) throws DotDataException, DotSecurityException { + + final String hostId = UtilMethods.isSet(()-> localContentType.inode()) + ? localContentType.host() + : Try.of(()->this.siteAPI.find(contentTypeIn.host(), APILocator.systemUser(), false).getIdentifier()) + .toJavaOptional() + .orElse(Host.SYSTEM_HOST); + + + // update host so that it works locally + final ContentType typeToSave = hostId.equals(contentTypeIn.host()) + ? contentTypeIn + : ContentTypeBuilder.builder(contentTypeIn).from(contentTypeIn).host(hostId).build(); + + + final List deferredFields = fields.stream() .map(field -> { if (field instanceof RelationshipField) { return RelationshipFieldBuilder.builder(field).skipRelationshipCreation(true).build(); } return field; }).collect(Collectors.toList()); - contentType.constructWithFields(deferredFields); - if(localContentType == null) { - typeAPI.save(contentType); + typeToSave.constructWithFields(deferredFields); + + if(UtilMethods.isEmpty(()->localContentType.inode())) { + + typeAPI.save(typeToSave); for (final FieldVariable fieldVariable : fieldVariables) { @@ -309,27 +329,50 @@ private ContentType saveOrUpdateContentType(final ContentTypeWrapper contentType } } else { - typeAPI.save(contentType, deferredFields, fieldVariables); + typeAPI.save(typeToSave, deferredFields, fieldVariables); } PushPublishLogger.log(getClass(), PushPublishHandler.CONTENT_TYPE, PushPublishAction.PUBLISH, - contentType.id(), contentType.inode(), contentType.name(), config.getId()); + typeToSave.id(), typeToSave.inode(), typeToSave.name(), config.getId()); + + - localContentType = typeAPI.find(contentType.inode()); + + + ContentType returnType = typeAPI.find(typeToSave.inode()); // set the workflow scheme - setWorkflowScheme(contentTypeWrapper, contentType, localContentType, localExists); - return localContentType; + this.setWorkflowScheme(contentTypeWrapper, typeToSave, returnType); + + + + if(!hostId.equals(contentTypeIn.host())){ + String siteName = Try.of(()->this.siteAPI.find(returnType.host(), APILocator.systemUser(), false).getHostname()).getOrElse(returnType.host()); + + SystemMessage message = new SystemMessageBuilder() + .setMessage("Content type: " + returnType.variable() + " imported successfully but moved from site id: " + contentTypeIn.host() + " to " + siteName) + .setType(MessageType.SIMPLE_MESSAGE) + .setLife(15) + .setSeverity(MessageSeverity.INFO) + .create(); + APILocator.getRoleAPI().findUserIdsForRole(APILocator.getRoleAPI().loadCMSAdminRole()); + + + SystemMessageEventUtil.getInstance().pushMessage(message, APILocator.getRoleAPI().findUserIdsForRole(APILocator.getRoleAPI().loadCMSAdminRole())); + + } + + return returnType; } + private void setWorkflowScheme(final ContentTypeWrapper contentTypeWrapper, final ContentType contentType, - final ContentType localContentType, - final boolean localExists) throws DotDataException, DotSecurityException { + final ContentType localContentType) throws DotDataException, DotSecurityException { + boolean localExists = UtilMethods.isSet(()->localContentType.inode()); if (hasAnyWorkflowScheme(contentTypeWrapper)) { - - this.saveWorkflowSchemes(contentTypeWrapper, contentType, localContentType, localExists); + this.saveWorkflowSchemes(contentTypeWrapper, contentType); } else { //if no workflow scheme is set. We need to reset the content type. workflowAPI.saveSchemeIdsForContentType(contentType, Collections.emptySet()); @@ -343,51 +386,38 @@ private void setWorkflowScheme(final ContentTypeWrapper contentTypeWrapper, } private void saveWorkflowSchemes(final ContentTypeWrapper contentTypeWrapper, - final ContentType contentType, - final ContentType localContentType, - final boolean localExists) { + final ContentType contentType) { try { - final ImmutableList.Builder schemes = new ImmutableList.Builder<>(); - WorkflowScheme scheme = null; - - for (int i = 0; i < contentTypeWrapper.getWorkflowSchemaIds().size(); i++) { + Set schemes = new HashSet<>(contentTypeWrapper.getWorkflowSchemaIds().stream().map(id-> + Try.of(()->workflowAPI + .findScheme(id).getId()) + .onFailure(e->Logger.warn(ContentTypeHandler.class,"Unable to find workflow scheme id:" + id)) + .getOrNull() + ) + .filter(Objects::nonNull) + .collect(Collectors.toSet())); + + // always add a workflow if there were none sent + if(schemes.isEmpty()){ + schemes.add(APILocator.getWorkflowAPI().findSystemWorkflowScheme().getId()); + } - final String workflowId = contentTypeWrapper.getWorkflowSchemaIds() - .get(i); - try { - scheme = workflowAPI - .findScheme(workflowId); - } catch (Exception ex) { - Logger.error(ContentTypeHandler.class, - String.format("Error retrieving Workflow Scheme ID [%s]: %s", - workflowId, ex.getMessage()), ex); - } + workflowAPI.saveSchemeIdsForContentType( + contentType, schemes); - if (scheme != null) { - schemes.add(scheme); - } else { - /* - Workflow Scheme should exist..., the workflow should be already - be processed by the WorkflowHandler. - */ - Logger.error(ContentTypeHandler.class, - String.format( - "Relating Workflow Scheme to Content Type [%s]. Workflow Scheme with id not found [%s]", - contentType.name(), workflowId)); - } - } - if (scheme != null) { - workflowAPI.saveSchemesForStruct( - new StructureTransformer(localExists ? localContentType : contentType).asStructure(), schemes.build()); - } } catch (final Exception ex) { - Logger.warn(ContentTypeHandler.class, String.format("Some of the target Schema IDs [ %s ] for Content Type" + - " '%s' [%s] don't exist: %s", contentTypeWrapper.getWorkflowSchemaIds().toString(), contentType - .name(), contentType.id(), ex.getMessage())); + Logger.warn(ContentTypeHandler.class, + "Some of the target Schema IDs: " + + contentTypeWrapper.getWorkflowSchemaIds().toString() + + " for Content Type" + + contentType.variable() + + "/" + + contentType.inode() + + " don't exist.", ex); } } diff --git a/dotCMS/src/main/java/com/dotcms/ai/service/OpenAIChatService.java b/dotCMS/src/main/java/com/dotcms/ai/api/ChatAPI.java similarity index 94% rename from dotCMS/src/main/java/com/dotcms/ai/service/OpenAIChatService.java rename to dotCMS/src/main/java/com/dotcms/ai/api/ChatAPI.java index af7b5bc2903c..363772bfa2b6 100644 --- a/dotCMS/src/main/java/com/dotcms/ai/service/OpenAIChatService.java +++ b/dotCMS/src/main/java/com/dotcms/ai/api/ChatAPI.java @@ -1,8 +1,8 @@ -package com.dotcms.ai.service; +package com.dotcms.ai.api; import com.dotmarketing.util.json.JSONObject; -public interface OpenAIChatService { +public interface ChatAPI { /** * Returns a JSONObject with the results of the text generation given the provided prompt diff --git a/dotCMS/src/main/java/com/dotcms/ai/api/ChatAPIProvider.java b/dotCMS/src/main/java/com/dotcms/ai/api/ChatAPIProvider.java new file mode 100644 index 000000000000..097dda902ba8 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/ai/api/ChatAPIProvider.java @@ -0,0 +1,6 @@ +package com.dotcms.ai.api; + +public interface ChatAPIProvider { + + ChatAPI getChatAPI(Object... initArguments); +} diff --git a/dotCMS/src/main/java/com/dotcms/ai/api/DotAIAPI.java b/dotCMS/src/main/java/com/dotcms/ai/api/DotAIAPI.java index c2afd9303808..034d32261994 100644 --- a/dotCMS/src/main/java/com/dotcms/ai/api/DotAIAPI.java +++ b/dotCMS/src/main/java/com/dotcms/ai/api/DotAIAPI.java @@ -6,7 +6,31 @@ */ public interface DotAIAPI { + /** + * Returns the completions API + * @param initArguments + * @return + */ CompletionsAPI getCompletionsAPI(Object... initArguments); + /** + * Returns the embeddings API + * @param initArguments + * @return + */ EmbeddingsAPI getEmbeddingsAPI(Object... initArguments); + + /** + * Returns the chat API + * @param initArguments + * @return + */ + ChatAPI getChatAPI(Object... initArguments); + + /** + * Returns the image API + * @param initArguments + * @return + */ + ImageAPI getImageAPI(Object... initArguments); } diff --git a/dotCMS/src/main/java/com/dotcms/ai/api/DotAIAPIFacadeImpl.java b/dotCMS/src/main/java/com/dotcms/ai/api/DotAIAPIFacadeImpl.java index 7601c4e8caf3..a269ad8d20f6 100644 --- a/dotCMS/src/main/java/com/dotcms/ai/api/DotAIAPIFacadeImpl.java +++ b/dotCMS/src/main/java/com/dotcms/ai/api/DotAIAPIFacadeImpl.java @@ -1,8 +1,12 @@ package com.dotcms.ai.api; import com.dotcms.ai.app.AppConfig; +import com.dotcms.rest.api.v1.temp.TempFileAPI; import com.dotmarketing.beans.Host; +import com.dotmarketing.business.APILocator; +import com.dotmarketing.portlets.contentlet.business.HostAPI; import com.dotmarketing.util.Logger; +import com.liferay.portal.model.User; import java.util.Map; import java.util.Objects; @@ -16,14 +20,20 @@ */ public class DotAIAPIFacadeImpl implements DotAIAPI { - private static final AtomicReference currentApiProviderName = new AtomicReference<>("default"); + + private static final String DEFAULT = "default"; + private static final AtomicReference currentApiProviderName = new AtomicReference<>(DEFAULT); private static final Map completionsProviderMap = new ConcurrentHashMap<>(); private static final Map embeddingsProviderMap = new ConcurrentHashMap<>(); + private static final Map chatProviderMap = new ConcurrentHashMap<>(); + private static final Map imageProviderMap = new ConcurrentHashMap<>(); static { try { - completionsProviderMap.put("default", new DefaultCompletionsAPIProvider()); - embeddingsProviderMap.put("default", new DefaultEmbeddingsAPIProvider()); + completionsProviderMap.put(DEFAULT, new DefaultCompletionsAPIProvider()); + embeddingsProviderMap.put(DEFAULT, new DefaultEmbeddingsAPIProvider()); + chatProviderMap.put(DEFAULT, new DefaultChatAPIProvider()); + imageProviderMap.put(DEFAULT, new DefaultImageAPIProvider()); } catch (Exception e) { Logger.error(DotAIAPI.class, e.getMessage(), e); } @@ -35,6 +45,47 @@ private static T unwrap(final Class clazz, final Object... initArguments) && clazz.isInstance(initArguments[0]) ? clazz.cast(initArguments[0]) : null; } + /** + * Default provider for the ChatAPI + */ + public static class DefaultChatAPIProvider implements ChatAPIProvider { + + @Override + public ChatAPI getChatAPI(final Object... initArguments) { + if (Objects.nonNull(initArguments) && initArguments.length > 0 && initArguments[0] instanceof AppConfig) { + return new OpenAIChatAPIImpl((AppConfig) initArguments[0]); + } + + throw new IllegalArgumentException("To create a ChatAPI you need to provide an AppConfig"); + } + } + + /** + * Default provider for the ImageAPI + */ + public static class DefaultImageAPIProvider implements ImageAPIProvider { + + @Override + public ImageAPI getImageAPI(final Object... initArguments) { + if (Objects.nonNull(initArguments) && initArguments.length >= 4 + && initArguments[0] instanceof AppConfig + && (Objects.isNull(initArguments[1]) || initArguments[1] instanceof User) + ) { + + final AppConfig config = (AppConfig) initArguments[0]; + final User user = (User) initArguments[1]; + final HostAPI hostApi = APILocator.getHostAPI(); + final TempFileAPI tempFileApi = APILocator.getTempFileAPI(); + return new OpenAIImageAPIImpl(config, user, hostApi, tempFileApi); + } + + throw new IllegalArgumentException("To create an Image you need to provide an AppConfig"); + } + } + + /** + * Default provider for the CompletionsAPI + */ private static class DefaultCompletionsAPIProvider implements CompletionsAPIProvider { @Override @@ -47,6 +98,9 @@ private AppConfig unwrap(final Object... initArguments) { } } + /** + * Default provider for the EmbeddingsAPI + */ public static class DefaultEmbeddingsAPIProvider implements EmbeddingsAPIProvider { @Override @@ -72,19 +126,35 @@ public static final void setCurrentApiProviderName(final String apiName) { * @param completionsAPI */ public static final void setDefaultCompletionsAPIProvider(final CompletionsAPIProvider completionsAPI) { - completionsProviderMap.put("default", completionsAPI); + completionsProviderMap.put(DEFAULT, completionsAPI); } /** - * Adds the default embeddings API Provider. + * Set the default embeddings API Provider. * @param embeddingsAPI */ public static final void setDefaultEmbeddingsAPIProvider(final EmbeddingsAPIProvider embeddingsAPI) { - embeddingsProviderMap.put("default", embeddingsAPI); + embeddingsProviderMap.put(DEFAULT, embeddingsAPI); + } + + /** + * Set the default image API Provider. + * @param imageAPIProvider + */ + public static final void setDefaultImageAPIProvider(final ImageAPIProvider imageAPIProvider) { + imageProviderMap.put(DEFAULT, imageAPIProvider); + } + + /** + * Set the default chat API Provider. + * @param chatAPIProviderq + */ + public static final void setDefaultChatAPIProvider(final ChatAPIProvider chatAPIProvider) { + chatProviderMap.put(DEFAULT, chatAPIProvider); } /** - * Adds the default completions API provider. + * Adds completions API provider. * @param completionsAPI */ public static final void addCompletionsAPIImplementation(final String apiName, final CompletionsAPIProvider completionsAPI) { @@ -92,21 +162,49 @@ public static final void addCompletionsAPIImplementation(final String apiName, f } /** - * Sets the default embeddings API provider. + * Adds default embeddings API provider. * @param embeddingsAPI */ - public static final void addDefaultEmbeddingsAPIImplementation(final String apiName, final EmbeddingsAPIProvider embeddingsAPI) { + public static final void addEmbeddingsAPIImplementation(final String apiName, final EmbeddingsAPIProvider embeddingsAPI) { embeddingsProviderMap.put(apiName, embeddingsAPI); } + /** + * Adds default chat API provider. + * @param chatAPI + */ + public static final void addChatAPIImplementation(final String apiName, final ChatAPIProvider chatAPI) { + chatProviderMap.put(apiName, chatAPI); + } + + /** + * Adds default image API provider. + * @param imageAPI + */ + public static final void addImageAPIImplementation(final String apiName, final ImageAPIProvider imageAPI) { + imageProviderMap.put(apiName, imageAPI); + } + @Override - public CompletionsAPI getCompletionsAPI(Object... initArguments) { + public CompletionsAPI getCompletionsAPI(final Object... initArguments) { return completionsProviderMap.get(currentApiProviderName.get()).getCompletionsAPI(initArguments); } @Override - public EmbeddingsAPI getEmbeddingsAPI(Object... initArguments) { + public EmbeddingsAPI getEmbeddingsAPI(final Object... initArguments) { return embeddingsProviderMap.get(currentApiProviderName.get()).getEmbeddingsAPI(initArguments); } + + @Override + public ChatAPI getChatAPI(final Object... initArguments) { + + return chatProviderMap.get(currentApiProviderName.get()).getChatAPI(initArguments); + } + + @Override + public ImageAPI getImageAPI(final Object... initArguments) { + + return imageProviderMap.get(currentApiProviderName.get()).getImageAPI(initArguments); + } } diff --git a/dotCMS/src/main/java/com/dotcms/ai/service/OpenAIImageService.java b/dotCMS/src/main/java/com/dotcms/ai/api/ImageAPI.java similarity index 93% rename from dotCMS/src/main/java/com/dotcms/ai/service/OpenAIImageService.java rename to dotCMS/src/main/java/com/dotcms/ai/api/ImageAPI.java index d0fc19ee479f..cd7083d36510 100644 --- a/dotCMS/src/main/java/com/dotcms/ai/service/OpenAIImageService.java +++ b/dotCMS/src/main/java/com/dotcms/ai/api/ImageAPI.java @@ -1,4 +1,4 @@ -package com.dotcms.ai.service; +package com.dotcms.ai.api; import com.dotcms.ai.model.AIImageRequestDTO; import com.dotmarketing.util.json.JSONObject; @@ -6,7 +6,7 @@ /** * Service to interact with the OpenAI Image API */ -public interface OpenAIImageService { +public interface ImageAPI { /** * Sends a text prompt to the OpenAI API. diff --git a/dotCMS/src/main/java/com/dotcms/ai/api/ImageAPIProvider.java b/dotCMS/src/main/java/com/dotcms/ai/api/ImageAPIProvider.java new file mode 100644 index 000000000000..c52773f2c5f8 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/ai/api/ImageAPIProvider.java @@ -0,0 +1,11 @@ +package com.dotcms.ai.api; + + +/** + * This class is in charge of providing the {@link ImageAPI}. + * @author jsanca + */ +public interface ImageAPIProvider { + + ImageAPI getImageAPI(Object... initArguments); +} diff --git a/dotCMS/src/main/java/com/dotcms/ai/service/OpenAIChatServiceImpl.java b/dotCMS/src/main/java/com/dotcms/ai/api/OpenAIChatAPIImpl.java similarity index 87% rename from dotCMS/src/main/java/com/dotcms/ai/service/OpenAIChatServiceImpl.java rename to dotCMS/src/main/java/com/dotcms/ai/api/OpenAIChatAPIImpl.java index 08edb4d5d691..2e94dbe4218d 100644 --- a/dotCMS/src/main/java/com/dotcms/ai/service/OpenAIChatServiceImpl.java +++ b/dotCMS/src/main/java/com/dotcms/ai/api/OpenAIChatAPIImpl.java @@ -1,4 +1,4 @@ -package com.dotcms.ai.service; +package com.dotcms.ai.api; import com.dotcms.ai.AiKeys; import com.dotcms.ai.app.AppConfig; @@ -12,11 +12,11 @@ import java.util.List; import java.util.Map; -public class OpenAIChatServiceImpl implements OpenAIChatService { +public class OpenAIChatAPIImpl implements ChatAPI { private final AppConfig config; - public OpenAIChatServiceImpl(final AppConfig appConfig) { + public OpenAIChatAPIImpl(final AppConfig appConfig) { this.config = appConfig; } @@ -47,7 +47,7 @@ public JSONObject sendTextPrompt(final String textPrompt) { } @VisibleForTesting - String doRequest(final String urlIn, final JSONObject json) { + public String doRequest(final String urlIn, final JSONObject json) { return OpenAIRequest.doRequest(urlIn, HttpMethod.POST, config, json); } diff --git a/dotCMS/src/main/java/com/dotcms/ai/service/OpenAIImageServiceImpl.java b/dotCMS/src/main/java/com/dotcms/ai/api/OpenAIImageAPIImpl.java similarity index 93% rename from dotCMS/src/main/java/com/dotcms/ai/service/OpenAIImageServiceImpl.java rename to dotCMS/src/main/java/com/dotcms/ai/api/OpenAIImageAPIImpl.java index 57b571dc140b..041a49b6e2d1 100644 --- a/dotCMS/src/main/java/com/dotcms/ai/service/OpenAIImageServiceImpl.java +++ b/dotCMS/src/main/java/com/dotcms/ai/api/OpenAIImageAPIImpl.java @@ -1,4 +1,4 @@ -package com.dotcms.ai.service; +package com.dotcms.ai.api; import com.dotcms.ai.AiKeys; import com.dotcms.ai.app.AppConfig; @@ -29,7 +29,7 @@ import java.text.SimpleDateFormat; import java.util.Date; -public class OpenAIImageServiceImpl implements OpenAIImageService { +public class OpenAIImageAPIImpl implements ImageAPI { private static StopWordsUtil stopWordsUtil = StopWordsUtil.get(); @@ -38,10 +38,10 @@ public class OpenAIImageServiceImpl implements OpenAIImageService { private final HostAPI hostApi; private final TempFileAPI tempFileApi; - public OpenAIImageServiceImpl(final AppConfig config, - final User user, - final HostAPI hostApi, - final TempFileAPI tempFileApi) { + public OpenAIImageAPIImpl(final AppConfig config, + final User user, + final HostAPI hostApi, + final TempFileAPI tempFileApi) { this.config = config; this.user = user; this.hostApi = hostApi; @@ -173,22 +173,22 @@ private String generateFileName(final String originalPrompt) { } @VisibleForTesting - String doRequest(final String urlIn, final JSONObject json) { + public String doRequest(final String urlIn, final JSONObject json) { return OpenAIRequest.doRequest(urlIn, HttpMethod.POST, config, json); } @VisibleForTesting - User getUser() { + public User getUser() { return APILocator.systemUser(); } @VisibleForTesting - AIImageRequestDTO.Builder getDtoBuilder() { + public AIImageRequestDTO.Builder getDtoBuilder() { return new AIImageRequestDTO.Builder(); } public static void setStopWordsUtil(final StopWordsUtil stopWordsUtil) { - OpenAIImageServiceImpl.stopWordsUtil = stopWordsUtil; + OpenAIImageAPIImpl.stopWordsUtil = stopWordsUtil; } } diff --git a/dotCMS/src/main/java/com/dotcms/ai/rest/ImageResource.java b/dotCMS/src/main/java/com/dotcms/ai/rest/ImageResource.java index 21903b41e291..375625d58adf 100644 --- a/dotCMS/src/main/java/com/dotcms/ai/rest/ImageResource.java +++ b/dotCMS/src/main/java/com/dotcms/ai/rest/ImageResource.java @@ -5,8 +5,8 @@ import com.dotcms.ai.app.AppConfig; import com.dotcms.ai.app.ConfigService; import com.dotcms.ai.model.AIImageRequestDTO; -import com.dotcms.ai.service.OpenAIImageService; -import com.dotcms.ai.service.OpenAIImageServiceImpl; +import com.dotcms.ai.api.ImageAPI; +import com.dotcms.ai.api.OpenAIImageAPIImpl; import com.dotcms.rest.WebResource; import com.dotmarketing.business.APILocator; import com.dotmarketing.business.web.WebAPILocator; @@ -113,7 +113,7 @@ public Response handleImageRequest(@Context final HttpServletRequest request, .build(); } - final OpenAIImageService service = new OpenAIImageServiceImpl( + final ImageAPI service = APILocator.getDotAIAPI().getImageAPI( config, user, APILocator.getHostAPI(), diff --git a/dotCMS/src/main/java/com/dotcms/ai/viewtool/AIViewTool.java b/dotCMS/src/main/java/com/dotcms/ai/viewtool/AIViewTool.java index 7891263733e4..050b56b1e535 100644 --- a/dotCMS/src/main/java/com/dotcms/ai/viewtool/AIViewTool.java +++ b/dotCMS/src/main/java/com/dotcms/ai/viewtool/AIViewTool.java @@ -3,10 +3,10 @@ import com.dotcms.ai.AiKeys; import com.dotcms.ai.app.AppConfig; import com.dotcms.ai.app.ConfigService; -import com.dotcms.ai.service.OpenAIChatService; -import com.dotcms.ai.service.OpenAIChatServiceImpl; -import com.dotcms.ai.service.OpenAIImageService; -import com.dotcms.ai.service.OpenAIImageServiceImpl; +import com.dotcms.ai.api.ChatAPI; +import com.dotcms.ai.api.OpenAIChatAPIImpl; +import com.dotcms.ai.api.ImageAPI; +import com.dotcms.ai.api.OpenAIImageAPIImpl; import com.dotmarketing.business.APILocator; import com.dotmarketing.business.web.WebAPILocator; import com.dotmarketing.util.json.JSONObject; @@ -28,8 +28,8 @@ public class AIViewTool implements ViewTool { private ViewContext context; private AppConfig config; - private OpenAIChatService chatService; - private OpenAIImageService imageService; + private ChatAPI chatService; + private ImageAPI imageService; @Override public void init(final Object obj) { @@ -127,13 +127,13 @@ User user() { } @VisibleForTesting - OpenAIChatService chatService() { - return new OpenAIChatServiceImpl(config); + ChatAPI chatService() { + return APILocator.getDotAIAPI().getChatAPI(config); } @VisibleForTesting - OpenAIImageService imageService() { - return new OpenAIImageServiceImpl(config, user(), APILocator.getHostAPI(), APILocator.getTempFileAPI()); + ImageAPI imageService() { + return APILocator.getDotAIAPI().getImageAPI(config, user(), APILocator.getHostAPI(), APILocator.getTempFileAPI()); } private

Try generate(final P prompt, final Function serviceCall) { diff --git a/dotCMS/src/main/java/com/dotcms/ai/workflow/OpenAIGenerateImageActionlet.java b/dotCMS/src/main/java/com/dotcms/ai/workflow/OpenAIGenerateImageActionlet.java index b1ef5eac9b75..8ded9b0bc9f1 100644 --- a/dotCMS/src/main/java/com/dotcms/ai/workflow/OpenAIGenerateImageActionlet.java +++ b/dotCMS/src/main/java/com/dotcms/ai/workflow/OpenAIGenerateImageActionlet.java @@ -38,7 +38,6 @@ public String getHowTo() { @Override public void executeAction(WorkflowProcessor processor, Map params) throws WorkflowActionFailureException { - final Runnable task = new OpenAIGenerateImageRunner(processor, params); task.run(); } diff --git a/dotCMS/src/main/java/com/dotcms/ai/workflow/OpenAIGenerateImageRunner.java b/dotCMS/src/main/java/com/dotcms/ai/workflow/OpenAIGenerateImageRunner.java index 29c3af893417..aa8260b1e4cb 100644 --- a/dotCMS/src/main/java/com/dotcms/ai/workflow/OpenAIGenerateImageRunner.java +++ b/dotCMS/src/main/java/com/dotcms/ai/workflow/OpenAIGenerateImageRunner.java @@ -1,16 +1,21 @@ package com.dotcms.ai.workflow; +import com.dotcms.ai.api.ImageAPI; import com.dotcms.ai.app.ConfigService; -import com.dotcms.ai.service.OpenAIImageService; -import com.dotcms.ai.service.OpenAIImageServiceImpl; import com.dotcms.ai.util.VelocityContextFactory; +import com.dotcms.api.system.event.message.MessageSeverity; +import com.dotcms.api.system.event.message.MessageType; +import com.dotcms.api.system.event.message.SystemMessageEventUtil; +import com.dotcms.api.system.event.message.builder.SystemMessageBuilder; import com.dotcms.api.web.HttpServletRequestThreadLocal; import com.dotcms.contenttype.model.field.BinaryField; import com.dotcms.contenttype.model.field.Field; import com.dotcms.contenttype.model.type.ContentType; +import com.dotcms.exception.ExceptionUtil; import com.dotcms.rendering.velocity.util.VelocityUtil; import com.dotmarketing.beans.Host; import com.dotmarketing.business.APILocator; +import com.dotmarketing.exception.DotRuntimeException; import com.dotmarketing.portlets.contentlet.model.Contentlet; import com.dotmarketing.portlets.workflows.model.WorkflowActionClassParameter; import com.dotmarketing.portlets.workflows.model.WorkflowProcessor; @@ -22,6 +27,8 @@ import org.apache.velocity.context.Context; import javax.servlet.http.HttpServletRequest; +import java.io.File; +import java.util.List; import java.util.Map; import java.util.Optional; @@ -30,60 +37,43 @@ * It implements the AsyncWorkflowRunner interface and overrides its methods to provide the functionality needed. * This class is designed to handle long-running tasks in a separate thread and needs to be serialized to a persistent storage. */ -public class OpenAIGenerateImageRunner implements AsyncWorkflowRunner { +public class OpenAIGenerateImageRunner implements Runnable { - final String identifier; - final long language; - final User user; - final String prompt; - final boolean overwriteField; - final String fieldToWrite; - final long runAt; + private final User user; + private final String prompt; + private final boolean overwriteField; + private final String fieldToWrite; + private final Contentlet contentlet; - OpenAIGenerateImageRunner(WorkflowProcessor processor, Map params) { + + public OpenAIGenerateImageRunner(final WorkflowProcessor processor, final Map params) { this( processor.getContentlet(), processor.getUser(), params.get(OpenAIParams.OPEN_AI_PROMPT.key).getValue(), Try.of(() -> Boolean.parseBoolean(params.get(OpenAIParams.OVERWRITE_FIELDS.key).getValue())) .getOrElse(false), - params.get(OpenAIParams.FIELD_TO_WRITE.key).getValue(), - Try.of(() -> Integer.parseInt(params.get(OpenAIParams.RUN_DELAY.key).getValue())).getOrElse(5) + params.get(OpenAIParams.FIELD_TO_WRITE.key).getValue() ); } - OpenAIGenerateImageRunner(final Contentlet contentlet, + public OpenAIGenerateImageRunner(final Contentlet contentlet, final User user, final String prompt, final boolean overwriteField, - final String fieldToWrite, - final int runDelay) { - this.identifier = contentlet.getIdentifier(); - this.language = contentlet.getLanguageId(); + final String fieldToWrite) { + + this.contentlet = contentlet; this.prompt = prompt; this.overwriteField = overwriteField; this.fieldToWrite = fieldToWrite; this.user = user; - this.runAt = System.currentTimeMillis() + runDelay; - } - - @Override - public long getRunAt() { - return this.runAt; - } - - @Override - public String getIdentifier() { - return this.identifier; } @Override - public long getLanguage() { - return this.language; - } + public void run() { - public void runInternal() { - final Contentlet workingContentlet = getLatest(identifier, language, user); + final Contentlet workingContentlet = this.contentlet; final Host host = Try.of( () -> APILocator.getHostAPI().find(workingContentlet.getHost(), APILocator.systemUser(), true)) .getOrElse(APILocator.systemHost()); @@ -120,27 +110,25 @@ public void runInternal() { } final String finalPrompt = VelocityUtil.eval(prompt, ctx); - final OpenAIImageService service = new OpenAIImageServiceImpl( + final ImageAPI imageAPI = APILocator.getDotAIAPI().getImageAPI( ConfigService.INSTANCE.config(host), user, APILocator.getHostAPI(), APILocator.getTempFileAPI()); - final JSONObject resp = Try.of(() -> service.sendTextPrompt(finalPrompt)) + final JSONObject resp = Try.of(() -> imageAPI.sendTextPrompt(finalPrompt)) .onFailure(e -> Logger.warn(OpenAIGenerateImageRunner.class, "error generating image:" + e)) .getOrElse(JSONObject::new); - final String tempFile = resp.optString("response"); - if (UtilMethods.isEmpty(tempFile)) { + final String tempFile = resp.optString("tempFile"); + if (UtilMethods.isEmpty(tempFile) && !new File(tempFile).exists()) { Logger.warn( this.getClass(), "Unable to generate image for contentlet: " + workingContentlet.getTitle()); return; } - final Contentlet contentToSave = checkoutLatest(identifier, language, user); - contentToSave.setProperty(fieldToTry.get().variable(), tempFile); - saveContentlet(contentToSave, user); + contentlet.setProperty(fieldToTry.get().variable(), new File(tempFile)); } catch (Exception e) { handleError(e, user); } finally{ @@ -150,7 +138,29 @@ public void runInternal() { } } + /** + * Handles any exceptions that occur during the execution of the workflow. + * It logs the error, sends a system message to the user, and rethrows the exception as a DotRuntimeException. + * + * @param e the exception that occurred. + * @param user the user who is running the workflow. + * @throws DotRuntimeException if an exception occurs during the execution of the workflow. + */ + private void handleError(final Exception e, final User user) { + + final String errorMsg = String.format("Error: %s", ExceptionUtil.getErrorMessage(e)); + final SystemMessageBuilder message = new SystemMessageBuilder() + .setMessage(errorMsg) + .setLife(5000) + .setType(MessageType.SIMPLE_MESSAGE) + .setSeverity(MessageSeverity.ERROR); + SystemMessageEventUtil.getInstance().pushMessage(message.create(), List.of(user.getUserId())); + Logger.error(this.getClass(), errorMsg, e); + throw new DotRuntimeException(e); + } + private Optional resolveField(final Contentlet contentlet) { + final ContentType type = contentlet.getContentType(); final Optional fieldToTry = Try.of(() -> type.fieldMap().get(this.fieldToWrite)).toJavaOptional(); if (UtilMethods.isSet(this.fieldToWrite)) { diff --git a/dotCMS/src/main/java/com/dotcms/business/bytebuddy/ByteBuddyFactory.java b/dotCMS/src/main/java/com/dotcms/business/bytebuddy/ByteBuddyFactory.java index f27bbf3fe8ce..93ee80d3ed3b 100644 --- a/dotCMS/src/main/java/com/dotcms/business/bytebuddy/ByteBuddyFactory.java +++ b/dotCMS/src/main/java/com/dotcms/business/bytebuddy/ByteBuddyFactory.java @@ -5,7 +5,6 @@ import com.dotcms.business.WrapInTransaction; import com.dotcms.util.EnterpriseFeature; import com.dotcms.util.LogTime; -import com.dotmarketing.util.Logger; import net.bytebuddy.agent.ByteBuddyAgent; import net.bytebuddy.agent.builder.AgentBuilder; import net.bytebuddy.asm.Advice; @@ -23,6 +22,8 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import static net.bytebuddy.matcher.ElementMatchers.declaresMethod; import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith; @@ -39,6 +40,9 @@ */ public class ByteBuddyFactory { + // Use base log4j logger here to prevent recursive issues with internal Logger class + private static final Logger LOGGER = LogManager.getLogger(ByteBuddyFactory.class); + private static final AtomicBoolean agentLoaded = new AtomicBoolean(false); private static final Map, Class> adviceMap = Map.of( WrapInTransaction.class, WrapInTransactionAdvice.class, @@ -69,16 +73,16 @@ public static void init() { if (!agentLoaded.get()) { try { premain(null, ByteBuddyAgent.install()); - Logger.info(ByteBuddyFactory.class, "Loaded ByteBuddy Advice"); + LOGGER.info("Loaded ByteBuddy Advice"); } catch (Exception e) { - Logger.error(ByteBuddyFactory.class, "Cannot install ByteBuddy Advice"); + LOGGER.error("Cannot install ByteBuddy Advice"); } } } public static void premain(final String arg, final Instrumentation inst) throws Exception { - Logger.info(ByteBuddyFactory.class, "Starting ByteBuddy Agent"); + LOGGER.info("Starting ByteBuddy Agent"); if (!agentLoaded.compareAndSet(false, true)) { return; } @@ -122,9 +126,9 @@ public ClassFileLocator classFileLocator(final ClassLoader classLoader, final Ja }) .installOn(inst); - Logger.info(ByteBuddyFactory.class, "ByteBuddy Initialized"); + LOGGER.info("ByteBuddy Initialized"); } catch (Exception e) { - Logger.error(ByteBuddyFactory.class, "Error Initializing ByteBuddy", e); + LOGGER.error("Error Initializing ByteBuddy", e); } diff --git a/dotCMS/src/main/java/com/dotcms/listeners/SessionMonitor.java b/dotCMS/src/main/java/com/dotcms/listeners/SessionMonitor.java index 74120fa57866..90dba56eac3b 100644 --- a/dotCMS/src/main/java/com/dotcms/listeners/SessionMonitor.java +++ b/dotCMS/src/main/java/com/dotcms/listeners/SessionMonitor.java @@ -96,10 +96,12 @@ public void attributeReplaced(HttpSessionBindingEvent event) { public void sessionCreated(final HttpSessionEvent event) { // Not implemented + Logger.debug(this, "Session created"); } public void sessionDestroyed(final HttpSessionEvent event) { + Logger.debug(this, "Session destroyed"); final String userId = (String) event.getSession().getAttribute(com.liferay.portal.util.WebKeys.USER_ID); if (userId != null) { diff --git a/dotCMS/src/main/java/com/dotmarketing/listeners/ContextLifecycleListener.java b/dotCMS/src/main/java/com/dotmarketing/listeners/ContextLifecycleListener.java index 431664eefd32..0cf3775d0d0c 100644 --- a/dotCMS/src/main/java/com/dotmarketing/listeners/ContextLifecycleListener.java +++ b/dotCMS/src/main/java/com/dotmarketing/listeners/ContextLifecycleListener.java @@ -7,10 +7,8 @@ import com.dotcms.util.AsciiArt; import com.dotmarketing.business.CacheLocator; import com.dotmarketing.common.reindex.ReindexThread; -import com.dotmarketing.loggers.Log4jUtil; import com.dotmarketing.quartz.QuartzUtils; import com.dotmarketing.util.Config; -import com.dotmarketing.util.ConfigUtils; import com.dotmarketing.util.Logger; import io.vavr.control.Try; @@ -18,7 +16,6 @@ import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.websocket.server.ServerContainer; -import java.io.File; /** * @@ -62,25 +59,6 @@ public void contextInitialized(ServletContextEvent arg0) { Config.setMyApp(arg0.getServletContext()); - - String path = null; - try { - - String contextPath = Config.CONTEXT.getRealPath("/"); - if ( !contextPath.endsWith( File.separator ) ) { - contextPath += File.separator; - } - File file = new File(contextPath + "WEB-INF" + File.separator + "log4j" + File.separator + "log4j2.xml"); - path = file.toURI().toString(); - - } catch (Exception e) { - Logger.error(this,e.getMessage(),e); - } - - //Initialises/reconfigures log4j based on a given log4j configuration file - Log4jUtil.initializeFromPath(path); - - installWebSocket(arg0.getServletContext()); } diff --git a/dotCMS/src/main/java/com/dotmarketing/loggers/Log4jUtil.java b/dotCMS/src/main/java/com/dotmarketing/loggers/Log4jUtil.java index ac941ba8604d..61d44a6929fd 100644 --- a/dotCMS/src/main/java/com/dotmarketing/loggers/Log4jUtil.java +++ b/dotCMS/src/main/java/com/dotmarketing/loggers/Log4jUtil.java @@ -27,15 +27,6 @@ public class Log4jUtil { private final static String LOG4J_CONTEXT_SELECTOR = "Log4jContextSelector"; - /** - * Configure default system properties - */ - public static void configureDefaultSystemProperties () { - if(!UtilMethods.isSet(System.getProperty(LOG4J_CONTEXT_SELECTOR))) { - System.setProperty(LOG4J_CONTEXT_SELECTOR, "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector"); - } - } - /** * Creates a ConsoleAppender in order to add it to the root logger */ @@ -128,33 +119,6 @@ public static void shutdown(LoggerContext context) { Configurator.shutdown(context); } - /** - * Initialises/reconfigures log4j based on a given log4j configuration file - * - * @param log4jConfigFilePath - */ - public static void initializeFromPath ( String log4jConfigFilePath ) { - - if ( log4jConfigFilePath != null ) { - - try { - - configureDefaultSystemProperties(); - LoggerContext loggerContext = (LoggerContext) LogManager.getContext(false); - - if ( !loggerContext.isInitialized() || loggerContext.isStopped() ) { - Configurator.initialize(null, log4jConfigFilePath); - } else { - loggerContext.setConfigLocation(URI.create(log4jConfigFilePath)); - loggerContext.reconfigure(); - } - } catch ( Exception e ) { - LogManager.getLogger().error("Error initializing log for " + log4jConfigFilePath + " configuration file.", e); - } - LogManager.getLogger().info("Async Logger enabled: "+ AsyncLoggerContextSelector.isSelected()); - } - } - /** * Returns the current dotCMS logger context * diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/ContentletCacheImpl.java b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/ContentletCacheImpl.java index 25abb2a82089..a53a6a6f3b8b 100644 --- a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/ContentletCacheImpl.java +++ b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/ContentletCacheImpl.java @@ -135,7 +135,7 @@ public void remove(final String key){ Logger.debug(this, "Cache not able to be removed", e); } - final Host host = CacheLocator.getHostCache().get(key); + final Host host = CacheLocator.getHostCache().getById(key); if(host != null){ CacheLocator.getHostCache().remove(host); } diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostAPIImpl.java b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostAPIImpl.java index ffa71a1a0709..504083e15fbe 100644 --- a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostAPIImpl.java +++ b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostAPIImpl.java @@ -121,11 +121,15 @@ public Host findDefaultHost(User user, boolean respectFrontendRoles) throws DotS @Override @CloseDBIfOpened public Host resolveHostName(String serverName, User user, boolean respectFrontendRoles) throws DotDataException, DotSecurityException { - Host host = hostCache.getHostByAlias(serverName); - User systemUser = APILocator.systemUser(); - - if(host == null){ - + Host host; + final Host cachedHostByAlias = hostCache.getHostByAlias(serverName); + if (UtilMethods.isSet(() -> cachedHostByAlias.getIdentifier())) { + if (HostCache.CACHE_404_HOST.equals(cachedHostByAlias.getIdentifier())) { + return null; + } + host = cachedHostByAlias; + } else { + final User systemUser = APILocator.systemUser(); try { final Optional optional = resolveHostNameWithoutDefault(serverName, systemUser, respectFrontendRoles); host = optional.isPresent() ? optional.get() : findDefaultHost(systemUser, respectFrontendRoles); @@ -133,12 +137,15 @@ public Host resolveHostName(String serverName, User user, boolean respectFronten host = findDefaultHost(systemUser, respectFrontendRoles); } - if(host != null){ + if (host != null) { hostCache.addHostAlias(serverName, host); + } else { + hostCache.addHostAlias(serverName, HostCache.cache404Contentlet); } } - - checkSitePermission(user, respectFrontendRoles, host); + if (host != null) { + checkSitePermission(user, respectFrontendRoles, host); + } return host; } @@ -146,17 +153,24 @@ public Host resolveHostName(String serverName, User user, boolean respectFronten @CloseDBIfOpened public Optional resolveHostNameWithoutDefault(String serverName, User user, boolean respectFrontendRoles) throws DotDataException, DotSecurityException { - Host host = hostCache.getHostByAlias(serverName); - User systemUser = APILocator.systemUser(); - - if(host == null){ + Host host; + final Host cachedHostByAlias = hostCache.getHostByAlias(serverName); + if (UtilMethods.isSet(() -> cachedHostByAlias.getIdentifier())) { + if (HostCache.CACHE_404_HOST.equals(cachedHostByAlias.getIdentifier())) { + return Optional.empty(); + } + host = cachedHostByAlias; + } else { + User systemUser = APILocator.systemUser(); host = findByNameNotDefault(serverName, systemUser, respectFrontendRoles); if(host == null){ host = findByAlias(serverName, systemUser, respectFrontendRoles); } - if(host != null){ + if (host == null) { + hostCache.addHostAlias(serverName, HostCache.cache404Contentlet); + } else { hostCache.addHostAlias(serverName, host); } } @@ -297,7 +311,14 @@ public Host find(final String id, final User user, return findSystemHost(); } - Host site = hostCache.get(id); + Host site = null; + Host cachedSiteById = hostCache.getById(id); + if (UtilMethods.isSet(() -> cachedSiteById.getIdentifier())) { + if (HostCache.CACHE_404_HOST.equals(cachedSiteById.getIdentifier())) { + return null; + } + site = cachedSiteById; + } if (site == null) { site = DBSearch(id,user,respectFrontendRoles); diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostCache.java b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostCache.java index a11feef5d0c2..780970871eae 100644 --- a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostCache.java +++ b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostCache.java @@ -8,10 +8,23 @@ public abstract class HostCache implements Cachable{ protected static String PRIMARY_GROUP = "HostCache"; protected static String ALIAS_GROUP = "HostAliasCache"; - + protected static String NOT_FOUND_BY_ID_GROUP = "Host404ByIdCache"; + protected static String NOT_FOUND_BY_NAME_GROUP = "Host404ByNameCache"; + + public static final String CACHE_404_HOST = "CACHE_404_HOST"; + + protected static final Host cache404Contentlet = new Host() { + @Override + public String getIdentifier() { + return CACHE_404_HOST; + } + }; + abstract protected Host add(Host host); - abstract protected Host get(String key); + abstract protected Host getById(String id); + + abstract protected Host getByName(String name); abstract public void clearCache(); @@ -26,5 +39,10 @@ public abstract class HostCache implements Cachable{ abstract protected Host getHostByAlias(String alias); abstract protected void addHostAlias(String alias, Host host); + + abstract protected void add404HostById(String id); + + abstract protected void add404HostByName(String name); + abstract protected void clearAliasCache() ; } \ No newline at end of file diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostCacheImpl.java b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostCacheImpl.java index 983678e2d903..38d7d363e2c0 100644 --- a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostCacheImpl.java +++ b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostCacheImpl.java @@ -23,7 +23,9 @@ public class HostCacheImpl extends HostCache { // region's name for the cache - private String[] groupNames = {PRIMARY_GROUP, ALIAS_GROUP}; + private final String[] groupNames = { + PRIMARY_GROUP, ALIAS_GROUP, NOT_FOUND_BY_ID_GROUP, NOT_FOUND_BY_NAME_GROUP + }; public HostCacheImpl() { cache = CacheLocator.getCacheAdministrator(); @@ -37,6 +39,9 @@ protected Host add(Host host) { String key = host.getIdentifier(); String key2 =host.getHostname(); + cache.remove(key, NOT_FOUND_BY_ID_GROUP); + cache.remove(key2, NOT_FOUND_BY_NAME_GROUP); + // Add the key to the cache cache.put(key, host,PRIMARY_GROUP); cache.put(key2, host,PRIMARY_GROUP); @@ -72,7 +77,10 @@ protected Host getHostByAlias(String key) { Host host = null; try{ String hostId = (String) cache.get(key,ALIAS_GROUP); - host = get(hostId); + if (CACHE_404_HOST.equals(hostId)) { + return cache404Contentlet; + } + host = get(hostId, NOT_FOUND_BY_ID_GROUP); if(host == null){ cache.remove(key, ALIAS_GROUP); } @@ -83,10 +91,17 @@ protected Host getHostByAlias(String key) { return host; } - protected Host get(String key) { + private Host get(String key, String notFoundCacheGroup) { Host host = null; try{ - host = (Host) cache.get(key,PRIMARY_GROUP); + if (UtilMethods.isSet(notFoundCacheGroup)) { + host = (Host) cache.get(key, notFoundCacheGroup); + } + if (host != null && CACHE_404_HOST.equals(host.getIdentifier())) { + return cache404Contentlet; + } else { + host = (Host) cache.get(key, PRIMARY_GROUP); + } }catch (DotCacheException e) { Logger.debug(this, "Cache Entry not found", e); } @@ -94,13 +109,37 @@ protected Host get(String key) { return host; } - /* (non-Javadoc) + /** + * Get a host by id + * @param id the id of the host + * @return the host or 404 if the host is in the not found cache, + * null if the host is not found in the cache + */ + @Override + protected Host getById(final String id) { + return get(id, NOT_FOUND_BY_ID_GROUP); + } + + /** + * Get a host by name + * @param name the name of the host + * @return the host or 404 if the host is in the not found cache, + * null if the host is not found in the cache + */ + @Override + protected Host getByName(final String name) { + return get(name, NOT_FOUND_BY_NAME_GROUP); + } + + /* (non-Javadoc) * @see com.dotmarketing.business.PermissionCache#clearCache() */ public void clearCache() { // clear the cache cache.flushGroup(PRIMARY_GROUP); cache.flushGroup(ALIAS_GROUP); + cache.flushGroup(NOT_FOUND_BY_ID_GROUP); + cache.flushGroup(NOT_FOUND_BY_NAME_GROUP); } /* (non-Javadoc) @@ -114,21 +153,19 @@ protected void remove(Host host){ String _defaultHost =PRIMARY_GROUP +DEFAULT_HOST; cache.remove(_defaultHost,PRIMARY_GROUP); - //remove aliases from host in cache - Host h = get(host.getIdentifier()); - - String key = host.getIdentifier(); String key2 = host.getHostname(); try{ cache.remove(key,PRIMARY_GROUP); + cache.remove(key,NOT_FOUND_BY_ID_GROUP); }catch (Exception e) { Logger.debug(this, "Cache not able to be removed", e); } try{ cache.remove(key2,PRIMARY_GROUP); + cache.remove(key2, NOT_FOUND_BY_NAME_GROUP); }catch (Exception e) { Logger.debug(this, "Cache not able to be removed", e); } @@ -147,7 +184,7 @@ public String getPrimaryGroup() { protected Host getDefaultHost(){ - return get(DEFAULT_HOST); + return get(DEFAULT_HOST, null); } protected void addHostAlias(String alias, Host host){ @@ -155,8 +192,29 @@ protected void addHostAlias(String alias, Host host){ cache.put(alias, host.getIdentifier(),ALIAS_GROUP); } } - - + + /** + * Add the host id to the 404 (not found) cache + * @param id the id of the host + */ + @Override + protected void add404HostById(String id) { + if (id != null) { + cache.put(id, cache404Contentlet, NOT_FOUND_BY_ID_GROUP); + } + } + + /** + * Add the host name to the 404 (not found) cache + * @param name the name of the host + */ + @Override + protected void add404HostByName(String name) { + if (name != null) { + cache.put(name, cache404Contentlet, NOT_FOUND_BY_NAME_GROUP); + } + } + protected void clearAliasCache() { // clear the alias cache cache.flushGroup(ALIAS_GROUP); diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostFactoryImpl.java b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostFactoryImpl.java index e1901a3a1f23..3c4e7132ad9f 100644 --- a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostFactoryImpl.java +++ b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/business/HostFactoryImpl.java @@ -189,8 +189,14 @@ protected ContentletAPI getContentletAPI() { @Override public Host bySiteName(final String siteName) { - Host site = siteCache.get(siteName); - if (null == site || !UtilMethods.isSet(site.getIdentifier())) { + Host site; + final Host cachedSiteByName = siteCache.getByName(siteName);; + if (UtilMethods.isSet(() -> cachedSiteByName.getIdentifier())) { + if (HostCache.CACHE_404_HOST.equals(cachedSiteByName.getIdentifier())) { + return null; + } + site = cachedSiteByName; + } else { final DotConnect dc = new DotConnect(); final StringBuilder sqlQuery = new StringBuilder().append(SELECT_SITE_INODE) .append(WHERE); @@ -200,6 +206,7 @@ public Host bySiteName(final String siteName) { try { final List> dbResults = dc.loadResults(); if (dbResults.isEmpty()) { + siteCache.add404HostByName(siteName); return null; } final String siteInode = dbResults.get(0).get("inode"); @@ -227,8 +234,14 @@ public Host bySiteName(final String siteName) { @Override public Host byAlias(String alias) { - Host site = this.siteCache.getHostByAlias(alias); - if (null == site) { + Host site = null; + Host cachedSiteByAlias = this.siteCache.getHostByAlias(alias); + if (UtilMethods.isSet(() -> cachedSiteByAlias.getIdentifier())) { + if (HostCache.CACHE_404_HOST.equals(cachedSiteByAlias.getIdentifier())) { + return null; + } + site = cachedSiteByAlias; + } else { final DotConnect dc = new DotConnect(); final StringBuilder sqlQuery = new StringBuilder().append(SELECT_SITE_INODE_AND_ALIASES) .append(WHERE) @@ -248,6 +261,7 @@ public Host byAlias(String alias) { try { final List> dbResults = dc.loadResults(); if (dbResults.isEmpty()) { + siteCache.addHostAlias(alias, HostCache.cache404Contentlet); return null; } if (dbResults.size() == 1) { @@ -335,7 +349,7 @@ public List findAll(final int limit, final int offset, final String orderB @Override public Host findSystemHost(final User user, final boolean respectFrontendRoles) throws DotDataException, DotSecurityException { - Host systemHost = this.siteCache.get(Host.SYSTEM_HOST); + Host systemHost = this.siteCache.getById(Host.SYSTEM_HOST); if (null != systemHost) { return systemHost; } @@ -409,6 +423,10 @@ public Host DBSearch(final String id, final boolean respectFrontendRoles) throws this.siteCache.add(site); } } + if (null == site && !Host.SYSTEM_HOST.equals(id)) { + this.siteCache.add404HostById(id); + Logger.warn(HostAPIImpl.class, String.format("Site with id '%s' not found", id)); + } return site; } diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/transform/strategy/FileViewStrategy.java b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/transform/strategy/FileViewStrategy.java index eea9e99ab61e..be2202cc0505 100644 --- a/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/transform/strategy/FileViewStrategy.java +++ b/dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/transform/strategy/FileViewStrategy.java @@ -111,6 +111,7 @@ public Map transform(final Field field, final Contentlet content //This does always assume we're getting a fileAsset we don't want to miss a dotAsset final Contentlet incoming = fileAsContentOptional.get(); if(incoming.isDotAsset()){ + incoming.setProperty(FileAssetAPI.BINARY_FIELD, Try.of(()->incoming.getBinary("asset")).getOrNull()); fileAsset = convertToFileAsset(incoming, fileAssetAPI); } else { fileAsset = fileAssetAPI.fromContentlet(incoming); diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/fileassets/business/FileAssetAPIImpl.java b/dotCMS/src/main/java/com/dotmarketing/portlets/fileassets/business/FileAssetAPIImpl.java index 0c7164a6fd3a..4d6726c17396 100644 --- a/dotCMS/src/main/java/com/dotmarketing/portlets/fileassets/business/FileAssetAPIImpl.java +++ b/dotCMS/src/main/java/com/dotmarketing/portlets/fileassets/business/FileAssetAPIImpl.java @@ -268,11 +268,13 @@ public FileAsset fromContentlet(final Contentlet con) throws DotStateException { throw new DotStateException("Content -> FileAsset Copy Failed :" + e.getMessage(), e); } fileAsset.setHost(con.getHost()); + Contentlet originalContentlet = null; if(UtilMethods.isSet(con.getFolder())){ try{ final Identifier ident = APILocator.getIdentifierAPI().find(con); final Host host = APILocator.getHostAPI().find(con.getHost(), APILocator.systemUser() , false); final Folder folder = APILocator.getFolderAPI().findFolderByPath(ident.getParentPath(), host, APILocator.systemUser(), false); + originalContentlet = APILocator.getContentletAPI().find(con.getInode(), APILocator.systemUser(), false); fileAsset.setFolder(folder.getInode()); }catch(Exception e){ try{ @@ -285,7 +287,9 @@ public FileAsset fromContentlet(final Contentlet con) throws DotStateException { } fileAsset.setVariantId(con.getVariantId()); - this.contentletCache.add(fileAsset); + if (null != originalContentlet && !originalContentlet.isDotAsset()){ + this.contentletCache.add(fileAsset); + } return fileAsset; } diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/htmlpageasset/business/render/HTMLPageAssetRenderedAPIImpl.java b/dotCMS/src/main/java/com/dotmarketing/portlets/htmlpageasset/business/render/HTMLPageAssetRenderedAPIImpl.java index e38951e44635..a1219b8d3f82 100644 --- a/dotCMS/src/main/java/com/dotmarketing/portlets/htmlpageasset/business/render/HTMLPageAssetRenderedAPIImpl.java +++ b/dotCMS/src/main/java/com/dotmarketing/portlets/htmlpageasset/business/render/HTMLPageAssetRenderedAPIImpl.java @@ -377,9 +377,9 @@ private void checkPagePermission(final PageContext context, final IHTMLPage html context.getPageMode().respectAnonPerms); if (!doesUserHavePermission) { - final String message = String.format("User: %s does not have permissions %s for object %s", + final String message = String.format("User: %s does not have permissions %s for page %s", context.getUser(), - PermissionLevel.READ, htmlPageAsset); + PermissionLevel.READ, htmlPageAsset.getURI()); throw new DotSecurityException(message); } } diff --git a/dotCMS/src/main/java/com/dotmarketing/util/Logger.java b/dotCMS/src/main/java/com/dotmarketing/util/Logger.java index b71305280cad..6a26004ce18b 100644 --- a/dotCMS/src/main/java/com/dotmarketing/util/Logger.java +++ b/dotCMS/src/main/java/com/dotmarketing/util/Logger.java @@ -6,19 +6,13 @@ package com.dotmarketing.util; import java.io.File; -import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; -import com.dotcms.api.system.event.Payload; -import com.dotcms.api.system.event.SystemEventType; -import com.dotcms.rest.ResponseEntityView; import com.dotcms.rest.api.v1.system.logger.ChangeLoggerLevelEvent; -import com.dotcms.rest.api.v1.system.logger.LoggerView; -import com.dotmarketing.business.APILocator; import com.liferay.util.StringPool; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; @@ -26,7 +20,6 @@ import org.apache.velocity.tools.view.tools.ViewTool; import com.dotcms.business.expiring.ExpiringMap; import com.dotcms.business.expiring.ExpiringMapBuilder; -import com.dotmarketing.loggers.Log4jUtil; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.RemovalCause; @@ -35,17 +28,11 @@ import io.vavr.Lazy; import io.vavr.control.Try; -import javax.ws.rs.core.Response; - /** * @author David Torres */ public class Logger { - static { - Log4jUtil.configureDefaultSystemProperties(); - } - /** * Caffeine Cache is going to be much more performant concurrently than a hashmap */ diff --git a/dotCMS/src/main/resources/container/tomcat9/bin/setenv.bat b/dotCMS/src/main/resources/container/tomcat9/bin/setenv.bat index 11db0ce193ff..907b1ad54e3d 100644 --- a/dotCMS/src/main/resources/container/tomcat9/bin/setenv.bat +++ b/dotCMS/src/main/resources/container/tomcat9/bin/setenv.bat @@ -1,5 +1,6 @@ @echo off +rem Set CATALINA_OPTS with multiple options set "CATALINA_OPTS=%CATALINA_OPTS% -Dfile.encoding=UTF8" set "CATALINA_OPTS=%CATALINA_OPTS% --illegal-access=deny" set "CATALINA_OPTS=%CATALINA_OPTS% --add-opens java.base/java.lang=ALL-UNNAMED" @@ -26,4 +27,33 @@ set "CATALINA_OPTS=%CATALINA_OPTS% --add-opens java.base/sun.util.locale=ALL-UNN set "CATALINA_OPTS=%CATALINA_OPTS% -Djavax.xml.transform.TransformerFactory=com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl" set "CATALINA_OPTS=%CATALINA_OPTS% -Djavax.xml.parsers.DocumentBuilderFactory=com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl" set "CATALINA_OPTS=%CATALINA_OPTS% -Djavax.xml.parsers.SAXParserFactory=com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl" -set "CATALINA_OPTS=%CATALINA_OPTS% -Dorg.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.digester.EnvironmentPropertySource" \ No newline at end of file +set "CATALINA_OPTS=%CATALINA_OPTS% -Dorg.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.digester.EnvironmentPropertySource" + + +rem Check if log4j2.configurationFile is already set +echo %CATALINA_OPTS% | findstr /C:"-Dlog4j2.configurationFile" >nul +if %errorlevel% neq 0 ( + echo Setting log4j2.configurationFile=%TOMCAT_HOME%\webapps\ROOT\WEB-INF\log4j\log4j2.xml + set "CATALINA_OPTS=%CATALINA_OPTS% -Dlog4j2.configurationFile=%TOMCAT_HOME%\webapps\ROOT\WEB-INF\log4j\log4j2.xml" +) else ( + echo Log4j configuration already set +) + +rem Check if Log4jContextSelector is already set +echo %CATALINA_OPTS% | findstr /C:"-DLog4jContextSelector" >nul +if %errorlevel% neq 0 ( + echo Setting Log4jContextSelector to org.apache.logging.log4j.core.async.BasicAsyncLoggerContextSelector + set "CATALINA_OPTS=%CATALINA_OPTS% -DLog4jContextSelector=org.apache.logging.log4j.core.async.BasicAsyncLoggerContextSelector" +) else ( + echo Log4jContextSelector already set +) + +rem Set the CLASSPATH +set "ADDITIONAL_CLASSPATH=%CATALINA_HOME%\log4j2\lib\*;%CATALINA_HOME%\session-manager\lib\*" +if "%CLASSPATH%" neq "" ( + set "CLASSPATH=%CLASSPATH%;%ADDITIONAL_CLASSPATH%" +) else ( + set "CLASSPATH=%ADDITIONAL_CLASSPATH%" +) + +set CLASSPATH \ No newline at end of file diff --git a/dotCMS/src/main/resources/container/tomcat9/bin/setenv.sh b/dotCMS/src/main/resources/container/tomcat9/bin/setenv.sh index 664f84a73b82..1d6d02d4ad80 100644 --- a/dotCMS/src/main/resources/container/tomcat9/bin/setenv.sh +++ b/dotCMS/src/main/resources/container/tomcat9/bin/setenv.sh @@ -1,3 +1,5 @@ +#!/bin/sh + export CATALINA_OPTS="$CATALINA_OPTS -Dfile.encoding=UTF8" export CATALINA_OPTS="$CATALINA_OPTS --illegal-access=deny" export CATALINA_OPTS="$CATALINA_OPTS --add-opens java.base/java.lang=ALL-UNNAMED" @@ -27,3 +29,29 @@ export CATALINA_OPTS="$CATALINA_OPTS -Djavax.xml.transform.TransformerFactory=co export CATALINA_OPTS="$CATALINA_OPTS -Djavax.xml.parsers.DocumentBuilderFactory=com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl" export CATALINA_OPTS="$CATALINA_OPTS -Djavax.xml.parsers.SAXParserFactory=com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl" export CATALINA_OPTS="$CATALINA_OPTS -Dorg.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.digester.EnvironmentPropertySource" + + +if echo "$CATALINA_OPTS" | grep -q '\-Dlog4j2\.configurationFile'; then + echo "Log4j configuration already set" +else + echo "Setting log4j2.configurationFile=$TOMCAT_HOME/webapps/ROOT/WEB-INF/log4j/log4j2.xml" + export CATALINA_OPTS="$CATALINA_OPTS -Dlog4j2.configurationFile=$TOMCAT_HOME/webapps/ROOT/WEB-INF/log4j/log4j2.xml" +fi + +if echo "$CATALINA_OPTS" | grep -q '\-DLog4jContextSelector'; then + echo "Log4jContextSelector already set" +else + echo "Setting Log4jContextSelector to org.apache.logging.log4j.core.async.BasicAsyncLoggerContextSelector" + export CATALINA_OPTS="$CATALINA_OPTS -DLog4jContextSelector=org.apache.logging.log4j.core.async.BasicAsyncLoggerContextSelector" +fi + +ADDITIONAL_CLASSPATH="$CATALINA_HOME/log4j2/lib/*:$CATALINA_HOME/session-manager/lib/*" + +if [ -n "$CLASSPATH" ]; then + CLASSPATH="$CLASSPATH:$ADDITIONAL_CLASSPATH" +else + CLASSPATH="$ADDITIONAL_CLASSPATH" +fi + +export CLASSPATH + diff --git a/dotCMS/src/main/resources/log4j.properties b/dotCMS/src/main/resources/log4j.properties deleted file mode 100644 index 2eb14485eebe..000000000000 --- a/dotCMS/src/main/resources/log4j.properties +++ /dev/null @@ -1,4 +0,0 @@ -##This is NOT the file where logging should be configured. You should config in the WEB-INF/log4j -log4j.rootLogger=INFO, CONSOLE -log4j.appender.CONSOLE=org.apache.logging.log4j.core.appender.ConsoleAppender -log4j.appender.CONSOLE.layout=org.apache.logging.log4j.core.layout.XmlLayout diff --git a/dotCMS/src/main/webapp/WEB-INF/velocity/static/htmlpage_assets/template_custom_field.vtl b/dotCMS/src/main/webapp/WEB-INF/velocity/static/htmlpage_assets/template_custom_field.vtl index 94c6937a6e56..e906b927dca2 100644 --- a/dotCMS/src/main/webapp/WEB-INF/velocity/static/htmlpage_assets/template_custom_field.vtl +++ b/dotCMS/src/main/webapp/WEB-INF/velocity/static/htmlpage_assets/template_custom_field.vtl @@ -1,49 +1,137 @@ diff --git a/dotCMS/src/main/webapp/html/css/dijit-dotcms/dotcms.css b/dotCMS/src/main/webapp/html/css/dijit-dotcms/dotcms.css index 32d5cde13d9b..348fa4439a37 100644 --- a/dotCMS/src/main/webapp/html/css/dijit-dotcms/dotcms.css +++ b/dotCMS/src/main/webapp/html/css/dijit-dotcms/dotcms.css @@ -3844,7 +3844,7 @@ color: #ffffff; line-height: 2.5rem; margin: 0; - font-size: 1.25rem; + font-size: 1rem; } .dijitDropDownActionButton .dijitButtonNode { height: 2.5rem; @@ -8829,7 +8829,7 @@ Styles for commons fields along the backend .lineDividerTitle { color: #6c7389; - font-size: 1.5rem; + font-size: 1.25rem; border-bottom: 1px solid #d1d4db; padding-bottom: 1rem; margin: 3rem 0 1.5rem; @@ -9358,7 +9358,7 @@ dd .buttonCaption { } .calendar-events .portlet-toolbar__info { flex: 1 0 auto; - font-size: 1.25rem; + font-size: 1rem; justify-content: center; } @@ -10141,7 +10141,7 @@ a.category_higlighted, a.tag_higlighted { .nameText { align-self: center; - font-size: 1.25rem; + font-size: 1rem; font-weight: normal; } @@ -10259,7 +10259,7 @@ a.category_higlighted, a.tag_higlighted { } .fullUserName { - font-size: 1.25rem; + font-size: 1rem; font-weight: bold; margin-bottom: 0.5rem; padding-bottom: 0; @@ -11234,6 +11234,7 @@ legend, input, button, textarea, +select, p, blockquote, th, diff --git a/dotCMS/src/main/webapp/html/portlet/ext/contentlet/edit_contentlet.jsp b/dotCMS/src/main/webapp/html/portlet/ext/contentlet/edit_contentlet.jsp index 8fc2678cd17f..aabb03f620fb 100644 --- a/dotCMS/src/main/webapp/html/portlet/ext/contentlet/edit_contentlet.jsp +++ b/dotCMS/src/main/webapp/html/portlet/ext/contentlet/edit_contentlet.jsp @@ -108,8 +108,6 @@ <% } %> <%}else{%> diff --git a/dotCMS/src/main/webapp/html/portlet/ext/dotai/dotai.css b/dotCMS/src/main/webapp/html/portlet/ext/dotai/dotai.css index 245725df00e0..328cc019c88e 100644 --- a/dotCMS/src/main/webapp/html/portlet/ext/dotai/dotai.css +++ b/dotCMS/src/main/webapp/html/portlet/ext/dotai/dotai.css @@ -281,7 +281,6 @@ input[type="text"] { - font-size: 1rem; padding: 10px; margin-top: -10px; border-color: var(--color-palette-primary-op-20); @@ -298,7 +297,6 @@ input[type="text"]:focus { } input[type="number"] { - font-size: 1rem; padding: 10px; min-width: 100px; margin-top: -10px; @@ -337,7 +335,6 @@ input[type="radio"]:hover { } textarea { - font-size: 1rem; padding: 10px; margin-top: -10px; border-color: var(--color-palette-primary-op-20); @@ -353,7 +350,6 @@ textarea:focus { } select { - font-size: 1rem; padding: 10px; margin-top: -10px; border-color: var(--color-palette-primary-op-20); @@ -370,7 +366,6 @@ select:focus { } .button { - font-size: 1rem; padding: 20px 40px; border: 1px solid #9D9D9D; border-radius: .25em; diff --git a/dotCMS/src/test/java/com/dotcms/ai/service/OpenAIChatServiceImplTest.java b/dotCMS/src/test/java/com/dotcms/ai/service/OpenAIChatServiceImplTest.java index e110608dbb2c..e4c43486c3f1 100644 --- a/dotCMS/src/test/java/com/dotcms/ai/service/OpenAIChatServiceImplTest.java +++ b/dotCMS/src/test/java/com/dotcms/ai/service/OpenAIChatServiceImplTest.java @@ -1,5 +1,7 @@ package com.dotcms.ai.service; +import com.dotcms.ai.api.ChatAPI; +import com.dotcms.ai.api.OpenAIChatAPIImpl; import com.dotcms.ai.app.AIModel; import com.dotcms.ai.app.AIModelType; import com.dotcms.ai.app.AppConfig; @@ -21,7 +23,7 @@ public class OpenAIChatServiceImplTest { "{\"data\":[{\"url\":\"http://localhost:8080\",\"value\":\"this is a response\"}]}"; private AppConfig config; - private OpenAIChatService service; + private ChatAPI service; @Before public void setUp() { @@ -51,10 +53,12 @@ public void test_sendTextPrompt() { assertNotNull(result); } - private OpenAIChatService prepareService(final String response) { - return new OpenAIChatServiceImpl(config) { + private ChatAPI prepareService(final String response) { + return new OpenAIChatAPIImpl(config) { + + @Override - String doRequest(final String urlIn, final JSONObject json) { + public String doRequest(final String urlIn, final JSONObject json) { return response; } }; diff --git a/dotCMS/src/test/java/com/dotcms/ai/service/OpenAIImageServiceImplTest.java b/dotCMS/src/test/java/com/dotcms/ai/service/OpenAIImageServiceImplTest.java index 1338b3110c74..6c3fc6822473 100644 --- a/dotCMS/src/test/java/com/dotcms/ai/service/OpenAIImageServiceImplTest.java +++ b/dotCMS/src/test/java/com/dotcms/ai/service/OpenAIImageServiceImplTest.java @@ -1,5 +1,7 @@ package com.dotcms.ai.service; +import com.dotcms.ai.api.ImageAPI; +import com.dotcms.ai.api.OpenAIImageAPIImpl; import com.dotcms.ai.app.AIModel; import com.dotcms.ai.app.AIModelType; import com.dotcms.ai.app.AppConfig; @@ -37,7 +39,7 @@ public class OpenAIImageServiceImplTest { private HostAPI hostApi; private TempFileAPI tempFileApi; private AIImageRequestDTO.Builder dtoBuilder; - private OpenAIImageService service; + private ImageAPI service; @Before public void setUp() { @@ -112,7 +114,7 @@ public void test_sendRequest_withErrorWhenGeneratingFileName() throws Exception final JSONObject jsonObject = prepareJsonObject("Hello World!"); final StopWordsUtil stopWordsUtil = mock(StopWordsUtil.class); - OpenAIImageServiceImpl.setStopWordsUtil(stopWordsUtil); + OpenAIImageAPIImpl.setStopWordsUtil(stopWordsUtil); when(stopWordsUtil.removeStopWords(anyString())).thenThrow(RuntimeException.class); final JSONObject result = service.sendRequest(jsonObject); @@ -197,21 +199,21 @@ private static void assertImageResponse(JSONObject result, boolean result1) { assertTrue(result.containsKey("tempFile")); } - private OpenAIImageService prepareService(final String response, - final User user) { - return new OpenAIImageServiceImpl(config, user, hostApi, tempFileApi) { + private ImageAPI prepareService(final String response, + final User user) { + return new OpenAIImageAPIImpl(config, user, hostApi, tempFileApi) { @Override - String doRequest(final String urlIn, final JSONObject json) { + public String doRequest(final String urlIn, final JSONObject json) { return response; } @Override - User getUser() { + public User getUser() { return user; } @Override - AIImageRequestDTO.Builder getDtoBuilder() { + public AIImageRequestDTO.Builder getDtoBuilder() { return dtoBuilder; } }; @@ -241,4 +243,4 @@ private JSONObject prepareJsonObject(final String prompt) throws Exception { return prepareJsonObject(prompt, false); } -} \ No newline at end of file +} diff --git a/dotcms-integration/ant-tasks.xml b/dotcms-integration/ant-tasks.xml index 6e459d3222ab..3d446dc46809 100644 --- a/dotcms-integration/ant-tasks.xml +++ b/dotcms-integration/ant-tasks.xml @@ -10,7 +10,7 @@ - + @@ -72,7 +72,7 @@ - + diff --git a/dotcms-integration/src/test/java/com/dotcms/MainSuite1a.java b/dotcms-integration/src/test/java/com/dotcms/MainSuite1a.java index fbeac0706673..e2cc7ed38e3e 100644 --- a/dotcms-integration/src/test/java/com/dotcms/MainSuite1a.java +++ b/dotcms-integration/src/test/java/com/dotcms/MainSuite1a.java @@ -1,5 +1,6 @@ package com.dotcms; +import com.dotcms.ai.workflow.OpenAIGenerateImageActionletTest; import com.dotcms.content.elasticsearch.business.ESContentletAPIImplTest; import com.dotcms.contenttype.business.SiteAndFolderResolverImplTest; import com.dotcms.enterprise.publishing.remote.PushPublishBundleGeneratorTest; @@ -103,7 +104,8 @@ ExperimentUrlPatternCalculatorIntegrationTest.class, JsEngineTest.class, Task240306MigrateLegacyLanguageVariablesTest.class, - EmailActionletTest.class + EmailActionletTest.class, + OpenAIGenerateImageActionletTest.class }) public class MainSuite1a { diff --git a/dotcms-integration/src/test/java/com/dotcms/ai/workflow/OpenAIGenerateImageActionletTest.java b/dotcms-integration/src/test/java/com/dotcms/ai/workflow/OpenAIGenerateImageActionletTest.java new file mode 100644 index 000000000000..8aa61917bb9f --- /dev/null +++ b/dotcms-integration/src/test/java/com/dotcms/ai/workflow/OpenAIGenerateImageActionletTest.java @@ -0,0 +1,225 @@ +package com.dotcms.ai.workflow; + +import com.dotcms.ai.AiTest; +import com.dotcms.ai.api.DotAIAPIFacadeImpl; +import com.dotcms.ai.api.ImageAPI; +import com.dotcms.ai.api.ImageAPIProvider; +import com.dotcms.ai.app.AppConfig; +import com.dotcms.ai.app.AppKeys; +import com.dotcms.ai.model.AIImageRequestDTO; +import com.dotcms.contenttype.model.field.BinaryField; +import com.dotcms.contenttype.model.field.Field; +import com.dotcms.contenttype.model.field.StoryBlockField; +import com.dotcms.contenttype.model.type.ContentType; +import com.dotcms.datagen.ContentTypeDataGen; +import com.dotcms.datagen.FieldDataGen; +import com.dotcms.datagen.SiteDataGen; +import com.dotcms.security.apps.Secret; +import com.dotcms.security.apps.Type; +import com.dotcms.util.IntegrationTestInitService; +import com.dotmarketing.beans.Host; +import com.dotmarketing.business.APILocator; +import com.dotmarketing.portlets.contentlet.model.Contentlet; +import com.dotmarketing.portlets.workflows.model.WorkflowActionClassParameter; +import com.dotmarketing.portlets.workflows.model.WorkflowProcessor; +import com.dotmarketing.util.UUIDGenerator; +import com.dotmarketing.util.json.JSONObject; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * This class contains unit tests for the {@link OpenAIGenerateImageActionlet} class. + * + * @author jsanca + */ +public class OpenAIGenerateImageActionletTest { + + private static AppConfig config; + private static Host host; + + @BeforeClass + public static void beforeClass() throws Exception { + IntegrationTestInitService.getInstance().init(); + host = new SiteDataGen().nextPersisted(); + int port = 8080; + final Map secrets = Map.of( + AppKeys.API_URL.key, + Secret.builder() + .withType(Type.STRING) + .withValue(String.format("test", port).toCharArray()) + .build(), + + AppKeys.API_IMAGE_URL.key, + Secret.builder() + .withType(Type.STRING) + .withValue(String.format(AiTest.API_IMAGE_URL, port).toCharArray()) + .build(), + + AppKeys.API_KEY.key, + Secret.builder().withType(Type.STRING).withValue(AiTest.API_KEY.toCharArray()).build(), + + AppKeys.TEXT_MODEL_NAMES.key, + Secret.builder().withType(Type.STRING).withValue(AiTest.MODEL.toCharArray()).build(), + + AppKeys.IMAGE_MODEL_NAMES.key, + Secret.builder().withType(Type.STRING).withValue(AiTest.IMAGE_MODEL.toCharArray()).build(), + + AppKeys.IMAGE_SIZE.key, + Secret.builder().withType(Type.SELECT).withValue(AiTest.IMAGE_SIZE.toCharArray()).build(), + + AppKeys.LISTENER_INDEXER.key, + Secret.builder() + .withType(Type.STRING) + .withValue("{\"default\":\"blog\"}".toCharArray()) + .build()); + config = new AppConfig(host.getHostname(), secrets); + DotAIAPIFacadeImpl.setDefaultImageAPIProvider(new ImageAPIProvider() { + @Override + public ImageAPI getImageAPI(Object... initArguments) { + return new ImageAPI() { + @Override + public JSONObject sendTextPrompt(String prompt) { + return new JSONObject("{\n" + + " \"response\":\"image_id123\",\n" + + " \"tempFile\":\"image_id123\"\n" + + "}"); + } + + @Override + public JSONObject sendRawRequest(String prompt) { + return null; + } + + @Override + public JSONObject sendRequest(JSONObject jsonObject) { + return null; + } + + @Override + public JSONObject sendRequest(AIImageRequestDTO dto) { + return null; + } + }; + } + }); + } + + /** + * Method to test: {@link OpenAIGenerateImageActionlet#executeAction(WorkflowProcessor, Map)} + * Given Scenario: Creates a contentlet with a title, binary, but without any prompt + * ExpectedResult: since the prompt is null, should not generate the image + */ + @Test () + public void test_content_no_prompt_do_not_generated() { + // 1) create a content type with title, body and tags + final ContentTypeDataGen dataGen = new ContentTypeDataGen(); + + //Add new fields + final List inputFields = new ArrayList<>(); + inputFields.add(new FieldDataGen().velocityVarName("title").next()); + inputFields.add(new FieldDataGen().type(BinaryField.class).velocityVarName("image").next()); + dataGen.fields(inputFields); + final ContentType contentType = dataGen.nextPersisted(); + + // 2) create an instance with non integer + final Contentlet contentlet = new Contentlet(); + contentlet.setContentType(contentType); + contentlet.setProperty("title", "dotCMS Party"); + contentlet.setIdentifier(UUIDGenerator.generateUuid()); + + final WorkflowProcessor processor = new WorkflowProcessor(contentlet, APILocator.systemUser()); + final Map params = Map.of( + OpenAIParams.OPEN_AI_PROMPT.key, new WorkflowActionClassParameter(""), + OpenAIParams.OVERWRITE_FIELDS.key, new WorkflowActionClassParameter("true"), + OpenAIParams.FIELD_TO_WRITE.key, new WorkflowActionClassParameter("image") + ); + + new OpenAIGenerateImageActionlet().executeAction(processor, params); + + Assert.assertNull("No prompt sent, no image generated",contentlet.get("image")); + } + + /** + * Method to test: {@link OpenAIGenerateImageActionlet#executeAction(WorkflowProcessor, Map)} + * Given Scenario: Creates a contentlet with a title, No binary and NO prompt + * ExpectedResult: since the does not have any prompt do not generated any body + */ + @Test () + public void test_content_without_prompt_field_do_not_generated() { + // 1) create a content type with title, body and tags + final ContentTypeDataGen dataGen = new ContentTypeDataGen(); + + //Add new fields + final List inputFields = new ArrayList<>(); + inputFields.add(new FieldDataGen().velocityVarName("title").next()); + inputFields.add(new FieldDataGen().type(StoryBlockField.class).velocityVarName("body").next()); + dataGen.fields(inputFields); + final ContentType contentType = dataGen.nextPersisted(); + + // 2) create an instance with non integer + final Contentlet contentlet = new Contentlet(); + contentlet.setContentType(contentType); + contentlet.setProperty("title", "dotCMS Party"); + contentlet.setIdentifier(UUIDGenerator.generateUuid()); + + final WorkflowProcessor processor = new WorkflowProcessor(contentlet, APILocator.systemUser()); + final Map params = Map.of( + OpenAIParams.OPEN_AI_PROMPT.key, new WorkflowActionClassParameter("Create an image about dotCMS party"), + OpenAIParams.OVERWRITE_FIELDS.key, new WorkflowActionClassParameter("true"), + OpenAIParams.FIELD_TO_WRITE.key, new WorkflowActionClassParameter("image") + ); + + new OpenAIGenerateImageActionlet().executeAction(processor, params); + final Object object = contentlet.get("body"); + Assert.assertNull("When not binary field as part of the contentlet, should not generate the image", object); + } + + + /** + * Method to test: {@link OpenAIContentPromptActionlet#executeAction(WorkflowProcessor, Map)} + * Given Scenario: Creates a contentlet with a title, body + * ExpectedResult: The body should be generated + */ + @Test + public void test_body_generation() { + // 1) create a content type with title, body and tags + final ContentTypeDataGen dataGen = new ContentTypeDataGen(); + + //Add new fields + final List inputFields = new ArrayList<>(); + inputFields.add(new FieldDataGen().velocityVarName("title").next()); + inputFields.add(new FieldDataGen().type(BinaryField.class).velocityVarName("image").next()); + + dataGen.fields(inputFields); + final ContentType contentType = dataGen.nextPersisted(); + // 2) create an instance with some text and publish it + final Contentlet contentlet = new Contentlet(); + contentlet.setContentType(contentType); + contentlet.setProperty("title", "Write an article about dotCMS"); + contentlet.setIdentifier(UUIDGenerator.generateUuid()); + contentlet.setHost(host.getIdentifier()); + + // 3) Run the actionlet with the content + final WorkflowProcessor processor = new WorkflowProcessor(contentlet, APILocator.systemUser()); + final Map params = Map.of( + OpenAIParams.OPEN_AI_PROMPT.key, new WorkflowActionClassParameter("Create an image about dotCMS party"), + OpenAIParams.OVERWRITE_FIELDS.key, new WorkflowActionClassParameter("true"), + OpenAIParams.FIELD_TO_WRITE.key, new WorkflowActionClassParameter("image") + ); + + new OpenAIGenerateImageActionlet().executeAction(processor, params); + + final Object bodyObject = contentlet.get("image"); + Assert.assertNotNull("Body returned can not be null",bodyObject); + Assert.assertTrue("Body returned should be a String",bodyObject instanceof File); + final File body = (File) bodyObject; + Assert.assertEquals("Body returned should be not empty", body.getName(), "image_id123"); + } + +} diff --git a/dotcms-integration/src/test/java/com/dotcms/enterprise/publishing/remote/handler/ContentHandlerTest.java b/dotcms-integration/src/test/java/com/dotcms/enterprise/publishing/remote/handler/ContentHandlerTest.java index 5f3d4dcd174d..d423f1356872 100644 --- a/dotcms-integration/src/test/java/com/dotcms/enterprise/publishing/remote/handler/ContentHandlerTest.java +++ b/dotcms-integration/src/test/java/com/dotcms/enterprise/publishing/remote/handler/ContentHandlerTest.java @@ -1,20 +1,38 @@ package com.dotcms.enterprise.publishing.remote.handler; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertFalse; +import com.dotcms.contenttype.model.field.Field; +import com.dotcms.contenttype.model.field.TagField; +import com.dotcms.contenttype.model.type.ContentType; +import com.dotcms.datagen.ContentTypeDataGen; +import com.dotcms.datagen.ContentletDataGen; +import com.dotcms.datagen.TestDataUtils; import com.dotcms.publisher.pusher.wrapper.ContentWrapper; +import com.dotcms.publishing.PublisherConfig; import com.dotcms.test.util.FileTestUtil; import com.dotcms.util.IntegrationTestInitService; import com.dotcms.util.xstream.XStreamHandler; import com.dotcms.util.xstream.XStreamHandler.TrustedListMatcher; +import com.dotmarketing.beans.Host; +import com.dotmarketing.business.APILocator; import com.dotmarketing.portlets.contentlet.model.Contentlet; +import com.dotmarketing.tag.model.Tag; +import com.dotmarketing.util.UUIDGenerator; import com.thoughtworks.xstream.XStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Objects; import org.junit.BeforeClass; import org.junit.Test; @@ -67,5 +85,54 @@ public void Test_TrustedListMatcher() { assertFalse(TrustedListMatcher.matches(disallowedClass1)); assertFalse(TrustedListMatcher.matches(disallowedClass2)); } + /** + * Method to test: {@link ContentHandler#relateTagsToContent(Contentlet content, Map> tags)} + * When: Content is pushed which has tags that live on a host not in the target system. + * Should: The tags should save to the system host + */ + @Test + public void TEST_SAVING_TAGS_ON_NON_EXISTING_HOST() throws Exception{ + // Given + final String nonExistantHost = "non-existing-host" + UUIDGenerator.shorty(); + final String[] tags = {"tag1_" + UUIDGenerator.shorty(),"tag2_" + UUIDGenerator.shorty()}; + final String nonExistantUser = UUIDGenerator.shorty(); + + Contentlet contentlet = TestDataUtils.getDotAssetLikeContentlet(); + + List tagList = new ArrayList<>(); + + Arrays.stream(tags).forEach(tag -> { + Tag t = new Tag(); + t.setTagName(tag); + t.setHostId(nonExistantHost); + t.setModDate(new Date()); + t.setUserId(nonExistantUser); + tagList.add(t); + }); + + Field field = contentlet.getContentType().fields(TagField.class).get(0); + + Map> fieldTags = Map.of(Objects.requireNonNull(field.variable()), tagList); + + // Should not throw an error + new ContentHandler(new PublisherConfig()).relateTagsToContent(contentlet,fieldTags); + + + assertEquals(APILocator.getTagAPI().getTagsByName(tags[0]).size(), 1); + + Tag savedTag = APILocator.getTagAPI().getTagsByName(tags[0]).get(0); + assertNotNull(savedTag); + assertEquals(savedTag.getTagName(), tags[0]); + assertEquals(Host.SYSTEM_HOST, savedTag.getHostId()); + + savedTag = APILocator.getTagAPI().getTagsByName(tags[1]).get(0); + assertNotNull(savedTag); + assertEquals(savedTag.getTagName(), tags[1]); + assertEquals(Host.SYSTEM_HOST, savedTag.getHostId()); + } + + + + } diff --git a/dotcms-integration/src/test/java/com/dotmarketing/portlets/contentlet/business/HostFactoryImplTest.java b/dotcms-integration/src/test/java/com/dotmarketing/portlets/contentlet/business/HostFactoryImplTest.java index d0ccdb13ae5d..de7eb7ba4c6e 100644 --- a/dotcms-integration/src/test/java/com/dotmarketing/portlets/contentlet/business/HostFactoryImplTest.java +++ b/dotcms-integration/src/test/java/com/dotmarketing/portlets/contentlet/business/HostFactoryImplTest.java @@ -1,36 +1,28 @@ package com.dotmarketing.portlets.contentlet.business; import com.dotcms.IntegrationTestBase; -import com.dotcms.LicenseTestUtil; import com.dotcms.datagen.SiteDataGen; import com.dotcms.datagen.UserDataGen; import com.dotcms.util.IntegrationTestInitService; -import com.dotcms.util.pagination.OrderDirection; import com.dotmarketing.beans.Host; import com.dotmarketing.business.APILocator; import com.dotmarketing.beans.Permission; import com.dotmarketing.business.*; -import com.dotmarketing.db.HibernateUtil; import com.dotmarketing.exception.DotDataException; -import com.dotmarketing.exception.DotHibernateException; import com.dotmarketing.exception.DotSecurityException; -import com.dotmarketing.init.DotInitScheduler; -import com.dotmarketing.portlets.contentlet.model.IndexPolicy; -import com.dotmarketing.util.Logger; -import com.dotmarketing.util.PaginatedArrayList; import com.liferay.portal.model.User; -import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import static com.dotmarketing.portlets.contentlet.business.HostFactoryImpl.SITE_IS_LIVE_OR_STOPPED; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.Optional; -import java.util.concurrent.ExecutionException; public class HostFactoryImplTest extends IntegrationTestBase { @@ -161,6 +153,42 @@ public void test_search_shouldIncludeSystemHost() throws DotDataException, DotSe //now the user has permissions over the system host assertTrue(hostsList.get().contains(APILocator.systemHost())); } + + /** + * Method to test: {@link HostFactoryImpl#bySiteName(String)} + * Given Scenario: get host by name for a non-existing host + * ExpectedResult: host cache should return 404 for not existing host by name + */ + @Test + public void test_get_404_for_not_existing_host_by_name() throws DotDataException, DotSecurityException { + + Host site = null; + final HostFactoryImpl hostFactory = new HostFactoryImpl(); + + // Create and remove test host + final String hostName = "NotExistingSite" + System.currentTimeMillis(); + try { + site = new SiteDataGen().name(hostName).nextPersisted(true); + final Host hostByName = APILocator.getHostAPI().findByName( + hostName, APILocator.systemUser(), false); + assertNotNull(hostByName); + assertNotEquals(HostCache.CACHE_404_HOST, hostByName.getIdentifier()); + } finally { + if (site != null) { + APILocator.getHostAPI().archive(site, APILocator.systemUser(), false); + APILocator.getHostAPI().delete(site, APILocator.systemUser(), false); + } + } + + // Check 404 after deletion of test host + final HostCache hostCache = new HostCacheImpl(); + final Host nonExistingHost = hostFactory.bySiteName(hostName); + final Host cached404Host = hostCache.getByName(hostName); + + assertNull(nonExistingHost); + assertNotNull(cached404Host); + assertEquals(HostCache.CACHE_404_HOST, cached404Host.getIdentifier()); + } } diff --git a/dotcms-postman/pom.xml b/dotcms-postman/pom.xml index 57c26cd6d645..8957e0ff6835 100644 --- a/dotcms-postman/pom.xml +++ b/dotcms-postman/pom.xml @@ -113,7 +113,7 @@ - WireMock: + [WireMock] green diff --git a/dotcms-postman/src/main/resources/postman/PagesResourceTests.json b/dotcms-postman/src/main/resources/postman/PagesResourceTests.json new file mode 100644 index 000000000000..e82d93fd4a40 --- /dev/null +++ b/dotcms-postman/src/main/resources/postman/PagesResourceTests.json @@ -0,0 +1,7342 @@ +{ + "info": { + "_postman_id": "7a488c87-858e-4edd-8722-c38e4071afdf", + "name": "Page API - [api/v1/page]", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "36473486" + }, + "item": [ + { + "name": "CreateTestContext", + "item": [ + { + "name": "Delete Image ContentType", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/contenttype/id/2c46b6586c38852ac08a824a303ced80", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "contenttype", + "id", + "2c46b6586c38852ac08a824a303ced80" + ] + }, + "description": "Given a content type ID.\nExpect that code is 200.\nExpect content type is deleted successfully." + }, + "response": [] + }, + { + "name": "Delete Video ContentType", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/contenttype/id/c77450b834901a20c8193ef9d561ee5b", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "contenttype", + "id", + "c77450b834901a20c8193ef9d561ee5b" + ] + }, + "description": "Given a content type ID.\nExpect that code is 200.\nExpect content type is deleted successfully." + }, + "response": [] + }, + { + "name": "pre_ImportBundleWithContext", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Bundle uploaded sucessfully\", function () {", + " pm.response.to.have.status(200);", + "", + " var jsonData = pm.response.json();", + " console.log(jsonData);", + "", + " pm.expect(jsonData[\"bundleName\"]).to.eql(\"assets.tar.gz\");", + " pm.expect(jsonData[\"status\"]).to.eql(\"SUCCESS\");", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/octet-stream" + }, + { + "key": "Content-Disposition", + "value": "attachment" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "file", + "type": "file", + "src": "resources/GraphQL/assets.tar.gz" + } + ] + }, + "url": { + "raw": "{{serverURL}}/api/bundle/sync", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "bundle", + "sync" + ], + "query": [ + { + "key": "AUTH_TOKEN", + "value": "", + "disabled": true + } + ] + }, + "description": "Imports a Bundle that includes:\n* HTMLPage /blog/index\n* HTMLPage /blog/destinations/costa-rica\n* Contentlet [Blog] Ecotourism in Costa Rica\n* Blog Detail Page /blog/blog-detail" + }, + "response": [] + } + ], + "description": "Imports a Bundle that includes:\n* HTMLPage /blog/index\n* HTMLPage /blog/destinations/costa-rica\n* Contentlet [Blog] Ecotourism in Costa Rica\n* Blog Detail Page /blog/blog-detail", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "JSON [api/v1/page/json]", + "item": [ + { + "name": "Using Actual Page URIs", + "item": [ + { + "name": "Invalidate Session", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/logout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "logout" + ] + } + }, + "response": [] + }, + { + "name": "Get Page Metadata With Invalid User", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 401, Need credentials\", function () {", + " pm.response.to.have.status(401);", + "});", + "", + "", + "", + "pm.test(\"Response body matches\", function () {", + " pm.expect(pm.response.text()).to.eq(\"Invalid User\");", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/json/destinations/costa-rica", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "json", + "destinations", + "costa-rica" + ] + }, + "description": "Given no user, should return 401 and \"Invalid User\" message" + }, + "response": [] + }, + { + "name": "Switch to 'demo.dotcms.com'", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200 \", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Valid response\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.entity.hostSwitched).equal(true);", + "});", + "", + "pm.environment.set(\"forcePreRequestScript\", false);", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "pm.environment.set(\"forcePreRequestScript\", true);", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{serverURL}}/api/v1/site/switch/48190c8c-42c4-46af-8d1a-0cd5db894797", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "site", + "switch", + "48190c8c-42c4-46af-8d1a-0cd5db894797" + ] + } + }, + "response": [] + }, + { + "name": "Get Valid HTML Page Metadata", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "", + "", + "pm.test(\"Include template\", function () {", + " pm.expect(pm.response.text()).to.include(\"template\");", + "});", + "", + "pm.test(\"Include layout\", function () {", + " pm.expect(pm.response.text()).to.include(\"layout\");", + "});", + "", + "pm.test(\"Include Containers\", function () {", + " pm.expect(pm.response.text()).to.include(\"containers\");", + "});", + "", + "pm.test(\"'page' element includes all properties\", function () {", + " var jsonData = pm.response.json();", + " var page = jsonData[\"entity\"][\"page\"];", + " pm.expect(page[\"__icon__\"]).equal(\"pageIcon\");", + " pm.expect(page[\"archived\"], 'FAILED:[archived]').equal(false);", + " pm.expect(page[\"baseType\"]).equal(\"HTMLPAGE\");", + " pm.expect(page[\"cachettl\"]).equal(\"0\");", + " pm.expect(page[\"canEdit\"], 'FAILED:[canEdit]').equal(true);", + " pm.expect(page[\"canLock\"], 'FAILED:[canLock]').equal(true);", + " pm.expect(page[\"canRead\"], 'FAILED:[canRead]').equal(true);", + " pm.expect(page[\"deleted\"], 'FAILED:[deleted]').equal(false);", + " pm.expect(page[\"extension\"]).equal(\"page\");", + " pm.expect(page[\"folder\"]).equal(\"6c8a2ac4-36a7-4b01-b9c0-c2c1d91ddfdb\");", + " pm.expect(page[\"friendlyName\"]).equal(\"Costa Rica Rain Forest\");", + " pm.expect(page[\"hasLiveVersion\"], 'FAILED:[hasLiveVersion]').equal(true);", + " pm.expect(page[\"hasTitleImage\"], 'FAILED:[hasTitleImage]').equal(true);", + " pm.expect(page[\"host\"]).equal(\"48190c8c-42c4-46af-8d1a-0cd5db894797\");", + " pm.expect(page[\"hostName\"]).equal(\"demo.dotcms.com\");", + " ////", + " pm.expect(page[\"httpsRequired\"], 'FAILED:[httpsRequired]').equal(false);", + " pm.expect(page[\"identifier\"]).equal(\"bec7b960-a8bf-4f14-a22b-0d94caf217f0\");", + " pm.expect(page[\"image\"]).equal(\"/dA/bec7b960-a8bf-4f14-a22b-0d94caf217f0/image/costa-rica-tree-frog.jpg\");", + " pm.expect(page[\"imageContentAsset\"]).equal(\"bec7b960-a8bf-4f14-a22b-0d94caf217f0/image\");", + " pm.expect(page[\"inode\"]).not.equal(null)", + " pm.expect(page[\"isContentlet\"], 'FAILED:[isContentlet]').equal(true);", + " pm.expect(page[\"languageId\"]).equal(1);", + " pm.expect(page[\"live\"], 'FAILED:[live]').equal(true);", + " pm.expect(page[\"liveInode\"]).not.equal(null)", + " pm.expect(page[\"locked\"], 'FAILED:[locked]').equal(false);", + " pm.expect(page[\"mimeType\"]).equal(\"application/dotpage\");", + " pm.expect(page[\"modDate\"]).not.equal(null)", + " ///", + " pm.expect(page[\"modUser\"]).equal(\"system\");", + " pm.expect(page[\"modUserName\"]).equal(\"system user system user\");", + " pm.expect(page[\"name\"]).equal(\"costa-rica\");", + " pm.expect(page[\"owner\"]).equal(\"dotcms.org.1\");", + " pm.expect(page[\"pageURI\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"pageUrl\"]).equal(\"costa-rica\");", + " pm.expect(page[\"path\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"publishDate\"]).not.equal(null)", + " pm.expect(page[\"seoTitle\"]).equal(\"Costa Rica Travel Destinations\");", + " pm.expect(page[\"seodescription\"]).equal(\"Visit Costa Rica a rugged, rainforested Central American country with coastlines on the Caribbean and Pacific.\");", + " pm.expect(page[\"shortDescription\"]).equal(\"Costa Rica is a rugged, rainforested Central American country with coastlines on the Caribbean and Pacific. Costa Rica is known for its beaches, volcanoes, and biodiversity. Roughly a quarter of its area is made up of protected jungle, teeming with wildlife including spider monkeys and quetzal birds.\");", + " pm.expect(page[\"shortyLive\"]).not.equal(null)", + " //", + " pm.expect(page[\"shortyWorking\"]).not.equal(null)", + " pm.expect(page[\"sortOrder\"]).equal(0);", + " pm.expect(page[\"stInode\"]).equal(\"91812c8b-0441-4139-8d4d-7423cfb0e979\");", + " pm.expect(page[\"statusIcons\"]).equal(\"\");", + " pm.expect(page[\"tags\"]).equal(\"diving\");", + " pm.expect(page[\"template\"]).equal(\"0c556e37-99e0-4458-a2cd-d42cc7a11045\");", + " pm.expect(page[\"title\"]).equal(\"Costa Rica Rain Forest\");", + " pm.expect(page[\"titleImage\"]).equal(\"image\");", + " pm.expect(page[\"type\"]).equal(\"htmlpage\");", + " pm.expect(page[\"url\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"working\"], 'FAILED:[working]').equal(true);", + " pm.expect(page[\"workingInode\"]).not.equal(null)", + "", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/json/destinations/costa-rica", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "json", + "destinations", + "costa-rica" + ] + }, + "description": "http://localhost:8080/api/v1/page/json/{page-url}" + }, + "response": [] + }, + { + "name": "Invalidate Session", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/logout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "logout" + ] + } + }, + "response": [] + }, + { + "name": "Get Non-Existing HTML Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404);", + "});", + "", + "", + "", + "pm.test(\"Valid response\", function () {", + " pm.expect(pm.response.text()).to.include(\"Page \\'about-us/index2\\' not found\");", + "});", + "", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/json/about-us/index2", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "json", + "about-us", + "index2" + ] + } + }, + "response": [] + }, + { + "name": "Get Metadata From URL Map", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"No errors\", function () {", + " ", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + "});", + "", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "}); ", + "", + "pm.test(\"Has Rows and Columns\", function () {", + " ", + " var jsonData = pm.response.json();", + " ", + " pm.expect(jsonData.entity.layout.body.rows.length).to.equal(2);", + " pm.expect(jsonData.entity.layout.body.rows[0].columns.length).to.equal(1);", + " ", + "});", + "", + "pm.test(\"Number of Contents\", function () {", + " ", + " var jsonData = pm.response.json();", + " ", + " pm.expect(jsonData.entity.numberContents).to.equal(2);", + " ", + " ", + "});", + "", + "pm.test(\"Page checks\", function () {", + " ", + " var jsonData = pm.response.json();", + " ", + " pm.expect(jsonData.entity.page.pageURI).to.equal('/blog/index');", + " pm.expect(jsonData.entity.page.title).to.equal('Blogs');", + " pm.expect(jsonData.entity.page.type).to.equal('htmlpage');", + " ", + "});", + "", + "pm.test(\"Site checks\", function () {", + " ", + " var jsonData = pm.response.json();", + " ", + " pm.expect(jsonData.entity.site.hostname).to.equal('demo.dotcms.com');", + " pm.expect(jsonData.entity.site.type).to.equal('contentlet');", + " ", + "});", + "", + "pm.test(\"Template checks\", function () {", + " ", + " var jsonData = pm.response.json();", + " ", + " pm.expect(jsonData.entity.template.title).to.equal('anonymous_layout_1571406924828');", + " pm.expect(jsonData.entity.template.type).to.equal('template');", + " ", + "});", + "", + "pm.test(\"Contentlets checks\", function () {", + " ", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.entity.containers[\"//demo.dotcms.com/application/containers/default/\"].contentlets[\"uuid-1\"][0].title).to.equal('Travel Blog Header');", + " pm.expect(jsonData.entity.containers[\"//demo.dotcms.com/application/containers/default/\"].contentlets[\"uuid-1\"][0].contentType).to.equal('webPageContent');", + "});", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/json/blog/index", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "json", + "blog", + "index" + ] + }, + "description": "Gets an Url content map" + }, + "response": [] + } + ], + "description": "Tests calling the `json` method passing down the actual URI of an HTML Page.", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "Using Vanity URLs", + "item": [ + { + "name": "Create Test Forward Vanity URL", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Forward Vanity URL was created successfully\", function () {", + " var jsonData = pm.response.json().entity;", + " pm.expect(jsonData.summary.failCount).to.eql(0, \"An error occurred when creating the test Vanity URL\");", + " pm.expect(jsonData.summary.successCount).to.eql(1, \"One piece of content should have been created\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlets\": [\n {\n \"contentType\": \"Vanityurl\",\n \"languageId\": 1,\n \"title\": \"Test Forward Vanity URL\",\n \"site\": \"demo.dotcms.com\",\n \"uri\": \"/forward-json\",\n \"action\": 200,\n \"forwardTo\": \"/destinations/costa-rica\",\n \"order\": 0\n }\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + }, + "description": "Create the original Contentlet." + }, + "response": [] + }, + { + "name": "Create Test Temporary Redirect Vanity URL", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Temporary Redirect Vanity URL was created successfully\", function () {", + " var jsonData = pm.response.json().entity;", + " pm.expect(jsonData.summary.failCount).to.eql(0, \"An error occurred when creating the test Vanity URL\");", + " pm.expect(jsonData.summary.successCount).to.eql(1, \"One piece of content should have been created\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlets\": [\n {\n \"contentType\": \"Vanityurl\",\n \"languageId\": 1,\n \"title\": \"Test Temporary Vanity URL\",\n \"site\": \"demo.dotcms.com\",\n \"uri\": \"/temporary-json\",\n \"action\": 302,\n \"forwardTo\": \"/destinations/costa-rica\",\n \"order\": 0\n }\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + }, + "description": "Create the original Contentlet." + }, + "response": [] + }, + { + "name": "Create Test Permanent Redirect Vanity URL", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Permanent Redirect Vanity URL was created successfully\", function () {", + " var jsonData = pm.response.json().entity;", + " pm.expect(jsonData.summary.failCount).to.eql(0, \"An error occurred when creating the test Vanity URL\");", + " pm.expect(jsonData.summary.successCount).to.eql(1, \"One piece of content should have been created\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlets\": [\n {\n \"contentType\": \"Vanityurl\",\n \"languageId\": 1,\n \"title\": \"Test Permanent Vanity URL\",\n \"site\": \"demo.dotcms.com\",\n \"uri\": \"/permanent-json\",\n \"action\": 301,\n \"forwardTo\": \"/destinations/costa-rica\",\n \"order\": 0\n }\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + }, + "description": "Create the original Contentlet." + }, + "response": [] + }, + { + "name": "Get HTML Page Metadata - Forward", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Response body contains the 'uuid' attribute\", function () {", + " pm.expect(pm.response.text()).to.include(\"uuid\");", + "});", + "", + "pm.test(\"The 'page' element includes all the expected properties\", function () {", + " var jsonData = pm.response.json();", + " var page = jsonData[\"entity\"][\"page\"];", + " pm.expect(page[\"__icon__\"]).equal(\"pageIcon\");", + " pm.expect(page[\"archived\"], 'FAILED:[archived]').equal(false);", + " pm.expect(page[\"baseType\"]).equal(\"HTMLPAGE\");", + " pm.expect(page[\"cachettl\"]).equal(\"0\");", + " pm.expect(page[\"canEdit\"], 'FAILED:[canEdit]').equal(true);", + " pm.expect(page[\"canLock\"], 'FAILED:[canLock]').equal(true);", + " pm.expect(page[\"canRead\"], 'FAILED:[canRead]').equal(true);", + " pm.expect(page[\"deleted\"], 'FAILED:[deleted]').equal(false);", + " pm.expect(page[\"extension\"]).equal(\"page\");", + " pm.expect(page[\"folder\"]).equal(\"6c8a2ac4-36a7-4b01-b9c0-c2c1d91ddfdb\");", + " pm.expect(page[\"friendlyName\"]).equal(\"Costa Rica Rain Forest\");", + " pm.expect(page[\"hasLiveVersion\"], 'FAILED:[hasLiveVersion]').equal(true);", + " pm.expect(page[\"hasTitleImage\"], 'FAILED:[hasTitleImage]').equal(true);", + " pm.expect(page[\"host\"]).equal(\"48190c8c-42c4-46af-8d1a-0cd5db894797\");", + " pm.expect(page[\"hostName\"]).equal(\"demo.dotcms.com\");", + " ////", + " pm.expect(page[\"httpsRequired\"], 'FAILED:[httpsRequired]').equal(false);", + " pm.expect(page[\"identifier\"]).equal(\"bec7b960-a8bf-4f14-a22b-0d94caf217f0\");", + " pm.expect(page[\"image\"]).equal(\"/dA/bec7b960-a8bf-4f14-a22b-0d94caf217f0/image/costa-rica-tree-frog.jpg\");", + " pm.expect(page[\"imageContentAsset\"]).equal(\"bec7b960-a8bf-4f14-a22b-0d94caf217f0/image\");", + " pm.expect(page[\"inode\"]).not.equal(null)", + " pm.expect(page[\"isContentlet\"], 'FAILED:[isContentlet]').equal(true);", + " pm.expect(page[\"languageId\"]).equal(1);", + " pm.expect(page[\"live\"], 'FAILED:[live]').equal(true);", + " pm.expect(page[\"liveInode\"]).not.equal(null)", + " pm.expect(page[\"locked\"], 'FAILED:[locked]').equal(false);", + " pm.expect(page[\"mimeType\"]).equal(\"application/dotpage\");", + " pm.expect(page[\"modDate\"]).not.equal(null)", + " ///", + " pm.expect(page[\"modUser\"]).equal(\"system\");", + " pm.expect(page[\"modUserName\"]).equal(\"system user system user\");", + " pm.expect(page[\"name\"]).equal(\"costa-rica\");", + " pm.expect(page[\"owner\"]).equal(\"dotcms.org.1\");", + " pm.expect(page[\"pageURI\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"pageUrl\"]).equal(\"costa-rica\");", + " pm.expect(page[\"path\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"publishDate\"]).not.equal(null)", + " pm.expect(page[\"seoTitle\"]).equal(\"Costa Rica Travel Destinations\");", + " pm.expect(page[\"seodescription\"]).equal(\"Visit Costa Rica a rugged, rainforested Central American country with coastlines on the Caribbean and Pacific.\");", + " pm.expect(page[\"shortDescription\"]).equal(\"Costa Rica is a rugged, rainforested Central American country with coastlines on the Caribbean and Pacific. Costa Rica is known for its beaches, volcanoes, and biodiversity. Roughly a quarter of its area is made up of protected jungle, teeming with wildlife including spider monkeys and quetzal birds.\");", + " pm.expect(page[\"shortyLive\"]).not.equal(null)", + " //", + " pm.expect(page[\"shortyWorking\"]).not.equal(null)", + " pm.expect(page[\"sortOrder\"]).equal(0);", + " pm.expect(page[\"stInode\"]).equal(\"91812c8b-0441-4139-8d4d-7423cfb0e979\");", + " pm.expect(page[\"statusIcons\"]).equal(\"\");", + " pm.expect(page[\"tags\"]).equal(\"diving\");", + " pm.expect(page[\"template\"]).equal(\"0c556e37-99e0-4458-a2cd-d42cc7a11045\");", + " pm.expect(page[\"title\"]).equal(\"Costa Rica Rain Forest\");", + " pm.expect(page[\"titleImage\"]).equal(\"image\");", + " pm.expect(page[\"type\"]).equal(\"htmlpage\");", + " pm.expect(page[\"url\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"working\"], 'FAILED:[working]').equal(true);", + " pm.expect(page[\"workingInode\"]).not.equal(null)", + "});", + "", + "pm.test(\"The 'Forward' Vanity URL data must be present\", function() {", + " var entity = pm.response.json().entity;", + " pm.expect(entity.vanityUrl).not.not.equal(undefined, \"The 'vanityUrl' attribute is missing\");", + " pm.expect(entity.vanityUrl.url).to.be.equal(\"/forward-json\", \"The 'url' attribute is NOT the expected one\");", + " pm.expect(entity.vanityUrl.response).to.be.equal(200, \"The 'response' attribute must be 200\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/json/forward-json", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "json", + "forward-json" + ] + } + }, + "response": [] + }, + { + "name": "Get HTML Page Metadata - Temporary Redirect", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"The 'Temporary Redirect' Vanity URL data must be present\", function() {", + " var entity = pm.response.json().entity;", + " pm.expect(entity.vanityUrl).to.not.equal(undefined, \"The 'vanityUrl' attribute must be present\");", + " pm.expect(entity.vanityUrl.response).to.be.equal(302, \"The 'response' attribute must be 302\");", + " pm.expect(entity.vanityUrl.temporaryRedirect).to.equal(true, \"The returned Vanity URL MUST be a temporary redirect\");", + " pm.expect(entity.vanityUrl.permanentRedirect).to.equal(false, \"The returned Vanity URL MUST NOT be a permanent redirect\");", + " pm.expect(entity.vanityUrl.forward).to.equal(false, \"The returned Vanity URL MUST NOT be a forward\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/json/temporary-json", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "json", + "temporary-json" + ] + } + }, + "response": [] + }, + { + "name": "Get HTML Page Metadata - Permanent Redirect", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"The 'Permanent Redirect' Vanity URL must be present\", function() {", + " var entity = pm.response.json().entity;", + " pm.expect(entity.vanityUrl).to.not.equal(undefined, \"The 'vanityUrl' attribute must be present\");", + " pm.expect(entity.vanityUrl.response).to.be.equal(301, \"The 'response' attribute must be 301\");", + " pm.expect(entity.vanityUrl.permanentRedirect).to.equal(true, \"The returned Vanity URL MUST be a permanent redirect\");", + " pm.expect(entity.vanityUrl.temporaryRedirect).to.equal(false, \"The returned Vanity URL MUST NOT be a temporary redirect\");", + " pm.expect(entity.vanityUrl.forward).to.equal(false, \"The returned Vanity URL MUST NOT be a forward\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/json/permanent-json", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "json", + "permanent-json" + ] + } + }, + "response": [] + } + ], + "description": "Tests calling the `json` method passing down a Vanity URL that references an HTML Page, using the three redirect options:\n\n1. Forward.\n \n2. Temporary Redirect.\n \n3. Permanent Redirect.", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"HTTP Status must be 200\", function() {", + " pm.response.to.have.status(200);", + "});", + "" + ] + } + } + ] + } + ], + "description": "Returns the metadata in JSON format of the objects that make up an HTML Page in the system.\n\nhttp://localhost:8080/api/v1/page/json/{page-url}", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "Render [api/v1/page/render]", + "item": [ + { + "name": "Using Actual Page URIs", + "item": [ + { + "name": "Invalidate Session", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/logout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "logout" + ] + } + }, + "response": [] + }, + { + "name": "Get Page Metadata With Invalid User", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 401, Need credentials\", function () {", + " pm.response.to.have.status(401);", + "});", + "", + "pm.test(\"Response body matches\", function () {", + " pm.expect(pm.response.text()).to.include(\"Invalid User\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/destinations/costa-rica", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "destinations", + "costa-rica" + ] + } + }, + "response": [] + }, + { + "name": "Switch to 'demo.dotcms.com'", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200 \", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Valid response\", function () {", + " var jsonData = pm.response.json();", + "", + " pm.expect(jsonData.entity.hostSwitched).equal(true);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{serverURL}}/api/v1/site/switch/48190c8c-42c4-46af-8d1a-0cd5db894797", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "site", + "switch", + "48190c8c-42c4-46af-8d1a-0cd5db894797" + ] + } + }, + "response": [] + }, + { + "name": "Get Valid HTML Page Metadata", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Response body contains\", function () {", + " pm.expect(pm.response.text()).to.include(\"rendered\");", + "});", + "", + "pm.test(\"Response body contains\", function () {", + " pm.expect(pm.response.text()).to.include(\"uuid\");", + "});", + "", + "pm.test(\"'page' element includes all properties\", function () {", + " var jsonData = pm.response.json();", + " var page = jsonData[\"entity\"][\"page\"];", + " pm.expect(page[\"__icon__\"]).equal(\"pageIcon\");", + " pm.expect(page[\"archived\"], 'FAILED:[archived]').equal(false);", + " pm.expect(page[\"baseType\"]).equal(\"HTMLPAGE\");", + " pm.expect(page[\"cachettl\"]).equal(\"0\");", + " pm.expect(page[\"canEdit\"], 'FAILED:[canEdit]').equal(true);", + " pm.expect(page[\"canLock\"], 'FAILED:[canLock]').equal(true);", + " pm.expect(page[\"canRead\"], 'FAILED:[canRead]').equal(true);", + " pm.expect(page[\"deleted\"], 'FAILED:[deleted]').equal(false);", + " pm.expect(page[\"extension\"]).equal(\"page\");", + " pm.expect(page[\"folder\"]).equal(\"6c8a2ac4-36a7-4b01-b9c0-c2c1d91ddfdb\");", + " pm.expect(page[\"friendlyName\"]).equal(\"Costa Rica Rain Forest\");", + " pm.expect(page[\"hasLiveVersion\"], 'FAILED:[hasLiveVersion]').equal(true);", + " pm.expect(page[\"hasTitleImage\"], 'FAILED:[hasTitleImage]').equal(true);", + " pm.expect(page[\"host\"]).equal(\"48190c8c-42c4-46af-8d1a-0cd5db894797\");", + " pm.expect(page[\"hostName\"]).equal(\"demo.dotcms.com\");", + " ////", + " pm.expect(page[\"httpsRequired\"], 'FAILED:[httpsRequired]').equal(false);", + " pm.expect(page[\"identifier\"]).equal(\"bec7b960-a8bf-4f14-a22b-0d94caf217f0\");", + " pm.expect(page[\"image\"]).equal(\"/dA/bec7b960-a8bf-4f14-a22b-0d94caf217f0/image/costa-rica-tree-frog.jpg\");", + " pm.expect(page[\"imageContentAsset\"]).equal(\"bec7b960-a8bf-4f14-a22b-0d94caf217f0/image\");", + " pm.expect(page[\"inode\"]).not.equal(null)", + " pm.expect(page[\"isContentlet\"], 'FAILED:[isContentlet]').equal(true);", + " pm.expect(page[\"languageId\"]).equal(1);", + " pm.expect(page[\"live\"], 'FAILED:[live]').equal(true);", + " pm.expect(page[\"liveInode\"]).not.equal(null)", + " pm.expect(page[\"locked\"], 'FAILED:[locked]').equal(false);", + " pm.expect(page[\"mimeType\"]).equal(\"application/dotpage\");", + " pm.expect(page[\"modDate\"]).not.equal(null)", + " ///", + " pm.expect(page[\"modUser\"]).equal(\"system\");", + " pm.expect(page[\"modUserName\"]).equal(\"system user system user\");", + " pm.expect(page[\"name\"]).equal(\"costa-rica\");", + " pm.expect(page[\"owner\"]).equal(\"dotcms.org.1\");", + " pm.expect(page[\"pageURI\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"pageUrl\"]).equal(\"costa-rica\");", + " pm.expect(page[\"path\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"publishDate\"]).not.equal(null)", + " pm.expect(page[\"seoTitle\"]).equal(\"Costa Rica Travel Destinations\");", + " pm.expect(page[\"seodescription\"]).equal(\"Visit Costa Rica a rugged, rainforested Central American country with coastlines on the Caribbean and Pacific.\");", + " pm.expect(page[\"shortDescription\"]).equal(\"Costa Rica is a rugged, rainforested Central American country with coastlines on the Caribbean and Pacific. Costa Rica is known for its beaches, volcanoes, and biodiversity. Roughly a quarter of its area is made up of protected jungle, teeming with wildlife including spider monkeys and quetzal birds.\");", + " pm.expect(page[\"shortyLive\"]).not.equal(null)", + " //", + " pm.expect(page[\"shortyWorking\"]).not.equal(null)", + " pm.expect(page[\"sortOrder\"]).equal(0);", + " pm.expect(page[\"stInode\"]).equal(\"91812c8b-0441-4139-8d4d-7423cfb0e979\");", + " pm.expect(page[\"statusIcons\"]).equal(\"\");", + " pm.expect(page[\"tags\"]).equal(\"diving\");", + " pm.expect(page[\"template\"]).equal(\"0c556e37-99e0-4458-a2cd-d42cc7a11045\");", + " pm.expect(page[\"title\"]).equal(\"Costa Rica Rain Forest\");", + " pm.expect(page[\"titleImage\"]).equal(\"image\");", + " pm.expect(page[\"type\"]).equal(\"htmlpage\");", + " pm.expect(page[\"url\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"working\"], 'FAILED:[working]').equal(true);", + " pm.expect(page[\"workingInode\"]).not.equal(null)", + "", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/destinations/costa-rica", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "destinations", + "costa-rica" + ] + } + }, + "response": [] + }, + { + "name": "Get Metadata From Non-Existing HTML Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404);", + "});", + "", + "", + "pm.test(\"Response body contains\", function () {", + " ", + " pm.expect( pm.response.json().message).to.eq(\"Page 'about-us/index2' not found\");", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/about-us/index2", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "about-us", + "index2" + ] + } + }, + "response": [] + }, + { + "name": "Reset workflow for contentlet", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200 \", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "", + "", + "pm.test(\"Correct identifier\", function () {", + " pm.expect(pm.response.json().entity.identifier).equal(\"57ee7cd3-66fc-4f01-9b7e-11e53553c220\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/2d1dc7718f/fire?identifier=57ee7cd3-66fc-4f01-9b7e-11e53553c220", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "2d1dc7718f", + "fire" + ], + "query": [ + { + "key": "identifier", + "value": "57ee7cd3-66fc-4f01-9b7e-11e53553c220" + } + ] + }, + "description": "The piece of content \"Ecoturism in Costarica\" gets somehow archived at this point after being imported in a previous bundle. This resets its workflow so it can be published in the next request" + }, + "response": [] + }, + { + "name": "Publish Archived Content", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200 \", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "", + "", + "pm.test(\"Correct identifier\", function () {", + " pm.expect(pm.response.json().entity.identifier).equal(\"57ee7cd3-66fc-4f01-9b7e-11e53553c220\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/175009d69e/fire?identifier=57ee7cd3-66fc-4f01-9b7e-11e53553c220", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "175009d69e", + "fire" + ], + "query": [ + { + "key": "identifier", + "value": "57ee7cd3-66fc-4f01-9b7e-11e53553c220" + } + ] + }, + "description": "This publishes the content `Ecotourism in Costa Rica` so it can be tested in the next request" + }, + "response": [] + }, + { + "name": "Get Metadata From URL Map", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"No errors\", function () {", + " ", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + "});", + "", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "}); ", + "", + "pm.test(\"Has Rows and Columns\", function () {", + " ", + " var jsonData = pm.response.json();", + " ", + " pm.expect(jsonData.entity.layout.body.rows.length).to.equal(1);", + " pm.expect(jsonData.entity.layout.body.rows[0].columns.length).to.equal(1);", + " ", + "});", + "", + "pm.test(\"Number of Contents\", function () {", + " ", + " var jsonData = pm.response.json();", + " ", + " pm.expect(jsonData.entity.numberContents).to.equal(1);", + " ", + " ", + "});", + "", + "pm.test(\"Page checks\", function () {", + " ", + " var jsonData = pm.response.json();", + " ", + " pm.expect(jsonData.entity.page.pageURI).to.equal('/blog/post/ecotourism-in-costa-rica');", + " pm.expect(jsonData.entity.page.title).to.equal('Blog Detail');", + " pm.expect(jsonData.entity.page.type).to.equal('htmlpage');", + " ", + "});", + "", + "pm.test(\"Site checks\", function () {", + " ", + " var jsonData = pm.response.json();", + " ", + " pm.expect(jsonData.entity.site.hostname).to.equal('demo.dotcms.com');", + " pm.expect(jsonData.entity.site.type).to.equal('contentlet');", + " ", + "});", + "", + "pm.test(\"Template checks\", function () {", + " ", + " var jsonData = pm.response.json();", + " ", + " pm.expect(jsonData.entity.template.title).to.equal('anonymous_layout_1582562696562');", + " pm.expect(jsonData.entity.template.type).to.equal('template');", + " ", + "});", + "", + "pm.test(\"Url Content Map checks\", function () {", + " ", + " var jsonData = pm.response.json();", + "", + " pm.expect(jsonData.entity.urlContentMap.hostName).to.equal('demo.dotcms.com');", + " pm.expect(jsonData.entity.urlContentMap.baseType).to.equal('CONTENT');", + " pm.expect(jsonData.entity.urlContentMap.contentType).to.equal('Blog');", + " pm.expect(jsonData.entity.urlContentMap.urlTitle).to.equal('ecotourism-in-costa-rica');", + " pm.expect(jsonData.entity.urlContentMap['URL_MAP_FOR_CONTENT']).to.equal('/blog/post/ecotourism-in-costa-rica');", + " pm.expect(jsonData.entity.urlContentMap['urlMap']).to.equal('/blog/post/ecotourism-in-costa-rica');", + "});", + "", + "", + "", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/blog/post/ecotourism-in-costa-rica?mode=EDIT_MODE", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "blog", + "post", + "ecotourism-in-costa-rica" + ], + "query": [ + { + "key": "mode", + "value": "EDIT_MODE" + } + ] + }, + "description": "Gets an Url content map" + }, + "response": [] + } + ], + "description": "Tests calling the `render` method passing down the actual URI of an HTML Page." + }, + { + "name": "Using Vanity URLs", + "item": [ + { + "name": "Create Test Forward Vanity URL", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Forward Vanity URL was created successfully\", function () {", + " var jsonData = pm.response.json().entity;", + " pm.expect(jsonData.summary.failCount).to.eql(0, \"An error occurred when creating the test Vanity URL\");", + " pm.expect(jsonData.summary.successCount).to.eql(1, \"One piece of content should have been created\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlets\": [\n {\n \"contentType\": \"Vanityurl\",\n \"languageId\": 1,\n \"title\": \"Test Forward Vanity URL\",\n \"site\": \"demo.dotcms.com\",\n \"uri\": \"/forward-render\",\n \"action\": 200,\n \"forwardTo\": \"/destinations/costa-rica\",\n \"order\": 0\n }\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + }, + "description": "Create the original Contentlet." + }, + "response": [] + }, + { + "name": "Create Test Temporary Redirect Vanity URL", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Temporary Redirect Vanity URL was created successfully\", function () {", + " var jsonData = pm.response.json().entity;", + " pm.expect(jsonData.summary.failCount).to.eql(0, \"An error occurred when creating the test Vanity URL\");", + " pm.expect(jsonData.summary.successCount).to.eql(1, \"One piece of content should have been created\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlets\": [\n {\n \"contentType\": \"Vanityurl\",\n \"languageId\": 1,\n \"title\": \"Test Temporary Vanity URL\",\n \"site\": \"demo.dotcms.com\",\n \"uri\": \"/temporary-render\",\n \"action\": 302,\n \"forwardTo\": \"/destinations/costa-rica\",\n \"order\": 0\n }\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + }, + "description": "Create the original Contentlet." + }, + "response": [] + }, + { + "name": "Create Test Permanent Redirect Vanity URL", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Permanent Redirect Vanity URL was created successfully\", function () {", + " var jsonData = pm.response.json().entity;", + " pm.expect(jsonData.summary.failCount).to.eql(0, \"An error occurred when creating the test Vanity URL\");", + " pm.expect(jsonData.summary.successCount).to.eql(1, \"One piece of content should have been created\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlets\": [\n {\n \"contentType\": \"Vanityurl\",\n \"languageId\": 1,\n \"title\": \"Test Permanent Vanity URL\",\n \"site\": \"demo.dotcms.com\",\n \"uri\": \"/permanent-render\",\n \"action\": 301,\n \"forwardTo\": \"/destinations/costa-rica\",\n \"order\": 0\n }\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + }, + "description": "Create the original Contentlet." + }, + "response": [] + }, + { + "name": "Get HTML Page Metadata - Forward", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Response body contains the 'rendered' attribute\", function () {", + " pm.expect(pm.response.text()).to.include(\"rendered\");", + "});", + "", + "pm.test(\"Response body contains the 'uuid' attribute\", function () {", + " pm.expect(pm.response.text()).to.include(\"uuid\");", + "});", + "", + "pm.test(\"The 'page' element includes all the expected properties\", function () {", + " var jsonData = pm.response.json();", + " var page = jsonData[\"entity\"][\"page\"];", + " pm.expect(page[\"__icon__\"]).equal(\"pageIcon\");", + " pm.expect(page[\"archived\"], 'FAILED:[archived]').equal(false);", + " pm.expect(page[\"baseType\"]).equal(\"HTMLPAGE\");", + " pm.expect(page[\"cachettl\"]).equal(\"0\");", + " pm.expect(page[\"canEdit\"], 'FAILED:[canEdit]').equal(true);", + " pm.expect(page[\"canLock\"], 'FAILED:[canLock]').equal(true);", + " pm.expect(page[\"canRead\"], 'FAILED:[canRead]').equal(true);", + " pm.expect(page[\"deleted\"], 'FAILED:[deleted]').equal(false);", + " pm.expect(page[\"extension\"]).equal(\"page\");", + " pm.expect(page[\"folder\"]).equal(\"6c8a2ac4-36a7-4b01-b9c0-c2c1d91ddfdb\");", + " pm.expect(page[\"friendlyName\"]).equal(\"Costa Rica Rain Forest\");", + " pm.expect(page[\"hasLiveVersion\"], 'FAILED:[hasLiveVersion]').equal(true);", + " pm.expect(page[\"hasTitleImage\"], 'FAILED:[hasTitleImage]').equal(true);", + " pm.expect(page[\"host\"]).equal(\"48190c8c-42c4-46af-8d1a-0cd5db894797\");", + " pm.expect(page[\"hostName\"]).equal(\"demo.dotcms.com\");", + " ////", + " pm.expect(page[\"httpsRequired\"], 'FAILED:[httpsRequired]').equal(false);", + " pm.expect(page[\"identifier\"]).equal(\"bec7b960-a8bf-4f14-a22b-0d94caf217f0\");", + " pm.expect(page[\"image\"]).equal(\"/dA/bec7b960-a8bf-4f14-a22b-0d94caf217f0/image/costa-rica-tree-frog.jpg\");", + " pm.expect(page[\"imageContentAsset\"]).equal(\"bec7b960-a8bf-4f14-a22b-0d94caf217f0/image\");", + " pm.expect(page[\"inode\"]).not.equal(null)", + " pm.expect(page[\"isContentlet\"], 'FAILED:[isContentlet]').equal(true);", + " pm.expect(page[\"languageId\"]).equal(1);", + " pm.expect(page[\"live\"], 'FAILED:[live]').equal(true);", + " pm.expect(page[\"liveInode\"]).not.equal(null)", + " pm.expect(page[\"locked\"], 'FAILED:[locked]').equal(false);", + " pm.expect(page[\"mimeType\"]).equal(\"application/dotpage\");", + " pm.expect(page[\"modDate\"]).not.equal(null)", + " ///", + " pm.expect(page[\"modUser\"]).equal(\"system\");", + " pm.expect(page[\"modUserName\"]).equal(\"system user system user\");", + " pm.expect(page[\"name\"]).equal(\"costa-rica\");", + " pm.expect(page[\"owner\"]).equal(\"dotcms.org.1\");", + " pm.expect(page[\"pageURI\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"pageUrl\"]).equal(\"costa-rica\");", + " pm.expect(page[\"path\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"publishDate\"]).not.equal(null)", + " pm.expect(page[\"seoTitle\"]).equal(\"Costa Rica Travel Destinations\");", + " pm.expect(page[\"seodescription\"]).equal(\"Visit Costa Rica a rugged, rainforested Central American country with coastlines on the Caribbean and Pacific.\");", + " pm.expect(page[\"shortDescription\"]).equal(\"Costa Rica is a rugged, rainforested Central American country with coastlines on the Caribbean and Pacific. Costa Rica is known for its beaches, volcanoes, and biodiversity. Roughly a quarter of its area is made up of protected jungle, teeming with wildlife including spider monkeys and quetzal birds.\");", + " pm.expect(page[\"shortyLive\"]).not.equal(null)", + " //", + " pm.expect(page[\"shortyWorking\"]).not.equal(null)", + " pm.expect(page[\"sortOrder\"]).equal(0);", + " pm.expect(page[\"stInode\"]).equal(\"91812c8b-0441-4139-8d4d-7423cfb0e979\");", + " pm.expect(page[\"statusIcons\"]).equal(\"\");", + " pm.expect(page[\"tags\"]).equal(\"diving\");", + " pm.expect(page[\"template\"]).equal(\"0c556e37-99e0-4458-a2cd-d42cc7a11045\");", + " pm.expect(page[\"title\"]).equal(\"Costa Rica Rain Forest\");", + " pm.expect(page[\"titleImage\"]).equal(\"image\");", + " pm.expect(page[\"type\"]).equal(\"htmlpage\");", + " pm.expect(page[\"url\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"working\"], 'FAILED:[working]').equal(true);", + " pm.expect(page[\"workingInode\"]).not.equal(null)", + "});", + "", + "pm.test(\"The 'Forward' Vanity URL data must be present\", function() {", + " var entity = pm.response.json().entity;", + " pm.expect(entity.vanityUrl).not.not.equal(undefined, \"The 'vanityUrl' attribute is missing\");", + " pm.expect(entity.vanityUrl.url).to.be.equal(\"/forward-render\", \"The 'url' attribute is NOT the expected one\");", + " pm.expect(entity.vanityUrl.response).to.be.equal(200, \"The 'response' attribute must be 200\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/forward-render", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "forward-render" + ] + } + }, + "response": [] + }, + { + "name": "Get HTML Page Metadata - Temporary Redirect", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"The 'Temporary Redirect' Vanity URL data must be present\", function() {", + " var entity = pm.response.json().entity;", + " pm.expect(entity.vanityUrl).to.not.equal(undefined, \"The 'vanityUrl' attribute must be present\");", + " pm.expect(entity.vanityUrl.response).to.be.equal(302, \"The 'response' attribute must be 302\");", + " pm.expect(entity.vanityUrl.temporaryRedirect).to.equal(true, \"The returned Vanity URL MUST be a temporary redirect\");", + " pm.expect(entity.vanityUrl.permanentRedirect).to.equal(false, \"The returned Vanity URL MUST NOT be a permanent redirect\");", + " pm.expect(entity.vanityUrl.forward).to.equal(false, \"The returned Vanity URL MUST NOT be a forward\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/temporary-render", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "temporary-render" + ] + } + }, + "response": [] + }, + { + "name": "Get HTML Page Metadata - Permanent Redirect", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"The 'Permanent Redirect' Vanity URL must be present\", function() {", + " var entity = pm.response.json().entity;", + " pm.expect(entity.vanityUrl).to.not.equal(undefined, \"The 'vanityUrl' attribute must be present\");", + " pm.expect(entity.vanityUrl.response).to.be.equal(301, \"The 'response' attribute must be 301\");", + " pm.expect(entity.vanityUrl.permanentRedirect).to.equal(true, \"The returned Vanity URL MUST be a permanent redirect\");", + " pm.expect(entity.vanityUrl.temporaryRedirect).to.equal(false, \"The returned Vanity URL MUST NOT be a temporary redirect\");", + " pm.expect(entity.vanityUrl.forward).to.equal(false, \"The returned Vanity URL MUST NOT be a forward\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/permanent-render", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "permanent-render" + ] + } + }, + "response": [] + } + ], + "description": "Tests calling the `render` method passing down a Vanity URL that references an HTML Page, using the three redirect options:\n\n1. Forward.\n \n2. Temporary Redirect.\n \n3. Permanent Redirect.", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"HTTP Status must be 200\", function() {", + " pm.response.to.have.status(200);", + "});", + "", + "" + ] + } + } + ] + }, + { + "name": "Check related content in depth 2", + "item": [ + { + "name": "Create content type with image field", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var contentType = pm.response.json().entity[0];", + "var jsonData = pm.response.json();", + "pm.collectionVariables.set(\"relatedContentTypeVarName\", contentType.variable);", + "", + "pm.test(\"Image field check\", function () {", + " pm.expect(jsonData.entity[0].fields[3].name).to.eql('myImage');", + "});", + "", + "pm.test(\"Check response\", function () {", + " pm.expect(jsonData.entity[0].baseType).to.eql(\"CONTENT\");", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"defaultType\": false,\n \"fixed\": false,\n \"system\": false,\n \"clazz\": \"com.dotcms.contenttype.model.type.ImmutableSimpleContentType\",\n \"description\": \"\",\n \"host\": \"8a7d5e23-da1e-420a-b4f0-471e7da8ea2d\",\n \"folder\": \"SYSTEM_FOLDER\",\n \"name\": \"content type with img\",\n \"workflow\": [\n \"d61a59e1-a49c-46f2-a929-db2b4bfa88b2\"\n ],\n \"fields\": [\n {\n \"clazz\": \"com.dotcms.contenttype.model.field.ImmutableTextField\",\n \"dataType\": \"TEXT\",\n \"fieldType\": \"Text\",\n \"fieldTypeLabel\": \"Text\",\n \"fieldVariables\": [],\n \"fixed\": false,\n \"indexed\": true,\n \"listed\": false,\n \"name\": \"Title\",\n \"readOnly\": false,\n \"required\": false,\n \"searchable\": true,\n \"sortOrder\": 1,\n \"unique\": false,\n \"variable\": \"title\"\n },\n {\n \"clazz\": \"com.dotcms.contenttype.model.field.ImmutableImageField\",\n \"dataType\": \"TEXT\",\n \"fieldType\": \"Image\",\n \"fieldTypeLabel\": \"Image\",\n \"fieldVariables\": [],\n \"fixed\": false,\n \"iDate\": 1585605564000,\n \"indexed\": true,\n \"listed\": false,\n \"modDate\": 1585605564000,\n \"name\": \"myImage\",\n \"readOnly\": false,\n \"required\": false,\n \"searchable\": false,\n \"sortOrder\": 3,\n \"unique\": false\n }\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/contenttype", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "contenttype" + ] + }, + "description": "Create content type with title and image fields" + }, + "response": [] + }, + { + "name": "Create content type with relationship field", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var contentType = pm.response.json().entity[0];", + "var jsonData = pm.response.json();", + "pm.collectionVariables.set(\"relationshipContentTypeId\", contentType.id);", + "pm.collectionVariables.set(\"relationshipContentTypeName\", contentType.name);", + "pm.collectionVariables.set(\"relationshipContentTypeVarName\", contentType.variable);", + "", + "pm.test(\"Relationship field check\", function () {", + " pm.expect(jsonData.entity[0].fields[3].name).to.eql('rel');", + "});", + "", + "pm.test(\"Check response\", function () {", + " pm.expect(jsonData.entity[0].baseType).to.eql(\"CONTENT\");", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"defaultType\": false,\n \"fixed\": false,\n \"system\": false,\n \"clazz\": \"com.dotcms.contenttype.model.type.ImmutableSimpleContentType\",\n \"description\": \"\",\n \"host\": \"8a7d5e23-da1e-420a-b4f0-471e7da8ea2d\",\n \"folder\": \"SYSTEM_FOLDER\",\n \"name\": \"content with relationship\",\n \"workflow\": [\n \"d61a59e1-a49c-46f2-a929-db2b4bfa88b2\"\n ],\n \"fields\": [\n {\n \"clazz\": \"com.dotcms.contenttype.model.field.ImmutableTextField\",\n \"dataType\": \"TEXT\",\n \"fieldType\": \"Text\",\n \"fieldTypeLabel\": \"Text\",\n \"fieldVariables\": [],\n \"fixed\": false,\n \"indexed\": true,\n \"listed\": false,\n \"name\": \"Title\",\n \"readOnly\": false,\n \"required\": false,\n \"searchable\": true,\n \"sortOrder\": 1,\n \"unique\": false,\n \"variable\": \"title\"\n },\n {\n\t\t \"clazz\":\"com.dotcms.contenttype.model.field.ImmutableRelationshipField\",\n\t\t \"required\":false,\n\t\t \"name\":\"rel\",\n\t\t \"relationships\":{\n\t\t \"velocityVar\":\"{{relatedContentTypeVarName}}\",\n\t\t \"cardinality\":0\n\t\t },\n\t\t \"searchable\":false\n\t\t}\n ]\n}\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/contenttype", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "contenttype" + ] + }, + "description": "Create a content type with title and relationship fields" + }, + "response": [] + }, + { + "name": "Upload Image", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "pm.test(\"Retrieving the ID of the custom Image contentlet\", function () {", + " ", + " pm.collectionVariables.set(\"imageContentIdentifier\", jsonData.entity.identifier);", + "});", + "", + "pm.test(\"Check response\", function () {", + " pm.expect(jsonData.entity.baseType).to.eql(\"DOTASSET\");", + " pm.expect(jsonData.entity.title).to.eql(\"Landscape_2008_urban_park_and_plaza_Ankaran.jpeg\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "json", + "value": "{\n \"contentlet\": {\n \"contentType\":\"DotAsset\",\n \"title\":\"test img\", \n \"hostFolder\":\"default\",\n \"indexPolicy\":\"WAIT_FOR\",\n \"showOnMenu\":\"true\",\n \"sortOrder\":\"2\"\n }\n}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "resources/image/Landscape_2008_urban_park_and_plaza_Ankaran.jpeg" + } + ] + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + }, + "description": "Upload an image as a dotasset type, in this test the image with src in \"_resources/image/_[Landscape_2008_urban_park_and_plaza_Ankaran.jpeg](https://github.com/dotCMS/core/blob/master/dotcms-postman/src/main/resources/postman/resources/image/Landscape_2008_urban_park_and_plaza_Ankaran.jpeg)_\"_ is being used" + }, + "response": [] + }, + { + "name": "Create Content", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "pm.test(\"Retrieving the ID of the contentlet with Image field\", function () {", + " pm.collectionVariables.set(\"contentImgIdentifier\", jsonData.entity.identifier);", + "});", + "", + "pm.test(\"Check response\", function () {", + " pm.expect(jsonData.entity.contentType).to.eql(pm.collectionVariables.get(\"relatedContentTypeVarName\"));", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"contentlet\": {\n \"contentType\":\"{{relatedContentTypeVarName}}\",\n \"title\":\"Content With Image\", \n \"contentHost\":\"default\",\n \"indexPolicy\":\"WAIT_FOR\",\n \"myImage\":\"{{imageContentIdentifier}}\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + }, + "description": "Create contentlet with the previously created content type with image field" + }, + "response": [] + }, + { + "name": "Create Content (relationship)", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "pm.test(\"Retrieving the ID of the contentlet with relationship fields\", function () {", + " pm.collectionVariables.set(\"contentRelationshipIdentifier\", jsonData.entity.identifier);", + "});", + "", + "pm.test(\"Check response\", function () {", + " pm.expect(jsonData.entity.contentType).to.eql(pm.collectionVariables.get(\"relationshipContentTypeVarName\"));", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"contentlet\": {\n \"contentType\":\"{{relationshipContentTypeVarName}}\",\n \"title\":\"content related\",\n \"rel\":\"{{contentImgIdentifier}}\",\n \"indexPolicy\":\"WAIT_FOR\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + }, + "description": "Create contentlet with the previously created content type with relationship field" + }, + "response": [] + }, + { + "name": "Create page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "", + "pm.collectionVariables.set(\"page_id\", jsonData.entity.identifier);", + "pm.collectionVariables.set(\"page_name\", jsonData.entity.title);", + "", + "", + "pm.test(\"Check response\", function () {", + " const responseData = pm.response.json();", + " ", + " pm.expect(responseData.entity.contentType).to.eql('htmlpageasset');", + " ", + "});", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{ \n \"contentlet\" : {\n \"title\" : \"page_to_test_content_with_image_related\",\n \"languageId\" : 1,\n \"stInode\": \"c541abb1-69b3-4bc5-8430-5e09e5239cc8\",\n \"url\": \"page_to_test_content_with_image_related\",\n \"hostFolder\": \"48190c8c-42c4-46af-8d1a-0cd5db894797\",\n \"template\": \"SYSTEM_TEMPLATE\",\n \"cachettl\": 0,\n \"friendlyName\": \"friendlyName\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + }, + "description": "Create a page" + }, + "response": [] + }, + { + "name": "Add contentlet into page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "pm.test(\"Check response\", function () {", + " ", + " pm.expect(jsonData.entity).to.eql('ok');", + " ", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "[\n {\n \"contentletsId\": [\"{{contentImgIdentifier}}\", \"{{contentRelationshipIdentifier}}\"],\n \"identifier\": \"SYSTEM_CONTAINER\",\n \"uuid\": \"1\" \n } \n]\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/{{page_id}}/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{page_id}}", + "content" + ] + }, + "description": "Add the two previously created contentlet to the created page" + }, + "response": [] + }, + { + "name": "render page data json", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "pm.test(\"Check response to have the correct related data\", function () {", + " pm.expect(jsonData.entity.containers.SYSTEM_CONTAINER.contentlets[\"uuid-1\"][1].rel[0].myImage.extension).to.eql('jpeg');", + " pm.expect(jsonData.entity.containers.SYSTEM_CONTAINER.contentlets[\"uuid-1\"][1].rel[0].myImage.metaData.name).to.eql('Landscape_2008_urban_park_and_plaza_Ankaran.jpeg');", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/page_to_test_content_with_image_related?language_id=1&depth=2", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "page_to_test_content_with_image_related" + ], + "query": [ + { + "key": "language_id", + "value": "1" + }, + { + "key": "depth", + "value": "2" + } + ] + }, + "description": "Check the metadata of the related content, it should not be null and have the correct values" + }, + "response": [] + } + ], + "description": "[https://github.com/dotCMS/core/issues/29259](https://github.com/dotCMS/core/issues/29259)\n\n1. Create a content type with title and image fields\n \n2. Create content type with title and relationship fields, and related to the previously created content type\n \n3. Upload an image\n \n4. Create a content with the content type from step 1\n \n5. Create a content with the content type from step 2 and relate it to the content created in step 4\n \n6. Create a page\n \n7. Add to the page both contents\n \n8. Render the page and check data in depth = 2", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ] + } + } + ] + } + ] + }, + { + "name": "Layout [/api/v1/page/{page-id}/layout]", + "item": [ + { + "name": "invalidateSession", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/logout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "logout" + ] + } + }, + "response": [] + }, + { + "name": "GivenInvalidUser_ShouldReturn401", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 401, Need credentials\", function () {", + " pm.response.to.have.status(401);", + "});", + "", + "", + "", + "pm.test(\"Response body matches\", function () {", + " pm.expect(pm.response.text()).to.include(\"Invalid User\");", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\"title\":null,\"layout\":{\"body\":{\"rows\":[{\"columns\":[{\"leftOffset\":1,\"width\":7,\"containers\":[{\"identifier\":\"a050073a-a31e-4aab-9307-86bfb248096a\",\"uuid\":\"1\"}]},{\"leftOffset\":8,\"width\":4,\"containers\":[{\"identifier\":\"5363c6c6-5ba0-4946-b7af-cf875188ac2e\",\"uuid\":\"1\"}]}]}]},\"header\":true,\"footer\":true,\"sidebar\":{\"location\":\"\",\"containers\":[],\"width\":\"small\"}}}" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/bec7b960-a8bf-4f14-a22b-0d94caf217f0/layout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "bec7b960-a8bf-4f14-a22b-0d94caf217f0", + "layout" + ] + }, + "description": "@Path(\"/{pageId}/layout\")" + }, + "response": [] + }, + { + "name": "GivenValidLayout_ShouldSaveLayout", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Response code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Response body contains 'rendered'\", function () {", + " pm.expect(pm.response.text()).to.include(\"rendered\");", + "});", + "", + "var jsonData = pm.response.json();", + "", + "pm.test(\"'Containers' section contains expected containers\", function () {", + " var containers = jsonData[\"entity\"][\"containers\"];", + " pm.expect(containers[\"//demo.dotcms.com/application/containers/default/\"].container.identifier).equal(\"69b3d24d-7e80-4be6-b04a-d352d16493ee\");", + "", + " pm.expect(containers[\"5a07f889-4536-4956-aa6e-e7967969ec3f\"].container.identifier).equal(\"5a07f889-4536-4956-aa6e-e7967969ec3f\");", + "});", + "", + "", + "var layout = jsonData[\"entity\"][\"layout\"];", + "var rows = layout[\"body\"][\"rows\"];", + "var columns = layout[\"body\"][\"rows\"][0][\"columns\"];", + "pm.expect(columns.length).equal(2);", + "", + "// column 1 ", + "var column1 = columns[0];", + "var containersColumn1 = column1[\"containers\"];", + "", + "// column 2", + "var column2 = columns[1];", + "var containersColumn2 = column2[\"containers\"];", + "", + "", + "", + "pm.test(\"Layout has 1 row\", function () {", + " pm.expect(rows.length).equal(1);", + "});", + "", + "pm.test(\"First row has 2 columns\", function () {", + " pm.expect(columns.length).equal(2);", + "});", + "", + "pm.test(\"First column has width of 7 \", function () {", + " pm.expect(column1[\"width\"]).equal(7);", + "}); ", + "", + "pm.test(\"First column has 1 container with expected identifier\", function () {", + " pm.expect(containersColumn1.length).equal(1);", + " pm.expect(containersColumn1[0].identifier).equal(\"//demo.dotcms.com/application/containers/default/\");", + "}); ", + "", + "pm.test(\"Second column has width of 4 \", function () {", + " pm.expect(column2[\"width\"]).equal(4);", + "}); ", + "", + "pm.test(\"Second column has 1 container with expected identifier\", function () {", + " pm.expect(containersColumn2.length).equal(1);", + " pm.expect(containersColumn2[0].identifier).equal(\"5a07f889-4536-4956-aa6e-e7967969ec3f\");", + "}); ", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"title\": null,\n \"layout\": {\n \"body\": {\n \"rows\": [\n {\n \"columns\": [\n {\n \"leftOffset\": 1,\n \"width\": 7,\n \"containers\": [\n {\n \"identifier\": \"//demo.dotcms.com/application/containers/default/\", \n \"uuid\": \"1\"\n }\n ]\n },\n {\n \"leftOffset\": 8,\n \"width\": 4,\n \"containers\": [\n {\n \"identifier\": \"5a07f889-4536-4956-aa6e-e7967969ec3f\",\n \"uuid\": \"1\"\n }\n ]\n }\n ]\n }\n ]\n },\n \"header\": true,\n \"footer\": true,\n \"sidebar\": {\n \"location\": \"\",\n \"containers\": [],\n \"width\": \"small\"\n }\n }\n}" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/bec7b960-a8bf-4f14-a22b-0d94caf217f0/layout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "bec7b960-a8bf-4f14-a22b-0d94caf217f0", + "layout" + ] + }, + "description": "@Path(\"/{pageId}/layout\")" + }, + "response": [] + }, + { + "name": "GivenInvalidPageId_ShouldReturn404", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404);", + "});", + "", + "", + "", + "pm.test(\"Response body contains\", function () {", + " pm.expect(pm.response.text()).to.include(\"Unable to find page with Identifier: 2c12fe7e6-d338-49d5-973b-2d974d57015b\");", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\"title\":null,\"layout\":{\"body\":{\"rows\":[{\"columns\":[{\"leftOffset\":1,\"width\":7,\"containers\":[{\"identifier\":\"a050073a-a31e-4aab-9307-86bfb248096a\",\"uuid\":\"1\"}]},{\"leftOffset\":8,\"width\":4,\"containers\":[{\"identifier\":\"5363c6c6-5ba0-4946-b7af-cf875188ac2e\",\"uuid\":\"1\"}]}]}]},\"header\":true,\"footer\":true,\"sidebar\":{\"location\":\"\",\"containers\":[],\"width\":\"small\"}}}" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/2c12fe7e6-d338-49d5-973b-2d974d57015b/layout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "2c12fe7e6-d338-49d5-973b-2d974d57015b", + "layout" + ] + }, + "description": "@Path(\"/{pageId}/layout\")" + }, + "response": [] + }, + { + "name": "RequestWihoutParameters", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "", + "", + "pm.test(\"Response body contains\", function () {", + " pm.expect(pm.response.text()).to.include(\"required\");", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/bec7b960-a8bf-4f14-a22b-0d94caf217f0/layout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "bec7b960-a8bf-4f14-a22b-0d94caf217f0", + "layout" + ] + }, + "description": "@Path(\"/{pageId}/layout\")" + }, + "response": [] + }, + { + "name": "BadRequest", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "", + "", + "pm.test(\"Response body contains\", function () {", + " pm.expect(pm.response.text()).to.include(\"Unrecognized field\");", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\"2title\":null,\"layout\":{\"body\":{\"rows\":[{\"columns\":[{\"leftOffset\":1,\"width\":7,\"containers\":[{\"identifier\":\"a050073a-a31e-4aab-9307-86bfb248096a\",\"uuid\":\"1\"}]},{\"leftOffset\":8,\"width\":4,\"containers\":[{\"identifier\":\"5363c6c6-5ba0-4946-b7af-cf875188ac2e\",\"uuid\":\"1\"}]}]}]},\"header\":true,\"footer\":true,\"sidebar\":{\"location\":\"\",\"containers\":[],\"width\":\"small\"}}}" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/bec7b960-a8bf-4f14-a22b-0d94caf217f0/layout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "bec7b960-a8bf-4f14-a22b-0d94caf217f0", + "layout" + ] + }, + "description": "@Path(\"/{pageId}/layout\")" + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "Add Content [/api/v1/page/{page-id}/content]", + "item": [ + { + "name": "Test_RespectOrder", + "item": [ + { + "name": "ImportBundle", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Success import\", function () {", + " var jsonData = pm.response.json();", + " console.log(jsonData);", + " pm.expect(jsonData[\"status\"]).to.eql(\"SUCCESS\");", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/octet-stream" + }, + { + "key": "Content-Disposition", + "value": "attachment" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "file", + "type": "file", + "src": "resources/testRespectOrder_Bundle.tar.gz" + } + ] + }, + "url": { + "raw": "{{serverURL}}/api/bundle/sync", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "bundle", + "sync" + ], + "query": [ + { + "key": "AUTH_TOKEN", + "value": "", + "disabled": true + } + ] + }, + "description": "Imports a Bundle that includes:\n\n* Page (testRespectOrder)\n* 2 Content (testOrder1 and testOrder2)" + }, + "response": [] + }, + { + "name": "Get Page To Check Order", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Response reorder check\", function () {", + " pm.expect(pm.response.text()).to.include(\"

testOrder2

testOrder1

\");", + "", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/testrespectorder?language_id=1&host_id=8a7d5e23-da1e-420a-b4f0-471e7da8ea2d", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "testrespectorder" + ], + "query": [ + { + "key": "language_id", + "value": "1" + }, + { + "key": "host_id", + "value": "8a7d5e23-da1e-420a-b4f0-471e7da8ea2d" + } + ] + } + }, + "response": [] + }, + { + "name": "ReorderContents", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Response body contains\", function () {", + " pm.expect(pm.response.text()).to.include(\"ok\");", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "[{\"identifier\":\"//default/application/containers/system/\",\"uuid\":\"1\",\"contentletsId\":[\"ffba6c6b2e90ce4dcc2a553c6b860822\",\"844cdd64de4fd9418613b3b53f860c6f\"]}]" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/773c1d064bfedacf26986a67ee90b490/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "773c1d064bfedacf26986a67ee90b490", + "content" + ] + }, + "description": "Reorder the page contents." + }, + "response": [] + }, + { + "name": "Get Page To Check Reorder", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Response reorder check\", function () {", + " pm.expect(pm.response.text()).to.include(\"

testOrder1

testOrder2

\");", + "", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/testrespectorder?language_id=1&host_id=8a7d5e23-da1e-420a-b4f0-471e7da8ea2d", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "testrespectorder" + ], + "query": [ + { + "key": "language_id", + "value": "1" + }, + { + "key": "host_id", + "value": "8a7d5e23-da1e-420a-b4f0-471e7da8ea2d" + } + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "" + ] + } + } + ] + }, + { + "name": "invalidateSession", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/logout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "logout" + ] + } + }, + "response": [] + }, + { + "name": "UserAuthenticationValidation", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 401, Need credentials\", function () {", + " pm.response.to.have.status(401);", + "});", + "", + "pm.test(\"Response body matches\", function () {", + " pm.expect(pm.response.text()).to.include(\"Invalid User\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "[{\"identifier\":\"a050073a-a31e-4aab-9307-86bfb248096a\",\"uuid\":\"1\",\"contentletsId\":[\"767509b1-2392-4661-a16b-e0e31ce27719\",\"3c30df49-ea78-417a-93ce-631cd25bc66c\"]},{\"identifier\":\"5363c6c6-5ba0-4946-b7af-cf875188ac2e\",\"uuid\":\"1\",\"contentletsId\":[\"2efc77b4-a54f-479b-8a81-a133b9e6da04\",\"5aef0c62-b7d6-4805-9e7c-77a67f4822f3\",\"66d47ebf-7b11-4076-85b0-b6c8c373d000\"]}]" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/bec7b960-a8bf-4f14-a22b-0d94caf217f0/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "bec7b960-a8bf-4f14-a22b-0d94caf217f0", + "content" + ] + }, + "description": "@Path(\"{pageId}/content\")" + }, + "response": [] + }, + { + "name": "SuccessRequest", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Response body contains\", function () {", + " pm.expect(pm.response.text()).to.include(\"ok\");", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "[{\"identifier\":\"5a07f889-4536-4956-aa6e-e7967969ec3f\",\"uuid\":\"1\",\"contentletsId\":[\"d4ed1990-b151-42ca-9bca-0725b07260de\"]},{\"identifier\":\"//demo.dotcms.com/application/containers/default/\",\"uuid\":\"1\",\"contentletsId\":[\"f827c41a-5689-4733-b4d7-916d3a31c9c6\",\"7c9cb3a7-bb68-4fd0-b21d-03ec4be491a7\"]}]" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/bec7b960-a8bf-4f14-a22b-0d94caf217f0/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "bec7b960-a8bf-4f14-a22b-0d94caf217f0", + "content" + ] + }, + "description": "Adds Content to a Page, the container, template, page and contentlets are imported.\n\n7c9cb3a7-bb68-4fd0-b21d-03ec4be491a7 = container Banner\n7c9cb3a7-bb68-4fd0-b21d-03ec4be491a7e = Banner contentlet\n7c9cb3a7-bb68-4fd0-b21d-03ec4be491a7 = Container as File Default\nf827c41a-5689-4733-b4d7-916d3a31c9c6 = Rich Text Contentlet\n7c9cb3a7-bb68-4fd0-b21d-03ec4be491a7 = Widget Contentlet" + }, + "response": [] + }, + { + "name": "Save Contentlets Not Valid BadRequest 400", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "[{\"identifier\":\"5a07f889-4536-4956-aa6e-e7967969ec3f\",\"uuid\":\"1\",\"contentletsId\":[\"f827c41a-5689-4733-b4d7-916d3a31c9c6\"]}]" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/bec7b960-a8bf-4f14-a22b-0d94caf217f0/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "bec7b960-a8bf-4f14-a22b-0d94caf217f0", + "content" + ] + }, + "description": "@Path(\"{pageId}/content\")" + }, + "response": [] + }, + { + "name": "InvalidPageId", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404);", + "});", + "", + "pm.test(\"Response body contains\", function () {", + " pm.expect(pm.response.text()).to.include(\"Page '2c12fe7e6-d338-49d5-973b-2d974d57015b' not found\");", + "});", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "[{\"identifier\":\"a050073a-a31e-4aab-9307-86bfb248096a\",\"uuid\":\"1\",\"contentletsId\":[\"767509b1-2392-4661-a16b-e0e31ce27719\",\"3c30df49-ea78-417a-93ce-631cd25bc66c\"]},{\"identifier\":\"5363c6c6-5ba0-4946-b7af-cf875188ac2e\",\"uuid\":\"1\",\"contentletsId\":[\"2efc77b4-a54f-479b-8a81-a133b9e6da04\",\"5aef0c62-b7d6-4805-9e7c-77a67f4822f3\",\"66d47ebf-7b11-4076-85b0-b6c8c373d000\"]}]" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/2c12fe7e6-d338-49d5-973b-2d974d57015b/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "2c12fe7e6-d338-49d5-973b-2d974d57015b", + "content" + ] + }, + "description": "@Path(\"{pageId}/content\")" + }, + "response": [] + }, + { + "name": "RequestWihoutParameters", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Layout is required\", function () {", + " pm.expect(pm.response.text()).to.include(\"Layout is required\");", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/bec7b960-a8bf-4f14-a22b-0d94caf217f0/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "bec7b960-a8bf-4f14-a22b-0d94caf217f0", + "content" + ] + }, + "description": "@Path(\"{pageId}/content\")" + }, + "response": [] + }, + { + "name": "BadRequest", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response body contains\", function () {", + " pm.expect(pm.response.text()).to.include(\"Container id and uuid are required\");", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "[{\"id222\":\"a050073a-a31e-4aab-9307-86bfb248096a\",\"uuid\":\"1\",\"contentlets\":[\"767509b1-2392-4661-a16b-e0e31ce27719\",\"3c30df49-ea78-417a-93ce-631cd25bc66c\"]},{\"id\":\"5363c6c6-5ba0-4946-b7af-cf875188ac2e\",\"uuid22\":\"1\",\"contentlets\":[\"2efc77b4-a54f-479b-8a81-a133b9e6da04\",\"5aef0c62-b7d6-4805-9e7c-77a67f4822f3\",\"66d47ebf-7b11-4076-85b0-b6c8c373d000\"]}]" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/bec7b960-a8bf-4f14-a22b-0d94caf217f0/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "bec7b960-a8bf-4f14-a22b-0d94caf217f0", + "content" + ] + }, + "description": "@Path(\"{pageId}/content\")" + }, + "response": [] + }, + { + "name": "Save Content Upsert Duplicated Containers Body", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Response body contains\", function () {", + " pm.expect(pm.response.text()).to.include(\"ok\");", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "[\n {\n \"identifier\":\"//demo.dotcms.com/application/containers/default/\",\n \"uuid\":\"1\",\n \"contentletsId\":[\"7c9cb3a7-bb68-4fd0-b21d-03ec4be491a7\"]\n },\n {\n \"identifier\":\"//demo.dotcms.com/application/containers/default/\",\n \"uuid\":\"1\",\n \"contentletsId\":[\"f827c41a-5689-4733-b4d7-916d3a31c9c6\"]\n },\n {\n \"identifier\":\"//demo.dotcms.com/application/containers/default/\",\n \"uuid\":\"1\",\n \"contentletsId\":[\"7c9cb3a7-bb68-4fd0-b21d-03ec4be491a7\"]\n }\n]", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/bec7b960-a8bf-4f14-a22b-0d94caf217f0/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "bec7b960-a8bf-4f14-a22b-0d94caf217f0", + "content" + ] + }, + "description": "This test is for when users make a request sending at the Body the same container and uuid diff times.\nThis will merge all those contentlets and save the page successfully." + }, + "response": [] + } + ], + "description": " @Path(\"{pageId}/content\")", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "Render HTML [/api/v1/page/renderHTML]", + "item": [ + { + "name": "invalidateSession", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/logout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "logout" + ] + } + }, + "response": [] + }, + { + "name": "UserAuthenticationValidation", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 401, Need credentials\", function () {", + " pm.response.to.have.status(401);", + "});", + "", + "pm.test(\"Invalid User\", function () {", + " pm.expect(pm.response.text()).to.include(\"Invalid User\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/renderHTML/destinations/costa-rica", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "renderHTML", + "destinations", + "costa-rica" + ] + }, + "description": "@Path(\"/renderHTML/{uri: .*}\")" + }, + "response": [] + }, + { + "name": "pre_ImportBundleWithDemoHost", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Bundle uploaded sucessfully\", function () {", + " pm.response.to.have.status(200);", + "", + " var jsonData = pm.response.json();", + " console.log(jsonData);", + "", + " pm.expect(jsonData[\"bundleName\"]).to.eql(\"demo.dotcms.com.tar.gz\");", + " pm.expect(jsonData[\"status\"]).to.eql(\"SUCCESS\");", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/octet-stream" + }, + { + "key": "Content-Disposition", + "value": "attachment" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "file", + "type": "file", + "src": "resources/GraphQL/demo.dotcms.com.tar.gz" + } + ] + }, + "url": { + "raw": "{{serverURL}}/api/bundle/sync", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "bundle", + "sync" + ], + "query": [ + { + "key": "AUTH_TOKEN", + "value": "", + "disabled": true + } + ] + }, + "description": "Imports a Bundle that includes:\n* Imports demo.dotcms.com" + }, + "response": [] + }, + { + "name": "SuccessRequest", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"renders expected HTML only\", function () {", + " pm.expect(pm.response.text().startsWith(\"\")).to.be.true;", + " pm.expect(pm.response.text()).to.include(\"body id=\\\"costa-rica-rain-forest\\\"\");", + "});", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/renderHTML/destinations/costa-rica", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "renderHTML", + "destinations", + "costa-rica" + ] + }, + "description": "@Path(\"/renderHTML/{uri: .*}\")" + }, + "response": [] + }, + { + "name": "InvalidPageURL", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404);", + "});", + "", + "pm.test(\"Valid response\", function () {", + " pm.expect(pm.response.text()).to.include(\"Page \\'about-us/our-team/index2\\' not found\");", + "});", + "", + "", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/renderHTML/about-us/our-team/index2", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "renderHTML", + "about-us", + "our-team", + "index2" + ] + }, + "description": "@Path(\"/renderHTML/{uri: .*}\")" + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "Whats Changed", + "item": [ + { + "name": "pre_ImportBundle", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Bundle imported\", function () {", + " var jsonData = pm.response.json();", + " console.log(jsonData);", + "", + " pm.expect(jsonData[\"bundleName\"]).to.contains(\"testWhatsChanged\");", + " pm.expect(jsonData[\"status\"]).to.eql(\"SUCCESS\");", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "admin", + "type": "string" + }, + { + "key": "username", + "value": "admin@dotcms.com", + "type": "string" + }, + { + "key": "saveHelperData", + "type": "any" + }, + { + "key": "showPassword", + "value": false, + "type": "boolean" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/octet-stream" + }, + { + "key": "Content-Disposition", + "value": "attachment" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "file", + "type": "file", + "src": "resources/testWhatsChanged-01FTGYNEP672VF4KFRFWSX3RPT.tar.gz" + } + ] + }, + "url": { + "raw": "{{serverURL}}/api/bundle/sync", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "bundle", + "sync" + ], + "query": [ + { + "key": "AUTH_TOKEN", + "value": "", + "disabled": true + } + ] + }, + "description": "Imports a Bundle that includes: a page with content, the content has diff versions working and live" + }, + "response": [] + }, + { + "name": "Check Whats Changed Endpoint", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"There are diff between live and working page\", function () {", + " var jsonData = pm.response.json().entity;", + " pm.expect(jsonData[\"diff\"]).equal(true);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/8afe50bc66533c6f0ed7711d74654b80/render/versions", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "8afe50bc66533c6f0ed7711d74654b80", + "render", + "versions" + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ] + } + } + ] + }, + { + "name": "TestHostVariables", + "item": [ + { + "name": "Create new Site For Test Host Variables", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "pm.test(\"Host check\", function () {", + " pm.expect(jsonData.entity.siteName).to.eql('sitevariables.site.com');", + "});", + "", + "pm.collectionVariables.set(\"siteIdTestHost\", jsonData.entity.identifier);", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"siteName\":\"sitevariables.site.com\"\n\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/site", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "site" + ] + } + }, + "response": [] + }, + { + "name": "Publish Site", + "request": { + "method": "PUT", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/site/{{siteIdTestHost}}/_publish", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "site", + "{{siteIdTestHost}}", + "_publish" + ] + } + }, + "response": [] + }, + { + "name": "Add Site Variable", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "var jsonData = pm.response.json();", + "", + "pm.test(\"Host check\", function () {", + " pm.expect(jsonData.entity.key).to.eql('onevar1');", + "});", + "", + "pm.collectionVariables.set(\"sitevariableIdTestHost\", jsonData.entity.id);", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"siteId\":\"{{siteIdTestHost}}\",\n \"name\":\"onevar1\",\n \"key\":\"onevar1\",\n \"value\":\"onevar-value\"\n}\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/site/variable", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "site", + "variable" + ] + } + }, + "response": [] + }, + { + "name": "CreateNewContainer Test Host Variables", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"No errors\", function () {", + " ", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + "});", + "", + "pm.test(\"Information Saved Correctly\", function () {", + " ", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.entity.title).to.eql(\"TestContainerHostVariables\");", + " pm.expect(jsonData.entity.notes).to.eql(\"Notes\");", + " ", + " ", + "});", + "", + "var jsonData = pm.response.json();", + "pm.collectionVariables.set(\"containeridentifier\", jsonData.entity.identifier);", + "pm.collectionVariables.set(\"inode\", jsonData.entity.inode);", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"title\":\"TestContainerHostVariables\",\n \"friendlyName\":\"TestContainer description HostVariables\",\n \"maxContentlets\":1,\n \"notes\":\"Notes\",\n \"preLoop\":\"preLoop $host_variable.onevar1\",\n \"postLoop\":\"postLoop xxxx\",\n \"containerStructures\":[\n {\n \"structureId\":\"webPageContent\",\n \"code\":\"$title on container\"\n }\n ]\n\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/containers", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "containers" + ] + }, + "description": "Create a container" + }, + "response": [] + }, + { + "name": "SavePublishNewTemplateTestHostVariables", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "pm.test(\"live check\", function () {", + " pm.expect(jsonData.entity.live).to.eql(true);", + "});", + "", + "", + "pm.test(\"Title check\", function () {", + " pm.expect(jsonData.entity.title).to.eql('PostMan Test Save Publish Test Host Variables');", + "});", + "", + "pm.collectionVariables.set(\"templateIdToPublishedHost\", jsonData.entity.identifier);", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"title\":\"PostMan Test Save Publish Test Host Variables\",\n \"friendlyName\":\"This is a postman test description\",\n \"body\":\"#parseContainer('{{containeridentifier}}','1659543155955')\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/templates/_savepublish", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "templates", + "_savepublish" + ] + } + }, + "response": [] + }, + { + "name": "Create Page using the template", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "pm.test(\"Path check\", function () {", + " pm.expect(jsonData.entity.path).to.eql(\"/testpagehostvariables\");", + "});", + "", + "", + "", + "var jsonData = pm.response.json();", + "pm.collectionVariables.set(\"pageUrlHostVariablestest\", pm.response.json().path);", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"contentlet\": {\n \"contentType\": \"htmlpageasset\",\n \"hostFolder\": \"{{siteIdTestHost}}\",\n \"title\": \"Test Page Host variables\",\n \"url\": \"testpagehostvariables\",\n \"template\":\"{{templateIdToPublishedHost}}\",\n \"sortOrder\":1,\n \"cachettl\":\"0\",\n \"friendlyName\":\"testpagehostvariables\"\n\n }\n}" + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + }, + "description": "Fire any action using the actionId\n\nOptional: If you pass ?inode={inode}, you don't need body here.\n\n@Path(\"/actions/{actionId}/fire\")" + }, + "response": [] + }, + { + "name": "Test the host variables", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var text = pm.response.text();", + "", + "pm.test(\"Path check\", function () {", + " pm.expect(text).to.include(\"onevar-value\");", + "});", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/testpagehostvariables?language_id=1&host_id={{siteIdTestHost}}", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "testpagehostvariables" + ], + "query": [ + { + "key": "language_id", + "value": "1" + }, + { + "key": "host_id", + "value": "{{siteIdTestHost}}" + } + ] + } + }, + "response": [] + } + ], + "description": "1. This test creates a Host with two variables\n2. Creates a container with the generic contentlet and use this two variables\n3. Creates a template that uses this container\n4. creates a page that uses this page\n5. Check that the page exists.", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"Response code should be 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ] + } + } + ] + }, + { + "name": "In-Place Content Copy", + "item": [ + { + "name": "Create Test Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Page created successfully\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + " pm.collectionVariables.set(\"pageIdentifier\", jsonData.entity.identifier);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\n\t\"contentlet\": {\n\t\t\"contentType\":\"htmlpageasset\",\n \"title\":\"testPageCopy\",\n \"url\":\"testPageCopy\",\n \"hostFolder\":\"default\",\n \"template\":\"SYSTEM_TEMPLATE\",\n \"friendlyName\":\"testPageCopy\",\n \"cachettl\":0\n\t\t\n\t}\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH?indexPolicy=WAIT_FOR", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ], + "query": [ + { + "key": "indexPolicy", + "value": "WAIT_FOR" + } + ] + } + }, + "response": [] + }, + { + "name": "Create Test Rich Text Contentlet", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Rich Text created successfully\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + " pm.collectionVariables.set(\"richContentIdentifier\", jsonData.entity.identifier);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\n\t\"contentlet\": {\n\t\t\"contentType\":\"webPageContent\",\n \"title\":\"textContent\",\n \"contentHost\":\"default\",\n \"body\":\"Text Content Body\"\n \n\t}\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH?indexPolicy=WAIT_FOR", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ], + "query": [ + { + "key": "indexPolicy", + "value": "WAIT_FOR" + } + ] + } + }, + "response": [] + }, + { + "name": "Add Test Content To Test Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Content added to Test Page successfuly\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "[\n {\n \"identifier\": \"SYSTEM_CONTAINER\",\n \"uuid\": \"1\",\n \"contentletsId\": [\n \"{{richContentIdentifier}}\"\n ]\n }\n]", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/{{pageIdentifier}}/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{pageIdentifier}}", + "content" + ] + } + }, + "response": [] + }, + { + "name": "Check That Multi-Tree Data Is Correct", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Retrieving Multi-Tree data for test Contentlet\", function () {", + " var entity = pm.response.json().entity;", + " var testContentId = pm.collectionVariables.get(\"richContentIdentifier\");", + " var found = false;", + " entity.forEach((treeEntry) => {", + "", + " if (testContentId == treeEntry.contentId) {", + " pm.collectionVariables.set(\"containerId\", treeEntry.containerId);", + " pm.collectionVariables.set(\"contentId\", treeEntry.contentId);", + " pm.collectionVariables.set(\"pageId\", treeEntry.pageId);", + " pm.collectionVariables.set(\"personalization\", treeEntry.personalization);", + " pm.collectionVariables.set(\"relationType\", treeEntry.relationType);", + " pm.collectionVariables.set(\"treeOrder\", treeEntry.treeOrder);", + " pm.collectionVariables.set(\"variantId\", treeEntry.variantId);", + " found = true;", + " }", + "", + " });", + " if (!found) {", + " pm.expect.fail(\"Expected test Contentlet with ID '\" + testContentId + \"' was not found\");", + " }", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/{{pageIdentifier}}/content/tree", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{pageIdentifier}}", + "content", + "tree" + ] + } + }, + "response": [] + }, + { + "name": "In-Place Copy Of Test Contentlet", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"HTTP Status code must be 200\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.entity.title).to.equal(\"textContent\");", + " pm.collectionVariables.set(\"copiedRichContentIdentifier\", jsonData.entity.identifier);", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"containerId\": \"{{containerId}}\",\n \"contentId\": \"{{contentId}}\",\n \"pageId\": \"{{pageId}}\",\n \"personalization\": \"{{personalization}}\",\n \"relationType\": \"{{relationType}}\",\n \"treeOrder\": \"{{treeOrder}}\",\n \"variantId\": \"{{variantId}}\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/copyContent", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "copyContent" + ] + } + }, + "response": [] + }, + { + "name": "Check Multitree Data After In-Place Copy", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Checking that duplicate Contentlet has replaced the existing one\", function () {", + " var entity = pm.response.json().entity;", + "", + " var containerId = pm.collectionVariables.get(\"containerId\");", + " var contentId = pm.collectionVariables.get(\"copiedRichContentIdentifier\");", + " var pageId = pm.collectionVariables.get(\"pageId\");", + " var personalization = pm.collectionVariables.get(\"personalization\");", + " var relationType = pm.collectionVariables.get(\"relationType\");", + " var variantId = pm.collectionVariables.get(\"variantId\");", + " ", + " var found = false;", + " entity.forEach((treeEntry) => {", + "", + " if (contentId == treeEntry.contentId) {", + " found = true;", + " pm.expect(treeEntry.containerId).to.eql(containerId);", + " pm.expect(treeEntry.contentId).to.eql(contentId);", + " pm.expect(treeEntry.pageId).to.eql(pageId);", + " pm.expect(treeEntry.personalization).to.eql(personalization);", + " pm.expect(treeEntry.relationType).to.eql(relationType);", + " pm.expect(treeEntry.variantId).to.eql(variantId);", + " }", + "", + " });", + " if (!found) {", + " pm.expect.fail(\"Copied test Contentlet with ID '\" + contentId + \"' was not found\");", + " }", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/{{pageIdentifier}}/content/tree", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{pageIdentifier}}", + "content", + "tree" + ] + } + }, + "response": [] + }, + { + "name": "Copy Non-Existing Contentlet", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Checking that the error message is present\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.message).not.eq(\"\");", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"containerId\": \"{{containerId}}\",\n \"contentId\": \"{{contentId}}xxx\",\n \"pageId\": \"{{pageId}}\",\n \"personalization\": \"{{personalization}}\",\n \"relationType\": \"{{relationType}}\",\n \"treeOrder\": \"{{treeOrder}}\",\n \"variantId\": \"{{variantId}}\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/copyContent", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "copyContent" + ] + } + }, + "response": [] + }, + { + "name": "Copy Contentlet to Non-Existing Container", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Checking that the error message is present\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.message).not.eq(\"\");", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"containerId\": \"{{containerId}}xx\",\n \"contentId\": \"{{contentId}}\",\n \"pageId\": \"{{pageId}}\",\n \"personalization\": \"{{personalization}}\",\n \"relationType\": \"{{relationType}}\",\n \"treeOrder\": \"{{treeOrder}}\",\n \"variantId\": \"{{variantId}}\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/copyContent", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "copyContent" + ] + } + }, + "response": [] + }, + { + "name": "Deep-Clone Test Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Validate page has been copied\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.entity.title).to.equal(\"testPageCopy\");", + " pm.collectionVariables.set(\"pageDeepCopyIdentifier\", jsonData.entity.identifier);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/{{pageIdentifier}}/_deepcopy", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{pageIdentifier}}", + "_deepcopy" + ] + } + }, + "response": [] + }, + { + "name": "Check Multi-Tree Data For Deep-Copied Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Checking Multi-Tree data Deep-Copied Page\", function () {", + " var jsonData = pm.response.json();", + " var containerId = pm.collectionVariables.get(\"containerId\");", + " var contentId = pm.collectionVariables.get(\"contentId\");", + " var pageId = pm.collectionVariables.get(\"pageId\");", + " var personalization = pm.collectionVariables.get(\"personalization\");", + " var relationType = pm.collectionVariables.get(\"relationType\");", + "", + " pm.expect(jsonData.entity[0].containerId).to.eql(containerId);", + " pm.expect(jsonData.entity[0].contentId).to.not.eql(contentId);", + " pm.expect(jsonData.entity[0].pageId).to.not.eql(pageId);", + " pm.expect(jsonData.entity[0].personalization).to.eql(personalization);", + " pm.expect(jsonData.entity[0].relationType).to.eql(relationType);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/{{pageDeepCopyIdentifier}}/content/tree", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{pageDeepCopyIdentifier}}", + "content", + "tree" + ] + } + }, + "response": [] + } + ], + "description": "This Test Collection verifies that the In-Place Contentlet Copy works correctly.\n\nThere are times where a given Contentlet is referenced by several pages. Sometimes, users just want to edit the Contentlet in one specific page without affecting they way such a Contentlet looks like in the other pages. This feature allows them to (1) create an exact copy of the Contentlet -- which replaces the existing one -- and (2) edit that copied Contentlet.", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"HTTP Status code must be 200 or 404\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 404]);", + "});" + ] + } + } + ] + }, + { + "name": "Number of Content References in Pages", + "item": [ + { + "name": "Get Default Site", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Getting 'default' Site ID\", function() {", + " var entity = pm.response.json().entity;", + " pm.collectionVariables.set(\"defaultSiteId\", entity.identifier);", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"siteName\": \"default\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/site/_byname", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "site", + "_byname" + ] + }, + "description": "Gets the Identifier of the \"default\" Site." + }, + "response": [] + }, + { + "name": "Create First Test Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"No page creation errors are present\", function() {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + " pm.collectionVariables.set(\"firstPageIdentifier\", jsonData.entity.identifier);", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "pm.collectionVariables.set(\"firstPageUrl\", \"first-test-page\" + Date.now());" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlet\": {\n \"contentType\": \"htmlpageasset\",\n \"title\": \"First Test Page\",\n \"url\": \"{{firstPageUrl}}\",\n \"hostFolder\": \"default\",\n \"template\": \"SYSTEM_TEMPLATE\",\n \"friendlyName\": \"First Test Page\",\n \"cachettl\": 0\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH?indexPolicy=WAIT_FOR", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ], + "query": [ + { + "key": "indexPolicy", + "value": "WAIT_FOR" + } + ] + } + }, + "response": [] + }, + { + "name": "Create Test Rich Text Contentlet", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"No contentlet creation errors are present\", function() {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + " pm.collectionVariables.set(\"richContentIdentifier\", jsonData.entity.identifier);", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlet\": {\n \"contentType\": \"webPageContent\",\n \"title\": \"Test Content\",\n \"contentHost\": \"default\",\n \"body\": \"Text Content Body\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH?indexPolicy=WAIT_FOR", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ], + "query": [ + { + "key": "indexPolicy", + "value": "WAIT_FOR" + } + ] + } + }, + "response": [] + }, + { + "name": "Add Test Contentlet To First Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"No contentlet addition errors are present\", function() {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "[\n {\n \"identifier\": \"SYSTEM_CONTAINER\",\n \"uuid\": \"1\",\n \"contentletsId\": [\n \"{{richContentIdentifier}}\"\n ]\n }\n]", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/{{firstPageIdentifier}}/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{firstPageIdentifier}}", + "content" + ] + } + }, + "response": [] + }, + { + "name": "Check Property in First Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Only one Contentlet must be present\", function() {", + " var entity = pm.response.json().entity;", + " var contentletList = entity.containers.SYSTEM_CONTAINER.contentlets[\"uuid-1\"];", + " pm.expect(contentletList.length).to.eql(1);", + "});", + "", + "pm.test(\"Check the 'onNumberOfPages' property in the test Contentlet map in first Page\", function() {", + " var entity = pm.response.json().entity;", + " var contentlet = entity.containers.SYSTEM_CONTAINER.contentlets[\"uuid-1\"][0];", + " pm.expect(contentlet.onNumberOfPages).to.eql(1, \"The 'onNumberOfPages' counter must be 1 at this point\");", + "});", + "", + "pm.test(\"The rendered section should contain data attribute 'data-dot-on-number-of-pages' for the contentlet object\", function() {", + " var entity = pm.response.json().entity;", + " var contentletData = entity.containers.SYSTEM_CONTAINER.rendered[\"uuid-1\"];", + " console.log(contentletData);", + " pm.expect(contentletData).includes(\"data-dot-on-number-of-pages\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/{{firstPageUrl}}?language_id=1&mode=EDIT_MODE&host_id={{defaultSiteId}}", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "{{firstPageUrl}}" + ], + "query": [ + { + "key": "language_id", + "value": "1" + }, + { + "key": "mode", + "value": "EDIT_MODE" + }, + { + "key": "host_id", + "value": "{{defaultSiteId}}" + } + ] + } + }, + "response": [] + }, + { + "name": "Create Second Test Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"No page creation errors are present\", function() {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + " pm.collectionVariables.set(\"secondPageIdentifier\", jsonData.entity.identifier);", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "pm.collectionVariables.set(\"secondPageUrl\", \"second-test-page\" + Date.now());" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlet\": {\n \"contentType\": \"htmlpageasset\",\n \"title\": \"Second Test Page\",\n \"url\": \"{{secondPageUrl}}\",\n \"hostFolder\": \"default\",\n \"template\": \"SYSTEM_TEMPLATE\",\n \"friendlyName\": \"Second Test Page\",\n \"cachettl\": 0\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH?indexPolicy=WAIT_FOR", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ], + "query": [ + { + "key": "indexPolicy", + "value": "WAIT_FOR" + } + ] + } + }, + "response": [] + }, + { + "name": "Add Test Contentlet To Second Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"No contentlet addition errors are present\", function() {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "[\n {\n \"identifier\": \"SYSTEM_CONTAINER\",\n \"uuid\": \"1\",\n \"contentletsId\": [\n \"{{richContentIdentifier}}\"\n ]\n }\n]", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/{{secondPageIdentifier}}/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{secondPageIdentifier}}", + "content" + ] + } + }, + "response": [] + }, + { + "name": "Check Property in Second Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Only one Contentlet must be present\", function() {", + " var entity = pm.response.json().entity;", + " var contentletList = entity.containers.SYSTEM_CONTAINER.contentlets[\"uuid-1\"];", + " pm.expect(contentletList.length).to.eql(1);", + "});", + "", + "pm.test(\"Check the 'onNumberOfPages' property in the test Contentlet map in second Page\", function() {", + " var entity = pm.response.json().entity;", + " var contentlet = entity.containers.SYSTEM_CONTAINER.contentlets[\"uuid-1\"][0];", + " pm.expect(contentlet.onNumberOfPages).to.eql(2, \"The 'onNumberOfPages' counter must be 2 at this point\");", + "});", + "", + "pm.test(\"The rendered section should contain data attribute 'data-dot-on-number-of-pages' for the contentlet object\", function() {", + " var entity = pm.response.json().entity;", + " var contentletData = entity.containers.SYSTEM_CONTAINER.rendered[\"uuid-1\"];", + " console.log(contentletData);", + " pm.expect(contentletData).includes(\"data-dot-on-number-of-pages\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/{{secondPageUrl}}?language_id=1&mode=EDIT_MODE&host_id={{defaultSiteId}}", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "{{secondPageUrl}}" + ], + "query": [ + { + "key": "language_id", + "value": "1" + }, + { + "key": "mode", + "value": "EDIT_MODE" + }, + { + "key": "host_id", + "value": "{{defaultSiteId}}" + } + ] + } + }, + "response": [] + } + ], + "description": "This Request Collection verifies that the \"onNumberOfPages\" property is added to the Page JSON response and calculated properly.\n\nThe \"onNumberOfPages\" provides the number of times that a given Contentlet is present in any HTML Page in dotCMS. This way, the Front-End Team can allow users to select whether they want to update that unique Contentlet, or if they want to (1) create a copy of it and (2) edit that new copy instead.", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"HTTP Status code must be 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "" + ] + } + } + ] + }, + { + "name": "Get Page Types", + "item": [ + { + "name": "Create new UrlMap Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "pm.test(\"No errors\", function () {", + " ", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + "});", + "", + "pm.collectionVariables.set(\"pageid\", jsonData.entity.identifier);", + "pm.collectionVariables.set(\"pagepath\", jsonData.entity.path);" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\n\t\"contentlet\": {\n\t\t\"contentType\":\"htmlpageasset\",\n \"title\":\"testPageCopy{{$randomBankAccount}}\",\n \"url\":\"testPageCopy{{$randomBankAccount}}\",\n \"hostFolder\":\"default\",\n \"template\":\"SYSTEM_TEMPLATE\",\n \"friendlyName\":\"testPageCopy{{$randomBankAccount}}\",\n \"cachettl\":0\n\t\t\n\t}\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH?indexPolicy=WAIT_FOR", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ], + "query": [ + { + "key": "indexPolicy", + "value": "WAIT_FOR" + } + ] + } + }, + "response": [] + }, + { + "name": "CreateNewTypeWithUrlMap", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "pm.test(\"Check response\", function () {", + " pm.expect(jsonData.entity[0].description).to.eql(\"My Structure\");", + "});", + "", + "pm.test(\"Validate that the 'errors' array is empty\", function () {", + " // Check that the 'errors' array is defined and its length is 0", + " pm.expect(jsonData.errors).to.be.an('array').that.is.empty;", + "});", + "", + "", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\"clazz\": \"com.dotcms.contenttype.model.type.SimpleContentType\",\n \"detailPage\": \"{{pageid}}\",\n \"urlMapPattern\": \"/blog/wasabi/{urlTitle}\",\n\t\"description\": \"My Structure\",\n\t\"defaultType\": false,\n\t\"system\": false,\n\t\"folder\": \"SYSTEM_FOLDER\",\n\t\"name\": \"TestTypeUrlMap{{$randomBankAccount}}\",\n\t\"variable\": \"TestTypeUrlMap{{$randomBankAccount}}\",\n\t\"host\": \"SYSTEM_HOST\",\n\t\"fixed\": false,\n \"icon\": \"testIcon\",\n \"sortOrder\": 3,\n\t\"fields\": [\n\t\t{\n\t\t\t\"clazz\": \"com.dotcms.contenttype.model.field.TextField\",\n\t\t\t\"indexed\": true,\n\t\t\t\"dataType\": \"TEXT\",\n\t\t\t\"readOnly\": false,\n\t\t\t\"required\": true,\n\t\t\t\"searchable\": true,\n\t\t\t\"listed\": true,\n\t\t\t\"sortOrder\": 2,\n\t\t\t\"unique\": false,\n\t\t\t\"name\": \"Name\",\n\t\t\t\"variable\": \"name\",\n\t\t\t\"fixed\": true\n\t\t}\n\t],\n \"workflow\":[\"d61a59e1-a49c-46f2-a929-db2b4bfa88b2\"]\n}\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/contenttype", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "contenttype" + ] + } + }, + "response": [] + }, + { + "name": "Create New Page Type", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "pm.test(\"Check response\", function () {", + " pm.expect(jsonData.entity[0].baseType).to.eql(\"HTMLPAGE\");", + "});", + "", + "pm.test(\"Validate that the 'errors' array is empty\", function () {", + " // Check that the 'errors' array is defined and its length is 0", + " pm.expect(jsonData.errors).to.be.an('array').that.is.empty;", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"defaultType\": false,\n \"icon\": null,\n \"fixed\": false,\n \"system\": false,\n \"clazz\": \"com.dotcms.contenttype.model.type.ImmutablePageContentType\",\n \"description\": \"\",\n \"host\": \"8a7d5e23-da1e-420a-b4f0-471e7da8ea2d\",\n \"folder\": \"SYSTEM_FOLDER\",\n \"name\": \"TestTypePage{{$randomBankAccount}}\",\n \"variable\": \"TestTypePage{{$randomBankAccount}}\"\n}\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/contenttype", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "contenttype" + ] + } + }, + "response": [] + }, + { + "name": "Get Types", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "pm.test(\"No errors\", function () {", + " ", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.entity.length).to.greaterThan(2);", + "", + " const urlMapType = jsonData.entity.filter(item => item.variable.startsWith('TestTypeUrlMap'))", + " const pageType = jsonData.entity.filter(item => item.variable.startsWith('TestTypePage'))", + "", + " pm.expect(urlMapType).to.not.eql(null);", + " pm.expect(pageType).to.not.eql(null);", + "});", + "", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "http://localhost:8080/api/v1/page/types", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "api", + "v1", + "page", + "types" + ] + } + }, + "response": [] + }, + { + "name": "Get Types Filtered", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "pm.test(\"No errors\", function () {", + " ", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.entity.length).to.greaterThan(1);", + "", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "http://localhost:8080/api/v1/page/types?filter=test", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "api", + "v1", + "page", + "types" + ], + "query": [ + { + "key": "filter", + "value": "test" + } + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ] + } + } + ] + }, + { + "name": "Permissions", + "item": [ + { + "name": "CallLogout", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Check response\", function () {", + " pm.expect(pm.response.text()).to.include(\"Logout successfully\");", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/logout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "logout" + ] + } + }, + "response": [] + }, + { + "name": "Create Test Page Permission", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Page created successfully\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + " pm.collectionVariables.set(\"pageIdentifier\", jsonData.entity.identifier);", + " pm.collectionVariables.set(\"host_id\", jsonData.entity.host);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const pagePost = Math.floor(Math.random()*100+1)", + "pm.globals.set(\"pagePost\", pagePost)" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\n\t\"contentlet\": {\n\t\t\"contentType\":\"htmlpageasset\",\n \"title\":\"testPagePermission{{pagePost}}\",\n \"url\":\"testPagePermission{{pagePost}}\",\n \"hostFolder\":\"default\",\n \"template\":\"SYSTEM_TEMPLATE\",\n \"friendlyName\":\"testPagePermission{{pagePost}}\",\n \"cachettl\":0\n\t\t\n\t}\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH?indexPolicy=WAIT_FOR", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ], + "query": [ + { + "key": "indexPolicy", + "value": "WAIT_FOR" + } + ] + } + }, + "response": [] + }, + { + "name": "CheckPermission", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Page created successfully\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + " pm.expect(jsonData.entity).to.eql(true);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"url\":\"/testPagePermission{{pagePost}}\",\n \"type\":\"READ\",\n \"language_id\":\"1\",\n \"host_id\":\"{{host_id}}\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/_check-permission", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "_check-permission" + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"HTTP Status code must be 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ] + } + } + ] + }, + { + "name": "Getting Available Workflow Actions In Page", + "item": [ + { + "name": "Find the Default Site ID", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Saving the Default Site's ID\", function () {", + " var entity = pm.response.json().entity;", + " pm.collectionVariables.set(\"host_id\", entity.identifier);", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"siteName\": \"default\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/site/_byname", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "site", + "_byname" + ] + } + }, + "response": [] + }, + { + "name": "Switch To Default Site", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Check that the Site has indeed switched to the 'default' Site\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.entity.hostSwitched).to.eql(true);", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/site/switch/{{host_id}}", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "site", + "switch", + "{{host_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Create a Test Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Check that the Test Page was created successfully\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + " pm.collectionVariables.set(\"pageIdentifier\", jsonData.entity.identifier);", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const pagePost = Math.floor(Math.random()*100+1)", + "pm.collectionVariables.set(\"pagePost2\", pagePost);" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlet\": {\n \"contentType\": \"htmlpageasset\",\n \"languageId\": 1,\n \"title\": \"testPageCopy{{pagePost2}}\",\n \"url\": \"testPageCopy{{pagePost2}}\",\n \"hostFolder\": \"{{host_id}}\",\n \"template\": \"SYSTEM_TEMPLATE\",\n \"friendlyName\": \"testPageCopy{{pagePost2}}\",\n \"cachettl\": 0,\n \"workflow\": [\n \"d61a59e1-a49c-46f2-a929-db2b4bfa88b2\"\n ]\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH?indexPolicy=WAIT_FOR", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ], + "query": [ + { + "key": "indexPolicy", + "value": "WAIT_FOR" + } + ] + } + }, + "response": [] + }, + { + "name": "Get Workflow Actions", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Check that Workflow Actions for the test HTML Page are available\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + " pm.expect(jsonData.entity.actions.length).to.greaterThan(0);", + " pm.expect(jsonData.entity.page.pageUrl).to.contains('testPageCopy');", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"host_id\":\"{{host_id}}\",\n \"url\":\"/testPageCopy{{pagePost2}}\",\n \"language_id\": \"1\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:8080/api/v1/page/actions", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "api", + "v1", + "page", + "actions" + ] + } + }, + "response": [] + } + ], + "description": "Retrieves the list of Workflow Actions that are availbale for a given HTML Page. These actions are basically the `Save`, `Publish`, `Archive`, or any other buttons you see in the Content Edit modal when you're creating or editing an HTML Page in the back-end.", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"HTTP Status code must be 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "" + ] + } + } + ] + }, + { + "name": "Check Languages for a Page", + "item": [ + { + "name": "Create Test Page in English", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Page created successfully\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + " pm.collectionVariables.set(\"pageIdentifier\", jsonData.entity.identifier);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const time = new Date().getTime();", + "pm.collectionVariables.set(\"testPageTitle\", \"My Test Page \" + time);", + "pm.collectionVariables.set(\"testPageUrl\", \"my-test-page-\" + time);" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlet\": {\n \"contentType\": \"htmlpageasset\",\n \"title\": \"{{testPageTitle}}\",\n \"url\": \"{{testPageUrl}}\",\n \"hostFolder\": \"default\",\n \"template\": \"SYSTEM_TEMPLATE\",\n \"friendlyName\": \"{{testPageTitle}}\",\n \"cachettl\": 0\n }\n}\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH?indexPolicy=WAIT_FOR", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ], + "query": [ + { + "key": "indexPolicy", + "value": "WAIT_FOR" + } + ] + } + }, + "response": [] + }, + { + "name": "Check page translation only in English", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Check that the test HTML Page is available in English, no matter how many languages there are\", function () {", + " const entity = pm.response.json().entity;", + " var isTranslated = false;", + " entity.forEach(function(lang) {", + " if (1 == lang.id && lang.translated) {", + " isTranslated = true;", + " }", + " });", + " pm.expect(isTranslated).to.be.equal(true, 'The test page must be available in English');", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/{{pageIdentifier}}/languages", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{pageIdentifier}}", + "languages" + ] + } + }, + "response": [] + } + ], + "description": "These requests are aimed to test the REST Endpoint that takes a Page ID, returns all Languages in the current instance and, for each of them, includes an additional attribute that indicates whether such a page is available in that specific language or not.", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"HTTP Status code must be 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ] + } + } + ] + }, + { + "name": "Checking JSON Attributes", + "item": [ + { + "name": "Checking Page Audit Attributes", + "item": [ + { + "name": "Retrieving HTML Page Data", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Checking that audit properties are present\", function () {", + " var entity = pm.response.json().entity.page;", + " ", + " pm.expect(entity.creationDate).to.not.equal(undefined, \"The 'creationDate' attribute must be present\");", + " pm.expect(entity.owner).to.not.equal(undefined, \"The 'owner' attribute must be present\");", + " pm.expect(entity.ownerName).to.not.equal(undefined, \"The 'ownerName' attribute must be present\");", + " pm.expect(entity.modDate).to.not.equal(undefined, \"The 'modDate' attribute must be present\");", + " pm.expect(entity.modUser).to.not.equal(undefined, \"The 'modUser' attribute must be present\");", + " pm.expect(entity.modUserName).to.not.equal(undefined, \"The 'modUserName' attribute must be present\");", + " pm.expect(entity.publishDate).to.not.equal(undefined, \"The 'publishDate' attribute must be present\");", + " pm.expect(entity.publishUser).to.not.equal(undefined, \"The 'publishUser' attribute must be present\");", + " pm.expect(entity.publishUserName).to.not.equal(undefined, \"The 'publishUserName' attribute must be present\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/json/destinations/costa-rica", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "json", + "destinations", + "costa-rica" + ] + }, + "description": "http://localhost:8080/api/v1/page/json/{page-url}" + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"HTTP Status code must be 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "" + ] + } + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "Moving layout not impact Contentlet position BUG", + "item": [ + { + "name": "Create a Content Type", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "", + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.collectionVariables.set(\"contentTypeIdMovingLayoutBUG\", jsonData.entity[0].id);", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"defaultType\":false,\n \"icon\":null,\n \"fixed\":false,\n \"system\":false,\n \"clazz\":\"com.dotcms.contenttype.model.type.ImmutableSimpleContentType\",\n \"description\":\"\",\n \"host\":\"8a7d5e23-da1e-420a-b4f0-471e7da8ea2d\",\n \"folder\":\"SYSTEM_FOLDER\",\n \"name\":\"CT1 Moving Layout BUG\",\n \"systemActionMappings\":{\"NEW\":\"\"},\n \"workflow\":[\"d61a59e1-a49c-46f2-a929-db2b4bfa88b2\"]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/contenttype", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "contenttype" + ] + } + }, + "response": [] + }, + { + "name": "Add Field to Content Type Copy", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"layout\":[\n {\"divider\":{\n \"clazz\":\"com.dotcms.contenttype.model.field.ImmutableRowField\",\n \"contentTypeId\":\"{{contentTypeIdMovingLayoutBUG}}\",\n \"dataType\":\"SYSTEM\",\n \"fieldContentTypeProperties\":[],\n \"fieldType\":\"Row\",\n \"fieldTypeLabel\":\"Row\",\n \"fieldVariables\":[],\n \"fixed\":false,\n \"iDate\":1667572217000,\n \"indexed\":false,\n \"listed\":false,\n \"modDate\":1667572217000,\n \"name\":\"Row Field\",\n \"readOnly\":false,\n \"required\":false,\n \"searchable\":false,\n \"sortOrder\":-1,\n \"unique\":false},\n \"columns\":[\n {\n \"columnDivider\":{\n \"clazz\":\"com.dotcms.contenttype.model.field.ImmutableColumnField\",\n \"dataType\":\"SYSTEM\",\n \"fieldContentTypeProperties\":[],\n \"fieldType\":\"Column\",\n \"fieldTypeLabel\":\"Column\",\n \"fieldVariables\":[],\n \"fixed\":false,\n \"iDate\":1667572217000,\n \"indexed\":false,\n \"listed\":false,\n \"modDate\":1667572217000,\n \"name\":\"Column Field\",\n \"readOnly\":false,\n \"required\":false,\n \"searchable\":false,\n \"sortOrder\":-1,\n \"unique\":false\n },\n \"fields\":[\n {\n \"clazz\":\"com.dotcms.contenttype.model.field.ImmutableTextField\",\n \"name\":\"title\",\n \"dataType\":\"TEXT\",\n \"regexCheck\":\"\",\n \"defaultValue\":\"\",\n \"hint\":\"\",\n \"required\":false,\n \"searchable\":false,\n \"indexed\":false,\n \"listed\":false,\n \"unique\":false,\n \"id\":null\n }\n ]\n }\n ]\n }\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v3/contenttype/{{contentTypeIdMovingLayoutBUG}}/fields/move", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v3", + "contenttype", + "{{contentTypeIdMovingLayoutBUG}}", + "fields", + "move" + ] + } + }, + "response": [] + }, + { + "name": "Create Container C1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "", + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.collectionVariables.set(\"containerIdMovingLayoutBUG\", jsonData.entity.identifier);", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"title\": \"C1 Moving Layout BUG\",\n \"friendlyName\": \"cContainer used on the test for Moving Layout BUF\",\n \"maxContentlets\": 1,\n \"containerStructures\": [{\n \"structureId\": \"{{contentTypeIdMovingLayoutBUG}}\",\n \"maxContentlets\": 1,\n \"code\": \"$!{dotContentMap.title}\"\n }]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/containers", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "containers" + ] + } + }, + "response": [] + }, + { + "name": "Create Template T1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "", + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.collectionVariables.set(\"tamplateIdMovingLayoutBUG\", jsonData.entity.identifier);", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\t\t\n \"layout\":{\n \"body\":{\n \"rows\":[\n {\n \"styleClass\":\"\",\n \"columns\":[\n {\n \"styleClass\":\"\",\n \"leftOffset\":1,\n \"width\":12,\n \"containers\":[\n {\"identifier\":\"{{containerIdMovingLayoutBUG}}\"}\n ]\n }\n ]\n },\n {\n \"styleClass\":\"\",\n \"columns\":[\n {\n \"styleClass\":\"\",\n \"leftOffset\":1,\n \"width\":12,\n \"containers\":[\n {\"identifier\":\"{{containerIdMovingLayoutBUG}}\"}\n ]\n }\n ]\n }\n ]\n } \n },\n \"friendlyName\": \"\",\n \"title\": \"T1 MovingLayoutBUG\",\n \"theme\": \"SYSTEM_THEME\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/templates", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "templates" + ] + } + }, + "response": [] + }, + { + "name": "Create page P1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "", + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.collectionVariables.set(\"p1IdMovingLayoutBUG\", jsonData.entity.identifier);", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{ \n \"contentlet\" : {\n \"title\" : \"P1 MovingLayoutBUG\",\n \"languageId\" : 1,\n \"stInode\": \"c541abb1-69b3-4bc5-8430-5e09e5239cc8\",\n \"url\": \"P1_MovingLayoutBUG\",\n \"hostFolder\": \"8a7d5e23-da1e-420a-b4f0-471e7da8ea2d\",\n \"template\": \"{{tamplateIdMovingLayoutBUG}}\",\n \"cachettl\": 0,\n \"friendlyName\": \"friendlyName\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + } + }, + "response": [] + }, + { + "name": "Create contentlet A", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "", + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.collectionVariables.set(\"contentAId\", jsonData.entity.identifier);", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{ \n \"contentlet\" : {\n \"title\" : \"A\",\n \"languageId\" : 1,\n \"stInode\": \"{{contentTypeIdMovingLayoutBUG}}\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + } + }, + "response": [] + }, + { + "name": "Create contentlet B", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "", + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.collectionVariables.set(\"contentBId\", jsonData.entity.identifier);", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{ \n \"contentlet\" : {\n \"title\" : \"B\",\n \"languageId\" : 1,\n \"stInode\": \"{{contentTypeIdMovingLayoutBUG}}\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + } + }, + "response": [] + }, + { + "name": "Add A and B into P1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Variants with correct weight\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "[\n {\n \"contentletsId\": [\"{{contentAId}}\"],\n \"identifier\": \"{{containerIdMovingLayoutBUG}}\",\n \"uuid\": \"1\" \n },\n {\n \"contentletsId\": [\"{{contentBId}}\"],\n \"identifier\": \"{{containerIdMovingLayoutBUG}}\",\n \"uuid\": \"2\" \n } \n]\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/{{p1IdMovingLayoutBUG}}/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{p1IdMovingLayoutBUG}}", + "content" + ] + } + }, + "response": [] + }, + { + "name": "Create page P2", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "", + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.collectionVariables.set(\"p2IdMovingLayoutBUG\", jsonData.entity.identifier);", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{ \n \"contentlet\" : {\n \"title\" : \"P2 MovingLayoutBUG\",\n \"languageId\" : 1,\n \"stInode\": \"c541abb1-69b3-4bc5-8430-5e09e5239cc8\",\n \"url\": \"P2_MovingLayoutBUG\",\n \"hostFolder\": \"8a7d5e23-da1e-420a-b4f0-471e7da8ea2d\",\n \"template\": \"{{tamplateIdMovingLayoutBUG}}\",\n \"cachettl\": 0,\n \"friendlyName\": \"friendlyName\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + } + }, + "response": [] + }, + { + "name": "Add A and B into P2", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Variants with correct weight\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "[\n {\n \"contentletsId\": [\"{{contentAId}}\"],\n \"identifier\": \"{{containerIdMovingLayoutBUG}}\",\n \"uuid\": \"1\" \n },\n {\n \"contentletsId\": [\"{{contentBId}}\"],\n \"identifier\": \"{{containerIdMovingLayoutBUG}}\",\n \"uuid\": \"2\" \n } \n]\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/{{p2IdMovingLayoutBUG}}/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{p2IdMovingLayoutBUG}}", + "content" + ] + } + }, + "response": [] + }, + { + "name": "Move Containers in P1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Variants with correct weight\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"layout\": {\n \"width\": \"\",\n \"title\": \"t1-movinglayoutbug\",\n \"header\": false,\n \"footer\": false,\n \"body\": {\n \"rows\": [\n {\n \"columns\": [\n {\n \"containers\": [\n {\n \"identifier\": \"{{containerIdMovingLayoutBUG}}\",\n \"uuid\": \"2\"\n }\n ],\n \"leftOffset\": 1,\n \"width\": 12,\n \"styleClass\": \"\"\n }\n ],\n \"styleClass\": null\n },\n {\n \"columns\": [\n {\n \"containers\": [\n {\n \"identifier\": \"{{containerIdMovingLayoutBUG}}\",\n \"uuid\": \"1\"\n }\n ],\n \"leftOffset\": 1,\n \"width\": 12,\n \"styleClass\": \"\"\n }\n ],\n \"styleClass\": null\n }\n ]\n },\n \"sidebar\": null\n },\n \"title\": null\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/{{p1IdMovingLayoutBUG}}/layout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{p1IdMovingLayoutBUG}}", + "layout" + ] + } + }, + "response": [] + }, + { + "name": "Render P1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "", + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "var containerId = pm.collectionVariables.get(\"containerIdMovingLayoutBUG\");", + "var contentlets = jsonData.entity.containers[containerId].contentlets;", + "", + "pm.expect('B').to.equal(contentlets['uuid-1'][0].title);", + "pm.expect('A').to.equal(contentlets['uuid-2'][0].title);", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/P1_MovingLayoutBUG?host_id=8a7d5e23-da1e-420a-b4f0-471e7da8ea2d&language_id=1&mode=PREVIEW_MODE", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "P1_MovingLayoutBUG" + ], + "query": [ + { + "key": "host_id", + "value": "8a7d5e23-da1e-420a-b4f0-471e7da8ea2d" + }, + { + "key": "language_id", + "value": "1" + }, + { + "key": "mode", + "value": "PREVIEW_MODE" + } + ] + } + }, + "response": [] + }, + { + "name": "Render P2", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "", + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "var containerId = pm.collectionVariables.get(\"containerIdMovingLayoutBUG\");", + "var contentlets = jsonData.entity.containers[containerId].contentlets;", + "", + "pm.expect('A').to.equal(contentlets['uuid-1'][0].title);", + "pm.expect('B').to.equal(contentlets['uuid-2'][0].title);", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/P2_MovingLayoutBUG?host_id=8a7d5e23-da1e-420a-b4f0-471e7da8ea2d&language_id=1&mode=PREVIEW_MODE", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "P2_MovingLayoutBUG" + ], + "query": [ + { + "key": "host_id", + "value": "8a7d5e23-da1e-420a-b4f0-471e7da8ea2d" + }, + { + "key": "language_id", + "value": "1" + }, + { + "key": "mode", + "value": "PREVIEW_MODE" + } + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Put Create Page With CacheTTL 100", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "var jsonData = pm.response.json();", + "", + "pm.test(\"Identifier must contains path\", function () {", + " pm.expect(jsonData.entity.template).eq(\"SYSTEM_TEMPLATE\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "admin", + "type": "string" + }, + { + "key": "username", + "value": "admin@dotcms.com", + "type": "string" + }, + { + "key": "saveHelperData", + "type": "any" + }, + { + "key": "showPassword", + "value": false, + "type": "boolean" + } + ] + }, + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\"contentlet\":{\n\t\t\"stName\": \"htmlpageasset\",\n\t\t\"title\": \"PageAsset SystemTemplate\",\n \"url\": \"pageassetsystemtemplate\",\n \"friendlyName\":\"pageassetsystemtemplate\",\n \"template\": \"SYSTEM_TEMPLATE\",\n \"sortOrder\": \"0\",\n \"cachettl\": \"100\",\n \"hostFolder\":\"48190c8c-42c4-46af-8d1a-0cd5db894797\"\n\t}\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + } + }, + "response": [] + }, + { + "name": "invalidateSession", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Body matches string\", function () {", + " pm.expect(pm.response.text()).to.include(\"Logout successfully\");", + "});", + "", + "pm.environment.unset('jwt');", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/logout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "logout" + ] + } + }, + "response": [] + }, + { + "name": "Check Cache-Control", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Cache-Control is correct\", function () {", + " pm.response.to.be.header('Cache-Control','max-age=100');", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/pageassetsystemtemplate", + "host": [ + "{{serverURL}}" + ], + "path": [ + "pageassetsystemtemplate" + ] + } + }, + "response": [] + } + ], + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + " const serverURL = pm.environment.get('serverURL'); // Get the server URL from the environment variable", + " const apiUrl = `${serverURL}/api/v1/apitoken`; // Construct the full API URL", + "", + "// If we are unable to get the JWT we need to generate a new one", + " if (!pm.environment.get('jwt')) {", + " const username = pm.environment.get(\"user\");", + " const password = pm.environment.get(\"password\");", + " const basicAuth = Buffer.from(`${username}:${password}`).toString('base64');", + "", + "", + " const requestOptions = {", + " url: apiUrl,", + " method: \"POST\",", + " header: {", + " \"accept\": \"*/*\",", + " \"content-type\": \"application/json\",", + " \"Authorization\": `Basic ${basicAuth}`", + " },", + " body: {", + " mode: \"raw\",", + " raw: JSON.stringify({", + " \"expirationSeconds\": 7200,", + " \"userId\": \"dotcms.org.1\",", + " \"network\": \"0.0.0.0/0\",", + " \"claims\": {\"label\": \"postman-tests\"}", + " })", + " }", + " };", + "", + "", + " pm.sendRequest(requestOptions, function (err, response) {", + " if (err) {", + " console.log(err);", + " } else {", + " const jwt = response.json().entity.jwt;", + " pm.environment.set('jwt', jwt);", + " console.log(jwt);", + " }", + " });", + " }" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "key": "contentTypeIdMovingLayoutBUG", + "value": "" + }, + { + "key": "spanish_content_container_id", + "value": "" + }, + { + "key": "containerIdMovingLayoutBUG", + "value": "" + }, + { + "key": "tamplateIdMovingLayoutBUG", + "value": "" + }, + { + "key": "p1IdMovingLayoutBUG", + "value": "" + }, + { + "key": "contentAId", + "value": "" + }, + { + "key": "contentBId", + "value": "" + }, + { + "key": "p2IdMovingLayoutBUG", + "value": "" + }, + { + "key": "relatedContentTypeVarName", + "value": "" + }, + { + "key": "relationshipContentTypeId", + "value": "" + }, + { + "key": "relationshipContentTypeName", + "value": "" + }, + { + "key": "relationshipContentTypeVarName", + "value": "" + }, + { + "key": "imageContentIdentifier", + "value": "" + }, + { + "key": "contentImgIdentifier", + "value": "" + }, + { + "key": "contentRelationshipIdentifier", + "value": "" + }, + { + "key": "page_id", + "value": "" + }, + { + "key": "page_name", + "value": "" + } + ] +} \ No newline at end of file diff --git a/dotcms-postman/src/main/resources/postman/resources/PagesResourceTests.json b/dotcms-postman/src/main/resources/postman/resources/PagesResourceTests.json new file mode 100644 index 000000000000..fd72b5ac289c --- /dev/null +++ b/dotcms-postman/src/main/resources/postman/resources/PagesResourceTests.json @@ -0,0 +1,6817 @@ + +{ + "info": { + "_postman_id": "5d246a25-bf38-49f7-86c8-1fafb5d88b0f", + "name": "Page API - [api/v1/page]", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "30436704" + }, + "item": [ + { + "name": "CreateTestContext", + "item": [ + { + "name": "Delete Image ContentType", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/contenttype/id/2c46b6586c38852ac08a824a303ced80", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "contenttype", + "id", + "2c46b6586c38852ac08a824a303ced80" + ] + }, + "description": "Given a content type ID.\nExpect that code is 200.\nExpect content type is deleted successfully." + }, + "response": [] + }, + { + "name": "Delete Video ContentType", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/contenttype/id/c77450b834901a20c8193ef9d561ee5b", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "contenttype", + "id", + "c77450b834901a20c8193ef9d561ee5b" + ] + }, + "description": "Given a content type ID.\nExpect that code is 200.\nExpect content type is deleted successfully." + }, + "response": [] + }, + { + "name": "pre_ImportBundleWithContext", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Bundle uploaded sucessfully\", function () {", + " pm.response.to.have.status(200);", + "", + " var jsonData = pm.response.json();", + " console.log(jsonData);", + "", + " pm.expect(jsonData[\"bundleName\"]).to.eql(\"assets.tar.gz\");", + " pm.expect(jsonData[\"status\"]).to.eql(\"SUCCESS\");", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/octet-stream" + }, + { + "key": "Content-Disposition", + "value": "attachment" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "file", + "type": "file", + "src": "resources/GraphQL/assets.tar.gz" + } + ] + }, + "url": { + "raw": "{{serverURL}}/api/bundle/sync", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "bundle", + "sync" + ], + "query": [ + { + "key": "AUTH_TOKEN", + "value": "", + "disabled": true + } + ] + }, + "description": "Imports a Bundle that includes:\n* HTMLPage /blog/index\n* HTMLPage /blog/destinations/costa-rica\n* Contentlet [Blog] Ecotourism in Costa Rica\n* Blog Detail Page /blog/blog-detail" + }, + "response": [] + } + ], + "description": "Imports a Bundle that includes:\n* HTMLPage /blog/index\n* HTMLPage /blog/destinations/costa-rica\n* Contentlet [Blog] Ecotourism in Costa Rica\n* Blog Detail Page /blog/blog-detail", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "JSON [api/v1/page/json]", + "item": [ + { + "name": "Using Actual Page URIs", + "item": [ + { + "name": "Invalidate Session", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/logout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "logout" + ] + } + }, + "response": [] + }, + { + "name": "Get Page Metadata With Invalid User", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 401, Need credentials\", function () {", + " pm.response.to.have.status(401);", + "});", + "", + "", + "", + "pm.test(\"Response body matches\", function () {", + " pm.expect(pm.response.text()).to.eq(\"Invalid User\");", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/json/destinations/costa-rica", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "json", + "destinations", + "costa-rica" + ] + }, + "description": "Given no user, should return 401 and \"Invalid User\" message" + }, + "response": [] + }, + { + "name": "Switch to 'demo.dotcms.com'", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200 \", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Valid response\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.entity.hostSwitched).equal(true);", + "});", + "", + "pm.environment.set(\"forcePreRequestScript\", false);", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "pm.environment.set(\"forcePreRequestScript\", true);", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{serverURL}}/api/v1/site/switch/48190c8c-42c4-46af-8d1a-0cd5db894797", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "site", + "switch", + "48190c8c-42c4-46af-8d1a-0cd5db894797" + ] + } + }, + "response": [] + }, + { + "name": "Get Valid HTML Page Metadata", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "", + "", + "pm.test(\"Include template\", function () {", + " pm.expect(pm.response.text()).to.include(\"template\");", + "});", + "", + "pm.test(\"Include layout\", function () {", + " pm.expect(pm.response.text()).to.include(\"layout\");", + "});", + "", + "pm.test(\"Include Containers\", function () {", + " pm.expect(pm.response.text()).to.include(\"containers\");", + "});", + "", + "pm.test(\"'page' element includes all properties\", function () {", + " var jsonData = pm.response.json();", + " var page = jsonData[\"entity\"][\"page\"];", + " pm.expect(page[\"__icon__\"]).equal(\"pageIcon\");", + " pm.expect(page[\"archived\"], 'FAILED:[archived]').equal(false);", + " pm.expect(page[\"baseType\"]).equal(\"HTMLPAGE\");", + " pm.expect(page[\"cachettl\"]).equal(\"0\");", + " pm.expect(page[\"canEdit\"], 'FAILED:[canEdit]').equal(true);", + " pm.expect(page[\"canLock\"], 'FAILED:[canLock]').equal(true);", + " pm.expect(page[\"canRead\"], 'FAILED:[canRead]').equal(true);", + " pm.expect(page[\"deleted\"], 'FAILED:[deleted]').equal(false);", + " pm.expect(page[\"extension\"]).equal(\"page\");", + " pm.expect(page[\"folder\"]).equal(\"6c8a2ac4-36a7-4b01-b9c0-c2c1d91ddfdb\");", + " pm.expect(page[\"friendlyName\"]).equal(\"Costa Rica Rain Forest\");", + " pm.expect(page[\"hasLiveVersion\"], 'FAILED:[hasLiveVersion]').equal(true);", + " pm.expect(page[\"hasTitleImage\"], 'FAILED:[hasTitleImage]').equal(true);", + " pm.expect(page[\"host\"]).equal(\"48190c8c-42c4-46af-8d1a-0cd5db894797\");", + " pm.expect(page[\"hostName\"]).equal(\"demo.dotcms.com\");", + " ////", + " pm.expect(page[\"httpsRequired\"], 'FAILED:[httpsRequired]').equal(false);", + " pm.expect(page[\"identifier\"]).equal(\"bec7b960-a8bf-4f14-a22b-0d94caf217f0\");", + " pm.expect(page[\"image\"]).equal(\"/dA/bec7b960-a8bf-4f14-a22b-0d94caf217f0/image/costa-rica-tree-frog.jpg\");", + " pm.expect(page[\"imageContentAsset\"]).equal(\"bec7b960-a8bf-4f14-a22b-0d94caf217f0/image\");", + " pm.expect(page[\"inode\"]).not.equal(null)", + " pm.expect(page[\"isContentlet\"], 'FAILED:[isContentlet]').equal(true);", + " pm.expect(page[\"languageId\"]).equal(1);", + " pm.expect(page[\"live\"], 'FAILED:[live]').equal(true);", + " pm.expect(page[\"liveInode\"]).not.equal(null)", + " pm.expect(page[\"locked\"], 'FAILED:[locked]').equal(false);", + " pm.expect(page[\"mimeType\"]).equal(\"application/dotpage\");", + " pm.expect(page[\"modDate\"]).not.equal(null)", + " ///", + " pm.expect(page[\"modUser\"]).equal(\"system\");", + " pm.expect(page[\"modUserName\"]).equal(\"system user system user\");", + " pm.expect(page[\"name\"]).equal(\"costa-rica\");", + " pm.expect(page[\"owner\"]).equal(\"dotcms.org.1\");", + " pm.expect(page[\"pageURI\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"pageUrl\"]).equal(\"costa-rica\");", + " pm.expect(page[\"path\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"publishDate\"]).not.equal(null)", + " pm.expect(page[\"seoTitle\"]).equal(\"Costa Rica Travel Destinations\");", + " pm.expect(page[\"seodescription\"]).equal(\"Visit Costa Rica a rugged, rainforested Central American country with coastlines on the Caribbean and Pacific.\");", + " pm.expect(page[\"shortDescription\"]).equal(\"Costa Rica is a rugged, rainforested Central American country with coastlines on the Caribbean and Pacific. Costa Rica is known for its beaches, volcanoes, and biodiversity. Roughly a quarter of its area is made up of protected jungle, teeming with wildlife including spider monkeys and quetzal birds.\");", + " pm.expect(page[\"shortyLive\"]).not.equal(null)", + " //", + " pm.expect(page[\"shortyWorking\"]).not.equal(null)", + " pm.expect(page[\"sortOrder\"]).equal(0);", + " pm.expect(page[\"stInode\"]).equal(\"91812c8b-0441-4139-8d4d-7423cfb0e979\");", + " pm.expect(page[\"statusIcons\"]).equal(\"\");", + " pm.expect(page[\"tags\"]).equal(\"diving\");", + " pm.expect(page[\"template\"]).equal(\"0c556e37-99e0-4458-a2cd-d42cc7a11045\");", + " pm.expect(page[\"title\"]).equal(\"Costa Rica Rain Forest\");", + " pm.expect(page[\"titleImage\"]).equal(\"image\");", + " pm.expect(page[\"type\"]).equal(\"htmlpage\");", + " pm.expect(page[\"url\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"working\"], 'FAILED:[working]').equal(true);", + " pm.expect(page[\"workingInode\"]).not.equal(null)", + "", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/json/destinations/costa-rica", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "json", + "destinations", + "costa-rica" + ] + }, + "description": "http://localhost:8080/api/v1/page/json/{page-url}" + }, + "response": [] + }, + { + "name": "Invalidate Session", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/logout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "logout" + ] + } + }, + "response": [] + }, + { + "name": "Get Non-Existing HTML Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404);", + "});", + "", + "", + "", + "pm.test(\"Valid response\", function () {", + " pm.expect(pm.response.text()).to.include(\"Page \\'about-us/index2\\' not found\");", + "});", + "", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/json/about-us/index2", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "json", + "about-us", + "index2" + ] + } + }, + "response": [] + }, + { + "name": "Get Metadata From URL Map", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"No errors\", function () {", + " ", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + "});", + "", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "}); ", + "", + "pm.test(\"Has Rows and Columns\", function () {", + " ", + " var jsonData = pm.response.json();", + " ", + " pm.expect(jsonData.entity.layout.body.rows.length).to.equal(2);", + " pm.expect(jsonData.entity.layout.body.rows[0].columns.length).to.equal(1);", + " ", + "});", + "", + "pm.test(\"Number of Contents\", function () {", + " ", + " var jsonData = pm.response.json();", + " ", + " pm.expect(jsonData.entity.numberContents).to.equal(2);", + " ", + " ", + "});", + "", + "pm.test(\"Page checks\", function () {", + " ", + " var jsonData = pm.response.json();", + " ", + " pm.expect(jsonData.entity.page.pageURI).to.equal('/blog/index');", + " pm.expect(jsonData.entity.page.title).to.equal('Blogs');", + " pm.expect(jsonData.entity.page.type).to.equal('htmlpage');", + " ", + "});", + "", + "pm.test(\"Site checks\", function () {", + " ", + " var jsonData = pm.response.json();", + " ", + " pm.expect(jsonData.entity.site.hostname).to.equal('demo.dotcms.com');", + " pm.expect(jsonData.entity.site.type).to.equal('contentlet');", + " ", + "});", + "", + "pm.test(\"Template checks\", function () {", + " ", + " var jsonData = pm.response.json();", + " ", + " pm.expect(jsonData.entity.template.title).to.equal('anonymous_layout_1571406924828');", + " pm.expect(jsonData.entity.template.type).to.equal('template');", + " ", + "});", + "", + "pm.test(\"Contentlets checks\", function () {", + " ", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.entity.containers[\"//demo.dotcms.com/application/containers/default/\"].contentlets[\"uuid-1\"][0].title).to.equal('Travel Blog Header');", + " pm.expect(jsonData.entity.containers[\"//demo.dotcms.com/application/containers/default/\"].contentlets[\"uuid-1\"][0].contentType).to.equal('webPageContent');", + "});", + "", + "", + "", + "", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/json/blog/index", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "json", + "blog", + "index" + ] + }, + "description": "Gets an Url content map" + }, + "response": [] + } + ], + "description": "Tests calling the `json` method passing down the actual URI of an HTML Page.", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "Using Vanity URLs", + "item": [ + { + "name": "Create Test Forward Vanity URL", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Forward Vanity URL was created successfully\", function () {", + " var jsonData = pm.response.json().entity;", + " pm.expect(jsonData.summary.failCount).to.eql(0, \"An error occurred when creating the test Vanity URL\");", + " pm.expect(jsonData.summary.successCount).to.eql(1, \"One piece of content should have been created\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlets\": [\n {\n \"contentType\": \"Vanityurl\",\n \"languageId\": 1,\n \"title\": \"Test Forward Vanity URL\",\n \"site\": \"demo.dotcms.com\",\n \"uri\": \"/forward-json\",\n \"action\": 200,\n \"forwardTo\": \"/destinations/costa-rica\",\n \"order\": 0\n }\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + }, + "description": "Create the original Contentlet." + }, + "response": [] + }, + { + "name": "Create Test Temporary Redirect Vanity URL", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Temporary Redirect Vanity URL was created successfully\", function () {", + " var jsonData = pm.response.json().entity;", + " pm.expect(jsonData.summary.failCount).to.eql(0, \"An error occurred when creating the test Vanity URL\");", + " pm.expect(jsonData.summary.successCount).to.eql(1, \"One piece of content should have been created\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlets\": [\n {\n \"contentType\": \"Vanityurl\",\n \"languageId\": 1,\n \"title\": \"Test Temporary Vanity URL\",\n \"site\": \"demo.dotcms.com\",\n \"uri\": \"/temporary-json\",\n \"action\": 302,\n \"forwardTo\": \"/destinations/costa-rica\",\n \"order\": 0\n }\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + }, + "description": "Create the original Contentlet." + }, + "response": [] + }, + { + "name": "Create Test Permanent Redirect Vanity URL", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Permanent Redirect Vanity URL was created successfully\", function () {", + " var jsonData = pm.response.json().entity;", + " pm.expect(jsonData.summary.failCount).to.eql(0, \"An error occurred when creating the test Vanity URL\");", + " pm.expect(jsonData.summary.successCount).to.eql(1, \"One piece of content should have been created\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlets\": [\n {\n \"contentType\": \"Vanityurl\",\n \"languageId\": 1,\n \"title\": \"Test Permanent Vanity URL\",\n \"site\": \"demo.dotcms.com\",\n \"uri\": \"/permanent-json\",\n \"action\": 301,\n \"forwardTo\": \"/destinations/costa-rica\",\n \"order\": 0\n }\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + }, + "description": "Create the original Contentlet." + }, + "response": [] + }, + { + "name": "Get HTML Page Metadata - Forward", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Response body contains the 'uuid' attribute\", function () {", + " pm.expect(pm.response.text()).to.include(\"uuid\");", + "});", + "", + "pm.test(\"The 'page' element includes all the expected properties\", function () {", + " var jsonData = pm.response.json();", + " var page = jsonData[\"entity\"][\"page\"];", + " pm.expect(page[\"__icon__\"]).equal(\"pageIcon\");", + " pm.expect(page[\"archived\"], 'FAILED:[archived]').equal(false);", + " pm.expect(page[\"baseType\"]).equal(\"HTMLPAGE\");", + " pm.expect(page[\"cachettl\"]).equal(\"0\");", + " pm.expect(page[\"canEdit\"], 'FAILED:[canEdit]').equal(true);", + " pm.expect(page[\"canLock\"], 'FAILED:[canLock]').equal(true);", + " pm.expect(page[\"canRead\"], 'FAILED:[canRead]').equal(true);", + " pm.expect(page[\"deleted\"], 'FAILED:[deleted]').equal(false);", + " pm.expect(page[\"extension\"]).equal(\"page\");", + " pm.expect(page[\"folder\"]).equal(\"6c8a2ac4-36a7-4b01-b9c0-c2c1d91ddfdb\");", + " pm.expect(page[\"friendlyName\"]).equal(\"Costa Rica Rain Forest\");", + " pm.expect(page[\"hasLiveVersion\"], 'FAILED:[hasLiveVersion]').equal(true);", + " pm.expect(page[\"hasTitleImage\"], 'FAILED:[hasTitleImage]').equal(true);", + " pm.expect(page[\"host\"]).equal(\"48190c8c-42c4-46af-8d1a-0cd5db894797\");", + " pm.expect(page[\"hostName\"]).equal(\"demo.dotcms.com\");", + " ////", + " pm.expect(page[\"httpsRequired\"], 'FAILED:[httpsRequired]').equal(false);", + " pm.expect(page[\"identifier\"]).equal(\"bec7b960-a8bf-4f14-a22b-0d94caf217f0\");", + " pm.expect(page[\"image\"]).equal(\"/dA/bec7b960-a8bf-4f14-a22b-0d94caf217f0/image/costa-rica-tree-frog.jpg\");", + " pm.expect(page[\"imageContentAsset\"]).equal(\"bec7b960-a8bf-4f14-a22b-0d94caf217f0/image\");", + " pm.expect(page[\"inode\"]).not.equal(null)", + " pm.expect(page[\"isContentlet\"], 'FAILED:[isContentlet]').equal(true);", + " pm.expect(page[\"languageId\"]).equal(1);", + " pm.expect(page[\"live\"], 'FAILED:[live]').equal(true);", + " pm.expect(page[\"liveInode\"]).not.equal(null)", + " pm.expect(page[\"locked\"], 'FAILED:[locked]').equal(false);", + " pm.expect(page[\"mimeType\"]).equal(\"application/dotpage\");", + " pm.expect(page[\"modDate\"]).not.equal(null)", + " ///", + " pm.expect(page[\"modUser\"]).equal(\"system\");", + " pm.expect(page[\"modUserName\"]).equal(\"system user system user\");", + " pm.expect(page[\"name\"]).equal(\"costa-rica\");", + " pm.expect(page[\"owner\"]).equal(\"dotcms.org.1\");", + " pm.expect(page[\"pageURI\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"pageUrl\"]).equal(\"costa-rica\");", + " pm.expect(page[\"path\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"publishDate\"]).not.equal(null)", + " pm.expect(page[\"seoTitle\"]).equal(\"Costa Rica Travel Destinations\");", + " pm.expect(page[\"seodescription\"]).equal(\"Visit Costa Rica a rugged, rainforested Central American country with coastlines on the Caribbean and Pacific.\");", + " pm.expect(page[\"shortDescription\"]).equal(\"Costa Rica is a rugged, rainforested Central American country with coastlines on the Caribbean and Pacific. Costa Rica is known for its beaches, volcanoes, and biodiversity. Roughly a quarter of its area is made up of protected jungle, teeming with wildlife including spider monkeys and quetzal birds.\");", + " pm.expect(page[\"shortyLive\"]).not.equal(null)", + " //", + " pm.expect(page[\"shortyWorking\"]).not.equal(null)", + " pm.expect(page[\"sortOrder\"]).equal(0);", + " pm.expect(page[\"stInode\"]).equal(\"91812c8b-0441-4139-8d4d-7423cfb0e979\");", + " pm.expect(page[\"statusIcons\"]).equal(\"\");", + " pm.expect(page[\"tags\"]).equal(\"diving\");", + " pm.expect(page[\"template\"]).equal(\"0c556e37-99e0-4458-a2cd-d42cc7a11045\");", + " pm.expect(page[\"title\"]).equal(\"Costa Rica Rain Forest\");", + " pm.expect(page[\"titleImage\"]).equal(\"image\");", + " pm.expect(page[\"type\"]).equal(\"htmlpage\");", + " pm.expect(page[\"url\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"working\"], 'FAILED:[working]').equal(true);", + " pm.expect(page[\"workingInode\"]).not.equal(null)", + "});", + "", + "pm.test(\"The 'Forward' Vanity URL data must be present\", function() {", + " var entity = pm.response.json().entity;", + " pm.expect(entity.vanityUrl).not.not.equal(undefined, \"The 'vanityUrl' attribute is missing\");", + " pm.expect(entity.vanityUrl.url).to.be.equal(\"/forward-json\", \"The 'url' attribute is NOT the expected one\");", + " pm.expect(entity.vanityUrl.response).to.be.equal(200, \"The 'response' attribute must be 200\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/json/forward-json", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "json", + "forward-json" + ] + } + }, + "response": [] + }, + { + "name": "Get HTML Page Metadata - Temporary Redirect", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"The 'Temporary Redirect' Vanity URL data must be present\", function() {", + " var entity = pm.response.json().entity;", + " pm.expect(entity.vanityUrl).to.not.equal(undefined, \"The 'vanityUrl' attribute must be present\");", + " pm.expect(entity.vanityUrl.response).to.be.equal(302, \"The 'response' attribute must be 302\");", + " pm.expect(entity.vanityUrl.temporaryRedirect).to.equal(true, \"The returned Vanity URL MUST be a temporary redirect\");", + " pm.expect(entity.vanityUrl.permanentRedirect).to.equal(false, \"The returned Vanity URL MUST NOT be a permanent redirect\");", + " pm.expect(entity.vanityUrl.forward).to.equal(false, \"The returned Vanity URL MUST NOT be a forward\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/json/temporary-json", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "json", + "temporary-json" + ] + } + }, + "response": [] + }, + { + "name": "Get HTML Page Metadata - Permanent Redirect", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"The 'Permanent Redirect' Vanity URL must be present\", function() {", + " var entity = pm.response.json().entity;", + " pm.expect(entity.vanityUrl).to.not.equal(undefined, \"The 'vanityUrl' attribute must be present\");", + " pm.expect(entity.vanityUrl.response).to.be.equal(301, \"The 'response' attribute must be 301\");", + " pm.expect(entity.vanityUrl.permanentRedirect).to.equal(true, \"The returned Vanity URL MUST be a permanent redirect\");", + " pm.expect(entity.vanityUrl.temporaryRedirect).to.equal(false, \"The returned Vanity URL MUST NOT be a temporary redirect\");", + " pm.expect(entity.vanityUrl.forward).to.equal(false, \"The returned Vanity URL MUST NOT be a forward\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/json/permanent-json", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "json", + "permanent-json" + ] + } + }, + "response": [] + } + ], + "description": "Tests calling the `json` method passing down a Vanity URL that references an HTML Page, using the three redirect options:\n\n1. Forward.\n \n2. Temporary Redirect.\n \n3. Permanent Redirect.", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"HTTP Status must be 200\", function() {", + " pm.response.to.have.status(200);", + "});", + "" + ] + } + } + ] + } + ], + "description": "Returns the metadata in JSON format of the objects that make up an HTML Page in the system.\n\nhttp://localhost:8080/api/v1/page/json/{page-url}", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "Render [api/v1/page/render]", + "item": [ + { + "name": "Using Actual Page URIs", + "item": [ + { + "name": "Invalidate Session", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/logout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "logout" + ] + } + }, + "response": [] + }, + { + "name": "Get Page Metadata With Invalid User", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 401, Need credentials\", function () {", + " pm.response.to.have.status(401);", + "});", + "", + "pm.test(\"Response body matches\", function () {", + " pm.expect(pm.response.text()).to.include(\"Invalid User\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/destinations/costa-rica", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "destinations", + "costa-rica" + ] + } + }, + "response": [] + }, + { + "name": "Switch to 'demo.dotcms.com'", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200 \", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Valid response\", function () {", + " var jsonData = pm.response.json();", + "", + " pm.expect(jsonData.entity.hostSwitched).equal(true);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{serverURL}}/api/v1/site/switch/48190c8c-42c4-46af-8d1a-0cd5db894797", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "site", + "switch", + "48190c8c-42c4-46af-8d1a-0cd5db894797" + ] + } + }, + "response": [] + }, + { + "name": "Get Valid HTML Page Metadata", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Response body contains\", function () {", + " pm.expect(pm.response.text()).to.include(\"rendered\");", + "});", + "", + "pm.test(\"Response body contains\", function () {", + " pm.expect(pm.response.text()).to.include(\"uuid\");", + "});", + "", + "pm.test(\"'page' element includes all properties\", function () {", + " var jsonData = pm.response.json();", + " var page = jsonData[\"entity\"][\"page\"];", + " pm.expect(page[\"__icon__\"]).equal(\"pageIcon\");", + " pm.expect(page[\"archived\"], 'FAILED:[archived]').equal(false);", + " pm.expect(page[\"baseType\"]).equal(\"HTMLPAGE\");", + " pm.expect(page[\"cachettl\"]).equal(\"0\");", + " pm.expect(page[\"canEdit\"], 'FAILED:[canEdit]').equal(true);", + " pm.expect(page[\"canLock\"], 'FAILED:[canLock]').equal(true);", + " pm.expect(page[\"canRead\"], 'FAILED:[canRead]').equal(true);", + " pm.expect(page[\"deleted\"], 'FAILED:[deleted]').equal(false);", + " pm.expect(page[\"extension\"]).equal(\"page\");", + " pm.expect(page[\"folder\"]).equal(\"6c8a2ac4-36a7-4b01-b9c0-c2c1d91ddfdb\");", + " pm.expect(page[\"friendlyName\"]).equal(\"Costa Rica Rain Forest\");", + " pm.expect(page[\"hasLiveVersion\"], 'FAILED:[hasLiveVersion]').equal(true);", + " pm.expect(page[\"hasTitleImage\"], 'FAILED:[hasTitleImage]').equal(true);", + " pm.expect(page[\"host\"]).equal(\"48190c8c-42c4-46af-8d1a-0cd5db894797\");", + " pm.expect(page[\"hostName\"]).equal(\"demo.dotcms.com\");", + " ////", + " pm.expect(page[\"httpsRequired\"], 'FAILED:[httpsRequired]').equal(false);", + " pm.expect(page[\"identifier\"]).equal(\"bec7b960-a8bf-4f14-a22b-0d94caf217f0\");", + " pm.expect(page[\"image\"]).equal(\"/dA/bec7b960-a8bf-4f14-a22b-0d94caf217f0/image/costa-rica-tree-frog.jpg\");", + " pm.expect(page[\"imageContentAsset\"]).equal(\"bec7b960-a8bf-4f14-a22b-0d94caf217f0/image\");", + " pm.expect(page[\"inode\"]).not.equal(null)", + " pm.expect(page[\"isContentlet\"], 'FAILED:[isContentlet]').equal(true);", + " pm.expect(page[\"languageId\"]).equal(1);", + " pm.expect(page[\"live\"], 'FAILED:[live]').equal(true);", + " pm.expect(page[\"liveInode\"]).not.equal(null)", + " pm.expect(page[\"locked\"], 'FAILED:[locked]').equal(false);", + " pm.expect(page[\"mimeType\"]).equal(\"application/dotpage\");", + " pm.expect(page[\"modDate\"]).not.equal(null)", + " ///", + " pm.expect(page[\"modUser\"]).equal(\"system\");", + " pm.expect(page[\"modUserName\"]).equal(\"system user system user\");", + " pm.expect(page[\"name\"]).equal(\"costa-rica\");", + " pm.expect(page[\"owner\"]).equal(\"dotcms.org.1\");", + " pm.expect(page[\"pageURI\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"pageUrl\"]).equal(\"costa-rica\");", + " pm.expect(page[\"path\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"publishDate\"]).not.equal(null)", + " pm.expect(page[\"seoTitle\"]).equal(\"Costa Rica Travel Destinations\");", + " pm.expect(page[\"seodescription\"]).equal(\"Visit Costa Rica a rugged, rainforested Central American country with coastlines on the Caribbean and Pacific.\");", + " pm.expect(page[\"shortDescription\"]).equal(\"Costa Rica is a rugged, rainforested Central American country with coastlines on the Caribbean and Pacific. Costa Rica is known for its beaches, volcanoes, and biodiversity. Roughly a quarter of its area is made up of protected jungle, teeming with wildlife including spider monkeys and quetzal birds.\");", + " pm.expect(page[\"shortyLive\"]).not.equal(null)", + " //", + " pm.expect(page[\"shortyWorking\"]).not.equal(null)", + " pm.expect(page[\"sortOrder\"]).equal(0);", + " pm.expect(page[\"stInode\"]).equal(\"91812c8b-0441-4139-8d4d-7423cfb0e979\");", + " pm.expect(page[\"statusIcons\"]).equal(\"\");", + " pm.expect(page[\"tags\"]).equal(\"diving\");", + " pm.expect(page[\"template\"]).equal(\"0c556e37-99e0-4458-a2cd-d42cc7a11045\");", + " pm.expect(page[\"title\"]).equal(\"Costa Rica Rain Forest\");", + " pm.expect(page[\"titleImage\"]).equal(\"image\");", + " pm.expect(page[\"type\"]).equal(\"htmlpage\");", + " pm.expect(page[\"url\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"working\"], 'FAILED:[working]').equal(true);", + " pm.expect(page[\"workingInode\"]).not.equal(null)", + "", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/destinations/costa-rica", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "destinations", + "costa-rica" + ] + } + }, + "response": [] + }, + { + "name": "Get Metadata From Non-Existing HTML Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404);", + "});", + "", + "", + "pm.test(\"Response body contains\", function () {", + " ", + " pm.expect( pm.response.json().message).to.eq(\"Page 'about-us/index2' not found\");", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/about-us/index2", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "about-us", + "index2" + ] + } + }, + "response": [] + }, + { + "name": "Reset workflow for contentlet", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200 \", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "", + "", + "pm.test(\"Correct identifier\", function () {", + " pm.expect(pm.response.json().entity.identifier).equal(\"57ee7cd3-66fc-4f01-9b7e-11e53553c220\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/2d1dc7718f/fire?identifier=57ee7cd3-66fc-4f01-9b7e-11e53553c220", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "2d1dc7718f", + "fire" + ], + "query": [ + { + "key": "identifier", + "value": "57ee7cd3-66fc-4f01-9b7e-11e53553c220" + } + ] + }, + "description": "The piece of content \"Ecoturism in Costarica\" gets somehow archived at this point after being imported in a previous bundle. This resets its workflow so it can be published in the next request" + }, + "response": [] + }, + { + "name": "Publish Archived Content", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200 \", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "", + "", + "pm.test(\"Correct identifier\", function () {", + " pm.expect(pm.response.json().entity.identifier).equal(\"57ee7cd3-66fc-4f01-9b7e-11e53553c220\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/175009d69e/fire?identifier=57ee7cd3-66fc-4f01-9b7e-11e53553c220", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "175009d69e", + "fire" + ], + "query": [ + { + "key": "identifier", + "value": "57ee7cd3-66fc-4f01-9b7e-11e53553c220" + } + ] + }, + "description": "This publishes the content `Ecotourism in Costa Rica` so it can be tested in the next request" + }, + "response": [] + }, + { + "name": "Get Metadata From URL Map", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"No errors\", function () {", + " ", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + "});", + "", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "}); ", + "", + "pm.test(\"Has Rows and Columns\", function () {", + " ", + " var jsonData = pm.response.json();", + " ", + " pm.expect(jsonData.entity.layout.body.rows.length).to.equal(1);", + " pm.expect(jsonData.entity.layout.body.rows[0].columns.length).to.equal(1);", + " ", + "});", + "", + "pm.test(\"Number of Contents\", function () {", + " ", + " var jsonData = pm.response.json();", + " ", + " pm.expect(jsonData.entity.numberContents).to.equal(1);", + " ", + " ", + "});", + "", + "pm.test(\"Page checks\", function () {", + " ", + " var jsonData = pm.response.json();", + " ", + " pm.expect(jsonData.entity.page.pageURI).to.equal('/blog/post/ecotourism-in-costa-rica');", + " pm.expect(jsonData.entity.page.title).to.equal('Blog Detail');", + " pm.expect(jsonData.entity.page.type).to.equal('htmlpage');", + " ", + "});", + "", + "pm.test(\"Site checks\", function () {", + " ", + " var jsonData = pm.response.json();", + " ", + " pm.expect(jsonData.entity.site.hostname).to.equal('demo.dotcms.com');", + " pm.expect(jsonData.entity.site.type).to.equal('contentlet');", + " ", + "});", + "", + "pm.test(\"Template checks\", function () {", + " ", + " var jsonData = pm.response.json();", + " ", + " pm.expect(jsonData.entity.template.title).to.equal('anonymous_layout_1582562696562');", + " pm.expect(jsonData.entity.template.type).to.equal('template');", + " ", + "});", + "", + "pm.test(\"Url Content Map checks\", function () {", + " ", + " var jsonData = pm.response.json();", + "", + " pm.expect(jsonData.entity.urlContentMap.hostName).to.equal('demo.dotcms.com');", + " pm.expect(jsonData.entity.urlContentMap.baseType).to.equal('CONTENT');", + " pm.expect(jsonData.entity.urlContentMap.contentType).to.equal('Blog');", + " pm.expect(jsonData.entity.urlContentMap.urlTitle).to.equal('ecotourism-in-costa-rica');", + " pm.expect(jsonData.entity.urlContentMap['URL_MAP_FOR_CONTENT']).to.equal('/blog/post/ecotourism-in-costa-rica');", + " pm.expect(jsonData.entity.urlContentMap['urlMap']).to.equal('/blog/post/ecotourism-in-costa-rica');", + "});", + "", + "", + "", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/blog/post/ecotourism-in-costa-rica?mode=EDIT_MODE", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "blog", + "post", + "ecotourism-in-costa-rica" + ], + "query": [ + { + "key": "mode", + "value": "EDIT_MODE" + } + ] + }, + "description": "Gets an Url content map" + }, + "response": [] + } + ], + "description": "Tests calling the `render` method passing down the actual URI of an HTML Page." + }, + { + "name": "Using Vanity URLs", + "item": [ + { + "name": "Create Test Forward Vanity URL", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Forward Vanity URL was created successfully\", function () {", + " var jsonData = pm.response.json().entity;", + " pm.expect(jsonData.summary.failCount).to.eql(0, \"An error occurred when creating the test Vanity URL\");", + " pm.expect(jsonData.summary.successCount).to.eql(1, \"One piece of content should have been created\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlets\": [\n {\n \"contentType\": \"Vanityurl\",\n \"languageId\": 1,\n \"title\": \"Test Forward Vanity URL\",\n \"site\": \"demo.dotcms.com\",\n \"uri\": \"/forward-render\",\n \"action\": 200,\n \"forwardTo\": \"/destinations/costa-rica\",\n \"order\": 0\n }\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + }, + "description": "Create the original Contentlet." + }, + "response": [] + }, + { + "name": "Create Test Temporary Redirect Vanity URL", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Temporary Redirect Vanity URL was created successfully\", function () {", + " var jsonData = pm.response.json().entity;", + " pm.expect(jsonData.summary.failCount).to.eql(0, \"An error occurred when creating the test Vanity URL\");", + " pm.expect(jsonData.summary.successCount).to.eql(1, \"One piece of content should have been created\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlets\": [\n {\n \"contentType\": \"Vanityurl\",\n \"languageId\": 1,\n \"title\": \"Test Temporary Vanity URL\",\n \"site\": \"demo.dotcms.com\",\n \"uri\": \"/temporary-render\",\n \"action\": 302,\n \"forwardTo\": \"/destinations/costa-rica\",\n \"order\": 0\n }\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + }, + "description": "Create the original Contentlet." + }, + "response": [] + }, + { + "name": "Create Test Permanent Redirect Vanity URL", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Permanent Redirect Vanity URL was created successfully\", function () {", + " var jsonData = pm.response.json().entity;", + " pm.expect(jsonData.summary.failCount).to.eql(0, \"An error occurred when creating the test Vanity URL\");", + " pm.expect(jsonData.summary.successCount).to.eql(1, \"One piece of content should have been created\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlets\": [\n {\n \"contentType\": \"Vanityurl\",\n \"languageId\": 1,\n \"title\": \"Test Permanent Vanity URL\",\n \"site\": \"demo.dotcms.com\",\n \"uri\": \"/permanent-render\",\n \"action\": 301,\n \"forwardTo\": \"/destinations/costa-rica\",\n \"order\": 0\n }\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + }, + "description": "Create the original Contentlet." + }, + "response": [] + }, + { + "name": "Get HTML Page Metadata - Forward", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Response body contains the 'rendered' attribute\", function () {", + " pm.expect(pm.response.text()).to.include(\"rendered\");", + "});", + "", + "pm.test(\"Response body contains the 'uuid' attribute\", function () {", + " pm.expect(pm.response.text()).to.include(\"uuid\");", + "});", + "", + "pm.test(\"The 'page' element includes all the expected properties\", function () {", + " var jsonData = pm.response.json();", + " var page = jsonData[\"entity\"][\"page\"];", + " pm.expect(page[\"__icon__\"]).equal(\"pageIcon\");", + " pm.expect(page[\"archived\"], 'FAILED:[archived]').equal(false);", + " pm.expect(page[\"baseType\"]).equal(\"HTMLPAGE\");", + " pm.expect(page[\"cachettl\"]).equal(\"0\");", + " pm.expect(page[\"canEdit\"], 'FAILED:[canEdit]').equal(true);", + " pm.expect(page[\"canLock\"], 'FAILED:[canLock]').equal(true);", + " pm.expect(page[\"canRead\"], 'FAILED:[canRead]').equal(true);", + " pm.expect(page[\"deleted\"], 'FAILED:[deleted]').equal(false);", + " pm.expect(page[\"extension\"]).equal(\"page\");", + " pm.expect(page[\"folder\"]).equal(\"6c8a2ac4-36a7-4b01-b9c0-c2c1d91ddfdb\");", + " pm.expect(page[\"friendlyName\"]).equal(\"Costa Rica Rain Forest\");", + " pm.expect(page[\"hasLiveVersion\"], 'FAILED:[hasLiveVersion]').equal(true);", + " pm.expect(page[\"hasTitleImage\"], 'FAILED:[hasTitleImage]').equal(true);", + " pm.expect(page[\"host\"]).equal(\"48190c8c-42c4-46af-8d1a-0cd5db894797\");", + " pm.expect(page[\"hostName\"]).equal(\"demo.dotcms.com\");", + " ////", + " pm.expect(page[\"httpsRequired\"], 'FAILED:[httpsRequired]').equal(false);", + " pm.expect(page[\"identifier\"]).equal(\"bec7b960-a8bf-4f14-a22b-0d94caf217f0\");", + " pm.expect(page[\"image\"]).equal(\"/dA/bec7b960-a8bf-4f14-a22b-0d94caf217f0/image/costa-rica-tree-frog.jpg\");", + " pm.expect(page[\"imageContentAsset\"]).equal(\"bec7b960-a8bf-4f14-a22b-0d94caf217f0/image\");", + " pm.expect(page[\"inode\"]).not.equal(null)", + " pm.expect(page[\"isContentlet\"], 'FAILED:[isContentlet]').equal(true);", + " pm.expect(page[\"languageId\"]).equal(1);", + " pm.expect(page[\"live\"], 'FAILED:[live]').equal(true);", + " pm.expect(page[\"liveInode\"]).not.equal(null)", + " pm.expect(page[\"locked\"], 'FAILED:[locked]').equal(false);", + " pm.expect(page[\"mimeType\"]).equal(\"application/dotpage\");", + " pm.expect(page[\"modDate\"]).not.equal(null)", + " ///", + " pm.expect(page[\"modUser\"]).equal(\"system\");", + " pm.expect(page[\"modUserName\"]).equal(\"system user system user\");", + " pm.expect(page[\"name\"]).equal(\"costa-rica\");", + " pm.expect(page[\"owner\"]).equal(\"dotcms.org.1\");", + " pm.expect(page[\"pageURI\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"pageUrl\"]).equal(\"costa-rica\");", + " pm.expect(page[\"path\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"publishDate\"]).not.equal(null)", + " pm.expect(page[\"seoTitle\"]).equal(\"Costa Rica Travel Destinations\");", + " pm.expect(page[\"seodescription\"]).equal(\"Visit Costa Rica a rugged, rainforested Central American country with coastlines on the Caribbean and Pacific.\");", + " pm.expect(page[\"shortDescription\"]).equal(\"Costa Rica is a rugged, rainforested Central American country with coastlines on the Caribbean and Pacific. Costa Rica is known for its beaches, volcanoes, and biodiversity. Roughly a quarter of its area is made up of protected jungle, teeming with wildlife including spider monkeys and quetzal birds.\");", + " pm.expect(page[\"shortyLive\"]).not.equal(null)", + " //", + " pm.expect(page[\"shortyWorking\"]).not.equal(null)", + " pm.expect(page[\"sortOrder\"]).equal(0);", + " pm.expect(page[\"stInode\"]).equal(\"91812c8b-0441-4139-8d4d-7423cfb0e979\");", + " pm.expect(page[\"statusIcons\"]).equal(\"\");", + " pm.expect(page[\"tags\"]).equal(\"diving\");", + " pm.expect(page[\"template\"]).equal(\"0c556e37-99e0-4458-a2cd-d42cc7a11045\");", + " pm.expect(page[\"title\"]).equal(\"Costa Rica Rain Forest\");", + " pm.expect(page[\"titleImage\"]).equal(\"image\");", + " pm.expect(page[\"type\"]).equal(\"htmlpage\");", + " pm.expect(page[\"url\"]).equal(\"/destinations/costa-rica\");", + " pm.expect(page[\"working\"], 'FAILED:[working]').equal(true);", + " pm.expect(page[\"workingInode\"]).not.equal(null)", + "});", + "", + "pm.test(\"The 'Forward' Vanity URL data must be present\", function() {", + " var entity = pm.response.json().entity;", + " pm.expect(entity.vanityUrl).not.not.equal(undefined, \"The 'vanityUrl' attribute is missing\");", + " pm.expect(entity.vanityUrl.url).to.be.equal(\"/forward-render\", \"The 'url' attribute is NOT the expected one\");", + " pm.expect(entity.vanityUrl.response).to.be.equal(200, \"The 'response' attribute must be 200\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/forward-render", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "forward-render" + ] + } + }, + "response": [] + }, + { + "name": "Get HTML Page Metadata - Temporary Redirect", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"The 'Temporary Redirect' Vanity URL data must be present\", function() {", + " var entity = pm.response.json().entity;", + " pm.expect(entity.vanityUrl).to.not.equal(undefined, \"The 'vanityUrl' attribute must be present\");", + " pm.expect(entity.vanityUrl.response).to.be.equal(302, \"The 'response' attribute must be 302\");", + " pm.expect(entity.vanityUrl.temporaryRedirect).to.equal(true, \"The returned Vanity URL MUST be a temporary redirect\");", + " pm.expect(entity.vanityUrl.permanentRedirect).to.equal(false, \"The returned Vanity URL MUST NOT be a permanent redirect\");", + " pm.expect(entity.vanityUrl.forward).to.equal(false, \"The returned Vanity URL MUST NOT be a forward\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/temporary-render", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "temporary-render" + ] + } + }, + "response": [] + }, + { + "name": "Get HTML Page Metadata - Permanent Redirect", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"The 'Permanent Redirect' Vanity URL must be present\", function() {", + " var entity = pm.response.json().entity;", + " pm.expect(entity.vanityUrl).to.not.equal(undefined, \"The 'vanityUrl' attribute must be present\");", + " pm.expect(entity.vanityUrl.response).to.be.equal(301, \"The 'response' attribute must be 301\");", + " pm.expect(entity.vanityUrl.permanentRedirect).to.equal(true, \"The returned Vanity URL MUST be a permanent redirect\");", + " pm.expect(entity.vanityUrl.temporaryRedirect).to.equal(false, \"The returned Vanity URL MUST NOT be a temporary redirect\");", + " pm.expect(entity.vanityUrl.forward).to.equal(false, \"The returned Vanity URL MUST NOT be a forward\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/permanent-render", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "permanent-render" + ] + } + }, + "response": [] + } + ], + "description": "Tests calling the `render` method passing down a Vanity URL that references an HTML Page, using the three redirect options:\n\n1. Forward.\n \n2. Temporary Redirect.\n \n3. Permanent Redirect.", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"HTTP Status must be 200\", function() {", + " pm.response.to.have.status(200);", + "});", + "", + "" + ] + } + } + ] + } + ] + }, + { + "name": "Layout [/api/v1/page/{page-id}/layout]", + "item": [ + { + "name": "invalidateSession", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/logout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "logout" + ] + } + }, + "response": [] + }, + { + "name": "GivenInvalidUser_ShouldReturn401", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 401, Need credentials\", function () {", + " pm.response.to.have.status(401);", + "});", + "", + "", + "", + "pm.test(\"Response body matches\", function () {", + " pm.expect(pm.response.text()).to.include(\"Invalid User\");", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\"title\":null,\"layout\":{\"body\":{\"rows\":[{\"columns\":[{\"leftOffset\":1,\"width\":7,\"containers\":[{\"identifier\":\"a050073a-a31e-4aab-9307-86bfb248096a\",\"uuid\":\"1\"}]},{\"leftOffset\":8,\"width\":4,\"containers\":[{\"identifier\":\"5363c6c6-5ba0-4946-b7af-cf875188ac2e\",\"uuid\":\"1\"}]}]}]},\"header\":true,\"footer\":true,\"sidebar\":{\"location\":\"\",\"containers\":[],\"width\":\"small\"}}}" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/bec7b960-a8bf-4f14-a22b-0d94caf217f0/layout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "bec7b960-a8bf-4f14-a22b-0d94caf217f0", + "layout" + ] + }, + "description": "@Path(\"/{pageId}/layout\")" + }, + "response": [] + }, + { + "name": "GivenValidLayout_ShouldSaveLayout", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Response code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Response body contains 'rendered'\", function () {", + " pm.expect(pm.response.text()).to.include(\"rendered\");", + "});", + "", + "var jsonData = pm.response.json();", + "", + "pm.test(\"'Containers' section contains expected containers\", function () {", + " var containers = jsonData[\"entity\"][\"containers\"];", + " pm.expect(containers[\"//demo.dotcms.com/application/containers/default/\"].container.identifier).equal(\"69b3d24d-7e80-4be6-b04a-d352d16493ee\");", + "", + " pm.expect(containers[\"5a07f889-4536-4956-aa6e-e7967969ec3f\"].container.identifier).equal(\"5a07f889-4536-4956-aa6e-e7967969ec3f\");", + "});", + "", + "", + "var layout = jsonData[\"entity\"][\"layout\"];", + "var rows = layout[\"body\"][\"rows\"];", + "var columns = layout[\"body\"][\"rows\"][0][\"columns\"];", + "pm.expect(columns.length).equal(2);", + "", + "// column 1 ", + "var column1 = columns[0];", + "var containersColumn1 = column1[\"containers\"];", + "", + "// column 2", + "var column2 = columns[1];", + "var containersColumn2 = column2[\"containers\"];", + "", + "", + "", + "pm.test(\"Layout has 1 row\", function () {", + " pm.expect(rows.length).equal(1);", + "});", + "", + "pm.test(\"First row has 2 columns\", function () {", + " pm.expect(columns.length).equal(2);", + "});", + "", + "pm.test(\"First column has width of 7 \", function () {", + " pm.expect(column1[\"width\"]).equal(7);", + "}); ", + "", + "pm.test(\"First column has 1 container with expected identifier\", function () {", + " pm.expect(containersColumn1.length).equal(1);", + " pm.expect(containersColumn1[0].identifier).equal(\"//demo.dotcms.com/application/containers/default/\");", + "}); ", + "", + "pm.test(\"Second column has width of 4 \", function () {", + " pm.expect(column2[\"width\"]).equal(4);", + "}); ", + "", + "pm.test(\"Second column has 1 container with expected identifier\", function () {", + " pm.expect(containersColumn2.length).equal(1);", + " pm.expect(containersColumn2[0].identifier).equal(\"5a07f889-4536-4956-aa6e-e7967969ec3f\");", + "}); ", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"title\": null,\n \"layout\": {\n \"body\": {\n \"rows\": [\n {\n \"columns\": [\n {\n \"leftOffset\": 1,\n \"width\": 7,\n \"containers\": [\n {\n \"identifier\": \"//demo.dotcms.com/application/containers/default/\", \n \"uuid\": \"1\"\n }\n ]\n },\n {\n \"leftOffset\": 8,\n \"width\": 4,\n \"containers\": [\n {\n \"identifier\": \"5a07f889-4536-4956-aa6e-e7967969ec3f\",\n \"uuid\": \"1\"\n }\n ]\n }\n ]\n }\n ]\n },\n \"header\": true,\n \"footer\": true,\n \"sidebar\": {\n \"location\": \"\",\n \"containers\": [],\n \"width\": \"small\"\n }\n }\n}" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/bec7b960-a8bf-4f14-a22b-0d94caf217f0/layout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "bec7b960-a8bf-4f14-a22b-0d94caf217f0", + "layout" + ] + }, + "description": "@Path(\"/{pageId}/layout\")" + }, + "response": [] + }, + { + "name": "GivenInvalidPageId_ShouldReturn404", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404);", + "});", + "", + "", + "", + "pm.test(\"Response body contains\", function () {", + " pm.expect(pm.response.text()).to.include(\"Unable to find page with Identifier: 2c12fe7e6-d338-49d5-973b-2d974d57015b\");", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\"title\":null,\"layout\":{\"body\":{\"rows\":[{\"columns\":[{\"leftOffset\":1,\"width\":7,\"containers\":[{\"identifier\":\"a050073a-a31e-4aab-9307-86bfb248096a\",\"uuid\":\"1\"}]},{\"leftOffset\":8,\"width\":4,\"containers\":[{\"identifier\":\"5363c6c6-5ba0-4946-b7af-cf875188ac2e\",\"uuid\":\"1\"}]}]}]},\"header\":true,\"footer\":true,\"sidebar\":{\"location\":\"\",\"containers\":[],\"width\":\"small\"}}}" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/2c12fe7e6-d338-49d5-973b-2d974d57015b/layout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "2c12fe7e6-d338-49d5-973b-2d974d57015b", + "layout" + ] + }, + "description": "@Path(\"/{pageId}/layout\")" + }, + "response": [] + }, + { + "name": "RequestWihoutParameters", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "", + "", + "pm.test(\"Response body contains\", function () {", + " pm.expect(pm.response.text()).to.include(\"required\");", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/bec7b960-a8bf-4f14-a22b-0d94caf217f0/layout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "bec7b960-a8bf-4f14-a22b-0d94caf217f0", + "layout" + ] + }, + "description": "@Path(\"/{pageId}/layout\")" + }, + "response": [] + }, + { + "name": "BadRequest", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "", + "", + "pm.test(\"Response body contains\", function () {", + " pm.expect(pm.response.text()).to.include(\"Unrecognized field\");", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\"2title\":null,\"layout\":{\"body\":{\"rows\":[{\"columns\":[{\"leftOffset\":1,\"width\":7,\"containers\":[{\"identifier\":\"a050073a-a31e-4aab-9307-86bfb248096a\",\"uuid\":\"1\"}]},{\"leftOffset\":8,\"width\":4,\"containers\":[{\"identifier\":\"5363c6c6-5ba0-4946-b7af-cf875188ac2e\",\"uuid\":\"1\"}]}]}]},\"header\":true,\"footer\":true,\"sidebar\":{\"location\":\"\",\"containers\":[],\"width\":\"small\"}}}" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/bec7b960-a8bf-4f14-a22b-0d94caf217f0/layout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "bec7b960-a8bf-4f14-a22b-0d94caf217f0", + "layout" + ] + }, + "description": "@Path(\"/{pageId}/layout\")" + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "Add Content [/api/v1/page/{page-id}/content]", + "item": [ + { + "name": "Test_RespectOrder", + "item": [ + { + "name": "ImportBundle", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Success import\", function () {", + " var jsonData = pm.response.json();", + " console.log(jsonData);", + " pm.expect(jsonData[\"status\"]).to.eql(\"SUCCESS\");", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/octet-stream" + }, + { + "key": "Content-Disposition", + "value": "attachment" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "file", + "type": "file", + "src": "resources/testRespectOrder_Bundle.tar.gz" + } + ] + }, + "url": { + "raw": "{{serverURL}}/api/bundle/sync", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "bundle", + "sync" + ], + "query": [ + { + "key": "AUTH_TOKEN", + "value": "", + "disabled": true + } + ] + }, + "description": "Imports a Bundle that includes:\n\n* Page (testRespectOrder)\n* 2 Content (testOrder1 and testOrder2)" + }, + "response": [] + }, + { + "name": "Get Page To Check Order", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Response reorder check\", function () {", + " pm.expect(pm.response.text()).to.include(\"

testOrder2

testOrder1

\");", + "", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/testrespectorder?language_id=1&host_id=8a7d5e23-da1e-420a-b4f0-471e7da8ea2d", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "testrespectorder" + ], + "query": [ + { + "key": "language_id", + "value": "1" + }, + { + "key": "host_id", + "value": "8a7d5e23-da1e-420a-b4f0-471e7da8ea2d" + } + ] + } + }, + "response": [] + }, + { + "name": "ReorderContents", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Response body contains\", function () {", + " pm.expect(pm.response.text()).to.include(\"ok\");", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "[{\"identifier\":\"//default/application/containers/system/\",\"uuid\":\"1\",\"contentletsId\":[\"ffba6c6b2e90ce4dcc2a553c6b860822\",\"844cdd64de4fd9418613b3b53f860c6f\"]}]" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/773c1d064bfedacf26986a67ee90b490/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "773c1d064bfedacf26986a67ee90b490", + "content" + ] + }, + "description": "Reorder the page contents." + }, + "response": [] + }, + { + "name": "Get Page To Check Reorder", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Response reorder check\", function () {", + " pm.expect(pm.response.text()).to.include(\"

testOrder1

testOrder2

\");", + "", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/testrespectorder?language_id=1&host_id=8a7d5e23-da1e-420a-b4f0-471e7da8ea2d", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "testrespectorder" + ], + "query": [ + { + "key": "language_id", + "value": "1" + }, + { + "key": "host_id", + "value": "8a7d5e23-da1e-420a-b4f0-471e7da8ea2d" + } + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "" + ] + } + } + ] + }, + { + "name": "invalidateSession", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/logout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "logout" + ] + } + }, + "response": [] + }, + { + "name": "UserAuthenticationValidation", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 401, Need credentials\", function () {", + " pm.response.to.have.status(401);", + "});", + "", + "pm.test(\"Response body matches\", function () {", + " pm.expect(pm.response.text()).to.include(\"Invalid User\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "[{\"identifier\":\"a050073a-a31e-4aab-9307-86bfb248096a\",\"uuid\":\"1\",\"contentletsId\":[\"767509b1-2392-4661-a16b-e0e31ce27719\",\"3c30df49-ea78-417a-93ce-631cd25bc66c\"]},{\"identifier\":\"5363c6c6-5ba0-4946-b7af-cf875188ac2e\",\"uuid\":\"1\",\"contentletsId\":[\"2efc77b4-a54f-479b-8a81-a133b9e6da04\",\"5aef0c62-b7d6-4805-9e7c-77a67f4822f3\",\"66d47ebf-7b11-4076-85b0-b6c8c373d000\"]}]" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/bec7b960-a8bf-4f14-a22b-0d94caf217f0/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "bec7b960-a8bf-4f14-a22b-0d94caf217f0", + "content" + ] + }, + "description": "@Path(\"{pageId}/content\")" + }, + "response": [] + }, + { + "name": "SuccessRequest", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Response body contains\", function () {", + " pm.expect(pm.response.text()).to.include(\"ok\");", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "[{\"identifier\":\"5a07f889-4536-4956-aa6e-e7967969ec3f\",\"uuid\":\"1\",\"contentletsId\":[\"d4ed1990-b151-42ca-9bca-0725b07260de\"]},{\"identifier\":\"//demo.dotcms.com/application/containers/default/\",\"uuid\":\"1\",\"contentletsId\":[\"f827c41a-5689-4733-b4d7-916d3a31c9c6\",\"7c9cb3a7-bb68-4fd0-b21d-03ec4be491a7\"]}]" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/bec7b960-a8bf-4f14-a22b-0d94caf217f0/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "bec7b960-a8bf-4f14-a22b-0d94caf217f0", + "content" + ] + }, + "description": "Adds Content to a Page, the container, template, page and contentlets are imported.\n\n7c9cb3a7-bb68-4fd0-b21d-03ec4be491a7 = container Banner\n7c9cb3a7-bb68-4fd0-b21d-03ec4be491a7e = Banner contentlet\n7c9cb3a7-bb68-4fd0-b21d-03ec4be491a7 = Container as File Default\nf827c41a-5689-4733-b4d7-916d3a31c9c6 = Rich Text Contentlet\n7c9cb3a7-bb68-4fd0-b21d-03ec4be491a7 = Widget Contentlet" + }, + "response": [] + }, + { + "name": "Save Contentlets Not Valid BadRequest 400", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "[{\"identifier\":\"5a07f889-4536-4956-aa6e-e7967969ec3f\",\"uuid\":\"1\",\"contentletsId\":[\"f827c41a-5689-4733-b4d7-916d3a31c9c6\"]}]" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/bec7b960-a8bf-4f14-a22b-0d94caf217f0/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "bec7b960-a8bf-4f14-a22b-0d94caf217f0", + "content" + ] + }, + "description": "@Path(\"{pageId}/content\")" + }, + "response": [] + }, + { + "name": "InvalidPageId", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404);", + "});", + "", + "pm.test(\"Response body contains\", function () {", + " pm.expect(pm.response.text()).to.include(\"Page '2c12fe7e6-d338-49d5-973b-2d974d57015b' not found\");", + "});", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "[{\"identifier\":\"a050073a-a31e-4aab-9307-86bfb248096a\",\"uuid\":\"1\",\"contentletsId\":[\"767509b1-2392-4661-a16b-e0e31ce27719\",\"3c30df49-ea78-417a-93ce-631cd25bc66c\"]},{\"identifier\":\"5363c6c6-5ba0-4946-b7af-cf875188ac2e\",\"uuid\":\"1\",\"contentletsId\":[\"2efc77b4-a54f-479b-8a81-a133b9e6da04\",\"5aef0c62-b7d6-4805-9e7c-77a67f4822f3\",\"66d47ebf-7b11-4076-85b0-b6c8c373d000\"]}]" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/2c12fe7e6-d338-49d5-973b-2d974d57015b/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "2c12fe7e6-d338-49d5-973b-2d974d57015b", + "content" + ] + }, + "description": "@Path(\"{pageId}/content\")" + }, + "response": [] + }, + { + "name": "RequestWihoutParameters", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Layout is required\", function () {", + " pm.expect(pm.response.text()).to.include(\"Layout is required\");", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/bec7b960-a8bf-4f14-a22b-0d94caf217f0/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "bec7b960-a8bf-4f14-a22b-0d94caf217f0", + "content" + ] + }, + "description": "@Path(\"{pageId}/content\")" + }, + "response": [] + }, + { + "name": "BadRequest", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response body contains\", function () {", + " pm.expect(pm.response.text()).to.include(\"Container id and uuid are required\");", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "[{\"id222\":\"a050073a-a31e-4aab-9307-86bfb248096a\",\"uuid\":\"1\",\"contentlets\":[\"767509b1-2392-4661-a16b-e0e31ce27719\",\"3c30df49-ea78-417a-93ce-631cd25bc66c\"]},{\"id\":\"5363c6c6-5ba0-4946-b7af-cf875188ac2e\",\"uuid22\":\"1\",\"contentlets\":[\"2efc77b4-a54f-479b-8a81-a133b9e6da04\",\"5aef0c62-b7d6-4805-9e7c-77a67f4822f3\",\"66d47ebf-7b11-4076-85b0-b6c8c373d000\"]}]" + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/bec7b960-a8bf-4f14-a22b-0d94caf217f0/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "bec7b960-a8bf-4f14-a22b-0d94caf217f0", + "content" + ] + }, + "description": "@Path(\"{pageId}/content\")" + }, + "response": [] + }, + { + "name": "Save Content Upsert Duplicated Containers Body", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Response body contains\", function () {", + " pm.expect(pm.response.text()).to.include(\"ok\");", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "[\n {\n \"identifier\":\"//demo.dotcms.com/application/containers/default/\",\n \"uuid\":\"1\",\n \"contentletsId\":[\"7c9cb3a7-bb68-4fd0-b21d-03ec4be491a7\"]\n },\n {\n \"identifier\":\"//demo.dotcms.com/application/containers/default/\",\n \"uuid\":\"1\",\n \"contentletsId\":[\"f827c41a-5689-4733-b4d7-916d3a31c9c6\"]\n },\n {\n \"identifier\":\"//demo.dotcms.com/application/containers/default/\",\n \"uuid\":\"1\",\n \"contentletsId\":[\"7c9cb3a7-bb68-4fd0-b21d-03ec4be491a7\"]\n }\n]", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/bec7b960-a8bf-4f14-a22b-0d94caf217f0/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "bec7b960-a8bf-4f14-a22b-0d94caf217f0", + "content" + ] + }, + "description": "This test is for when users make a request sending at the Body the same container and uuid diff times.\nThis will merge all those contentlets and save the page successfully." + }, + "response": [] + } + ], + "description": " @Path(\"{pageId}/content\")", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "Render HTML [/api/v1/page/renderHTML]", + "item": [ + { + "name": "invalidateSession", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/logout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "logout" + ] + } + }, + "response": [] + }, + { + "name": "UserAuthenticationValidation", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "pm.test(\"Status code is 401, Need credentials\", function () {", + " pm.response.to.have.status(401);", + "});", + "", + "pm.test(\"Invalid User\", function () {", + " pm.expect(pm.response.text()).to.include(\"Invalid User\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "noauth" + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/renderHTML/destinations/costa-rica", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "renderHTML", + "destinations", + "costa-rica" + ] + }, + "description": "@Path(\"/renderHTML/{uri: .*}\")" + }, + "response": [] + }, + { + "name": "pre_ImportBundleWithDemoHost", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Bundle uploaded sucessfully\", function () {", + " pm.response.to.have.status(200);", + "", + " var jsonData = pm.response.json();", + " console.log(jsonData);", + "", + " pm.expect(jsonData[\"bundleName\"]).to.eql(\"demo.dotcms.com.tar.gz\");", + " pm.expect(jsonData[\"status\"]).to.eql(\"SUCCESS\");", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/octet-stream" + }, + { + "key": "Content-Disposition", + "value": "attachment" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "file", + "type": "file", + "src": "resources/GraphQL/demo.dotcms.com.tar.gz" + } + ] + }, + "url": { + "raw": "{{serverURL}}/api/bundle/sync", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "bundle", + "sync" + ], + "query": [ + { + "key": "AUTH_TOKEN", + "value": "", + "disabled": true + } + ] + }, + "description": "Imports a Bundle that includes:\n* Imports demo.dotcms.com" + }, + "response": [] + }, + { + "name": "SuccessRequest", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"renders expected HTML only\", function () {", + " pm.expect(pm.response.text().startsWith(\"\")).to.be.true;", + " pm.expect(pm.response.text()).to.include(\"body id=\\\"costa-rica-rain-forest\\\"\");", + "});", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/renderHTML/destinations/costa-rica", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "renderHTML", + "destinations", + "costa-rica" + ] + }, + "description": "@Path(\"/renderHTML/{uri: .*}\")" + }, + "response": [] + }, + { + "name": "InvalidPageURL", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404);", + "});", + "", + "pm.test(\"Valid response\", function () {", + " pm.expect(pm.response.text()).to.include(\"Page \\'about-us/our-team/index2\\' not found\");", + "});", + "", + "", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/renderHTML/about-us/our-team/index2", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "renderHTML", + "about-us", + "our-team", + "index2" + ] + }, + "description": "@Path(\"/renderHTML/{uri: .*}\")" + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "Whats Changed", + "item": [ + { + "name": "pre_ImportBundle", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Bundle imported\", function () {", + " var jsonData = pm.response.json();", + " console.log(jsonData);", + "", + " pm.expect(jsonData[\"bundleName\"]).to.contains(\"testWhatsChanged\");", + " pm.expect(jsonData[\"status\"]).to.eql(\"SUCCESS\");", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "admin", + "type": "string" + }, + { + "key": "username", + "value": "admin@dotcms.com", + "type": "string" + }, + { + "key": "saveHelperData", + "type": "any" + }, + { + "key": "showPassword", + "value": false, + "type": "boolean" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/octet-stream" + }, + { + "key": "Content-Disposition", + "value": "attachment" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "file", + "type": "file", + "src": "resources/testWhatsChanged-01FTGYNEP672VF4KFRFWSX3RPT.tar.gz" + } + ] + }, + "url": { + "raw": "{{serverURL}}/api/bundle/sync", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "bundle", + "sync" + ], + "query": [ + { + "key": "AUTH_TOKEN", + "value": "", + "disabled": true + } + ] + }, + "description": "Imports a Bundle that includes: a page with content, the content has diff versions working and live" + }, + "response": [] + }, + { + "name": "Check Whats Changed Endpoint", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"There are diff between live and working page\", function () {", + " var jsonData = pm.response.json().entity;", + " pm.expect(jsonData[\"diff\"]).equal(true);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/8afe50bc66533c6f0ed7711d74654b80/render/versions", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "8afe50bc66533c6f0ed7711d74654b80", + "render", + "versions" + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ] + } + } + ] + }, + { + "name": "TestHostVariables", + "item": [ + { + "name": "Create new Site For Test Host Variables", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "pm.test(\"Host check\", function () {", + " pm.expect(jsonData.entity.siteName).to.eql('sitevariables.site.com');", + "});", + "", + "pm.collectionVariables.set(\"siteIdTestHost\", jsonData.entity.identifier);", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"siteName\":\"sitevariables.site.com\"\n\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/site", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "site" + ] + } + }, + "response": [] + }, + { + "name": "Publish Site", + "request": { + "method": "PUT", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/site/{{siteIdTestHost}}/_publish", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "site", + "{{siteIdTestHost}}", + "_publish" + ] + } + }, + "response": [] + }, + { + "name": "Add Site Variable", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "var jsonData = pm.response.json();", + "", + "pm.test(\"Host check\", function () {", + " pm.expect(jsonData.entity.key).to.eql('onevar1');", + "});", + "", + "pm.collectionVariables.set(\"sitevariableIdTestHost\", jsonData.entity.id);", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"siteId\":\"{{siteIdTestHost}}\",\n \"name\":\"onevar1\",\n \"key\":\"onevar1\",\n \"value\":\"onevar-value\"\n}\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/site/variable", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "site", + "variable" + ] + } + }, + "response": [] + }, + { + "name": "CreateNewContainer Test Host Variables", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"No errors\", function () {", + " ", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + "});", + "", + "pm.test(\"Information Saved Correctly\", function () {", + " ", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.entity.title).to.eql(\"TestContainerHostVariables\");", + " pm.expect(jsonData.entity.notes).to.eql(\"Notes\");", + " ", + " ", + "});", + "", + "var jsonData = pm.response.json();", + "pm.collectionVariables.set(\"containeridentifier\", jsonData.entity.identifier);", + "pm.collectionVariables.set(\"inode\", jsonData.entity.inode);", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"title\":\"TestContainerHostVariables\",\n \"friendlyName\":\"TestContainer description HostVariables\",\n \"maxContentlets\":1,\n \"notes\":\"Notes\",\n \"preLoop\":\"preLoop $host_variable.onevar1\",\n \"postLoop\":\"postLoop xxxx\",\n \"containerStructures\":[\n {\n \"structureId\":\"webPageContent\",\n \"code\":\"$title on container\"\n }\n ]\n\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/containers", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "containers" + ] + }, + "description": "Create a container" + }, + "response": [] + }, + { + "name": "SavePublishNewTemplateTestHostVariables", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "pm.test(\"live check\", function () {", + " pm.expect(jsonData.entity.live).to.eql(true);", + "});", + "", + "", + "pm.test(\"Title check\", function () {", + " pm.expect(jsonData.entity.title).to.eql('PostMan Test Save Publish Test Host Variables');", + "});", + "", + "pm.collectionVariables.set(\"templateIdToPublishedHost\", jsonData.entity.identifier);", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"title\":\"PostMan Test Save Publish Test Host Variables\",\n \"friendlyName\":\"This is a postman test description\",\n \"body\":\"#parseContainer('{{containeridentifier}}','1659543155955')\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/templates/_savepublish", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "templates", + "_savepublish" + ] + } + }, + "response": [] + }, + { + "name": "Create Page using the template", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "pm.test(\"Path check\", function () {", + " pm.expect(jsonData.entity.path).to.eql(\"/testpagehostvariables\");", + "});", + "", + "", + "", + "var jsonData = pm.response.json();", + "pm.collectionVariables.set(\"pageUrlHostVariablestest\", pm.response.json().path);", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"contentlet\": {\n \"contentType\": \"htmlpageasset\",\n \"hostFolder\": \"{{siteIdTestHost}}\",\n \"title\": \"Test Page Host variables\",\n \"url\": \"testpagehostvariables\",\n \"template\":\"{{templateIdToPublishedHost}}\",\n \"sortOrder\":1,\n \"cachettl\":\"0\",\n \"friendlyName\":\"testpagehostvariables\"\n\n }\n}" + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + }, + "description": "Fire any action using the actionId\n\nOptional: If you pass ?inode={inode}, you don't need body here.\n\n@Path(\"/actions/{actionId}/fire\")" + }, + "response": [] + }, + { + "name": "Test the host variables", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var text = pm.response.text();", + "", + "pm.test(\"Path check\", function () {", + " pm.expect(text).to.include(\"onevar-value\");", + "});", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/testpagehostvariables?language_id=1&host_id={{siteIdTestHost}}", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "testpagehostvariables" + ], + "query": [ + { + "key": "language_id", + "value": "1" + }, + { + "key": "host_id", + "value": "{{siteIdTestHost}}" + } + ] + } + }, + "response": [] + } + ], + "description": "1. This test creates a Host with two variables\n2. Creates a container with the generic contentlet and use this two variables\n3. Creates a template that uses this container\n4. creates a page that uses this page\n5. Check that the page exists.", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"Response code should be 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ] + } + } + ] + }, + { + "name": "In-Place Content Copy", + "item": [ + { + "name": "Create Test Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Page created successfully\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + " pm.collectionVariables.set(\"pageIdentifier\", jsonData.entity.identifier);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\n\t\"contentlet\": {\n\t\t\"contentType\":\"htmlpageasset\",\n \"title\":\"testPageCopy\",\n \"url\":\"testPageCopy\",\n \"hostFolder\":\"default\",\n \"template\":\"SYSTEM_TEMPLATE\",\n \"friendlyName\":\"testPageCopy\",\n \"cachettl\":0\n\t\t\n\t}\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH?indexPolicy=WAIT_FOR", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ], + "query": [ + { + "key": "indexPolicy", + "value": "WAIT_FOR" + } + ] + } + }, + "response": [] + }, + { + "name": "Create Test Rich Text Contentlet", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Rich Text created successfully\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + " pm.collectionVariables.set(\"richContentIdentifier\", jsonData.entity.identifier);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\n\t\"contentlet\": {\n\t\t\"contentType\":\"webPageContent\",\n \"title\":\"textContent\",\n \"contentHost\":\"default\",\n \"body\":\"Text Content Body\"\n \n\t}\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH?indexPolicy=WAIT_FOR", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ], + "query": [ + { + "key": "indexPolicy", + "value": "WAIT_FOR" + } + ] + } + }, + "response": [] + }, + { + "name": "Add Test Content To Test Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Content added to Test Page successfuly\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "[\n {\n \"identifier\": \"SYSTEM_CONTAINER\",\n \"uuid\": \"1\",\n \"contentletsId\": [\n \"{{richContentIdentifier}}\"\n ]\n }\n]", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/{{pageIdentifier}}/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{pageIdentifier}}", + "content" + ] + } + }, + "response": [] + }, + { + "name": "Check That Multi-Tree Data Is Correct", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Retrieving Multi-Tree data for test Contentlet\", function () {", + " var entity = pm.response.json().entity;", + " var testContentId = pm.collectionVariables.get(\"richContentIdentifier\");", + " var found = false;", + " entity.forEach((treeEntry) => {", + "", + " if (testContentId == treeEntry.contentId) {", + " pm.collectionVariables.set(\"containerId\", treeEntry.containerId);", + " pm.collectionVariables.set(\"contentId\", treeEntry.contentId);", + " pm.collectionVariables.set(\"pageId\", treeEntry.pageId);", + " pm.collectionVariables.set(\"personalization\", treeEntry.personalization);", + " pm.collectionVariables.set(\"relationType\", treeEntry.relationType);", + " pm.collectionVariables.set(\"treeOrder\", treeEntry.treeOrder);", + " pm.collectionVariables.set(\"variantId\", treeEntry.variantId);", + " found = true;", + " }", + "", + " });", + " if (!found) {", + " pm.expect.fail(\"Expected test Contentlet with ID '\" + testContentId + \"' was not found\");", + " }", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/{{pageIdentifier}}/content/tree", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{pageIdentifier}}", + "content", + "tree" + ] + } + }, + "response": [] + }, + { + "name": "In-Place Copy Of Test Contentlet", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"HTTP Status code must be 200\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.entity.title).to.equal(\"textContent\");", + " pm.collectionVariables.set(\"copiedRichContentIdentifier\", jsonData.entity.identifier);", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"containerId\": \"{{containerId}}\",\n \"contentId\": \"{{contentId}}\",\n \"pageId\": \"{{pageId}}\",\n \"personalization\": \"{{personalization}}\",\n \"relationType\": \"{{relationType}}\",\n \"treeOrder\": \"{{treeOrder}}\",\n \"variantId\": \"{{variantId}}\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/copyContent", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "copyContent" + ] + } + }, + "response": [] + }, + { + "name": "Check Multitree Data After In-Place Copy", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Checking that duplicate Contentlet has replaced the existing one\", function () {", + " var entity = pm.response.json().entity;", + "", + " var containerId = pm.collectionVariables.get(\"containerId\");", + " var contentId = pm.collectionVariables.get(\"copiedRichContentIdentifier\");", + " var pageId = pm.collectionVariables.get(\"pageId\");", + " var personalization = pm.collectionVariables.get(\"personalization\");", + " var relationType = pm.collectionVariables.get(\"relationType\");", + " var variantId = pm.collectionVariables.get(\"variantId\");", + " ", + " var found = false;", + " entity.forEach((treeEntry) => {", + "", + " if (contentId == treeEntry.contentId) {", + " found = true;", + " pm.expect(treeEntry.containerId).to.eql(containerId);", + " pm.expect(treeEntry.contentId).to.eql(contentId);", + " pm.expect(treeEntry.pageId).to.eql(pageId);", + " pm.expect(treeEntry.personalization).to.eql(personalization);", + " pm.expect(treeEntry.relationType).to.eql(relationType);", + " pm.expect(treeEntry.variantId).to.eql(variantId);", + " }", + "", + " });", + " if (!found) {", + " pm.expect.fail(\"Copied test Contentlet with ID '\" + contentId + \"' was not found\");", + " }", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/{{pageIdentifier}}/content/tree", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{pageIdentifier}}", + "content", + "tree" + ] + } + }, + "response": [] + }, + { + "name": "Copy Non-Existing Contentlet", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Checking that the error message is present\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.message).not.eq(\"\");", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"containerId\": \"{{containerId}}\",\n \"contentId\": \"{{contentId}}xxx\",\n \"pageId\": \"{{pageId}}\",\n \"personalization\": \"{{personalization}}\",\n \"relationType\": \"{{relationType}}\",\n \"treeOrder\": \"{{treeOrder}}\",\n \"variantId\": \"{{variantId}}\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/copyContent", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "copyContent" + ] + } + }, + "response": [] + }, + { + "name": "Copy Contentlet to Non-Existing Container", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Checking that the error message is present\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.message).not.eq(\"\");", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"containerId\": \"{{containerId}}xx\",\n \"contentId\": \"{{contentId}}\",\n \"pageId\": \"{{pageId}}\",\n \"personalization\": \"{{personalization}}\",\n \"relationType\": \"{{relationType}}\",\n \"treeOrder\": \"{{treeOrder}}\",\n \"variantId\": \"{{variantId}}\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/copyContent", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "copyContent" + ] + } + }, + "response": [] + }, + { + "name": "Deep-Clone Test Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Validate page has been copied\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.entity.title).to.equal(\"testPageCopy\");", + " pm.collectionVariables.set(\"pageDeepCopyIdentifier\", jsonData.entity.identifier);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/{{pageIdentifier}}/_deepcopy", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{pageIdentifier}}", + "_deepcopy" + ] + } + }, + "response": [] + }, + { + "name": "Check Multi-Tree Data For Deep-Copied Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Checking Multi-Tree data Deep-Copied Page\", function () {", + " var jsonData = pm.response.json();", + " var containerId = pm.collectionVariables.get(\"containerId\");", + " var contentId = pm.collectionVariables.get(\"contentId\");", + " var pageId = pm.collectionVariables.get(\"pageId\");", + " var personalization = pm.collectionVariables.get(\"personalization\");", + " var relationType = pm.collectionVariables.get(\"relationType\");", + "", + " pm.expect(jsonData.entity[0].containerId).to.eql(containerId);", + " pm.expect(jsonData.entity[0].contentId).to.not.eql(contentId);", + " pm.expect(jsonData.entity[0].pageId).to.not.eql(pageId);", + " pm.expect(jsonData.entity[0].personalization).to.eql(personalization);", + " pm.expect(jsonData.entity[0].relationType).to.eql(relationType);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/{{pageDeepCopyIdentifier}}/content/tree", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{pageDeepCopyIdentifier}}", + "content", + "tree" + ] + } + }, + "response": [] + } + ], + "description": "This Test Collection verifies that the In-Place Contentlet Copy works correctly.\n\nThere are times where a given Contentlet is referenced by several pages. Sometimes, users just want to edit the Contentlet in one specific page without affecting they way such a Contentlet looks like in the other pages. This feature allows them to (1) create an exact copy of the Contentlet -- which replaces the existing one -- and (2) edit that copied Contentlet.", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"HTTP Status code must be 200 or 404\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 404]);", + "});" + ] + } + } + ] + }, + { + "name": "Number of Content References in Pages", + "item": [ + { + "name": "Get Default Site", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Getting 'default' Site ID\", function() {", + " var entity = pm.response.json().entity;", + " pm.collectionVariables.set(\"defaultSiteId\", entity.identifier);", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"siteName\": \"default\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/site/_byname", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "site", + "_byname" + ] + }, + "description": "Gets the Identifier of the \"default\" Site." + }, + "response": [] + }, + { + "name": "Create First Test Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"No page creation errors are present\", function() {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + " pm.collectionVariables.set(\"firstPageIdentifier\", jsonData.entity.identifier);", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "pm.collectionVariables.set(\"firstPageUrl\", \"first-test-page\" + Date.now());" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlet\": {\n \"contentType\": \"htmlpageasset\",\n \"title\": \"First Test Page\",\n \"url\": \"{{firstPageUrl}}\",\n \"hostFolder\": \"default\",\n \"template\": \"SYSTEM_TEMPLATE\",\n \"friendlyName\": \"First Test Page\",\n \"cachettl\": 0\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH?indexPolicy=WAIT_FOR", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ], + "query": [ + { + "key": "indexPolicy", + "value": "WAIT_FOR" + } + ] + } + }, + "response": [] + }, + { + "name": "Create Test Rich Text Contentlet", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"No contentlet creation errors are present\", function() {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + " pm.collectionVariables.set(\"richContentIdentifier\", jsonData.entity.identifier);", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlet\": {\n \"contentType\": \"webPageContent\",\n \"title\": \"Test Content\",\n \"contentHost\": \"default\",\n \"body\": \"Text Content Body\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH?indexPolicy=WAIT_FOR", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ], + "query": [ + { + "key": "indexPolicy", + "value": "WAIT_FOR" + } + ] + } + }, + "response": [] + }, + { + "name": "Add Test Contentlet To First Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"No contentlet addition errors are present\", function() {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "[\n {\n \"identifier\": \"SYSTEM_CONTAINER\",\n \"uuid\": \"1\",\n \"contentletsId\": [\n \"{{richContentIdentifier}}\"\n ]\n }\n]", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/{{firstPageIdentifier}}/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{firstPageIdentifier}}", + "content" + ] + } + }, + "response": [] + }, + { + "name": "Check Property in First Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Only one Contentlet must be present\", function() {", + " var entity = pm.response.json().entity;", + " var contentletList = entity.containers.SYSTEM_CONTAINER.contentlets[\"uuid-1\"];", + " pm.expect(contentletList.length).to.eql(1);", + "});", + "", + "pm.test(\"Check the 'onNumberOfPages' property in the test Contentlet map in first Page\", function() {", + " var entity = pm.response.json().entity;", + " var contentlet = entity.containers.SYSTEM_CONTAINER.contentlets[\"uuid-1\"][0];", + " pm.expect(contentlet.onNumberOfPages).to.eql(1, \"The 'onNumberOfPages' counter must be 1 at this point\");", + "});", + "", + "pm.test(\"The rendered section should contain data attribute 'data-dot-on-number-of-pages' for the contentlet object\", function() {", + " var entity = pm.response.json().entity;", + " var contentletData = entity.containers.SYSTEM_CONTAINER.rendered[\"uuid-1\"];", + " console.log(contentletData);", + " pm.expect(contentletData).includes(\"data-dot-on-number-of-pages\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/{{firstPageUrl}}?language_id=1&mode=EDIT_MODE&host_id={{defaultSiteId}}", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "{{firstPageUrl}}" + ], + "query": [ + { + "key": "language_id", + "value": "1" + }, + { + "key": "mode", + "value": "EDIT_MODE" + }, + { + "key": "host_id", + "value": "{{defaultSiteId}}" + } + ] + } + }, + "response": [] + }, + { + "name": "Create Second Test Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"No page creation errors are present\", function() {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + " pm.collectionVariables.set(\"secondPageIdentifier\", jsonData.entity.identifier);", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "pm.collectionVariables.set(\"secondPageUrl\", \"second-test-page\" + Date.now());" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlet\": {\n \"contentType\": \"htmlpageasset\",\n \"title\": \"Second Test Page\",\n \"url\": \"{{secondPageUrl}}\",\n \"hostFolder\": \"default\",\n \"template\": \"SYSTEM_TEMPLATE\",\n \"friendlyName\": \"Second Test Page\",\n \"cachettl\": 0\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH?indexPolicy=WAIT_FOR", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ], + "query": [ + { + "key": "indexPolicy", + "value": "WAIT_FOR" + } + ] + } + }, + "response": [] + }, + { + "name": "Add Test Contentlet To Second Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"No contentlet addition errors are present\", function() {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "[\n {\n \"identifier\": \"SYSTEM_CONTAINER\",\n \"uuid\": \"1\",\n \"contentletsId\": [\n \"{{richContentIdentifier}}\"\n ]\n }\n]", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/{{secondPageIdentifier}}/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{secondPageIdentifier}}", + "content" + ] + } + }, + "response": [] + }, + { + "name": "Check Property in Second Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Only one Contentlet must be present\", function() {", + " var entity = pm.response.json().entity;", + " var contentletList = entity.containers.SYSTEM_CONTAINER.contentlets[\"uuid-1\"];", + " pm.expect(contentletList.length).to.eql(1);", + "});", + "", + "pm.test(\"Check the 'onNumberOfPages' property in the test Contentlet map in second Page\", function() {", + " var entity = pm.response.json().entity;", + " var contentlet = entity.containers.SYSTEM_CONTAINER.contentlets[\"uuid-1\"][0];", + " pm.expect(contentlet.onNumberOfPages).to.eql(2, \"The 'onNumberOfPages' counter must be 2 at this point\");", + "});", + "", + "pm.test(\"The rendered section should contain data attribute 'data-dot-on-number-of-pages' for the contentlet object\", function() {", + " var entity = pm.response.json().entity;", + " var contentletData = entity.containers.SYSTEM_CONTAINER.rendered[\"uuid-1\"];", + " console.log(contentletData);", + " pm.expect(contentletData).includes(\"data-dot-on-number-of-pages\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/{{secondPageUrl}}?language_id=1&mode=EDIT_MODE&host_id={{defaultSiteId}}", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "{{secondPageUrl}}" + ], + "query": [ + { + "key": "language_id", + "value": "1" + }, + { + "key": "mode", + "value": "EDIT_MODE" + }, + { + "key": "host_id", + "value": "{{defaultSiteId}}" + } + ] + } + }, + "response": [] + } + ], + "description": "This Request Collection verifies that the \"onNumberOfPages\" property is added to the Page JSON response and calculated properly.\n\nThe \"onNumberOfPages\" provides the number of times that a given Contentlet is present in any HTML Page in dotCMS. This way, the Front-End Team can allow users to select whether they want to update that unique Contentlet, or if they want to (1) create a copy of it and (2) edit that new copy instead.", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"HTTP Status code must be 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "" + ] + } + } + ] + }, + { + "name": "Get Page Types", + "item": [ + { + "name": "Create new UrlMap Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "pm.test(\"No errors\", function () {", + " ", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + "});", + "", + "pm.collectionVariables.set(\"pageid\", jsonData.entity.identifier);", + "pm.collectionVariables.set(\"pagepath\", jsonData.entity.path);" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\n\t\"contentlet\": {\n\t\t\"contentType\":\"htmlpageasset\",\n \"title\":\"testPageCopy{{$randomBankAccount}}\",\n \"url\":\"testPageCopy{{$randomBankAccount}}\",\n \"hostFolder\":\"default\",\n \"template\":\"SYSTEM_TEMPLATE\",\n \"friendlyName\":\"testPageCopy{{$randomBankAccount}}\",\n \"cachettl\":0\n\t\t\n\t}\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH?indexPolicy=WAIT_FOR", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ], + "query": [ + { + "key": "indexPolicy", + "value": "WAIT_FOR" + } + ] + } + }, + "response": [] + }, + { + "name": "CreateNewTypeWithUrlMap", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "pm.test(\"Check response\", function () {", + " pm.expect(jsonData.entity[0].description).to.eql(\"My Structure\");", + "});", + "", + "pm.test(\"Validate that the 'errors' array is empty\", function () {", + " // Check that the 'errors' array is defined and its length is 0", + " pm.expect(jsonData.errors).to.be.an('array').that.is.empty;", + "});", + "", + "", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\"clazz\": \"com.dotcms.contenttype.model.type.SimpleContentType\",\n \"detailPage\": \"{{pageid}}\",\n \"urlMapPattern\": \"/blog/wasabi/{urlTitle}\",\n\t\"description\": \"My Structure\",\n\t\"defaultType\": false,\n\t\"system\": false,\n\t\"folder\": \"SYSTEM_FOLDER\",\n\t\"name\": \"TestTypeUrlMap{{$randomBankAccount}}\",\n\t\"variable\": \"TestTypeUrlMap{{$randomBankAccount}}\",\n\t\"host\": \"SYSTEM_HOST\",\n\t\"fixed\": false,\n \"icon\": \"testIcon\",\n \"sortOrder\": 3,\n\t\"fields\": [\n\t\t{\n\t\t\t\"clazz\": \"com.dotcms.contenttype.model.field.TextField\",\n\t\t\t\"indexed\": true,\n\t\t\t\"dataType\": \"TEXT\",\n\t\t\t\"readOnly\": false,\n\t\t\t\"required\": true,\n\t\t\t\"searchable\": true,\n\t\t\t\"listed\": true,\n\t\t\t\"sortOrder\": 2,\n\t\t\t\"unique\": false,\n\t\t\t\"name\": \"Name\",\n\t\t\t\"variable\": \"name\",\n\t\t\t\"fixed\": true\n\t\t}\n\t],\n \"workflow\":[\"d61a59e1-a49c-46f2-a929-db2b4bfa88b2\"]\n}\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/contenttype", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "contenttype" + ] + } + }, + "response": [] + }, + { + "name": "Create New Page Type", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "pm.test(\"Check response\", function () {", + " pm.expect(jsonData.entity[0].baseType).to.eql(\"HTMLPAGE\");", + "});", + "", + "pm.test(\"Validate that the 'errors' array is empty\", function () {", + " // Check that the 'errors' array is defined and its length is 0", + " pm.expect(jsonData.errors).to.be.an('array').that.is.empty;", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"defaultType\": false,\n \"icon\": null,\n \"fixed\": false,\n \"system\": false,\n \"clazz\": \"com.dotcms.contenttype.model.type.ImmutablePageContentType\",\n \"description\": \"\",\n \"host\": \"8a7d5e23-da1e-420a-b4f0-471e7da8ea2d\",\n \"folder\": \"SYSTEM_FOLDER\",\n \"name\": \"TestTypePage{{$randomBankAccount}}\",\n \"variable\": \"TestTypePage{{$randomBankAccount}}\"\n}\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/contenttype", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "contenttype" + ] + } + }, + "response": [] + }, + { + "name": "Get Types", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "pm.test(\"No errors\", function () {", + " ", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.entity.length).to.greaterThan(2);", + "", + " const urlMapType = jsonData.entity.filter(item => item.variable.startsWith('TestTypeUrlMap'))", + " const pageType = jsonData.entity.filter(item => item.variable.startsWith('TestTypePage'))", + "", + " pm.expect(urlMapType).to.not.eql(null);", + " pm.expect(pageType).to.not.eql(null);", + "});", + "", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "http://localhost:8080/api/v1/page/types", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "api", + "v1", + "page", + "types" + ] + } + }, + "response": [] + }, + { + "name": "Get Types Filtered", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "pm.test(\"No errors\", function () {", + " ", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.entity.length).to.greaterThan(1);", + "", + "});", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "http://localhost:8080/api/v1/page/types?filter=test", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "api", + "v1", + "page", + "types" + ], + "query": [ + { + "key": "filter", + "value": "test" + } + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ] + } + } + ] + }, + { + "name": "Permissions", + "item": [ + { + "name": "CallLogout", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Check response\", function () {", + " pm.expect(pm.response.text()).to.include(\"Logout successfully\");", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/logout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "logout" + ] + } + }, + "response": [] + }, + { + "name": "Create Test Page Permission", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Page created successfully\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + " pm.collectionVariables.set(\"pageIdentifier\", jsonData.entity.identifier);", + " pm.collectionVariables.set(\"host_id\", jsonData.entity.host);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const pagePost = Math.floor(Math.random()*100+1)", + "pm.globals.set(\"pagePost\", pagePost)" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\n\t\"contentlet\": {\n\t\t\"contentType\":\"htmlpageasset\",\n \"title\":\"testPagePermission{{pagePost}}\",\n \"url\":\"testPagePermission{{pagePost}}\",\n \"hostFolder\":\"default\",\n \"template\":\"SYSTEM_TEMPLATE\",\n \"friendlyName\":\"testPagePermission{{pagePost}}\",\n \"cachettl\":0\n\t\t\n\t}\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH?indexPolicy=WAIT_FOR", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ], + "query": [ + { + "key": "indexPolicy", + "value": "WAIT_FOR" + } + ] + } + }, + "response": [] + }, + { + "name": "CheckPermission", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Page created successfully\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + " pm.expect(jsonData.entity).to.eql(true);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"url\":\"/testPagePermission{{pagePost}}\",\n \"type\":\"READ\",\n \"language_id\":\"1\",\n \"host_id\":\"{{host_id}}\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/_check-permission", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "_check-permission" + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"HTTP Status code must be 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ] + } + } + ] + }, + { + "name": "Getting Available Workflow Actions In Page", + "item": [ + { + "name": "Find the Default Site ID", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Saving the Default Site's ID\", function () {", + " var entity = pm.response.json().entity;", + " pm.collectionVariables.set(\"host_id\", entity.identifier);", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"siteName\": \"default\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/site/_byname", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "site", + "_byname" + ] + } + }, + "response": [] + }, + { + "name": "Switch To Default Site", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Check that the Site has indeed switched to the 'default' Site\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.entity.hostSwitched).to.eql(true);", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/site/switch/{{host_id}}", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "site", + "switch", + "{{host_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Create a Test Page", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Check that the Test Page was created successfully\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + " pm.collectionVariables.set(\"pageIdentifier\", jsonData.entity.identifier);", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const pagePost = Math.floor(Math.random()*100+1)", + "pm.collectionVariables.set(\"pagePost2\", pagePost);" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlet\": {\n \"contentType\": \"htmlpageasset\",\n \"languageId\": 1,\n \"title\": \"testPageCopy{{pagePost2}}\",\n \"url\": \"testPageCopy{{pagePost2}}\",\n \"hostFolder\": \"{{host_id}}\",\n \"template\": \"SYSTEM_TEMPLATE\",\n \"friendlyName\": \"testPageCopy{{pagePost2}}\",\n \"cachettl\": 0,\n \"workflow\": [\n \"d61a59e1-a49c-46f2-a929-db2b4bfa88b2\"\n ]\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH?indexPolicy=WAIT_FOR", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ], + "query": [ + { + "key": "indexPolicy", + "value": "WAIT_FOR" + } + ] + } + }, + "response": [] + }, + { + "name": "Get Workflow Actions", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Check that Workflow Actions for the test HTML Page are available\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + " pm.expect(jsonData.entity.actions.length).to.greaterThan(0);", + " pm.expect(jsonData.entity.page.pageUrl).to.contains('testPageCopy');", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"host_id\":\"{{host_id}}\",\n \"url\":\"/testPageCopy{{pagePost2}}\",\n \"language_id\": \"1\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:8080/api/v1/page/actions", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "api", + "v1", + "page", + "actions" + ] + } + }, + "response": [] + } + ], + "description": "Retrieves the list of Workflow Actions that are availbale for a given HTML Page. These actions are basically the `Save`, `Publish`, `Archive`, or any other buttons you see in the Content Edit modal when you're creating or editing an HTML Page in the back-end.", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"HTTP Status code must be 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "" + ] + } + } + ] + }, + { + "name": "Check Languages for a Page", + "item": [ + { + "name": "Create Test Page in English", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Test Page created successfully\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.errors.length).to.eql(0);", + " pm.collectionVariables.set(\"pageIdentifier\", jsonData.entity.identifier);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const time = new Date().getTime();", + "pm.collectionVariables.set(\"testPageTitle\", \"My Test Page \" + time);", + "pm.collectionVariables.set(\"testPageUrl\", \"my-test-page-\" + time);" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"contentlet\": {\n \"contentType\": \"htmlpageasset\",\n \"title\": \"{{testPageTitle}}\",\n \"url\": \"{{testPageUrl}}\",\n \"hostFolder\": \"default\",\n \"template\": \"SYSTEM_TEMPLATE\",\n \"friendlyName\": \"{{testPageTitle}}\",\n \"cachettl\": 0\n }\n}\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH?indexPolicy=WAIT_FOR", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ], + "query": [ + { + "key": "indexPolicy", + "value": "WAIT_FOR" + } + ] + } + }, + "response": [] + }, + { + "name": "Check page translation only in English", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Check that the test HTML Page is available in English, no matter how many languages there are\", function () {", + " const entity = pm.response.json().entity;", + " var isTranslated = false;", + " entity.forEach(function(lang) {", + " if (1 == lang.id && lang.translated) {", + " isTranslated = true;", + " }", + " });", + " pm.expect(isTranslated).to.be.equal(true, 'The test page must be available in English');", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/{{pageIdentifier}}/languages", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{pageIdentifier}}", + "languages" + ] + } + }, + "response": [] + } + ], + "description": "These requests are aimed to test the REST Endpoint that takes a Page ID, returns all Languages in the current instance and, for each of them, includes an additional attribute that indicates whether such a page is available in that specific language or not.", + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"HTTP Status code must be 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ] + } + } + ] + }, + { + "name": "Checking JSON Attributes", + "item": [ + { + "name": "Checking Page Audit Attributes", + "item": [ + { + "name": "Retrieving HTML Page Data", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Checking that audit properties are present\", function () {", + " var entity = pm.response.json().entity.page;", + " ", + " pm.expect(entity.creationDate).to.not.equal(undefined, \"The 'creationDate' attribute must be present\");", + " pm.expect(entity.owner).to.not.equal(undefined, \"The 'owner' attribute must be present\");", + " pm.expect(entity.ownerName).to.not.equal(undefined, \"The 'ownerName' attribute must be present\");", + " pm.expect(entity.modDate).to.not.equal(undefined, \"The 'modDate' attribute must be present\");", + " pm.expect(entity.modUser).to.not.equal(undefined, \"The 'modUser' attribute must be present\");", + " pm.expect(entity.modUserName).to.not.equal(undefined, \"The 'modUserName' attribute must be present\");", + " pm.expect(entity.publishDate).to.not.equal(undefined, \"The 'publishDate' attribute must be present\");", + " pm.expect(entity.publishUser).to.not.equal(undefined, \"The 'publishUser' attribute must be present\");", + " pm.expect(entity.publishUserName).to.not.equal(undefined, \"The 'publishUserName' attribute must be present\");", + "});", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/json/destinations/costa-rica", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "json", + "destinations", + "costa-rica" + ] + }, + "description": "http://localhost:8080/api/v1/page/json/{page-url}" + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"HTTP Status code must be 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "" + ] + } + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "Moving layout not impact Contentlet position BUG", + "item": [ + { + "name": "Create a Content Type", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "", + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.collectionVariables.set(\"contentTypeIdMovingLayoutBUG\", jsonData.entity[0].id);", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"defaultType\":false,\n \"icon\":null,\n \"fixed\":false,\n \"system\":false,\n \"clazz\":\"com.dotcms.contenttype.model.type.ImmutableSimpleContentType\",\n \"description\":\"\",\n \"host\":\"8a7d5e23-da1e-420a-b4f0-471e7da8ea2d\",\n \"folder\":\"SYSTEM_FOLDER\",\n \"name\":\"CT1 Moving Layout BUG\",\n \"systemActionMappings\":{\"NEW\":\"\"},\n \"workflow\":[\"d61a59e1-a49c-46f2-a929-db2b4bfa88b2\"]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/contenttype", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "contenttype" + ] + } + }, + "response": [] + }, + { + "name": "Add Field to Content Type Copy", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"layout\":[\n {\"divider\":{\n \"clazz\":\"com.dotcms.contenttype.model.field.ImmutableRowField\",\n \"contentTypeId\":\"{{contentTypeIdMovingLayoutBUG}}\",\n \"dataType\":\"SYSTEM\",\n \"fieldContentTypeProperties\":[],\n \"fieldType\":\"Row\",\n \"fieldTypeLabel\":\"Row\",\n \"fieldVariables\":[],\n \"fixed\":false,\n \"iDate\":1667572217000,\n \"indexed\":false,\n \"listed\":false,\n \"modDate\":1667572217000,\n \"name\":\"Row Field\",\n \"readOnly\":false,\n \"required\":false,\n \"searchable\":false,\n \"sortOrder\":-1,\n \"unique\":false},\n \"columns\":[\n {\n \"columnDivider\":{\n \"clazz\":\"com.dotcms.contenttype.model.field.ImmutableColumnField\",\n \"dataType\":\"SYSTEM\",\n \"fieldContentTypeProperties\":[],\n \"fieldType\":\"Column\",\n \"fieldTypeLabel\":\"Column\",\n \"fieldVariables\":[],\n \"fixed\":false,\n \"iDate\":1667572217000,\n \"indexed\":false,\n \"listed\":false,\n \"modDate\":1667572217000,\n \"name\":\"Column Field\",\n \"readOnly\":false,\n \"required\":false,\n \"searchable\":false,\n \"sortOrder\":-1,\n \"unique\":false\n },\n \"fields\":[\n {\n \"clazz\":\"com.dotcms.contenttype.model.field.ImmutableTextField\",\n \"name\":\"title\",\n \"dataType\":\"TEXT\",\n \"regexCheck\":\"\",\n \"defaultValue\":\"\",\n \"hint\":\"\",\n \"required\":false,\n \"searchable\":false,\n \"indexed\":false,\n \"listed\":false,\n \"unique\":false,\n \"id\":null\n }\n ]\n }\n ]\n }\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v3/contenttype/{{contentTypeIdMovingLayoutBUG}}/fields/move", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v3", + "contenttype", + "{{contentTypeIdMovingLayoutBUG}}", + "fields", + "move" + ] + } + }, + "response": [] + }, + { + "name": "Create Container C1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "", + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.collectionVariables.set(\"containerIdMovingLayoutBUG\", jsonData.entity.identifier);", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"title\": \"C1 Moving Layout BUG\",\n \"friendlyName\": \"cContainer used on the test for Moving Layout BUF\",\n \"maxContentlets\": 1,\n \"containerStructures\": [{\n \"structureId\": \"{{contentTypeIdMovingLayoutBUG}}\",\n \"maxContentlets\": 1,\n \"code\": \"$!{dotContentMap.title}\"\n }]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/containers", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "containers" + ] + } + }, + "response": [] + }, + { + "name": "Create Template T1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "", + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.collectionVariables.set(\"tamplateIdMovingLayoutBUG\", jsonData.entity.identifier);", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\t\t\n \"layout\":{\n \"body\":{\n \"rows\":[\n {\n \"styleClass\":\"\",\n \"columns\":[\n {\n \"styleClass\":\"\",\n \"leftOffset\":1,\n \"width\":12,\n \"containers\":[\n {\"identifier\":\"{{containerIdMovingLayoutBUG}}\"}\n ]\n }\n ]\n },\n {\n \"styleClass\":\"\",\n \"columns\":[\n {\n \"styleClass\":\"\",\n \"leftOffset\":1,\n \"width\":12,\n \"containers\":[\n {\"identifier\":\"{{containerIdMovingLayoutBUG}}\"}\n ]\n }\n ]\n }\n ]\n } \n },\n \"friendlyName\": \"\",\n \"title\": \"T1 MovingLayoutBUG\",\n \"theme\": \"SYSTEM_THEME\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/templates", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "templates" + ] + } + }, + "response": [] + }, + { + "name": "Create page P1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "", + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.collectionVariables.set(\"p1IdMovingLayoutBUG\", jsonData.entity.identifier);", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{ \n \"contentlet\" : {\n \"title\" : \"P1 MovingLayoutBUG\",\n \"languageId\" : 1,\n \"stInode\": \"c541abb1-69b3-4bc5-8430-5e09e5239cc8\",\n \"url\": \"P1_MovingLayoutBUG\",\n \"hostFolder\": \"8a7d5e23-da1e-420a-b4f0-471e7da8ea2d\",\n \"template\": \"{{tamplateIdMovingLayoutBUG}}\",\n \"cachettl\": 0,\n \"friendlyName\": \"friendlyName\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + } + }, + "response": [] + }, + { + "name": "Create contentlet A", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "", + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.collectionVariables.set(\"contentAId\", jsonData.entity.identifier);", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{ \n \"contentlet\" : {\n \"title\" : \"A\",\n \"languageId\" : 1,\n \"stInode\": \"{{contentTypeIdMovingLayoutBUG}}\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + } + }, + "response": [] + }, + { + "name": "Create contentlet B", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "", + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.collectionVariables.set(\"contentBId\", jsonData.entity.identifier);", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{ \n \"contentlet\" : {\n \"title\" : \"B\",\n \"languageId\" : 1,\n \"stInode\": \"{{contentTypeIdMovingLayoutBUG}}\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + } + }, + "response": [] + }, + { + "name": "Add A and B into P1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Variants with correct weight\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "[\n {\n \"contentletsId\": [\"{{contentAId}}\"],\n \"identifier\": \"{{containerIdMovingLayoutBUG}}\",\n \"uuid\": \"1\" \n },\n {\n \"contentletsId\": [\"{{contentBId}}\"],\n \"identifier\": \"{{containerIdMovingLayoutBUG}}\",\n \"uuid\": \"2\" \n } \n]\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/{{p1IdMovingLayoutBUG}}/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{p1IdMovingLayoutBUG}}", + "content" + ] + } + }, + "response": [] + }, + { + "name": "Create page P2", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "", + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.collectionVariables.set(\"p2IdMovingLayoutBUG\", jsonData.entity.identifier);", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{ \n \"contentlet\" : {\n \"title\" : \"P2 MovingLayoutBUG\",\n \"languageId\" : 1,\n \"stInode\": \"c541abb1-69b3-4bc5-8430-5e09e5239cc8\",\n \"url\": \"P2_MovingLayoutBUG\",\n \"hostFolder\": \"8a7d5e23-da1e-420a-b4f0-471e7da8ea2d\",\n \"template\": \"{{tamplateIdMovingLayoutBUG}}\",\n \"cachettl\": 0,\n \"friendlyName\": \"friendlyName\"\n }\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + } + }, + "response": [] + }, + { + "name": "Add A and B into P2", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Variants with correct weight\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "[\n {\n \"contentletsId\": [\"{{contentAId}}\"],\n \"identifier\": \"{{containerIdMovingLayoutBUG}}\",\n \"uuid\": \"1\" \n },\n {\n \"contentletsId\": [\"{{contentBId}}\"],\n \"identifier\": \"{{containerIdMovingLayoutBUG}}\",\n \"uuid\": \"2\" \n } \n]\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/{{p2IdMovingLayoutBUG}}/content", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{p2IdMovingLayoutBUG}}", + "content" + ] + } + }, + "response": [] + }, + { + "name": "Move Containers in P1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Variants with correct weight\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"layout\": {\n \"width\": \"\",\n \"title\": \"t1-movinglayoutbug\",\n \"header\": false,\n \"footer\": false,\n \"body\": {\n \"rows\": [\n {\n \"columns\": [\n {\n \"containers\": [\n {\n \"identifier\": \"{{containerIdMovingLayoutBUG}}\",\n \"uuid\": \"2\"\n }\n ],\n \"leftOffset\": 1,\n \"width\": 12,\n \"styleClass\": \"\"\n }\n ],\n \"styleClass\": null\n },\n {\n \"columns\": [\n {\n \"containers\": [\n {\n \"identifier\": \"{{containerIdMovingLayoutBUG}}\",\n \"uuid\": \"1\"\n }\n ],\n \"leftOffset\": 1,\n \"width\": 12,\n \"styleClass\": \"\"\n }\n ],\n \"styleClass\": null\n }\n ]\n },\n \"sidebar\": null\n },\n \"title\": null\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/page/{{p1IdMovingLayoutBUG}}/layout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "{{p1IdMovingLayoutBUG}}", + "layout" + ] + } + }, + "response": [] + }, + { + "name": "Render P1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "", + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "var containerId = pm.collectionVariables.get(\"containerIdMovingLayoutBUG\");", + "var contentlets = jsonData.entity.containers[containerId].contentlets;", + "", + "pm.expect('B').to.equal(contentlets['uuid-1'][0].title);", + "pm.expect('A').to.equal(contentlets['uuid-2'][0].title);", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/P1_MovingLayoutBUG?host_id=8a7d5e23-da1e-420a-b4f0-471e7da8ea2d&language_id=1&mode=PREVIEW_MODE", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "P1_MovingLayoutBUG" + ], + "query": [ + { + "key": "host_id", + "value": "8a7d5e23-da1e-420a-b4f0-471e7da8ea2d" + }, + { + "key": "language_id", + "value": "1" + }, + { + "key": "mode", + "value": "PREVIEW_MODE" + } + ] + } + }, + "response": [] + }, + { + "name": "Render P2", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();", + "", + "", + "pm.test(\"Status code should be ok 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "var containerId = pm.collectionVariables.get(\"containerIdMovingLayoutBUG\");", + "var contentlets = jsonData.entity.containers[containerId].contentlets;", + "", + "pm.expect('A').to.equal(contentlets['uuid-1'][0].title);", + "pm.expect('B').to.equal(contentlets['uuid-2'][0].title);", + "", + "", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/page/render/P2_MovingLayoutBUG?host_id=8a7d5e23-da1e-420a-b4f0-471e7da8ea2d&language_id=1&mode=PREVIEW_MODE", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "page", + "render", + "P2_MovingLayoutBUG" + ], + "query": [ + { + "key": "host_id", + "value": "8a7d5e23-da1e-420a-b4f0-471e7da8ea2d" + }, + { + "key": "language_id", + "value": "1" + }, + { + "key": "mode", + "value": "PREVIEW_MODE" + } + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Put Create Page With CacheTTL 100", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code should be 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "var jsonData = pm.response.json();", + "", + "pm.test(\"Identifier must contains path\", function () {", + " pm.expect(jsonData.entity.template).eq(\"SYSTEM_TEMPLATE\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "admin", + "type": "string" + }, + { + "key": "username", + "value": "admin@dotcms.com", + "type": "string" + }, + { + "key": "saveHelperData", + "type": "any" + }, + { + "key": "showPassword", + "value": false, + "type": "boolean" + } + ] + }, + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\"contentlet\":{\n\t\t\"stName\": \"htmlpageasset\",\n\t\t\"title\": \"PageAsset SystemTemplate\",\n \"url\": \"pageassetsystemtemplate\",\n \"friendlyName\":\"pageassetsystemtemplate\",\n \"template\": \"SYSTEM_TEMPLATE\",\n \"sortOrder\": \"0\",\n \"cachettl\": \"100\",\n \"hostFolder\":\"48190c8c-42c4-46af-8d1a-0cd5db894797\"\n\t}\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{serverURL}}/api/v1/workflow/actions/default/fire/PUBLISH", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "workflow", + "actions", + "default", + "fire", + "PUBLISH" + ] + } + }, + "response": [] + }, + { + "name": "invalidateSession", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Body matches string\", function () {", + " pm.expect(pm.response.text()).to.include(\"Logout successfully\");", + "});", + "", + "pm.environment.unset('jwt');", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/api/v1/logout", + "host": [ + "{{serverURL}}" + ], + "path": [ + "api", + "v1", + "logout" + ] + } + }, + "response": [] + }, + { + "name": "Check Cache-Control", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Cache-Control is correct\", function () {", + " pm.response.to.be.header('Cache-Control','max-age=100');", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{serverURL}}/pageassetsystemtemplate", + "host": [ + "{{serverURL}}" + ], + "path": [ + "pageassetsystemtemplate" + ] + } + }, + "response": [] + } + ], + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{jwt}}", + "type": "string" + } + ] + }, + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + " const serverURL = pm.environment.get('serverURL'); // Get the server URL from the environment variable", + " const apiUrl = `${serverURL}/api/v1/apitoken`; // Construct the full API URL", + "", + "// If we are unable to get the JWT we need to generate a new one", + " if (!pm.environment.get('jwt')) {", + " const username = pm.environment.get(\"user\");", + " const password = pm.environment.get(\"password\");", + " const basicAuth = Buffer.from(`${username}:${password}`).toString('base64');", + "", + "", + " const requestOptions = {", + " url: apiUrl,", + " method: \"POST\",", + " header: {", + " \"accept\": \"*/*\",", + " \"content-type\": \"application/json\",", + " \"Authorization\": `Basic ${basicAuth}`", + " },", + " body: {", + " mode: \"raw\",", + " raw: JSON.stringify({", + " \"expirationSeconds\": 7200,", + " \"userId\": \"dotcms.org.1\",", + " \"network\": \"0.0.0.0/0\",", + " \"claims\": {\"label\": \"postman-tests\"}", + " })", + " }", + " };", + "", + "", + " pm.sendRequest(requestOptions, function (err, response) {", + " if (err) {", + " console.log(err);", + " } else {", + " const jwt = response.json().entity.jwt;", + " pm.environment.set('jwt', jwt);", + " console.log(jwt);", + " }", + " });", + " }" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "key": "contentTypeIdMovingLayoutBUG", + "value": "" + }, + { + "key": "spanish_content_container_id", + "value": "" + }, + { + "key": "containerIdMovingLayoutBUG", + "value": "" + }, + { + "key": "tamplateIdMovingLayoutBUG", + "value": "" + }, + { + "key": "p1IdMovingLayoutBUG", + "value": "" + }, + { + "key": "contentAId", + "value": "" + }, + { + "key": "contentBId", + "value": "" + }, + { + "key": "p2IdMovingLayoutBUG", + "value": "" + } + ] +} diff --git a/examples/angular/package-lock.json b/examples/angular/package-lock.json index 8af79e80c618..b7482daf612d 100644 --- a/examples/angular/package-lock.json +++ b/examples/angular/package-lock.json @@ -16,8 +16,8 @@ "@angular/platform-browser": "^17.1.0", "@angular/platform-browser-dynamic": "^17.1.0", "@angular/router": "^17.1.0", - "@dotcms/angular": "0.0.1-alpha.29", - "@dotcms/client": "0.0.1-alpha.29", + "@dotcms/angular": "0.0.1-alpha.32", + "@dotcms/client": "0.0.1-alpha.32", "@tinymce/tinymce-angular": "^8.0.0", "rxjs": "~7.8.0", "tslib": "^2.3.0", @@ -2396,10 +2396,10 @@ } }, "node_modules/@dotcms/angular": { - "version": "0.0.1-alpha.29", - "resolved": "https://registry.npmjs.org/@dotcms/angular/-/angular-0.0.1-alpha.29.tgz", - "integrity": "sha512-L3LhTOKjRce1r3mxyANEF2m7adzyqnNTdCX/qXTSorw8jLvUbSpXxZyG95NsMH0fi7+iJDmNXNvtQyx0opTD/g==", - + "version": "0.0.1-alpha.32", + "resolved": "https://registry.npmjs.org/@dotcms/angular/-/angular-0.0.1-alpha.32.tgz", + "integrity": "sha512-iyekrLnIDPMIiopjwCHUfTQc1lDOdClRvbKjSAdeSZ/9YzYlTuE4ZlwYVMrxaRwru4NB2VT+8Bz7yb/tOVq1kw==", + "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, @@ -2407,15 +2407,16 @@ "@angular/common": "^17.1.0", "@angular/core": "^17.1.0", "@angular/router": "^17.1.0", - "@dotcms/client": "0.0.1-alpha.29", + "@dotcms/client": "0.0.1-alpha.32", "@tinymce/tinymce-angular": "^8.0.0", "rxjs": "^7.8.0" } }, "node_modules/@dotcms/client": { - "version": "0.0.1-alpha.29", - "resolved": "https://registry.npmjs.org/@dotcms/client/-/client-0.0.1-alpha.29.tgz", - "integrity": "sha512-e+npJyvfpIzPnvmJ28AqEwdbOcb6AXcAXF4Aa/lAGGJTABjjTd/FOHdLFEEeCG5OkGbAi6DzP6lQH75OzYzStw==" + "version": "0.0.1-alpha.32", + "resolved": "file:../../core-web/dist/libs/sdk/client/dotcms-client-0.0.1-alpha.32.tgz", + "integrity": "sha512-CqBpqbBGMW9WI8VEHDRDuD11Ue4ywuJi/OYyZBJ2l/DvsDPlepLvT9OFpJO1ot3dOyQTHgaupRKvaeZTQBVPkg==", + "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { "version": "0.20.1", diff --git a/examples/angular/package.json b/examples/angular/package.json index 1f03317a969b..9bfc5d64f181 100644 --- a/examples/angular/package.json +++ b/examples/angular/package.json @@ -10,9 +10,6 @@ }, "private": true, "dependencies": { - "rxjs": "~7.8.0", - "tslib": "^2.3.0", - "zone.js": "~0.14.2", "@angular/animations": "^17.1.0", "@angular/common": "^17.1.0", "@angular/compiler": "^17.1.0", @@ -21,9 +18,12 @@ "@angular/platform-browser": "^17.1.0", "@angular/platform-browser-dynamic": "^17.1.0", "@angular/router": "^17.1.0", - "@dotcms/client": "0.0.1-alpha.31", - "@dotcms/angular": "0.0.1-alpha.31", - "@tinymce/tinymce-angular": "^8.0.0" + "@dotcms/angular": "0.0.1-alpha.32", + "@dotcms/client": "0.0.1-alpha.32", + "@tinymce/tinymce-angular": "^8.0.0", + "rxjs": "~7.8.0", + "tslib": "^2.3.0", + "zone.js": "~0.14.2" }, "devDependencies": { "@angular-devkit/build-angular": "^17.0.7", diff --git a/examples/nextjs/package.json b/examples/nextjs/package.json index 05a29df463f1..d24ace61533d 100644 --- a/examples/nextjs/package.json +++ b/examples/nextjs/package.json @@ -9,9 +9,9 @@ "lint": "next lint" }, "dependencies": { - "@dotcms/client": "0.0.1-alpha.31", - "@dotcms/react": "0.0.1-alpha.31", - "@dotcms/experiments": "0.0.1-alpha.31", + "@dotcms/client": "0.0.1-alpha.32", + "@dotcms/react": "0.0.1-alpha.32", + "@dotcms/experiments": "0.0.1-alpha.32", "next": "14.1.1", "react": "^18", "react-dom": "^18" diff --git a/examples/vuejs/package.json b/examples/vuejs/package.json index ea548ce66863..8b9b11e0b7d4 100644 --- a/examples/vuejs/package.json +++ b/examples/vuejs/package.json @@ -11,7 +11,7 @@ "format": "prettier --write src/" }, "dependencies": { - "@dotcms/client": "^0.0.1-alpha.31", + "@dotcms/client": "^0.0.1-alpha.32", "vue": "^3.4.15", "vue-router": "^4.2.5" }, diff --git a/parent/pom.xml b/parent/pom.xml index be41efd3b0bd..2c94adbf8d21 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -306,7 +306,7 @@ listening on IPv4 address "0.0.0.0", port 5432 - DB: + [DB] magenta @@ -345,7 +345,7 @@ 5000 - ES: + [ES] cyan @@ -392,7 +392,7 @@ opensearch:es - DOTCMS: + [DOTCMS] cyan @@ -708,6 +708,13 @@ false + + + org.apache.maven.surefire + surefire-junit47 + ${version.failsafe.plugin} + + org.apache.maven.plugins @@ -861,6 +868,13 @@ true + + + org.apache.maven.surefire + surefire-junit47 + ${version.surefire.plugin} + + org.apache.maven.plugins