diff --git a/tests/Umbraco.Tests.AcceptanceTest/package-lock.json b/tests/Umbraco.Tests.AcceptanceTest/package-lock.json index 29384f472849..0ee8eeaea89d 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/package-lock.json +++ b/tests/Umbraco.Tests.AcceptanceTest/package-lock.json @@ -8,7 +8,7 @@ "hasInstallScript": true, "dependencies": { "@umbraco/json-models-builders": "^2.0.5", - "@umbraco/playwright-testhelpers": "^2.0.0-beta.51", + "@umbraco/playwright-testhelpers": "^2.0.0-beta.54", "camelize": "^1.0.0", "dotenv": "^16.3.1", "faker": "^4.1.0", @@ -146,9 +146,9 @@ "integrity": "sha512-9tCqYEDHI5RYFQigXFwF1hnCwcWCOJl/hmll0lr5D2Ljjb0o4wphb69wikeJDz5qCEzXCoPvG6ss5SDP6IfOdg==" }, "node_modules/@umbraco/playwright-testhelpers": { - "version": "2.0.0-beta.51", - "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-2.0.0-beta.51.tgz", - "integrity": "sha512-MVPsjv5nInf5oZ5F7NbnqjguWWOJ5/Dv/EHWBhv5QKBxanub+NeJGujJLBPPI7ifijNb2fWPzV6G5M3cD+aPvA==", + "version": "2.0.0-beta.54", + "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-2.0.0-beta.54.tgz", + "integrity": "sha512-5nj4aMd2eDI04qEi6iPgh1FlhC86UbMpucBcliZyyZDlC8WGleiOf3jwPzYMIDOR0xuju3i65OHgcmDT0QWuOg==", "dependencies": { "@umbraco/json-models-builders": "2.0.6", "camelize": "^1.0.0", diff --git a/tests/Umbraco.Tests.AcceptanceTest/package.json b/tests/Umbraco.Tests.AcceptanceTest/package.json index e4a061402451..81cd3194bdb4 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/package.json +++ b/tests/Umbraco.Tests.AcceptanceTest/package.json @@ -22,7 +22,7 @@ }, "dependencies": { "@umbraco/json-models-builders": "^2.0.5", - "@umbraco/playwright-testhelpers": "^2.0.0-beta.51", + "@umbraco/playwright-testhelpers": "^2.0.0-beta.54", "camelize": "^1.0.0", "dotenv": "^16.3.1", "faker": "^4.1.0", diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/ApiTesting/Document/Document.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/ApiTesting/Document/Document.spec.ts new file mode 100644 index 000000000000..045f98e5fb3b --- /dev/null +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/ApiTesting/Document/Document.spec.ts @@ -0,0 +1,55 @@ +import {test} from '@umbraco/playwright-testhelpers'; +import {expect} from "@playwright/test"; + +test.describe('Documents tests', () => { + let documentTypeId = ''; + let documentId = ''; + const documentName = 'TestDocument'; + const documentTypeName = 'TestDocumentType'; + + test.beforeEach(async ({umbracoApi}) => { + await umbracoApi.documentType.ensureNameNotExists(documentTypeName); + documentTypeId = await umbracoApi.documentType.createDefaultDocumentTypeWithAllowAsRoot(documentTypeName); + }); + + test.afterEach(async ({umbracoApi}) => { + await umbracoApi.document.ensureNameNotExists(documentName); + await umbracoApi.documentType.ensureNameNotExists(documentTypeName); + }); + + test('can create a document', async ({umbracoApi}) => { + // Act + await umbracoApi.document.createDefaultDocument(documentName, documentTypeId); + + // Assert + expect(await umbracoApi.document.doesNameExist(documentName)).toBeTruthy(); + }); + + test('can delete a document', async ({umbracoApi}) => { + // Arrange + documentId = await umbracoApi.document.createDefaultDocument(documentName, documentTypeId); + expect(umbracoApi.document.doesExist(documentId)).toBeTruthy(); + + // Act + await umbracoApi.document.delete(documentId); + + // Assert + expect(await umbracoApi.document.doesNameExist(documentName)).toBeFalsy(); + }); + + test('can update a document', async ({umbracoApi}) => { + // Arrange + const wrongName = 'WrongDocument'; + documentId = await umbracoApi.document.createDefaultDocument(wrongName, documentTypeId); + expect(await umbracoApi.document.doesNameExist(wrongName)).toBeTruthy(); + let documentData = await umbracoApi.document.get(documentId); + documentData.variants[0].name = documentName; + + // Act + await umbracoApi.document.update(documentData.id, documentData); + + // Assert + const updatedDocumentData = await umbracoApi.document.get(documentId); + expect(updatedDocumentData.variants[0].name).toEqual(documentName); + }); +}); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ChildrenContent.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ChildrenContent.spec.ts new file mode 100644 index 000000000000..bcbb9656dc66 --- /dev/null +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ChildrenContent.spec.ts @@ -0,0 +1,134 @@ +import {ConstantHelper, test} from '@umbraco/playwright-testhelpers'; +import {expect} from "@playwright/test"; + +let documentTypeId = ''; +let childDocumentTypeId = ''; +let contentId = ''; +const contentName = 'TestContent'; +const childContentName = 'ChildContent'; +const documentTypeName = 'DocumentTypeForContent'; +const childDocumentTypeName = 'ChildDocumentTypeForContent'; + +test.beforeEach(async ({umbracoApi}) => { + await umbracoApi.documentType.ensureNameNotExists(documentTypeName); + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.documentType.ensureNameNotExists(childDocumentTypeName); +}); + +test.afterEach(async ({umbracoApi}) => { + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.documentType.ensureNameNotExists(childDocumentTypeName); + await umbracoApi.documentType.ensureNameNotExists(documentTypeName); +}); + +test('can create child node', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => { + // Arrange + childDocumentTypeId = await umbracoApi.documentType.createDefaultDocumentType(childDocumentTypeName); + documentTypeId = await umbracoApi.documentType.createDocumentTypeWithAllowedChildNode(documentTypeName, childDocumentTypeId, true); + contentId = await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.clickActionsMenuForContent(contentName); + await umbracoUi.content.clickCreateButton(); + await umbracoUi.content.chooseDocumentType(documentTypeName); + await umbracoUi.content.enterContentName(childContentName); + await umbracoUi.content.clickSaveButton(); + + // Assert + await umbracoUi.content.isSuccessNotificationVisible(); + expect(await umbracoApi.document.doesNameExist(childContentName)).toBeTruthy(); + const childData = await umbracoApi.document.getChildren(contentId); + expect(childData[0].variants[0].name).toBe(childContentName); + // verify that the child content displays in the tree after reloading children + await umbracoUi.content.clickActionsMenuForContent(contentName); + await umbracoUi.content.clickReloadButton(); + await umbracoUi.content.clickCaretButtonForContentName(contentName); + await umbracoUi.content.doesContentTreeHaveName(childContentName); + + // Clean + await umbracoApi.document.ensureNameNotExists(childContentName); +}); + +// TODO: Remove skip when the front-end is ready. +test.skip('can create child node in child node', async ({umbracoApi, umbracoUi}) => { + // Arrange + const childOfChildContentName = 'ChildOfChildContent'; + const childOfChildDocumentTypeName = 'ChildOfChildDocumentType'; + let childOfChildDocumentTypeId: any; + let childContentId: any; + await umbracoApi.documentType.ensureNameNotExists(childOfChildDocumentTypeName); + childOfChildDocumentTypeId = await umbracoApi.documentType.createDefaultDocumentType(childOfChildDocumentTypeName); + childDocumentTypeId = await umbracoApi.documentType.createDocumentTypeWithAllowedChildNode(childDocumentTypeName, childOfChildDocumentTypeId, true); + documentTypeId = await umbracoApi.documentType.createDocumentTypeWithAllowedChildNode(documentTypeName, childDocumentTypeId, true); + contentId = await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); + childContentId = await umbracoApi.document.createDefaultDocumentWithParent(childContentName, childDocumentTypeId, contentId); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.clickCaretButtonForContentName(contentName); + await umbracoUi.content.clickActionsMenuForContent(childContentName); + await umbracoUi.content.clickCreateButton(); + await umbracoUi.content.clickLabelWithName(childOfChildDocumentTypeName); + // This wait is needed + await umbracoUi.waitForTimeout(500); + await umbracoUi.content.enterContentName(childOfChildContentName); + await umbracoUi.content.clickSaveButton(); + + // Assert + await umbracoUi.content.isSuccessNotificationVisible(); + const childOfChildData = await umbracoApi.document.getChildren(childContentId); + expect(childOfChildData[0].variants[0].name).toBe(childOfChildContentName); + // verify that the child content displays in the tree after reloading children + await umbracoUi.content.clickActionsMenuForContent(contentName); + await umbracoUi.content.clickReloadButton(); + await umbracoUi.content.clickCaretButtonForContentName(childContentName); + await umbracoUi.content.doesContentTreeHaveName(childOfChildContentName); + + // Clean + await umbracoApi.documentType.ensureNameNotExists(childOfChildDocumentTypeName); + await umbracoApi.document.ensureNameNotExists(childOfChildContentName); +}); + +test('cannot publish child if the parent is not published', async ({umbracoApi, umbracoUi}) => { + // Arrange + childDocumentTypeId = await umbracoApi.documentType.createDefaultDocumentType(childDocumentTypeName); + documentTypeId = await umbracoApi.documentType.createDocumentTypeWithAllowedChildNode(documentTypeName, childDocumentTypeId, true); + contentId = await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); + await umbracoApi.document.createDefaultDocumentWithParent(childContentName, childDocumentTypeId, contentId); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.clickCaretButtonForContentName(contentName); + await umbracoUi.content.clickActionsMenuForContent(childContentName); + await umbracoUi.content.clickPublishButton(); + + // Assert + await umbracoUi.content.isErrorNotificationVisible(); + const contentData = await umbracoApi.document.getByName(childContentName); + expect(contentData.variants[0].state).toBe('Draft'); +}); + +test('can publish with descendants', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => { + // Arrange + childDocumentTypeId = await umbracoApi.documentType.createDefaultDocumentType(childDocumentTypeName); + documentTypeId = await umbracoApi.documentType.createDocumentTypeWithAllowedChildNode(documentTypeName, childDocumentTypeId, true); + contentId = await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); + await umbracoApi.document.createDefaultDocumentWithParent(childContentName, childDocumentTypeId, contentId); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.clickActionsMenuForContent(contentName); + await umbracoUi.content.clickPublishButton(); + + // Assert + await umbracoUi.content.isSuccessNotificationVisible(); + const contentData = await umbracoApi.document.getByName(contentName); + expect(contentData.variants[0].state).toBe('Published'); + const childContentData = await umbracoApi.document.getByName(contentName); + expect(childContentData.variants[0].state).toBe('Published'); +}); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/Content.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/Content.spec.ts new file mode 100644 index 000000000000..98f0a6ec2170 --- /dev/null +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/Content.spec.ts @@ -0,0 +1,162 @@ +import {ConstantHelper, test} from '@umbraco/playwright-testhelpers'; +import {expect} from "@playwright/test"; + +let documentTypeId = ''; +let contentId = ''; +const contentName = 'TestContent'; +const documentTypeName = 'TestDocumentTypeForContent'; +const dataTypeName = 'Textstring'; +const contentText = 'This is test content text'; + +test.beforeEach(async ({umbracoApi}) => { + await umbracoApi.documentType.ensureNameNotExists(documentTypeName); +}); + +test.afterEach(async ({umbracoApi}) => { + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.documentType.ensureNameNotExists(documentTypeName); +}); + +test('can create empty content', async ({umbracoApi, umbracoUi}) => { + // Arrange + const expectedState = 'Draft'; + await umbracoApi.documentType.createDefaultDocumentTypeWithAllowAsRoot(documentTypeName); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.clickActionsMenuAtRoot(); + await umbracoUi.content.clickCreateButton(); + await umbracoUi.content.chooseDocumentType(documentTypeName); + await umbracoUi.content.enterContentName(contentName); + await umbracoUi.content.clickSaveButton(); + + // Assert + await umbracoUi.content.isSuccessNotificationVisible(); + expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy(); + const contentData = await umbracoApi.document.getByName(contentName); + expect(contentData.variants[0].state).toBe(expectedState); +}); + +test('can save and publish empty content', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => { + // Arrange + const expectedState = 'Published'; + await umbracoApi.documentType.createDefaultDocumentTypeWithAllowAsRoot(documentTypeName); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.clickActionsMenuAtRoot(); + await umbracoUi.content.clickCreateButton(); + await umbracoUi.content.chooseDocumentType(documentTypeName); + await umbracoUi.content.enterContentName(contentName); + await umbracoUi.content.clickSaveAndPublishButton(); + + // Assert + await umbracoUi.content.doesSuccessNotificationsHaveCount(2); + expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy(); + const contentData = await umbracoApi.document.getByName(contentName); + expect(contentData.variants[0].state).toBe(expectedState); +}); + +test('can create content', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => { + // Arrange + const dataTypeData = await umbracoApi.dataType.getByName(dataTypeName); + await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, dataTypeName, dataTypeData.id); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.clickActionsMenuAtRoot(); + await umbracoUi.content.clickCreateButton(); + await umbracoUi.content.chooseDocumentType(documentTypeName); + await umbracoUi.content.enterContentName(contentName); + await umbracoUi.content.enterTextstring(contentText); + await umbracoUi.content.clickSaveButton(); + + // Assert + await umbracoUi.content.isSuccessNotificationVisible(); + expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy(); + const contentData = await umbracoApi.document.getByName(contentName); + expect(contentData.values[0].value).toBe(contentText); +}); + +test('can rename content', async ({umbracoApi, umbracoUi}) => { + // Arrange + const wrongContentName = 'Wrong Content Name'; + documentTypeId = await umbracoApi.documentType.createDefaultDocumentTypeWithAllowAsRoot(documentTypeName); + contentId = await umbracoApi.document.createDefaultDocument(wrongContentName, documentTypeId); + expect(await umbracoApi.document.doesNameExist(wrongContentName)).toBeTruthy(); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.openContent(wrongContentName); + await umbracoUi.content.enterContentName(contentName); + await umbracoUi.content.clickSaveButton(); + + // Assert + await umbracoUi.content.isSuccessNotificationVisible(); + const updatedContentData = await umbracoApi.document.get(contentId); + expect(updatedContentData.variants[0].name).toEqual(contentName); +}); + +test('can update content', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => { + // Arrange + const wrongContentText = 'This is wrong test content text'; + const dataTypeData = await umbracoApi.dataType.getByName(dataTypeName); + documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, dataTypeName, dataTypeData.id); + contentId = await umbracoApi.document.createDocumentWithTextContent(contentName, documentTypeId, wrongContentText, dataTypeName); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.openContent(contentName); + await umbracoUi.content.enterTextstring(contentText); + await umbracoUi.content.clickSaveButton(); + + // Assert + await umbracoUi.content.isSuccessNotificationVisible(); + const updatedContentData = await umbracoApi.document.get(contentId); + expect(updatedContentData.variants[0].name).toEqual(contentName); + expect(updatedContentData.values[0].value).toBe(contentText); +}); + +test('can publish content', async ({umbracoApi, umbracoUi}) => { + // Arrange + const dataTypeData = await umbracoApi.dataType.getByName(dataTypeName); + documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, dataTypeName, dataTypeData.id); + contentId = await umbracoApi.document.createDocumentWithTextContent(contentName, documentTypeId, contentText, dataTypeName); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.clickActionsMenuForContent(contentName); + await umbracoUi.content.clickPublishButton(); + + // Assert + await umbracoUi.content.isSuccessNotificationVisible(); + const contentData = await umbracoApi.document.getByName(contentName); + expect(contentData.variants[0].state).toBe('Published'); +}); + +test('can unpublish content', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => { + // Arrange + const dataTypeData = await umbracoApi.dataType.getByName(dataTypeName); + documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, dataTypeName, dataTypeData.id); + contentId = await umbracoApi.document.createDocumentWithTextContent(contentName, documentTypeId, contentText, dataTypeName); + const publishData = {"publishSchedules":[{"culture":null}]}; + await umbracoApi.document.publish(contentId, publishData); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.clickActionsMenuForContent(contentName); + await umbracoUi.content.clickUnpublishButton(); + await umbracoUi.content.clickConfirmToUnpublishButton(); + + // Assert + await umbracoUi.content.isSuccessNotificationVisible(); + const contentData = await umbracoApi.document.getByName(contentName); + expect(contentData.variants[0].state).toBe('Draft'); +}); \ No newline at end of file diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentInfoTab.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentInfoTab.spec.ts new file mode 100644 index 000000000000..79cf1211e052 --- /dev/null +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentInfoTab.spec.ts @@ -0,0 +1,143 @@ +import { expect } from '@playwright/test'; +import {ConstantHelper, test} from '@umbraco/playwright-testhelpers'; + +let documentTypeId = ''; +let contentId = ''; +const contentName = 'TestInfoTab'; +const documentTypeName = 'TestDocumentTypeForContent'; + +test.beforeEach(async ({umbracoApi}) => { + await umbracoApi.documentType.ensureNameNotExists(documentTypeName); +}); + +test.afterEach(async ({umbracoApi}) => { + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.documentType.ensureNameNotExists(documentTypeName); +}); + +test('can see correct information when published', async ({umbracoApi, umbracoUi}) => { + // Arrange + const notPublishContentLink = 'This document is published but is not in the cache'; + documentTypeId = await umbracoApi.documentType.createDefaultDocumentTypeWithAllowAsRoot(documentTypeName); + contentId = await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.openContent(contentName); + await umbracoUi.content.clickInfoTab(); + await umbracoUi.content.doesLinkHaveText(notPublishContentLink); + await umbracoUi.content.clickSaveAndPublishButton(); + + // Assert + const contentData = await umbracoApi.document.get(contentId); + // TODO: Uncomment this when front-end is ready. Currently the link is not updated immediately after publishing + //await umbracoUi.content.doesLinkHaveText(contentData.urls[0].url); + await umbracoUi.content.doesIdHaveText(contentData.id); + await umbracoUi.content.doesPublicationStatusHaveText(contentData.variants[0].state === 'Draft' ? 'Unpublished' : contentData.variants[0].state); + const expectedCreatedDate = new Date(contentData.variants[0].createDate).toLocaleString("en-US", { + year: "numeric", + month: "long", + day: "numeric", + hour: "numeric", + minute: "numeric", + second: "numeric", + hour12: true, + }); + await umbracoUi.content.doesCreatedDateHaveText(expectedCreatedDate); +}); + +// TODO: Remove skip when the frond-end is ready. Currently the document type is not opened after clicking to the button +test.skip('can open document type', async ({umbracoApi, umbracoUi}) => { + // Arrange + documentTypeId = await umbracoApi.documentType.createDefaultDocumentTypeWithAllowAsRoot(documentTypeName); + contentId = await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.openContent(contentName); + await umbracoUi.content.clickInfoTab(); + await umbracoUi.content.clickDocumentTypeByName(documentTypeName); + + // Assert + await umbracoUi.content.isDocumentTypeModalVisible(documentTypeName); +}); + +test('can open template', async ({umbracoApi, umbracoUi}) => { + // Arrange + const templateName = "TestTemplateForContent"; + await umbracoApi.template.ensureNameNotExists(templateName); + const templateId = await umbracoApi.template.createDefaultTemplate(templateName); + documentTypeId = await umbracoApi.documentType.createDocumentTypeWithAllowedTemplate(documentTypeName, templateId, true); + contentId = await umbracoApi.document.createDocumentWithTemplate(contentName, documentTypeId, templateId); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.openContent(contentName); + await umbracoUi.content.clickInfoTab(); + await umbracoUi.content.clickTemplateByName(templateName); + + // Assert + await umbracoUi.content.isTemplateModalVisible(templateName); + + // Clean + await umbracoApi.template.ensureNameNotExists(templateName); +}); + +test('can change template', async ({umbracoApi, umbracoUi}) => { + // Arrange + const firstTemplateName = "TestTemplateOneForContent"; + const secondTemplateName = "TestTemplateTwoForContent"; + await umbracoApi.template.ensureNameNotExists(firstTemplateName); + await umbracoApi.template.ensureNameNotExists(secondTemplateName); + const firstTemplateId = await umbracoApi.template.createDefaultTemplate(firstTemplateName); + const secondTemplateId = await umbracoApi.template.createDefaultTemplate(secondTemplateName); + documentTypeId = await umbracoApi.documentType.createDocumentTypeWithTwoAllowedTemplates(documentTypeName, firstTemplateId, secondTemplateId, true); + contentId = await umbracoApi.document.createDocumentWithTemplate(contentName, documentTypeId, firstTemplateId); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.openContent(contentName); + await umbracoUi.content.clickInfoTab(); + await umbracoUi.content.changeTemplate(firstTemplateName, secondTemplateName); + await umbracoUi.content.clickSaveButton(); + + // Assert + const contentData = await umbracoApi.document.getByName(contentName); + expect(contentData.template.id).toBe(secondTemplateId); + + // Clean + await umbracoApi.template.ensureNameNotExists(firstTemplateName); + await umbracoApi.template.ensureNameNotExists(secondTemplateName); +}); + +test('cannot change to a template that is not allowed in the document type', async ({umbracoApi, umbracoUi}) => { + // Arrange + const firstTemplateName = "TestTemplateOneForContent"; + const secondTemplateName = "TestTemplateTwoForContent"; + await umbracoApi.template.ensureNameNotExists(firstTemplateName); + await umbracoApi.template.ensureNameNotExists(secondTemplateName); + const firstTemplateId = await umbracoApi.template.createDefaultTemplate(firstTemplateName); + await umbracoApi.template.createDefaultTemplate(secondTemplateName); + documentTypeId = await umbracoApi.documentType.createDocumentTypeWithAllowedTemplate(documentTypeName, firstTemplateId, true); + contentId = await umbracoApi.document.createDocumentWithTemplate(contentName, documentTypeId, firstTemplateId); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.openContent(contentName); + await umbracoUi.content.clickInfoTab(); + await umbracoUi.content.clickEditTemplateByName(firstTemplateName); + + // Assert + // This wait is needed to make sure the template name is visible when the modal is opened + await umbracoUi.waitForTimeout(1000); + await umbracoUi.content.isTemplateNameDisabled(secondTemplateName); + + // Clean + await umbracoApi.template.ensureNameNotExists(firstTemplateName); + await umbracoApi.template.ensureNameNotExists(secondTemplateName); +}); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithPropertyEditors.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithPropertyEditors.spec.ts new file mode 100644 index 000000000000..a6f998e80acf --- /dev/null +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithPropertyEditors.spec.ts @@ -0,0 +1,176 @@ +import {ConstantHelper, test} from '@umbraco/playwright-testhelpers'; +import {expect} from "@playwright/test"; + +const contentName = 'TestContent'; +const documentTypeName = 'TestDocumentTypeForContent'; + +test.beforeEach(async ({umbracoApi}) => { + await umbracoApi.documentType.ensureNameNotExists(documentTypeName); + await umbracoApi.document.ensureNameNotExists(contentName); +}); + +test.afterEach(async ({umbracoApi}) => { + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.documentType.ensureNameNotExists(documentTypeName); +}); + +test('can create content with the Rich Text Editor datatype', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => { + // Arrange + const dataTypeName = 'Richtext editor'; + const contentText = 'This is Rich Text Editor content!'; + const expectedContentValue = { + blocks: { + contentData: [], + layout: {}, + propertyEditorAlias: 'Umbraco.TinyMCE', + settingsData: [], + }, + markup: '

' + contentText + '

', + }; + const dataTypeData = await umbracoApi.dataType.getByName(dataTypeName); + await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, dataTypeName, dataTypeData.id); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.clickActionsMenuAtRoot(); + await umbracoUi.content.clickCreateButton(); + await umbracoUi.content.chooseDocumentType(documentTypeName); + await umbracoUi.content.enterContentName(contentName); + await umbracoUi.content.enterRichTextArea(contentText); + await umbracoUi.content.clickSaveAndPublishButton(); + + // Assert + await umbracoUi.content.doesSuccessNotificationsHaveCount(2); + expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy(); + const contentData = await umbracoApi.document.getByName(contentName); + expect(contentData.values[0].value).toEqual(expectedContentValue); +}); + +test('can create content with the text area datatype', async ({umbracoApi, umbracoUi}) => { + // Arrange + const dataTypeName = 'Textarea'; + const contentText = 'This is Textarea content!'; + const dataTypeData = await umbracoApi.dataType.getByName(dataTypeName); + await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, dataTypeName, dataTypeData.id); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.clickActionsMenuAtRoot(); + await umbracoUi.content.clickCreateButton(); + await umbracoUi.content.chooseDocumentType(documentTypeName); + await umbracoUi.content.enterContentName(contentName); + await umbracoUi.content.enterTextArea(contentText); + await umbracoUi.content.clickSaveAndPublishButton(); + + // Assert + await umbracoUi.content.doesSuccessNotificationsHaveCount(2); + expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy(); + const contentData = await umbracoApi.document.getByName(contentName); + expect(contentData.values[0].value).toEqual(contentText); +}); + +// TODO: Remove skip when the front-end is ready. Currently it returns error when publishing a content +test.skip('can create content with the upload file datatype', async ({umbracoApi, umbracoUi}) => { + // Arrange + const dataTypeName = 'Upload File'; + const uploadFilePath = 'Umbraco.png'; + const dataTypeData = await umbracoApi.dataType.getByName(dataTypeName); + await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, dataTypeName, dataTypeData.id); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.clickActionsMenuAtRoot(); + await umbracoUi.content.clickCreateButton(); + await umbracoUi.content.chooseDocumentType(documentTypeName); + await umbracoUi.content.enterContentName(contentName); + await umbracoUi.content.changeFileTypeWithFileChooser('./fixtures/mediaLibrary/' + uploadFilePath); + await umbracoUi.content.clickSaveAndPublishButton(); + + // Assert + await umbracoUi.content.doesSuccessNotificationsHaveCount(2); + expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy(); + const contentData = await umbracoApi.document.getByName(contentName); + expect(contentData.values[0].value.src).toContainEqual(uploadFilePath); +}); + +test('can create content with the tags datatype', async ({umbracoApi, umbracoUi}) => { + // Arrange + const dataTypeName = 'Tags'; + const tagName = 'test'; + const dataTypeData = await umbracoApi.dataType.getByName(dataTypeName); + await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, dataTypeName, dataTypeData.id); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.clickActionsMenuAtRoot(); + await umbracoUi.content.clickCreateButton(); + await umbracoUi.content.chooseDocumentType(documentTypeName); + await umbracoUi.content.enterContentName(contentName); + await umbracoUi.content.addTags(tagName); + await umbracoUi.content.clickSaveAndPublishButton(); + + // Assert + await umbracoUi.content.doesSuccessNotificationsHaveCount(2); + expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy(); + const contentData = await umbracoApi.document.getByName(contentName); + expect(contentData.values[0].value).toEqual([tagName]); +}); + +test('can create content with the content picker datatype', async ({umbracoApi, umbracoUi}) => { + // Arrange + const dataTypeName = 'Content Picker'; + const contentPickerName = 'TestContentPicker'; + const dataTypeData = await umbracoApi.dataType.getByName(dataTypeName); + const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, dataTypeName, dataTypeData.id); + const contentPickerId = await umbracoApi.document.createDefaultDocument(contentPickerName, documentTypeId); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.clickActionsMenuAtRoot(); + await umbracoUi.content.clickCreateButton(); + await umbracoUi.content.chooseDocumentType(documentTypeName); + await umbracoUi.content.enterContentName(contentName); + await umbracoUi.content.addContentPicker(contentPickerName); + await umbracoUi.content.clickSaveAndPublishButton(); + + // Assert + await umbracoUi.content.doesSuccessNotificationsHaveCount(2); + expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy(); + const contentData = await umbracoApi.document.getByName(contentName); + expect(contentData.values[0].value).toEqual(contentPickerId); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentPickerName); +}); + +// TODO: Remove skip and update the test when the front-end is ready. Currently the list of content is not displayed. +test.skip('can create content with the list view - content datatype', async ({umbracoApi, umbracoUi}) => { + // Arrange + const dataTypeName = 'List View - Content'; + const contentListViewName = 'TestListViewContent'; + const dataTypeData = await umbracoApi.dataType.getByName(dataTypeName); + const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, dataTypeName, dataTypeData.id); + const contentPickerId = await umbracoApi.document.createDefaultDocument(contentListViewName, documentTypeId); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.clickActionsMenuAtRoot(); + await umbracoUi.content.clickCreateButton(); + await umbracoUi.content.chooseDocumentType(documentTypeName); + await umbracoUi.content.enterContentName(contentName); + // TODO: add step to interact with the list + await umbracoUi.content.clickSaveAndPublishButton(); + + // Assert + await umbracoUi.content.doesSuccessNotificationsHaveCount(2); + expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy(); + + // Clean + await umbracoApi.document.delete(contentPickerId); +}); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/CultureAndHostnames.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/CultureAndHostnames.spec.ts new file mode 100644 index 000000000000..4a09329f9bcd --- /dev/null +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/CultureAndHostnames.spec.ts @@ -0,0 +1,125 @@ +import {ConstantHelper, test} from '@umbraco/playwright-testhelpers'; +import {expect} from "@playwright/test"; + +let documentTypeId = ''; +let contentId = ''; +const contentName = 'TestCultureAndHostnames'; +const documentTypeName = 'TestDocumentTypeForContent'; +const languageName = 'Danish'; +const isoCode = 'da'; +const domainName = 'testdomain'; +const domainValue = [ + { + "domainName": domainName, + "isoCode": isoCode + } +]; + +test.beforeEach(async ({umbracoApi, umbracoUi}) => { + await umbracoApi.documentType.ensureNameNotExists(documentTypeName); + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.language.ensureNameNotExists(languageName); + documentTypeId = await umbracoApi.documentType.createDefaultDocumentTypeWithAllowAsRoot(documentTypeName); + contentId = await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); + await umbracoApi.language.create(languageName, false, false, isoCode); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); +}); + +test.afterEach(async ({umbracoApi}) => { + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.documentType.ensureNameNotExists(documentTypeName); + await umbracoApi.language.ensureNameNotExists(languageName); +}); + +test('can add a culture', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => { + // Act + await umbracoUi.content.clickActionsMenuForContent(contentName); + await umbracoUi.content.clickCultureAndHostnamesButton(); + await umbracoUi.content.selectCultureLanguageOption(languageName); + await umbracoUi.content.clickSaveModalButton(); + + // Assert + const domainsData = await umbracoApi.document.getDomains(contentId); + expect(domainsData.defaultIsoCode).toEqual(isoCode); +}); + +test('can add a domain', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => { + // Act + await umbracoUi.content.clickActionsMenuForContent(contentName); + await umbracoUi.content.clickCultureAndHostnamesButton(); + await umbracoUi.content.clickAddNewDomainButton(); + await umbracoUi.content.enterDomain(domainName); + await umbracoUi.content.selectDomainLanguageOption(languageName); + await umbracoUi.content.clickSaveModalButton(); + + // Assert + const domainsData = await umbracoApi.document.getDomains(contentId); + expect(domainsData.domains.length).toBe(1); + expect(domainsData.domains[0].domainName).toEqual(domainName); + expect(domainsData.domains[0].isoCode).toEqual(isoCode); +}); + +test('can update culture and hostname', async ({umbracoApi, umbracoUi}) => { + // Arrange + const updatedDomainName = 'updateddomain'; + let domainsData = await umbracoApi.document.getDomains(contentId); + domainsData.domains = domainValue; + await umbracoApi.document.updateDomains(contentId, domainsData); + + // Act + await umbracoUi.content.clickActionsMenuForContent(contentName); + await umbracoUi.content.clickCultureAndHostnamesButton(); + await umbracoUi.content.enterDomain(updatedDomainName); + await umbracoUi.content.clickSaveModalButton(); + + // Assert + domainsData = await umbracoApi.document.getDomains(contentId); + expect(domainsData.domains[0].domainName).toEqual(updatedDomainName); + expect(domainsData.domains[0].isoCode).toEqual(isoCode); +}); + +test('can delete culture and hostname', async ({umbracoApi, umbracoUi}) => { + // Arrange + let domainsData = await umbracoApi.document.getDomains(contentId); + domainsData.domains = domainValue; + await umbracoApi.document.updateDomains(contentId, domainsData); + + // Act + await umbracoUi.content.clickActionsMenuForContent(contentName); + await umbracoUi.content.clickCultureAndHostnamesButton(); + await umbracoUi.content.clickDeleteDomainButton(); + await umbracoUi.content.clickSaveModalButton(); + + // Assert + domainsData = await umbracoApi.document.getDomains(contentId); + expect(domainsData.domains.length).toBe(0); +}); + +test('can add culture and hostname for multiple languages', async ({umbracoApi, umbracoUi}) => { + // Arrange + const secondDomainName = 'testdomain2'; + const secondLanguageName = 'Vietnamese'; + const secondIsoCode = 'vi'; + await umbracoApi.language.ensureNameNotExists(secondLanguageName); + await umbracoApi.language.create(secondLanguageName, false, false, secondIsoCode); + + // Act + await umbracoUi.content.clickActionsMenuForContent(contentName); + await umbracoUi.content.clickCultureAndHostnamesButton(); + await umbracoUi.content.clickAddNewDomainButton(); + await umbracoUi.content.enterDomain(domainName, 0); + await umbracoUi.content.selectDomainLanguageOption(languageName, 0); + await umbracoUi.content.clickAddNewDomainButton(); + await umbracoUi.content.enterDomain(secondDomainName, 1); + await umbracoUi.content.selectDomainLanguageOption(secondLanguageName, 1); + await umbracoUi.content.clickSaveModalButton(); + + // Assert + const domainsData = await umbracoApi.document.getDomains(contentId); + expect(domainsData.domains.length).toBe(2); + expect(domainsData.domains[0].domainName).toEqual(domainName); + expect(domainsData.domains[0].isoCode).toEqual(isoCode); + expect(domainsData.domains[1].domainName).toEqual(secondDomainName); + expect(domainsData.domains[1].isoCode).toEqual(secondIsoCode); +}); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/RedirectManagement.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/RedirectManagement.spec.ts new file mode 100644 index 000000000000..0cfe5e2c18d7 --- /dev/null +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/RedirectManagement.spec.ts @@ -0,0 +1,115 @@ +import {ConstantHelper, test} from '@umbraco/playwright-testhelpers'; +import {expect} from "@playwright/test"; + +const disableStatus = 'Disabled'; +const enableStatus = 'Enabled'; +let documentTypeId = ''; +let contentId = ''; +const contentName = 'TestContent'; +const documentTypeName = 'TestDocumentType'; +const updatedContentName = 'UpdatedContentName'; + +test.beforeEach(async ({umbracoApi, umbracoUi}) => { + await umbracoApi.redirectManagement.setStatus(enableStatus); + await umbracoUi.goToBackOffice(); + // Create a content + await umbracoApi.documentType.ensureNameNotExists(documentTypeName); + documentTypeId = await umbracoApi.documentType.createDefaultDocumentTypeWithAllowAsRoot(documentTypeName); + contentId = await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); + // Publish the content + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + await umbracoUi.content.clickActionsMenuForContent(contentName); + await umbracoUi.content.clickPublishButton(); +}); + +test.afterEach(async ({umbracoApi}) => { + await umbracoApi.redirectManagement.setStatus(enableStatus); + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.documentType.ensureNameNotExists(documentTypeName); +}); + +test('can disable URL tracker', async ({umbracoApi, umbracoUi}) => { + // Act + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + await umbracoUi.redirectManagement.clickRedirectManagementTab(); + await umbracoUi.redirectManagement.clickDisableURLTrackerButton(); + await umbracoUi.redirectManagement.clickDisableButton(); + + // Assert + // Verfiy that if renaming a published page, there are no redirects have been made + // rename the published content + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + await umbracoUi.content.openContent(contentName); + await umbracoUi.content.enterContentName(updatedContentName); + await umbracoUi.content.clickSaveAndPublishButton(); + // verify that there is no redirects have been made + const contentData = await umbracoApi.document.get(contentId); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + await umbracoUi.redirectManagement.clickRedirectManagementTab(); + await umbracoUi.redirectManagement.isTextWithExactNameVisible(contentData.urls[0].url, false); + // Verify that the status is Disable + const statusData = await umbracoApi.redirectManagement.getStatus(); + expect(statusData.status).toBe(disableStatus); +}); + +// TODO: Remove skip when the frond-end is ready. Currently there is no redirect have been made after renaming a published page +test.skip('can re-enable URL tracker', async ({umbracoApi, umbracoUi}) => { + // Arrange + await umbracoApi.redirectManagement.setStatus(disableStatus); + + // Act + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + await umbracoUi.redirectManagement.clickRedirectManagementTab(); + await umbracoUi.redirectManagement.clickEnableURLTrackerButton(); + + // Assert + // Verfiy that if renaming a published page, there are one redirects have been made + // rename the published content + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + await umbracoUi.content.openContent(contentName); + await umbracoUi.content.enterContentName(updatedContentName); + await umbracoUi.content.clickSaveAndPublishButton(); + // verify that there is one redirects have been made + const contentData = await umbracoApi.document.get(contentId); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + await umbracoUi.redirectManagement.clickRedirectManagementTab(); + await umbracoUi.redirectManagement.isTextWithExactNameVisible(contentData.urls[0].url); + // Verify that the status is Enable + const statusData = await umbracoApi.redirectManagement.getStatus(); + expect(statusData.status).toBe(enableStatus); +}); + +// TODO: Remove skip and update this when the front-end is ready. Currently it always return "No redirects matching this search criteria" when searching. +test.skip('can search for original URL', async ({umbracoUi}) => { + // Arrange + const searchKeyword = '/test-content/'; + // TODO: rename content to add an item in the redirect url management + + // Act + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + await umbracoUi.redirectManagement.clickRedirectManagementTab(); + await umbracoUi.redirectManagement.enterOriginalUrl(searchKeyword); + await umbracoUi.redirectManagement.clickSearchButton(); + + // Assert + // TODO: verify the search result +}); + +// TODO: Remove skip when the frond-end is ready. Currently there is no redirect have been made after renaming a published page +test.skip('can delete a redirect', async ({umbracoApi, umbracoUi}) => { + // Arrange + // Rename the published content + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + await umbracoUi.content.openContent(contentName); + await umbracoUi.content.enterContentName(updatedContentName); + await umbracoUi.content.clickSaveAndPublishButton(); + + // Act + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + await umbracoUi.redirectManagement.clickRedirectManagementTab(); + await umbracoUi.redirectManagement.deleteFirstRedirectURL(); + + // Assert + const contentData = await umbracoApi.document.get(contentId); + await umbracoUi.redirectManagement.isTextWithExactNameVisible(contentData.urls[0].url, false); +});