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..43adbc21fe --- /dev/null +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/ModelsBuilder/modelsbuilder.spec.ts @@ -0,0 +1,282 @@ +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 umbracoApi.content.verifyRenderedContent("/", "

" + propertyValue + "

Fancy body text

", true); + + await umbracoApi.content.deleteAllContent(); + await umbracoApi.documentTypes.ensureNameNotExists(docTypeName); + await umbracoApi.templates.ensureNameNotExists(docTypeName) + }); +});