diff --git a/tests/Umbraco.Tests.AcceptanceTest/package-lock.json b/tests/Umbraco.Tests.AcceptanceTest/package-lock.json index d9d26331d6..480c6e60fb 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": "^1.0.0", - "@umbraco/playwright-testhelpers": "^1.0.3", + "@umbraco/playwright-testhelpers": "^1.0.10", "camelize": "^1.0.0", "dotenv": "^16.0.2", "faker": "^4.1.0", @@ -101,9 +101,9 @@ } }, "node_modules/@umbraco/playwright-testhelpers": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-1.0.3.tgz", - "integrity": "sha512-PmUnIaoKitxAC4JWSiPEOPg74Ypt6DNLjUQEATV0n9yVbw5aFQhql+KrdN4F30gFNr1c6Gw6I5iDXzNmq5/zfg==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-1.0.10.tgz", + "integrity": "sha512-4NTuMbbNWGcawZIuYnDdPUGN4W2F9iw0EvsyJ2Pr5rYj8Rg1PCu2MXW77r27fGhfr31PYDEL6RSL9zp8SyxfJg==", "dependencies": { "@umbraco/json-models-builders": "^1.0.0", "camelize": "^1.0.0", @@ -906,9 +906,9 @@ } }, "@umbraco/playwright-testhelpers": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-1.0.3.tgz", - "integrity": "sha512-PmUnIaoKitxAC4JWSiPEOPg74Ypt6DNLjUQEATV0n9yVbw5aFQhql+KrdN4F30gFNr1c6Gw6I5iDXzNmq5/zfg==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-1.0.10.tgz", + "integrity": "sha512-4NTuMbbNWGcawZIuYnDdPUGN4W2F9iw0EvsyJ2Pr5rYj8Rg1PCu2MXW77r27fGhfr31PYDEL6RSL9zp8SyxfJg==", "requires": { "@umbraco/json-models-builders": "^1.0.0", "camelize": "^1.0.0", diff --git a/tests/Umbraco.Tests.AcceptanceTest/package.json b/tests/Umbraco.Tests.AcceptanceTest/package.json index 7464e119e0..55da15670c 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/package.json +++ b/tests/Umbraco.Tests.AcceptanceTest/package.json @@ -19,7 +19,7 @@ }, "dependencies": { "@umbraco/json-models-builders": "^1.0.0", - "@umbraco/playwright-testhelpers": "^1.0.3", + "@umbraco/playwright-testhelpers": "^1.0.10", "camelize": "^1.0.0", "faker": "^4.1.0", "form-data": "^4.0.0", diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/content.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/content.spec.ts index ea95f45dc3..c3a78183cf 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/content.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/content.spec.ts @@ -290,11 +290,14 @@ test.describe('Content tests', () => { await umbracoUi.setEditorHeaderName(newNodeName); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); await umbracoUi.isSuccessNotificationVisible(); + await page.locator('span:has-text("×")').click(); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.rollback)); // Not a very nice selector, but there's sadly no alternative :( await page.locator('.-selectable.cursor-pointer').first().click(); - // Sadly can't use the button by label key here since there's another one in the DOM + // Sadly can't use the button by label key here since there's another one in the DOM + const helpText = await page.locator('[key="rollback_diffHelp"]'); + await expect(helpText).toBeVisible(); await page.locator('[action="vm.rollback()"]').click(); await umbracoUi.refreshContentTree(); @@ -663,10 +666,10 @@ test.describe('Content tests', () => { .build(); const alias = AliasHelper.toAlias(name); - + // Save grid and get the ID const dataType = await umbracoApi.dataTypes.save(grid) - + // Create a document type using the data type const docType = new DocumentTypeBuilder() .withName(name) @@ -690,7 +693,7 @@ test.describe('Content tests', () => { .build(); await umbracoApi.content.save(contentNode); - + // Ugly wait but we have to wait for cache to rebuild await page.waitForTimeout(1000); @@ -719,7 +722,7 @@ test.describe('Content tests', () => { // Save and publish await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); await umbracoUi.isSuccessNotificationVisible(); - + const expected = `
diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataTypes/dataTypes.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataTypes/dataTypes.spec.ts index 1da0c016f0..ba6637c693 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataTypes/dataTypes.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataTypes/dataTypes.spec.ts @@ -48,6 +48,7 @@ test.describe('DataTypes', () => { // Save await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); await umbracoUi.isSuccessNotificationVisible(); + await page.locator('span:has-text("×")').click(); // Assert const expected = `

Lorem ipsum dolor sit amet

`; @@ -158,6 +159,7 @@ test.describe('DataTypes', () => { await umbracoUi.setEditorHeaderName('UrlPickerContent'); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); await umbracoUi.isSuccessNotificationVisible(); + await page.locator('span:has-text("×")').click(); await page.locator('.umb-node-preview-add').click(); // Should really try and find a better way to do this, but umbracoTreeItem tries to click the content pane in the background diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/ModelsBuilder/modelsbuilder.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/ModelsBuilder/modelsbuilder.spec.ts new file mode 100644 index 0000000000..998a738e2f --- /dev/null +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/ModelsBuilder/modelsbuilder.spec.ts @@ -0,0 +1,283 @@ +import {AliasHelper, ApiHelpers, ConstantHelper, test, UiHelpers} from '@umbraco/playwright-testhelpers'; +import { + ContentBuilder, + DocumentTypeBuilder, +} from "@umbraco/json-models-builders"; + +test.describe('Modelsbuilder tests', () => { + + test.beforeEach(async ({page, umbracoApi}) => { + await umbracoApi.login(); + }); + + test('Can create and render content', async ({page, umbracoApi, umbracoUi}) => { + const docTypeName = "TestDocument"; + const docTypeAlias = AliasHelper.toAlias(docTypeName); + const contentName = "Home"; + + await umbracoApi.content.deleteAllContent(); + await umbracoApi.documentTypes.ensureNameNotExists(docTypeName); + await umbracoApi.templates.ensureNameNotExists(docTypeName); + + const docType = new DocumentTypeBuilder() + .withName(docTypeName) + .withAlias(docTypeAlias) + .withAllowAsRoot(true) + .withDefaultTemplate(docTypeAlias) + .addTab() + .withName("Content") + .addTextBoxProperty() + .withAlias("title") + .done() + .done() + .build(); + + await umbracoApi.documentTypes.save(docType); + await umbracoApi.templates.edit(docTypeName, `@using Umbraco.Cms.Web.Common.PublishedModels; +@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage +@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels; +@{ +\tLayout = null; +} + +

@Model.Title

`); + + // Time to manually create the content + await umbracoUi.createContentWithDocumentType(docTypeName); + await umbracoUi.setEditorHeaderName(contentName); + // Fortunately for us the input field of a text box has the alias of the property as an id :) + await page.locator("#title").type("Hello world!") + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); + await umbracoUi.isSuccessNotificationVisible(); + // Ensure that we can render it on the frontend = we can compile the models and views + await umbracoApi.content.verifyRenderedContent("/", "

Hello world!

", true); + + await umbracoApi.content.deleteAllContent(); + await umbracoApi.documentTypes.ensureNameNotExists(docTypeName); + await umbracoApi.templates.ensureNameNotExists(docTypeName); + }); + + test('Can update document type without updating view', async ({page, umbracoApi, umbracoUi}) => { + const docTypeName = "TestDocument"; + const docTypeAlias = AliasHelper.toAlias(docTypeName); + const propertyAlias = "title"; + const propertyValue = "Hello world!" + + await umbracoApi.content.deleteAllContent(); + await umbracoApi.documentTypes.ensureNameNotExists(docTypeName); + await umbracoApi.templates.ensureNameNotExists(docTypeName); + + const docType = new DocumentTypeBuilder() + .withName(docTypeName) + .withAlias(docTypeAlias) + .withAllowAsRoot(true) + .withDefaultTemplate(docTypeAlias) + .addTab() + .withName("Content") + .addTextBoxProperty() + .withAlias(propertyAlias) + .done() + .done() + .build(); + + const savedDocType = await umbracoApi.documentTypes.save(docType); + await umbracoApi.templates.edit(docTypeName, `@using Umbraco.Cms.Web.Common.PublishedModels; +@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage +@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels; +@{ +\tLayout = null; +} + +

@Model.Title

`); + + const content = new ContentBuilder() + .withContentTypeAlias(savedDocType["alias"]) + .withAction("publishNew") + .addVariant() + .withName("Home") + .withSave(true) + .withPublish(true) + .addProperty() + .withAlias(propertyAlias) + .withValue(propertyValue) + .done() + .done() + .build() + + await umbracoApi.content.save(content); + + // Navigate to the document type + await umbracoUi.goToSection(ConstantHelper.sections.settings); + await umbracoUi.clickElement(umbracoUi.getTreeItem("settings", ["Document Types", docTypeName])); + // Add a new property (this might cause a version error if the viewcache is not cleared, hence this test + await page.locator('.umb-box-content >> [data-element="property-add"]').click(); + await page.locator('[data-element="property-name"]').type("Second Title"); + await page.locator('[data-element="editor-add"]').click(); + await page.locator('[input-id="datatype-search"]').type("Textstring"); + await page.locator('.umb-card-grid >> [title="Textstring"]').click(); + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.submit)); + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)); + await umbracoUi.isSuccessNotificationVisible(); + + // Now that the content is updated and the models are rebuilt, ensure that we can still render the frontend. + await umbracoApi.content.verifyRenderedContent("/", "

" + propertyValue + "

", true) + + await umbracoApi.content.deleteAllContent(); + await umbracoApi.documentTypes.ensureNameNotExists(docTypeName); + await umbracoApi.templates.ensureNameNotExists(docTypeName); + }); + + test('Can update view without updating document type', async ({page, umbracoApi, umbracoUi}) => { + const docTypeName = "TestDocument"; + const docTypeAlias = AliasHelper.toAlias(docTypeName); + const propertyAlias = "title"; + const propertyValue = "Hello world!" + + await umbracoApi.content.deleteAllContent(); + await umbracoApi.documentTypes.ensureNameNotExists(docTypeName); + await umbracoApi.templates.ensureNameNotExists(docTypeName); + + const docType = new DocumentTypeBuilder() + .withName(docTypeName) + .withAlias(docTypeAlias) + .withAllowAsRoot(true) + .withDefaultTemplate(docTypeAlias) + .addTab() + .withName("Content") + .addTextBoxProperty() + .withAlias(propertyAlias) + .done() + .done() + .build(); + + const savedDocType = await umbracoApi.documentTypes.save(docType); + await umbracoApi.templates.edit(docTypeName, `@using Umbraco.Cms.Web.Common.PublishedModels; +@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage +@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels; +@{ +\tLayout = null; +} + +

@Model.Title

`); + + const content = new ContentBuilder() + .withContentTypeAlias(savedDocType["alias"]) + .withAction("publishNew") + .addVariant() + .withName("Home") + .withSave(true) + .withPublish(true) + .addProperty() + .withAlias(propertyAlias) + .withValue(propertyValue) + .done() + .done() + .build() + + await umbracoApi.content.save(content); + + // Navigate to the document type + await umbracoUi.goToSection(ConstantHelper.sections.settings); + await umbracoUi.clickElement(umbracoUi.getTreeItem("settings", ["templates", docTypeName])); + const editor = await page.locator('.ace_content'); + await editor.click(); + // We only have to type out the opening tag, the editor adds the closing tag automatically. + await editor.type("

Edited") + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)) + + await umbracoUi.isSuccessNotificationVisible(); + await umbracoApi.content.verifyRenderedContent("/", "

" + propertyValue + "

Edited

", true) + + await umbracoApi.content.deleteAllContent(); + await umbracoApi.documentTypes.ensureNameNotExists(docTypeName); + await umbracoApi.templates.ensureNameNotExists(docTypeName); + }); + + test('Can update view and document type', async ({page, umbracoApi, umbracoUi}) => { + const docTypeName = "TestDocument"; + const docTypeAlias = AliasHelper.toAlias(docTypeName); + const propertyAlias = "title"; + const propertyValue = "Hello world!" + const contentName = "Home"; + + await umbracoApi.content.deleteAllContent(); + await umbracoApi.documentTypes.ensureNameNotExists(docTypeName); + await umbracoApi.templates.ensureNameNotExists(docTypeName); + + const docType = new DocumentTypeBuilder() + .withName(docTypeName) + .withAlias(docTypeAlias) + .withAllowAsRoot(true) + .withDefaultTemplate(docTypeAlias) + .addTab() + .withName("Content") + .addTextBoxProperty() + .withAlias(propertyAlias) + .done() + .done() + .build(); + + const savedDocType = await umbracoApi.documentTypes.save(docType); + await umbracoApi.templates.edit(docTypeName, `@using Umbraco.Cms.Web.Common.PublishedModels; +@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage +@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels; +@{ +\tLayout = null; +} + +

@Model.Title

`); + + const content = new ContentBuilder() + .withContentTypeAlias(savedDocType["alias"]) + .withAction("publishNew") + .addVariant() + .withName(contentName) + .withSave(true) + .withPublish(true) + .addProperty() + .withAlias(propertyAlias) + .withValue(propertyValue) + .done() + .done() + .build() + + await umbracoApi.content.save(content); + + // Navigate to the document type + await umbracoUi.goToSection(ConstantHelper.sections.settings); + await umbracoUi.clickElement(umbracoUi.getTreeItem("settings", ["Document Types", docTypeName])); + // Add a new property (this might cause a version error if the viewcache is not cleared, hence this test + await page.locator('.umb-box-content >> [data-element="property-add"]').click(); + await page.locator('[data-element="property-name"]').type("Bod"); + await page.locator('[data-element="editor-add"]').click(); + await page.locator('[input-id="datatype-search"]').type("Textstring"); + await page.locator('.umb-card-grid >> [title="Textstring"]').click(); + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.submit)); + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)); + await umbracoUi.isSuccessNotificationVisible(); + await page.locator('span:has-text("×")').click(); + + // Update the template + await umbracoUi.clickElement(umbracoUi.getTreeItem("settings", ["templates", docTypeName])); + const editor = await page.locator('.ace_content'); + await editor.click(); + // We only have to type out the opening tag, the editor adds the closing tag automatically. + await editor.type("

@Model.Bod") + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)) + await umbracoUi.isSuccessNotificationVisible(); + await page.locator('span:has-text("×")').click(); + + // Navigate to the content section and update the content + await umbracoUi.goToSection(ConstantHelper.sections.content); + await umbracoUi.refreshContentTree(); + await umbracoUi.clickElement(umbracoUi.getTreeItem("content", [contentName])); + await page.locator("#bod").type("Fancy body text"); + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)) + + await umbracoApi.content.verifyRenderedContent("/", "

" + propertyValue + "

Fancy body text

", true); + + await umbracoApi.content.deleteAllContent(); + await umbracoApi.documentTypes.ensureNameNotExists(docTypeName); + await umbracoApi.templates.ensureNameNotExists(docTypeName) + }); +}); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Packages/packages.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Packages/packages.spec.ts index ba91e6ba82..86eff05eec 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Packages/packages.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Packages/packages.spec.ts @@ -88,7 +88,8 @@ test.describe('Packages', () => { // Navigate pack to packages and Assert the file is created // Waits until the button download is visible - await page.locator('[label-key="general_download"]').isVisible(); + await expect(await page.locator('[label-key="general_download"]')).toBeVisible({timeout: 60000}); + // Checks if the packages was created const doesExist = await umbracoApi.packages.doesNameExist(packageName); await expect(doesExist).toBe(true); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/macro.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/macro.spec.ts index c54907d315..895bff5366 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/macro.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/macro.spec.ts @@ -31,6 +31,7 @@ test.describe('Macros', () => { // Adds partial view to macro await page.locator('[data-element="property-label-macroPartialViewPickerProperty"]').click(); + await page.locator('[data-element="tree-item-' + partialViewName + '.cshtml"]').click(); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/relationTypes.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/relationTypes.spec.ts index d1a375ef6e..e49cecde54 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/relationTypes.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/relationTypes.spec.ts @@ -30,11 +30,9 @@ test.describe('Relation Types', () => { await page.selectOption('select[name="relationType-child"]', {label: "Media"}); await form.locator('[name="relationType-isdependency"]').last().click({force: true}); await form.locator('.btn-primary').click(); + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)) + await umbracoUi.isSuccessNotificationVisible(); - await page.waitForNavigation(); - - expect(page.url()).toContain("#/settings/relationTypes/edit/"); - //Clean up await umbracoApi.relationTypes.ensureNameNotExists(name); });