diff --git a/tests/Umbraco.Tests.AcceptanceTest/package-lock.json b/tests/Umbraco.Tests.AcceptanceTest/package-lock.json index 72f6c5904e..70229528bb 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.1", + "@umbraco/playwright-testhelpers": "^1.0.2", "camelize": "^1.0.0", "dotenv": "^16.0.2", "faker": "^4.1.0", @@ -101,11 +101,11 @@ } }, "node_modules/@umbraco/playwright-testhelpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-1.0.1.tgz", - "integrity": "sha512-o3UnVpIlwd9KMKp5Hnv31cUBCkzzIagFY2quQsMFeVfaKXr7Ku1+3egArB9S3bwQhz3aan0jzlmwIp9D9r8vxg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-1.0.2.tgz", + "integrity": "sha512-j1y6YRq2Rg5AXyYk/304P2rTrDCLU7Sz67/MMfkPBHSvadjdof7EW8649Aio29xGAg1YAR4y+Zeyw6XnM35ZkA==", "dependencies": { - "@umbraco/playwright-models": "^5.0.0", + "@umbraco/json-models-builders": "^1.0.0", "camelize": "^1.0.0", "faker": "^4.1.0", "form-data": "^4.0.0", @@ -113,15 +113,6 @@ "xhr2": "^0.2.1" } }, - "node_modules/@umbraco/playwright-testhelpers/node_modules/@umbraco/playwright-models": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@umbraco/playwright-models/-/playwright-models-5.0.0.tgz", - "integrity": "sha512-HOf81JzlGysH9MoZTOH77jjHBEjveTMcxQRpyIfXfQmjdOar6nrEv5MPBMXwgiizLwnkhQBFkRuzKA/YASQnAg==", - "dependencies": { - "camelize": "^1.0.0", - "faker": "^4.1.0" - } - }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -915,27 +906,16 @@ } }, "@umbraco/playwright-testhelpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-1.0.1.tgz", - "integrity": "sha512-o3UnVpIlwd9KMKp5Hnv31cUBCkzzIagFY2quQsMFeVfaKXr7Ku1+3egArB9S3bwQhz3aan0jzlmwIp9D9r8vxg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-1.0.2.tgz", + "integrity": "sha512-j1y6YRq2Rg5AXyYk/304P2rTrDCLU7Sz67/MMfkPBHSvadjdof7EW8649Aio29xGAg1YAR4y+Zeyw6XnM35ZkA==", "requires": { - "@umbraco/playwright-models": "^5.0.0", + "@umbraco/json-models-builders": "^1.0.0", "camelize": "^1.0.0", "faker": "^4.1.0", "form-data": "^4.0.0", "node-fetch": "^2.6.7", "xhr2": "^0.2.1" - }, - "dependencies": { - "@umbraco/playwright-models": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@umbraco/playwright-models/-/playwright-models-5.0.0.tgz", - "integrity": "sha512-HOf81JzlGysH9MoZTOH77jjHBEjveTMcxQRpyIfXfQmjdOar6nrEv5MPBMXwgiizLwnkhQBFkRuzKA/YASQnAg==", - "requires": { - "camelize": "^1.0.0", - "faker": "^4.1.0" - } - } } }, "aggregate-error": { diff --git a/tests/Umbraco.Tests.AcceptanceTest/package.json b/tests/Umbraco.Tests.AcceptanceTest/package.json index b48fafb781..8996b7dbaa 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.1", + "@umbraco/playwright-testhelpers": "^1.0.2", "camelize": "^1.0.0", "faker": "^4.1.0", "form-data": "^4.0.0", diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataTypes/dataTypes.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataTypes/dataTypes.spec.ts new file mode 100644 index 0000000000..1da0c016f0 --- /dev/null +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataTypes/dataTypes.spec.ts @@ -0,0 +1,185 @@ +import {AliasHelper, ConstantHelper, test} from '@umbraco/playwright-testhelpers'; +import {expect} from "@playwright/test"; +import { + ApprovedColorPickerDataTypeBuilder, + DocumentTypeBuilder, + TextBoxDataTypeBuilder +} from "@umbraco/json-models-builders"; + +test.describe('DataTypes', () => { + + test.beforeEach(async ({page, umbracoApi}) => { + await umbracoApi.login(); + }); + + test('Tests Approved Colors', async ({page, umbracoApi, umbracoUi}) => { + const name = 'Approved Colour Test'; + const alias = AliasHelper.toAlias(name); + + await umbracoApi.documentTypes.ensureNameNotExists(name); + await umbracoApi.content.deleteAllContent(); + await umbracoApi.dataTypes.ensureNameNotExists(name); + await umbracoApi.templates.ensureNameNotExists(name); + + const pickerDataType = new ApprovedColorPickerDataTypeBuilder() + .withName(name) + .withPrevalues(['000000', 'FF0000']) + .build() + await umbracoApi.content.createDocTypeWithContent(name, alias, pickerDataType); + + // This is an ugly wait, but we have to wait for cache to rebuild + await page.waitForTimeout(5000); + + // Editing template with some content + await umbracoApi.templates.edit(name, + '@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage' + + '\n@{' + + '\n Layout = null;' + + '\n}' + + '\n

Lorem ipsum dolor sit amet

'); + + // Enter content + await umbracoUi.refreshContentTree(); + await umbracoUi.clickElement(umbracoUi.getTreeItem("content", [name])); + + // Pick a colour + await page.locator('.btn-000000').click(); + + // Save + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); + await umbracoUi.isSuccessNotificationVisible(); + + // Assert + const expected = `

Lorem ipsum dolor sit amet

`; + await expect(umbracoApi.content.verifyRenderedContent('/', expected, true)).toBeTruthy(); + await expect(await page.locator('.umb-button__overlay')).not.toBeVisible(); + + // Pick another colour to verify both work + await page.locator('.btn-FF0000').click(); + + // Save + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); + await umbracoUi.isSuccessNotificationVisible(); + await expect(await page.locator('.umb-button__overlay')).not.toBeVisible(); + + // Assert + const expected2 = '

Lorem ipsum dolor sit amet

'; + await expect(await umbracoApi.content.verifyRenderedContent('/', expected2, true)).toBeTruthy(); + + // Clean + await umbracoApi.documentTypes.ensureNameNotExists(name); + await umbracoApi.content.deleteAllContent(); + await umbracoApi.dataTypes.ensureNameNotExists(name); + await umbracoApi.templates.ensureNameNotExists(name); + }); + + test('Tests Textbox Maxlength', async ({page, umbracoApi, umbracoUi}) => { + const name = 'Textbox Maxlength Test'; + const alias = AliasHelper.toAlias(name); + + await umbracoApi.documentTypes.ensureNameNotExists(name); + await umbracoApi.content.deleteAllContent(); + await umbracoApi.dataTypes.ensureNameNotExists(name); + await umbracoApi.templates.ensureNameNotExists(name); + + const textBoxDataType = new TextBoxDataTypeBuilder() + .withName(name) + .withMaxChars(10) + .build() + await umbracoApi.content.createDocTypeWithContent(name, alias, textBoxDataType); + + // Needs to wait for content to be created. + await page.waitForTimeout(1000); + await umbracoUi.refreshContentTree(); + + // Enter content + await umbracoUi.clickElement(umbracoUi.getTreeItem('content', [name])); + await page.locator('input[name="textbox"]').type('12345678'); + await expect(await page.locator('localize[key="textbox_characters_left"]')).not.toBeVisible(); + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); + await umbracoUi.isSuccessNotificationVisible(); + + // Add char and assert helptext appears - no publish to save time & has been asserted above & below + await page.locator('input[name="textbox"]').type('9'); + await expect(page.locator('localize[key="textbox_characters_left"]', {hasText: "characters left"}).first()).toBeVisible(); + await expect(await umbracoUi.getErrorNotification()).not.toBeVisible(); + + // Add char and assert errortext appears and can't save + await page.locator('input[name="textbox"]').type('10'); // 1 char over max + await expect(page.locator('localize[key="textbox_characters_exceed"]', {hasText: 'too many'}).first()).toBeVisible(); + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); + await expect(await page.locator('.property-error')).toBeVisible(); + + // Clean + await umbracoApi.documentTypes.ensureNameNotExists(name); + await umbracoApi.content.deleteAllContent(); + await umbracoApi.dataTypes.ensureNameNotExists(name); + await umbracoApi.templates.ensureNameNotExists(name); + }); + + test('Test Url Picker', async ({page, umbracoApi, umbracoUi}) => { + + const urlPickerDocTypeName = 'Url Picker Test'; + const pickerDocTypeAlias = AliasHelper.toAlias(urlPickerDocTypeName); + + await umbracoApi.documentTypes.ensureNameNotExists(urlPickerDocTypeName); + await umbracoApi.content.deleteAllContent(); + await umbracoApi.templates.ensureNameNotExists(urlPickerDocTypeName); + + const pickerDocType = new DocumentTypeBuilder() + .withName(urlPickerDocTypeName) + .withAlias(pickerDocTypeAlias) + .withAllowAsRoot(true) + .withDefaultTemplate(pickerDocTypeAlias) + .addGroup() + .withName('ContentPickerGroup') + .addUrlPickerProperty() + .withAlias('picker') + .done() + .done() + .build(); + await umbracoApi.documentTypes.save(pickerDocType); + + await umbracoApi.templates.edit(urlPickerDocTypeName, '@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage' + + '\n@{' + + '\n Layout = null;' + + '\n}' + + '\n@foreach(var link in @Model.Picker)' + + '\n{' + + '\n @link.Name' + + '\n}'); + + // Create content with url picker + await page.locator('.umb-tree-root').click({button: "right"}); + await page.locator('[data-element="action-create"]').click(); + await page.locator('[data-element="action-create-' + pickerDocTypeAlias + '"] > .umb-action-link').click(); + + // Fill out content + await umbracoUi.setEditorHeaderName('UrlPickerContent'); + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); + await umbracoUi.isSuccessNotificationVisible(); + 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 + await page.locator('#treePicker >> [data-element="tree-item-UrlPickerContent"]').click(); + await page.locator('.umb-editor-footer-content__right-side > [button-style="success"] > .umb-button > .btn > .umb-button__content').click(); + await expect(await page.locator('.umb-node-preview__name').first()).toBeVisible(); + + // Save and publish + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); + await umbracoUi.isSuccessNotificationVisible(); + + // Assert + await expect(await umbracoUi.getErrorNotification()).not.toBeVisible(); + + // Testing if the edits match the expected results + const expected = 'UrlPickerContent'; + await expect(await umbracoApi.content.verifyRenderedContent('/', expected, true)).toBeTruthy(); + + // Clean + await umbracoApi.documentTypes.ensureNameNotExists(urlPickerDocTypeName); + await umbracoApi.content.deleteAllContent(); + await umbracoApi.content.deleteAllContent(); + await umbracoApi.templates.ensureNameNotExists(urlPickerDocTypeName); + }); +}); \ No newline at end of file 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 9677418ae2..b0bb06e2a8 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Packages/packages.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Packages/packages.spec.ts @@ -7,7 +7,6 @@ test.describe('Packages', () => { const packageName = "TestPackage"; const rootDocTypeName = "Test document type"; const nodeName = "1) Home"; - test.beforeEach(async ({page, umbracoApi}) => { // TODO: REMOVE THIS WHEN SQLITE IS FIXED // Wait so we don't bombard the API @@ -46,9 +45,60 @@ test.describe('Packages', () => { .build(); const generatedContent = await umbracoApi.content.save(rootContentNode); await CreatePackage(umbracoApi, generatedContent.Id); - } + test('Creates a simple package', async ({page, umbracoApi, umbracoUi}) => { + await umbracoApi.packages.ensureNameNotExists(packageName); + await umbracoApi.content.deleteAllContent(); + await umbracoApi.documentTypes.ensureNameNotExists(rootDocTypeName); + + const rootDocType = new DocumentTypeBuilder() + .withName(rootDocTypeName) + .withAllowAsRoot(true) + .build(); + + const generatedRootDocType = await umbracoApi.documentTypes.save(rootDocType); + const rootDocTypeAlias = generatedRootDocType["alias"]; + + const rootContentNode = new ContentBuilder() + .withContentTypeAlias(rootDocTypeAlias) + .withAction("saveNew") + .addVariant() + .withName(nodeName) + .withSave(true) + .done() + .build(); + await umbracoApi.content.save(rootContentNode); + + // We have to wait for navigation to the packages section, if not it can cause the test to fail + await Promise.all([ + page.waitForNavigation(), + umbracoUi.goToSection(ConstantHelper.sections.packages) + ]); + await page.locator('[data-element="sub-view-umbCreatedPackages"]').click(); + await page.locator("button", {hasText: "Create package"}).click(); + + // Fill out package creation form + // Waits until the element package Content is visible + await page.locator('[key="packager_packageContent"]').isVisible(); + await page.locator("#headerName").type(packageName); + await page.locator('.controls > .umb-node-preview-add').click(); + await page.locator('.umb-tree-item__label').first().click(); + await page.locator("button", {hasText: "Create"}).click(); + + // 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 umbracoUi.goToSection(ConstantHelper.sections.packages); + await page.locator('[data-element="sub-view-umbCreatedPackages"]').click(); + await expect(await page.locator("body", {hasText: packageName})).toBeVisible(); + + // Cleanup + await umbracoApi.packages.ensureNameNotExists(packageName); + await umbracoApi.content.deleteAllContent(); + await umbracoApi.documentTypes.ensureNameNotExists(rootDocTypeName); + }); + test('Deletes a package', async ({page, umbracoApi, umbracoUi}) => { await umbracoApi.content.deleteAllContent(); await umbracoApi.documentTypes.ensureNameNotExists(rootDocTypeName); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/macro.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/macro.spec.ts new file mode 100644 index 0000000000..d127ae5186 --- /dev/null +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/macro.spec.ts @@ -0,0 +1,45 @@ +import {ConstantHelper, test} from '@umbraco/playwright-testhelpers'; +import {PartialViewMacroBuilder} from "@umbraco/json-models-builders"; + +test.describe('Macros', () => { + + test.beforeEach(async ({ page, umbracoApi }) => { + await umbracoApi.login(); + }); + + test('Create macro', async ({ page, umbracoApi, umbracoUi }) => { + const name = "Test macro"; + const partialViewName = "Test partialView"; + + await umbracoApi.macros.ensureNameNotExists(name); + await umbracoApi.partialViews.ensureMacroFileNameNotExists(partialViewName); + + const partialViewMacro = new PartialViewMacroBuilder() + .withName(partialViewName) + .withContent("@inherits Umbraco.Web.Macros.PartialViewMacroPage") + .build(); + await umbracoApi.partialViews.save(partialViewMacro); + + await umbracoUi.goToSection(ConstantHelper.sections.settings); + await umbracoUi.clickElement(umbracoUi.getTreeItem("settings", ["Macros"]), {button: "right"}); + + // Creates macro + await umbracoUi.clickElement(umbracoUi.getContextMenuAction(ConstantHelper.actions.create)); + let form = await page.locator('form[name="createMacroForm"]'); + await form.locator('input[name="itemKey"]').type(name); + await form.locator(".btn-primary").click(); + + // Adds partial view to macro + await page.locator('[label="Macro partial view"]').click(); + await page.locator('[data-element="tree-item-' + partialViewName + '.cshtml"]').click(); + + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)); + + // Assert + await umbracoUi.isSuccessNotificationVisible(); + + // Clean up + await umbracoApi.macros.ensureNameNotExists(name); + await umbracoApi.partialViews.ensureMacroFileNameNotExists(partialViewName); + }); +}); \ No newline at end of file diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Tabs/tabs.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Tabs/tabs.spec.ts index cff2a2ba7b..f009af5ce1 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Tabs/tabs.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Tabs/tabs.spec.ts @@ -451,6 +451,60 @@ test.describe('Tabs', () => { await expect(await page.locator('[title="aTab 2"]').first()).toBeVisible(); }); + test('Drags and drops a property in a tab', async ({umbracoUi, umbracoApi, page}) => { + await umbracoApi.documentTypes.ensureNameNotExists(tabsDocTypeName); + const tabsDocType = new DocumentTypeBuilder() + .withName(tabsDocTypeName) + .withAlias(tabsDocTypeAlias) + .withAllowAsRoot(true) + .withDefaultTemplate(tabsDocTypeAlias) + .addTab() + .withName('Tab 1') + .addGroup() + .withName('Tab group') + .addUrlPickerProperty() + .withAlias("urlPicker") + .withLabel('UrlPickerOne') + .done() + .done() + .done() + .addTab() + .withName('Tab 2') + .addGroup() + .withName('Tab group tab 2') + .addUrlPickerProperty() + .withAlias('urlPickerTabTwo') + .withLabel('UrlPickerTabTwo') + .done() + .addUrlPickerProperty() + .withAlias('urlPickerTwo') + .withLabel('UrlPickerTwo') + .done() + .done() + .done() + .build(); + await umbracoApi.documentTypes.save(tabsDocType); + await openDocTypeFolder(umbracoUi, page); + await page.locator('[alias="reorder"]').click(); + await page.locator('.umb-group-builder__tab').last().click(); + + // Drag and drop property from tab 2 into tab 1 + await page.locator('.umb-group-builder__property-meta > .flex > .icon >> nth=1').last().hover(); + await page.mouse.down(); + await page.locator('.umb-group-builder__tab >> nth=1').hover({force:true}); + await page.waitForTimeout(500); + await page.locator('[data-element="group-Tab group"]').hover({force:true}); + await page.mouse.up(); + + // Stop reordering and save + await page.locator('[alias="reorder"]').click(); + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)); + + // Assert + await umbracoUi.isSuccessNotificationVisible(); + await expect(await page.locator('[title="urlPickerTabTwo"]')).toBeVisible(); + }); + test('Drags and drops a group and converts to tab', async ({umbracoUi, umbracoApi, page}) => { await umbracoApi.documentTypes.ensureNameNotExists(tabsDocTypeName); const tabsDocType = new DocumentTypeBuilder() @@ -496,7 +550,7 @@ test.describe('Tabs', () => { await page.waitForTimeout(2000); await page.mouse.up(); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)); - //Assert + // Assert await umbracoUi.isSuccessNotificationVisible(); await expect(await page.locator('[title="tabGroup"]').first()).toBeVisible(); });