From 158cef16929de4991a3917636e0ec41d3db76d7d Mon Sep 17 00:00:00 2001 From: Andreas Zerbst <73799582+andr317c@users.noreply.github.com> Date: Wed, 20 Sep 2023 12:15:24 +0200 Subject: [PATCH 1/4] V10 fixed up failing acceptance test (#14829) * Updated playwright, our builders, and our helpers * Updated the use of our testhelper methods, we removed the need for sending umbracoApi through the methods as a parameter since it was unnecessary * Added a timeout * Updated successNotifications and added a locator * Removed timeout from successNotification * Added additional timeouts and updated old locators which were failing * Updated locator so it only finds one element * Removed timeouts and added a waitForTimeout * Removed timeouts * Removed timeouts * Added timeouts * Updated locator * Added a timeout * Updated locators for clicking button * Changed locator for adding the image, sometimes the old locator would find 2 locators --- .../package-lock.json | 114 ++++++++++-------- .../Umbraco.Tests.AcceptanceTest/package.json | 6 +- .../Content/blockGridEditorAdvanced.spec.ts | 24 ++-- .../blockGridEditorAreasContent.spec.ts | 96 +++++++-------- .../Content/blockGridEditorContent.spec.ts | 56 ++++----- .../Content/blockGridEditorRendering.spec.ts | 60 ++++----- .../Content/blockGridEditorSettings.spec.ts | 38 +++--- .../BlockGridEditorDataTypeBlocks.spec.ts | 23 ++-- .../blockListEditorContent.spec.ts | 7 +- .../blockListEditorDocument.spec.ts | 17 ++- .../DefaultConfig/Content/content.spec.ts | 12 +- .../DefaultConfig/Content/routing.spec.ts | 14 +-- .../DefaultConfig/DataTypes/dataTypes.spec.ts | 15 ++- .../DataTypes/textBoxVariation.spec.ts | 6 +- .../DefaultConfig/Media/mediaSection.spec.ts | 2 +- .../ModelsBuilder/modelsbuilder.spec.ts | 22 ++-- .../Settings/partialViewMacroFiles.spec.ts | 24 ++-- .../Settings/partialViews.spec.ts | 8 +- 18 files changed, 281 insertions(+), 263 deletions(-) diff --git a/tests/Umbraco.Tests.AcceptanceTest/package-lock.json b/tests/Umbraco.Tests.AcceptanceTest/package-lock.json index e0c761a08b..cb06c7964d 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/package-lock.json +++ b/tests/Umbraco.Tests.AcceptanceTest/package-lock.json @@ -7,8 +7,8 @@ "name": "acceptancetest", "hasInstallScript": true, "dependencies": { - "@umbraco/json-models-builders": "^1.0.5", - "@umbraco/playwright-testhelpers": "^1.0.22", + "@umbraco/json-models-builders": "^1.0.6", + "@umbraco/playwright-testhelpers": "^1.0.25", "camelize": "^1.0.0", "dotenv": "^16.0.2", "faker": "^4.1.0", @@ -17,7 +17,7 @@ "xhr2": "^0.2.1" }, "devDependencies": { - "@playwright/test": "^1.32", + "@playwright/test": "^1.38", "del": "^6.0.0", "ncp": "^2.0.0", "prompt": "^1.2.0", @@ -70,45 +70,35 @@ } }, "node_modules/@playwright/test": { - "version": "1.32.3", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.32.3.tgz", - "integrity": "sha512-BvWNvK0RfBriindxhLVabi8BRe3X0J9EVjKlcmhxjg4giWBD/xleLcg2dz7Tx0agu28rczjNIPQWznwzDwVsZQ==", + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.38.0.tgz", + "integrity": "sha512-xis/RXXsLxwThKnlIXouxmIvvT3zvQj1JE39GsNieMUrMpb3/GySHDh2j8itCG22qKVD4MYLBp7xB73cUW/UUw==", "dev": true, "dependencies": { - "@types/node": "*", - "playwright-core": "1.32.3" + "playwright": "1.38.0" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=14" - }, - "optionalDependencies": { - "fsevents": "2.3.2" + "node": ">=16" } }, - "node_modules/@types/node": { - "version": "14.17.33", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.33.tgz", - "integrity": "sha512-noEeJ06zbn3lOh4gqe2v7NMGS33jrulfNqYFDjjEbhpDEHR5VTxgYNQSBqBlJIsBJW3uEYDgD6kvMnrrhGzq8g==", - "dev": true - }, "node_modules/@umbraco/json-models-builders": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@umbraco/json-models-builders/-/json-models-builders-1.0.5.tgz", - "integrity": "sha512-14xowT8oiW9+DQVOoundRPvcvnNrU0Ey+06G/q/iZyUnqaNRu/i5nUqcbUZGdv6VBCdxaxq2H3WwtSET3gtneA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@umbraco/json-models-builders/-/json-models-builders-1.0.6.tgz", + "integrity": "sha512-bXwfXcpuqG1Ye714L9KJEGXuSzJfckysE/6CuPjdG8FqHWTE1brv28teR2oMw+ih8ca2u2zUboRgdzLEU/1D3Q==", "dependencies": { "camelize": "^1.0.0", "faker": "^4.1.0" } }, "node_modules/@umbraco/playwright-testhelpers": { - "version": "1.0.22", - "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-1.0.22.tgz", - "integrity": "sha512-hFqqQvEIylagfqFyhQ2rSyYlUP+xpWA5lkhJjkpb2qpxkIISxjwC/FYJTJGvcoBHuUaZrjsSv4lM2aJy2ZWHMA==", + "version": "1.0.25", + "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-1.0.25.tgz", + "integrity": "sha512-6H452J6LhP0EHjF4jR7V7i0U8WPTiAbSyhN1J459BbbYEJ4QX1A2ZlCdA6VSBAsK1xYdMXD+yxsVJq7AAwiy9A==", "dependencies": { - "@umbraco/json-models-builders": "^1.0.5", + "@umbraco/json-models-builders": "^1.0.6", "camelize": "^1.0.0", "faker": "^4.1.0", "form-data": "^4.0.0", @@ -647,16 +637,34 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/playwright-core": { - "version": "1.32.3", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.32.3.tgz", - "integrity": "sha512-SB+cdrnu74ZIn5Ogh/8278ngEh9NEEV0vR4sJFmK04h2iZpybfbqBY0bX6+BLYWVdV12JLLI+JEFtSnYgR+mWg==", + "node_modules/playwright": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.38.0.tgz", + "integrity": "sha512-fJGw+HO0YY+fU/F1N57DMO+TmXHTrmr905J05zwAQE9xkuwP/QLDk63rVhmyxh03dYnEhnRbsdbH9B0UVVRB3A==", "dev": true, + "dependencies": { + "playwright-core": "1.38.0" + }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=14" + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.38.0.tgz", + "integrity": "sha512-f8z1y8J9zvmHoEhKgspmCvOExF2XdcxMW8jNRuX4vkQFrzV4MlZ55iwb5QeyiFQgOFCUolXiRHgpjSEnqvO48g==", + "dev": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=16" } }, "node_modules/prompt": { @@ -898,37 +906,29 @@ } }, "@playwright/test": { - "version": "1.32.3", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.32.3.tgz", - "integrity": "sha512-BvWNvK0RfBriindxhLVabi8BRe3X0J9EVjKlcmhxjg4giWBD/xleLcg2dz7Tx0agu28rczjNIPQWznwzDwVsZQ==", + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.38.0.tgz", + "integrity": "sha512-xis/RXXsLxwThKnlIXouxmIvvT3zvQj1JE39GsNieMUrMpb3/GySHDh2j8itCG22qKVD4MYLBp7xB73cUW/UUw==", "dev": true, "requires": { - "@types/node": "*", - "fsevents": "2.3.2", - "playwright-core": "1.32.3" + "playwright": "1.38.0" } }, - "@types/node": { - "version": "14.17.33", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.33.tgz", - "integrity": "sha512-noEeJ06zbn3lOh4gqe2v7NMGS33jrulfNqYFDjjEbhpDEHR5VTxgYNQSBqBlJIsBJW3uEYDgD6kvMnrrhGzq8g==", - "dev": true - }, "@umbraco/json-models-builders": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@umbraco/json-models-builders/-/json-models-builders-1.0.5.tgz", - "integrity": "sha512-14xowT8oiW9+DQVOoundRPvcvnNrU0Ey+06G/q/iZyUnqaNRu/i5nUqcbUZGdv6VBCdxaxq2H3WwtSET3gtneA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@umbraco/json-models-builders/-/json-models-builders-1.0.6.tgz", + "integrity": "sha512-bXwfXcpuqG1Ye714L9KJEGXuSzJfckysE/6CuPjdG8FqHWTE1brv28teR2oMw+ih8ca2u2zUboRgdzLEU/1D3Q==", "requires": { "camelize": "^1.0.0", "faker": "^4.1.0" } }, "@umbraco/playwright-testhelpers": { - "version": "1.0.22", - "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-1.0.22.tgz", - "integrity": "sha512-hFqqQvEIylagfqFyhQ2rSyYlUP+xpWA5lkhJjkpb2qpxkIISxjwC/FYJTJGvcoBHuUaZrjsSv4lM2aJy2ZWHMA==", + "version": "1.0.25", + "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-1.0.25.tgz", + "integrity": "sha512-6H452J6LhP0EHjF4jR7V7i0U8WPTiAbSyhN1J459BbbYEJ4QX1A2ZlCdA6VSBAsK1xYdMXD+yxsVJq7AAwiy9A==", "requires": { - "@umbraco/json-models-builders": "^1.0.5", + "@umbraco/json-models-builders": "^1.0.6", "camelize": "^1.0.0", "faker": "^4.1.0", "form-data": "^4.0.0", @@ -1329,10 +1329,20 @@ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, + "playwright": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.38.0.tgz", + "integrity": "sha512-fJGw+HO0YY+fU/F1N57DMO+TmXHTrmr905J05zwAQE9xkuwP/QLDk63rVhmyxh03dYnEhnRbsdbH9B0UVVRB3A==", + "dev": true, + "requires": { + "fsevents": "2.3.2", + "playwright-core": "1.38.0" + } + }, "playwright-core": { - "version": "1.32.3", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.32.3.tgz", - "integrity": "sha512-SB+cdrnu74ZIn5Ogh/8278ngEh9NEEV0vR4sJFmK04h2iZpybfbqBY0bX6+BLYWVdV12JLLI+JEFtSnYgR+mWg==", + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.38.0.tgz", + "integrity": "sha512-f8z1y8J9zvmHoEhKgspmCvOExF2XdcxMW8jNRuX4vkQFrzV4MlZ55iwb5QeyiFQgOFCUolXiRHgpjSEnqvO48g==", "dev": true }, "prompt": { diff --git a/tests/Umbraco.Tests.AcceptanceTest/package.json b/tests/Umbraco.Tests.AcceptanceTest/package.json index 6262fe6ced..5cabb6b091 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/package.json +++ b/tests/Umbraco.Tests.AcceptanceTest/package.json @@ -10,7 +10,7 @@ "createTest": "node createTest.js" }, "devDependencies": { - "@playwright/test": "^1.32", + "@playwright/test": "^1.38", "typescript": "^4.8.3", "tslib": "^2.4.0", "del": "^6.0.0", @@ -18,8 +18,8 @@ "prompt": "^1.2.0" }, "dependencies": { - "@umbraco/json-models-builders": "^1.0.5", - "@umbraco/playwright-testhelpers": "^1.0.22", + "@umbraco/json-models-builders": "^1.0.6", + "@umbraco/playwright-testhelpers": "^1.0.25", "camelize": "^1.0.0", "faker": "^4.1.0", "form-data": "^4.0.0", diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorAdvanced.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorAdvanced.spec.ts index 87b19b8776..79a5cacf71 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorAdvanced.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorAdvanced.spec.ts @@ -44,7 +44,7 @@ test.describe('BlockGridEditorAdvancedContent', () => { await umbracoApi.media.ensureNameNotExists(customViewItemName); const imageData = await umbracoApi.media.createImageWithFile(imageName, umbracoFileValue, imageFileName, imagePath, imageMimeType); - + const customViewData = await umbracoApi.media.createFileWithFile(customViewItemName, customViewFileName, customViewPath, customViewMimeType); const customViewMediaPath = customViewData.mediaLink; @@ -72,7 +72,7 @@ test.describe('BlockGridEditorAdvancedContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -101,7 +101,7 @@ test.describe('BlockGridEditorAdvancedContent', () => { await umbracoUi.navigateToContent(blockGridName); // Assert - // Checks if the block has the correct CustomView + // Checks if the block has the correct CustomView await expect(page.locator('[data-content-element-type-key="' + element['key'] + '"]').locator('[view="' + customViewMediaPath + '"]')).toBeVisible(); // Checks if the custom view updated the block by locating a name in the customView await expect(page.locator('[data-content-element-type-key="' + element['key'] + '"]').locator('[view="' + customViewMediaPath + '"]').locator('[name="BlockGridCustomView"]')).toBeVisible(); @@ -134,10 +134,10 @@ test.describe('BlockGridEditorAdvancedContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); - + // Assert // Checks if the block has the correct template await expect(page.locator('umb-block-grid-entry', {hasText: elementName}).locator('umb-block-grid-block')).toHaveAttribute('stylesheet', stylesheetDataPath); @@ -160,7 +160,7 @@ test.describe('BlockGridEditorAdvancedContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); @@ -186,7 +186,7 @@ test.describe('BlockGridEditorAdvancedContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); @@ -213,7 +213,7 @@ test.describe('BlockGridEditorAdvancedContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); @@ -250,7 +250,7 @@ test.describe('BlockGridEditorAdvancedContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); @@ -288,7 +288,7 @@ test.describe('BlockGridEditorAdvancedContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); @@ -336,7 +336,7 @@ test.describe('BlockGridEditorAdvancedContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); @@ -352,4 +352,4 @@ test.describe('BlockGridEditorAdvancedContent', () => { await umbracoApi.media.ensureNameNotExists(imageName); }); }); -}); \ No newline at end of file +}); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorAreasContent.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorAreasContent.spec.ts index a55c12a7d9..5419c74adc 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorAreasContent.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorAreasContent.spec.ts @@ -6,26 +6,26 @@ import {expect} from "@playwright/test"; test.describe('BlockGridEditorAreasContent', () => { const documentName = 'DocumentTest'; const blockGridName = 'BlockGridTest'; - const elementTitleName = 'ElementTitle'; + const elementTitleName = 'ElementTitle'; const titleText = 'ElementTitle'; const titleArea = 'AreaTitle'; const elementBodyName = 'ElementBody'; const bodyText = 'Lorem ipsum dolor sit amet'; - + const elementBodyAlias = AliasHelper.toAlias(elementBodyName); const documentAlias = AliasHelper.toAlias(documentName); const blockGridAlias = AliasHelper.toAlias(blockGridName); const elementTitleAlias = AliasHelper.toAlias(elementTitleName); - + async function createContentWithABlockInAnotherBlock(umbracoApi,elementParent, elementChild, dataType?, document?) { if (dataType == null) { - dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(umbracoApi, elementParent, elementChild, blockGridName, titleArea); + dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(elementParent, elementChild, blockGridName, titleArea); } if (document == null) { - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, elementParent, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(elementParent, dataType); } - + const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) .withAction(ConstantHelper.actions.save) @@ -58,7 +58,7 @@ test.describe('BlockGridEditorAreasContent', () => { .build(); return await umbracoApi.content.save(rootContentNode); } - + test.beforeEach(async ({page, umbracoApi, umbracoUi}, testInfo) => { await umbracoApi.report.report(testInfo); await umbracoApi.login(); @@ -80,12 +80,12 @@ test.describe('BlockGridEditorAreasContent', () => { const element = await umbracoApi.documentTypes.createDefaultElementType(elementTitleName, elementTitleAlias); const elementBody = await umbracoApi.documentTypes.createDefaultElementType(elementBodyName, elementBodyAlias); - const dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(umbracoApi, element, elementBody, blockGridName, titleArea); - - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + const dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(element, elementBody, blockGridName, titleArea); + + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); - + // Adds a body to the area await page.locator('[data-content-element-type-key="' + element['key'] + '"] >> [data-area-alias="' + titleArea + '"]').click(); await page.locator('[name="infiniteEditorForm"]').locator('[data-element="editor-container"]').getByRole('button', {name: elementBodyName}).click(); @@ -166,9 +166,9 @@ test.describe('BlockGridEditorAreasContent', () => { .done() .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - + await createContentWithABlockInAnotherBlock(umbracoApi, element, elementBody, dataType); - + await umbracoUi.navigateToContent(blockGridName); // Adds another body to the area @@ -204,7 +204,7 @@ test.describe('BlockGridEditorAreasContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); @@ -212,12 +212,12 @@ test.describe('BlockGridEditorAreasContent', () => { // Checks if the area in content has the value that is defined in the block grid editor await expect(page.locator('[data-content-element-type-key="' + element['key'] + '"]').locator('[data-area-alias="' + titleArea + '"]')).toHaveAttribute('data-area-col-span', '6'); }); - + test('can add two different blocks in a area with different grid columns', async ({page, umbracoApi, umbracoUi}) => { const secondArea = 'AreaFour'; const columnSpanEight = "8"; const columnSpanFour = "4"; - + const element = await umbracoApi.documentTypes.createDefaultElementType(elementTitleName, elementTitleAlias); const elementBody = await umbracoApi.documentTypes.createDefaultElementType(elementBodyName, elementBodyAlias); @@ -239,8 +239,8 @@ test.describe('BlockGridEditorAreasContent', () => { .done() .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -275,14 +275,14 @@ test.describe('BlockGridEditorAreasContent', () => { await umbracoApi.content.save(rootContentNode); await umbracoUi.navigateToContent(blockGridName); - + // Adds a block to the area with a different column span await page.locator('[data-content-element-type-key="' + element['key'] + '"]').locator('[data-area-alias="' + secondArea + '"]').getByRole('button', {name: 'Add content'}).click(); await page.locator('[name="infiniteEditorForm"]').locator('[data-element="editor-container"]').getByRole('button', {name: elementBodyName}).click(); await page.locator('[id="sub-view-0"]').locator('[id="title"]').fill('BodyTwoText'); await page.locator('[label="Create"]').click(); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); - + // Assert await umbracoUi.isSuccessNotificationVisible(); // Checks if there are two block in the ElementTitle Area @@ -311,14 +311,14 @@ test.describe('BlockGridEditorAreasContent', () => { .done() .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, false); + + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); // Checks if the button has the correct row span await expect(page.locator('[data-content-element-type-key="' + element['key'] + '"]').locator('[data-area-row-span="3"]').getByRole('button', {name: 'Add content'})).toBeVisible(); - + // Adds a block to the area await page.locator('[data-content-element-type-key="' + element['key'] + '"]').locator('[data-area-alias="' + titleArea + '"]').getByRole('button', {name: 'Add content'}).click(); await page.locator('[name="infiniteEditorForm"]').locator('[data-element="editor-container"]').getByRole('button', {name: elementBodyName}).click(); @@ -336,7 +336,7 @@ test.describe('BlockGridEditorAreasContent', () => { await expect(page.locator('[data-content-element-type-key="' + element['key'] + '"]').locator('[data-content-element-type-alias="' + elementBodyAlias + '"]')).toHaveAttribute('data-row-span', '3'); }); }); - + test.describe('Create Button Label', () => { test('can add a create button label for an area in block grid editor', async ({page, umbracoApi, umbracoUi}) => { const newButtonLabel = 'NewAreaBlock'; @@ -358,9 +358,9 @@ test.describe('BlockGridEditorAreasContent', () => { .done() .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, false); - + + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); + await umbracoUi.navigateToContent(blockGridName); // Assert @@ -371,7 +371,7 @@ test.describe('BlockGridEditorAreasContent', () => { await createButtonLocator.click(); }); }); - + test.describe('Number of blocks', () => { test('can add a minimum number of blocks for a block grid editor', async ({page, umbracoApi, umbracoUi}) => { const element = await umbracoApi.documentTypes.createDefaultElementType(elementTitleName, elementTitleAlias); @@ -418,7 +418,7 @@ test.describe('BlockGridEditorAreasContent', () => { test('can add a maximum number of blocks for a block grid editor', async ({page, umbracoApi, umbracoUi}) => { const bodyTextTwo = 'AnotherBody'; - + const element = await umbracoApi.documentTypes.createDefaultElementType(elementTitleName, elementTitleAlias); const elementBody = await umbracoApi.documentTypes.createDefaultElementType(elementBodyName, elementBodyAlias); @@ -437,7 +437,7 @@ test.describe('BlockGridEditorAreasContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -522,7 +522,7 @@ test.describe('BlockGridEditorAreasContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -551,7 +551,7 @@ test.describe('BlockGridEditorAreasContent', () => { await umbracoApi.content.save(rootContentNode); await umbracoUi.navigateToContent(blockGridName); - + // Adds a ElementBody await page.locator('[data-content-element-type-key="' + element['key'] + '"]').locator('[data-area-alias="' + titleArea + '"]').click(); // Since the ElementBody is added as the only Specified Allowance for the area of the Element, then we should be instantly directed to it, instead of having to pick it. @@ -586,7 +586,7 @@ test.describe('BlockGridEditorAreasContent', () => { const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); await createContentWithABlockInAnotherBlock(umbracoApi, element, elementBody, dataType, null); - + await umbracoUi.navigateToContent(blockGridName); // Checks if a validation error is visible @@ -630,7 +630,7 @@ test.describe('BlockGridEditorAreasContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -736,7 +736,7 @@ test.describe('BlockGridEditorAreasContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -778,7 +778,7 @@ test.describe('BlockGridEditorAreasContent', () => { await umbracoApi.content.save(rootContentNode); await umbracoUi.navigateToContent(blockGridName); - + // Checks if there is validation error for both blocks await expect(page.locator('[key="blockEditor_areaValidationEntriesExceed"]', {hasText: elementBodyName})).toBeVisible(); await expect(page.locator('[key="blockEditor_areaValidationEntriesShort"]', {hasText: elementFooterName})).toBeVisible(); @@ -808,7 +808,7 @@ test.describe('BlockGridEditorAreasContent', () => { await expect(page.locator('[data-content-element-type-key="' + element['key'] + '"]').locator('[data-content-element-type-alias="' + elementBodyAlias + '"]')).toHaveCount(1); await expect(page.locator('[data-content-element-type-key="' + element['key'] + '"]').locator('[data-content-element-type-alias="' + elementFooterAlias + '"]')).toHaveCount(1); - // Clean + // Clean await umbracoApi.documentTypes.ensureNameNotExists(elementFooterName); }); }); @@ -818,9 +818,9 @@ test.describe('BlockGridEditorAreasContent', () => { const element = await umbracoApi.documentTypes.createDefaultElementType(elementTitleName, elementTitleAlias); const elementBody = await umbracoApi.documentTypes.createDefaultElementType(elementBodyName, elementBodyAlias); - const dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(umbracoApi, element, elementBody, blockGridName, titleArea); + const dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(element, elementBody, blockGridName, titleArea); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -869,9 +869,9 @@ test.describe('BlockGridEditorAreasContent', () => { const element = await umbracoApi.documentTypes.createDefaultElementType(elementTitleName, elementTitleAlias); const elementBody = await umbracoApi.documentTypes.createDefaultElementType(elementBodyName, elementBodyAlias); - const dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(umbracoApi, element, elementBody, blockGridName, titleArea); + const dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(element, elementBody, blockGridName, titleArea); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -935,9 +935,9 @@ test.describe('BlockGridEditorAreasContent', () => { const element = await umbracoApi.documentTypes.createDefaultElementType(elementTitleName, elementTitleAlias); const elementBody = await umbracoApi.documentTypes.createDefaultElementType(elementBodyName, elementBodyAlias); - const dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(umbracoApi, element, elementBody, blockGridName, titleArea); + const dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(element, elementBody, blockGridName, titleArea); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -1002,9 +1002,9 @@ test.describe('BlockGridEditorAreasContent', () => { const element = await umbracoApi.documentTypes.createDefaultElementType(elementTitleName, elementTitleAlias); const elementBody = await umbracoApi.documentTypes.createDefaultElementType(elementBodyName, elementBodyAlias); - const dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(umbracoApi, element, elementBody, blockGridName, titleArea); + const dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(element, elementBody, blockGridName, titleArea); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -1041,14 +1041,14 @@ test.describe('BlockGridEditorAreasContent', () => { const blockParentUdi = rootContentNode.variants[0].properties[0].value.contentData[1].udi; await umbracoUi.navigateToContent(blockGridName); - + // Copies and pastes the block into another block await page.locator('[data-element-udi="' + blockParentUdi + '"]').getByRole('button', {name: 'Copy'}).nth(1).click(); await page.locator('[data-element="property-' + blockGridAlias + '"]').getByRole('button', {name: 'Clipboard'}).click(); await page.locator('[data-element="editor-container"]').locator('umb-block-card', {hasText: elementTitleName}).click(); - + // Checks if the blocks were copied await expect(page.locator('[data-content-element-type-alias="' + elementTitleAlias + '"]')).toHaveCount(2); }); }); -}); \ No newline at end of file +}); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorContent.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorContent.spec.ts index 9eb4d75e92..8b2f86db74 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorContent.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorContent.spec.ts @@ -27,8 +27,8 @@ test.describe('BlockGridEditorContent', () => { }); test('can create content with a block grid editor', async ({page, umbracoApi, umbracoUi}) => { - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, null, null); - + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(null, null); + const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) .withAction(ConstantHelper.actions.save) @@ -58,11 +58,11 @@ test.describe('BlockGridEditorContent', () => { const newContentValue = 'UpdatedTitle'; const newSettingValue = 'UpdatedSetting'; - const element = await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, null, null, null); + const element = await umbracoApi.content.createDefaultContentWithABlockGridEditor(null, null, null); await umbracoUi.navigateToContent(blockGridName); - // Updates the already created content text + // Updates the already created content text await page.locator('[data-content-element-type-key="' + element['key'] + '"]', {hasText: elementName}).click(); await page.locator('[id="sub-view-0"]').locator('[id="title"]').fill(newContentValue); await umbracoUi.clickDataElementByElementName('sub-view-settings'); @@ -71,7 +71,7 @@ test.describe('BlockGridEditorContent', () => { await page.locator('[label="Submit"]').click(); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); - // Assert + // Assert await umbracoUi.isSuccessNotificationVisible(); // Checks if the Content and Setting were updated after it was saved await page.locator('[data-content-element-type-key="' + element['key'] + '"]', {hasText: elementName}).click(); @@ -81,13 +81,13 @@ test.describe('BlockGridEditorContent', () => { }); test('can delete a block grid editor in content', async ({page, umbracoApi, umbracoUi}) => { - const element = await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, null, null, null); + const element = await umbracoApi.content.createDefaultContentWithABlockGridEditor(null, null, null); await umbracoUi.navigateToContent(blockGridName); // Deletes the block grid editor inside of the content await page.getByTitle("Delete").click(); - + // Can't use our constant helper because the action for delete does not contain an s. The correct way is 'action-delete' await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey('actions_delete')); @@ -101,7 +101,7 @@ test.describe('BlockGridEditorContent', () => { }); test('can copy block grid content and paste it', async ({page, umbracoApi, umbracoUi}) => { - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, null, null, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(null, null, null); await umbracoUi.navigateToContent(blockGridName); // Checks to make sure that there is only one item @@ -134,7 +134,7 @@ test.describe('BlockGridEditorContent', () => { const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias); - const dataType = await umbracoApi.dataTypes.createDefaultBlockGrid(umbracoApi, blockGridName, element); + const dataType = await umbracoApi.dataTypes.createDefaultBlockGrid(blockGridName, element); const docType = new DocumentTypeBuilder() .withName(documentName) @@ -157,7 +157,7 @@ test.describe('BlockGridEditorContent', () => { .build(); await umbracoApi.documentTypes.save(docType); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, true); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, true); await umbracoUi.navigateToContent(blockGridName); @@ -192,9 +192,9 @@ test.describe('BlockGridEditorContent', () => { const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias); // We give the dataType a label so we can differentiate between the top and bottom block in the content editor. - const dataType = await umbracoApi.dataTypes.createDefaultBlockGrid(umbracoApi, blockGridName, element, '{{' + element.groups[0].properties[0].alias + '}}'); + const dataType = await umbracoApi.dataTypes.createDefaultBlockGrid(blockGridName, element, '{{' + element.groups[0].properties[0].alias + '}}'); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -226,7 +226,7 @@ test.describe('BlockGridEditorContent', () => { await umbracoApi.content.save(rootContentNode); await umbracoUi.navigateToContent(blockGridName); - + // Drag and Drop const dragFromLocator = await page.locator('[data-content-element-type-key="' + element['key'] + '"]', {hasText: bottomBlock}); const dragToLocator = await page.locator('[data-content-element-type-key="' + element['key'] + '"]', {hasText: topBlock}); @@ -253,7 +253,7 @@ test.describe('BlockGridEditorContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -319,7 +319,7 @@ test.describe('BlockGridEditorContent', () => { await umbracoApi.media.createDefaultImage(imageName); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, null); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, null); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -346,7 +346,7 @@ test.describe('BlockGridEditorContent', () => { // Selects the created image for the block await page.locator('[data-content-element-type-key="' + element['key'] + '"]').click(); - await page.locator('[data-element="property-image"]').locator('[key="' + ConstantHelper.buttons.add + '"]').click(); + await page.getByRole('button', { name: 'Add', exact: true }).click(); await page.locator('[data-element="media-grid"] >> [title="' + imageName + '"]').click(); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.select)); await page.locator('[label="Submit"]').click(); @@ -374,7 +374,7 @@ test.describe('BlockGridEditorContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, false); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); // Checks if there is validation for needing 2 entries or more @@ -408,7 +408,7 @@ test.describe('BlockGridEditorContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -470,7 +470,7 @@ test.describe('BlockGridEditorContent', () => { test.describe('Live editing mode', () => { test('can use live editing mode in content with a block grid editor', async ({page, umbracoApi, umbracoUi}) => { const newText = 'LiveUpdatedContent'; - + const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias); const dataTypeBlockGrid = new BlockGridDataTypeBuilder() @@ -485,17 +485,17 @@ test.describe('BlockGridEditorContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, false); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); // Checks if the block contains the correct text before being edited await expect(page.locator('[data-content-element-type-alias="'+elementAlias +'"]')).toContainText('aliasTest'); - + // Updates the text without saving the changes. await page.locator('[data-content-element-type-key="' + element['key'] + '"]').click(); await page.locator('[id="sub-view-0"]').locator('[id="title"]').fill(newText); - + // Checks if the block is being live updated as the content is being updated. await expect(page.locator('[data-content-element-type-alias="'+elementAlias +'"]')).toContainText(newText); }); @@ -515,7 +515,7 @@ test.describe('BlockGridEditorContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, false); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); @@ -540,7 +540,7 @@ test.describe('BlockGridEditorContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, false); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); @@ -571,8 +571,8 @@ test.describe('BlockGridEditorContent', () => { .withLayoutStylesheet(stylesheetDataPath) .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, null); await umbracoUi.navigateToContent(blockGridName); @@ -600,7 +600,7 @@ test.describe('BlockGridEditorContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, false); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); // Goes to the created Content await umbracoUi.goToSection(ConstantHelper.sections.content); @@ -614,4 +614,4 @@ test.describe('BlockGridEditorContent', () => { await page.locator('[data-element="property-' + blockGridAlias + '"] >> .umb-block-grid__actions', {hasText: newButtonLabel}).click(); }); }); -}); \ No newline at end of file +}); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorRendering.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorRendering.spec.ts index d95d39ccaa..0d8bdd58ac 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorRendering.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorRendering.spec.ts @@ -9,14 +9,14 @@ test.describe('BlockGridEditorRending', () => { const blockGridName = 'BlockGridTest'; const elementTitleName = 'ElementTitle'; const contentText = "ContentTest"; - + const documentAlias = 'documentTest'; const blockGridAlias = 'blockGridTest'; const elementTitleAlias = "elementTitle"; const elementTitleLabel = 'Title'; const elementTitleLabelAlias = AliasHelper.toAlias(elementTitleLabel); - + test.beforeEach(async ({page, umbracoApi, umbracoUi}, testInfo) => { await umbracoApi.report.report(testInfo); await umbracoApi.login(); @@ -51,7 +51,7 @@ test.describe('BlockGridEditorRending', () => { .build(); return await umbracoApi.documentTypes.save(element); } - + async function createDocumentWithTemplateAndDataType(umbracoApi, dataType){ const docType = new DocumentTypeBuilder() .withName(documentName) @@ -69,14 +69,14 @@ test.describe('BlockGridEditorRending', () => { .build(); return await umbracoApi.documentTypes.save(docType); } - + async function editDefaultTemplate(umbracoApi){ await umbracoApi.templates.edit(documentName, '@using Umbraco.Cms.Web.Common.PublishedModels;\n' + '@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage\n' + '@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels;' + '\n' + '@await Html.GetBlockGridHtmlAsync(Model.' + blockGridName + ')'); } - + async function createPartialViewWithArea(umbracoApi, elementAlias, elementLabelAlias){ const partialViewElementTitle = new PartialViewBuilder() .withName(elementAlias) @@ -91,7 +91,7 @@ test.describe('BlockGridEditorRending', () => { partialViewElementTitle.virtualPath = "/Views/Partials/blockgrid/Components/"; return await umbracoApi.partialViews.save(partialViewElementTitle); } - + async function createPartialViewWithBlock(umbracoApi,elementAlias, elementLabelAlias){ const partialViewElementBody = new PartialViewBuilder() .withName(elementAlias) @@ -105,11 +105,11 @@ test.describe('BlockGridEditorRending', () => { partialViewElementBody.virtualPath = "/Views/Partials/blockgrid/Components/"; await umbracoApi.partialViews.save(partialViewElementBody); } - + test('can render content with a block grid editor', async ({page, umbracoApi, umbracoUi}) => { const element = await createElementWithRTE(umbracoApi, elementTitleName, elementTitleAlias, elementTitleLabel, elementTitleLabelAlias); - const dataType = await umbracoApi.dataTypes.createDefaultBlockGrid(umbracoApi, blockGridName, element); + const dataType = await umbracoApi.dataTypes.createDefaultBlockGrid(blockGridName, element); await createDocumentWithTemplateAndDataType(umbracoApi, dataType); @@ -140,7 +140,7 @@ test.describe('BlockGridEditorRending', () => { .withTemplateAlias(documentName) .build(); await umbracoApi.content.save(rootContentNode); - + // Assert await page.goto(umbracoConfig.environment.baseUrl); await expect(page).toHaveScreenshot('Block-grid-editor.png'); @@ -158,7 +158,7 @@ test.describe('BlockGridEditorRending', () => { const element = await createElementWithRTE(umbracoApi, elementTitleName, elementTitleAlias, elementTitleLabel, elementTitleLabelAlias); const elementBody = await createElementWithRTE(umbracoApi, elementBodyName, elementBodyAlias, elementBodyLabel, elementBodyLabelAlias); - + const dataTypeBlockGrid = new BlockGridDataTypeBuilder() .withName(blockGridName) .addBlock() @@ -179,7 +179,7 @@ test.describe('BlockGridEditorRending', () => { // Creates partial view for the ElementBody await createPartialViewWithBlock(umbracoApi, elementBodyAlias, elementBodyLabelAlias); - + const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) .withAction(ConstantHelper.actions.publish) @@ -210,12 +210,12 @@ test.describe('BlockGridEditorRending', () => { .withTemplateAlias(documentName) .build(); await umbracoApi.content.save(rootContentNode); - + // Assert await page.goto(umbracoConfig.environment.baseUrl); await expect(page).toHaveScreenshot('Block-grid-editor-with-two-elements.png'); - // Clean + // Clean await umbracoApi.documentTypes.ensureNameNotExists(elementBodyName); await umbracoApi.partialViews.ensureNameNotExists('blockgrid/Components', elementBodyAlias + '.cshtml'); }); @@ -257,7 +257,7 @@ test.describe('BlockGridEditorRending', () => { // Creates partial view for the ElementBody await createPartialViewWithBlock(umbracoApi, elementBodyAlias, elementBodyLabelAlias); - + const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) .withAction(ConstantHelper.actions.publish) @@ -291,12 +291,12 @@ test.describe('BlockGridEditorRending', () => { .withTemplateAlias(documentName) .build(); await umbracoApi.content.save(rootContentNode); - + // Assert await page.goto(umbracoConfig.environment.baseUrl); await expect(page).toHaveScreenshot('Block-grid-editor-with-area.png'); - - // Clean + + // Clean await umbracoApi.documentTypes.ensureNameNotExists(elementBodyName); await umbracoApi.partialViews.ensureNameNotExists('blockgrid/Components', elementBodyAlias + '.cshtml'); }) @@ -392,7 +392,7 @@ test.describe('BlockGridEditorRending', () => { .withTemplateAlias(documentName) .build(); await umbracoApi.content.save(rootContentNode); - + // Assert await page.goto(umbracoConfig.environment.baseUrl); await expect(page).toHaveScreenshot('Block-grid-editor-with-multiple-areas.png'); @@ -433,7 +433,7 @@ test.describe('BlockGridEditorRending', () => { .done() .done() .addBlock() - .withContentElementTypeKey(elementBody['key']) + .withContentElementTypeKey(elementBody['key']) .addArea() .withAlias('bodyArea') .done() @@ -551,7 +551,7 @@ test.describe('BlockGridEditorRending', () => { .build(); partialViewElement.virtualPath = "/Views/Partials/blockgrid/Components/"; await umbracoApi.partialViews.save(partialViewElement); - + const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) .withAction(ConstantHelper.actions.publish) @@ -595,7 +595,7 @@ test.describe('BlockGridEditorRending', () => { // ElementBody const elementBodyName = "ElementBody"; const elementBodyAlias = AliasHelper.toAlias(elementBodyName); - + await umbracoApi.documentTypes.ensureNameNotExists(elementBodyName); await umbracoApi.media.ensureNameNotExists(stylesheetTitleName); await umbracoApi.media.ensureNameNotExists(stylesheetBodyName); @@ -695,7 +695,7 @@ test.describe('BlockGridEditorRending', () => { // Assert await page.goto(umbracoConfig.environment.baseUrl); await expect(page).toHaveScreenshot('Block-grid-editor-with-two-custom-stylesheets.png'); - + // Clean await umbracoApi.documentTypes.ensureNameNotExists(elementBodyName); await umbracoApi.media.ensureNameNotExists(stylesheetTitleName); @@ -703,7 +703,7 @@ test.describe('BlockGridEditorRending', () => { await umbracoApi.partialViews.ensureNameNotExists('blockgrid/Components', elementBodyAlias + '.cshtml'); }); }); - + test.describe('Image', () => { test('can render a block grid with an image', async ({page, umbracoApi, umbracoUi}) => { // Image @@ -714,9 +714,9 @@ test.describe('BlockGridEditorRending', () => { const imageMimeType = "image/png"; await umbracoApi.media.ensureNameNotExists(imageName); - + const imageData = await umbracoApi.media.createImageWithFile(imageName, umbracoFileValue, imageFileName, imagePath, imageMimeType); - + const element = new DocumentTypeBuilder() .withName(elementTitleName) .withAlias(elementTitleAlias) @@ -756,7 +756,7 @@ test.describe('BlockGridEditorRending', () => { .build(); partialViewImage.virtualPath = "/Views/Partials/blockgrid/Components/"; await umbracoApi.partialViews.save(partialViewImage); - + const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) .withAction(ConstantHelper.actions.publish) @@ -771,7 +771,7 @@ test.describe('BlockGridEditorRending', () => { .addImage() .withMediaKey(imageData.key) .done() - .done() + .done() .addLayout() .withContentUdi(element['key']) .done() @@ -780,12 +780,12 @@ test.describe('BlockGridEditorRending', () => { .done() .build(); await umbracoApi.content.save(rootContentNode); - + // Assert await page.goto(umbracoConfig.environment.baseUrl); await expect(page).toHaveScreenshot('Block-grid-editor-with-image.png'); - - // Clean + + // Clean await umbracoApi.media.ensureNameNotExists(imageName); }); }); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorSettings.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorSettings.spec.ts index 358a979a43..5f6fd950e1 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorSettings.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorSettings.spec.ts @@ -29,7 +29,7 @@ test.describe('BlockGridEditorSettings', () => { test.describe('General', () => { test('can see label in content for a block grid editor', async ({page, umbracoApi, umbracoUi}) => { const newLabel = "New Label"; - + const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias); const dataTypeBlockGrid = new BlockGridDataTypeBuilder() @@ -41,14 +41,14 @@ test.describe('BlockGridEditorSettings', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); - + // Assert // Checks if the element contains the correct label await expect(page.locator('[data-content-element-type-alias="' + elementAlias + '"]')).toContainText(newLabel); - // Checks if the element is clickable + // Checks if the element is clickable await page.locator('[data-content-element-type-alias="' + elementAlias + '"]').click(); }); }); @@ -65,9 +65,9 @@ test.describe('BlockGridEditorSettings', () => { .done() .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); - + + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); + const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) .withAction(ConstantHelper.actions.save) @@ -77,21 +77,21 @@ test.describe('BlockGridEditorSettings', () => { .done() .build(); await umbracoApi.content.save(rootContentNode); - + await umbracoUi.navigateToContent(blockGridName); - + // Checks if adding a block is disabled await expect(page.locator('[data-element="property-'+blockGridAlias+'"]').locator('umb-block-grid-root').locator('[disabled="disabled"]')).toBeDisabled(); // Checks if the button is not clickable await expect(page.locator('[data-element="property-' + blockGridAlias + '"]').locator('[key="blockEditor_addBlock"]')).not.toBeEnabled(); }); - + test('can set allow in areas to false for an element in a block grid editor', async ({page, umbracoApi, umbracoUi}) => { const elementBodyName = 'BodyElement'; const elementBodyAlias = AliasHelper.toAlias(elementBodyName); - + await umbracoApi.documentTypes.ensureNameNotExists(elementBodyName); - + const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias); const elementBody = await umbracoApi.documentTypes.createDefaultElementType(elementBodyName, elementBodyAlias); @@ -110,14 +110,14 @@ test.describe('BlockGridEditorSettings', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi,element,dataType,false); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element,dataType, false); await umbracoUi.navigateToContent(blockGridName); - + // Assert // Checks if the elementTitle is the only element selectable to be in a area await expect(page.locator('[data-area-alias="titleArea"]').locator('[key="blockEditor_addThis"]')).toContainText('Add ' + elementName); - + // Clean await umbracoApi.documentTypes.ensureNameNotExists(elementBodyName); }); @@ -136,20 +136,20 @@ test.describe('BlockGridEditorSettings', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); - + // Drags the blocks from a columnSpan of 12 to 6 const dragFrom = await page.locator('[data-content-element-type-key="' + element['key'] + '"]', {hasText: elementName}).locator('[title="Drag to scale"]'); const dragTo = await page.locator('[data-content-element-type-key="' + element['key'] + '"]', {hasText: elementName}); await umbracoUi.dragAndDrop(dragFrom,dragTo, 0, 0 ,10); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); - // Assert + // Assert await umbracoUi.isSuccessNotificationVisible(); // Checks if the block is resized to a column span of 6 await expect(page.locator('[data-content-element-type-key="' + element['key'] + '"], [data-col-span="6"]', {hasText: elementName})).toBeVisible(); }); }); -}); \ No newline at end of file +}); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Datatype/BlockGridEditorDataTypeBlocks.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Datatype/BlockGridEditorDataTypeBlocks.spec.ts index 2acd818661..c88fbd43e5 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Datatype/BlockGridEditorDataTypeBlocks.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Datatype/BlockGridEditorDataTypeBlocks.spec.ts @@ -43,7 +43,7 @@ test.describe('BlockGridEditorDataTypeBlock', () => { return blockGridType; } - + test('can create empty block grid editor', async ({page, umbracoApi, umbracoUi}) => { await umbracoUi.goToSection(ConstantHelper.sections.settings); @@ -261,7 +261,7 @@ test.describe('BlockGridEditorDataTypeBlock', () => { test('can create a block grid datatype with multiple groups and multiple element in each group', async ({page, umbracoApi, umbracoUi},testInfo) => { await testInfo.slow(); - + const GroupOne = 'GroupOne'; const elementNameFourth = 'FourthElement'; const elementFourthAlias = AliasHelper.toAlias(elementNameFourth); @@ -362,7 +362,7 @@ test.describe('BlockGridEditorDataTypeBlock', () => { await expect(await umbracoApi.dataTypes.exists(blockGridName)).toBe(true); await umbracoUi.doesDataTypeExist(blockGridName); - // Clean + // Clean await umbracoApi.documentTypes.ensureNameNotExists(elementName); await umbracoApi.documentTypes.ensureNameNotExists(elementNameTwo); await umbracoApi.documentTypes.ensureNameNotExists(elementNameThree); @@ -552,6 +552,9 @@ test.describe('BlockGridEditorDataTypeBlock', () => { await umbracoUi.clickDataElementByElementName(ConstantHelper.actions.delete); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.delete)); + // We need a wait to make sure the block grid editor is deleted + await page.waitForTimeout(1000); + // Assert // Checks if the block grid editor still exists await umbracoUi.goToSection(ConstantHelper.sections.settings); @@ -586,7 +589,9 @@ test.describe('BlockGridEditorDataTypeBlock', () => { const dragFrom = await page.locator('.umb-block-card-group').nth(0).locator('[data-content-element-type-key="' + element['key'] + '"]'); const dragTo = await page.locator('[key="blockEditor_addBlockType"]').nth(1); await umbracoUi.dragAndDrop(dragFrom, dragTo, 0, 0, 15); - + + // We need a wait to make sure the element is moved + await page.waitForTimeout(2000); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)); // Assert @@ -626,7 +631,7 @@ test.describe('BlockGridEditorDataTypeBlock', () => { const dragFrom = await page.locator('.umb-block-card-group >> [icon="icon-navigation"]').nth(0); const dragTo = await page.locator('[key="blockEditor_addBlockType"]').nth(2); await umbracoUi.dragAndDrop(dragFrom, dragTo, 0, 0, 15); - + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)); // Assert @@ -642,7 +647,7 @@ test.describe('BlockGridEditorDataTypeBlock', () => { test('can move a group with elements in a block grid editor', async ({page, umbracoApi, umbracoUi}, testInfo) => { await testInfo.slow(); - + const GroupMove = 'GroupMove'; const GroupNotMoving = 'GroupNotMoving'; @@ -685,9 +690,9 @@ test.describe('BlockGridEditorDataTypeBlock', () => { const dragFrom = await page.locator('.umb-block-card-group >> [icon="icon-navigation"]').nth(0); const dragTo = await page.locator('[key="blockEditor_addBlockType"]').nth(2); await umbracoUi.dragAndDrop(dragFrom, dragTo, 20, 0, 15); - + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)); - + // Assert await umbracoUi.isSuccessNotificationVisible(); // Checks if the elements were moved with their group @@ -716,4 +721,4 @@ test.describe('BlockGridEditorDataTypeBlock', () => { await umbracoApi.documentTypes.ensureNameNotExists(elementNameTwo); await umbracoApi.documentTypes.ensureNameNotExists(elementNameThree); }); -}); \ No newline at end of file +}); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockListEditor/blockListEditorContent.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockListEditor/blockListEditorContent.spec.ts index 0c99d46ab5..ca67427968 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockListEditor/blockListEditorContent.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockListEditor/blockListEditorContent.spec.ts @@ -312,7 +312,7 @@ test.describe('BlockListEditorContent', () => { await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); // Assert - await umbracoUi.getSuccessNotification(); + await umbracoUi.isSuccessNotificationVisible(); }); test('can set a maximum of required blocks in content with a block list editor', async ({page, umbracoApi, umbracoUi}) => { @@ -374,8 +374,11 @@ test.describe('BlockListEditorContent', () => { // Can't use our constant helper because the action for delete does not contain an s. The correct way is 'action-delete' await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey('actions_delete')); + // Now that we deleted the block, we should be able to save our content + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); + // Assert - await umbracoUi.getSuccessNotification(); + await umbracoUi.isSuccessNotificationVisible(); }); test('can use inline editing mode in content with a block list editor', async ({page, umbracoApi, umbracoUi}) => { diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockListEditor/blockListEditorDocument.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockListEditor/blockListEditorDocument.spec.ts index 55588a2848..51e7e98934 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockListEditor/blockListEditorDocument.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockListEditor/blockListEditorDocument.spec.ts @@ -17,12 +17,12 @@ test.describe('BlockListEditorDocument', () => { await umbracoApi.documentTypes.ensureNameNotExists(documentName); await umbracoApi.dataTypes.ensureNameNotExists(blockListName); }); - + test.afterEach(async ({page, umbracoApi, umbracoUi}) => { await umbracoApi.documentTypes.ensureNameNotExists(documentName); await umbracoApi.dataTypes.ensureNameNotExists(blockListName); }); - + test('can create empty block list in a document', async ({page, umbracoApi, umbracoUi}) => { const groupName = 'blockListGroup'; @@ -38,8 +38,7 @@ test.describe('BlockListEditorDocument', () => { await umbracoUi.goToAddEditor(groupName, blockListName); // Waits until the selector is visible await expect(page.locator('[data-element="datatype-Block List"]')).toBeVisible(); - await umbracoUi.clickDataElementByElementName('datatype-Block List'); - + await page.getByRole('button', { name: 'Block List' }).click(); // Creates new BlockList editor await page.locator('[title="Create a new configuration of Block List"]').click(); await page.locator('[id="dataTypeName"]').fill(blockListName); @@ -49,14 +48,14 @@ test.describe('BlockListEditorDocument', () => { // Checks to ensure that the button is visible await expect(page.locator('[name="propertySettingsForm"]').locator('[label-key=' + ConstantHelper.buttons.submit + ']')).toBeVisible(); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.submit)); - + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)); // Assert await expect(page.locator('.umb-notifications__notifications > .alert-success', {hasText: "Datatype saved"})).toBeVisible(); await expect(page.locator('.umb-notifications__notifications > .alert-success', {hasText: "Document Type saved"})).toBeVisible(); }); - + test('can create multiple block list editors in a document', async ({page, umbracoApi, umbracoUi}) => { const elementNameSecond = 'TestElementTwo'; const blockListNameSecond = 'BlockListTestNumbaTwo'; @@ -127,7 +126,7 @@ test.describe('BlockListEditorDocument', () => { await umbracoApi.documentTypes.save(rootDocType); await umbracoUi.navigateToDocumentType(documentName); - + // Adds another block list editor to the first group await page.locator('[data-element="group-TestName"]').locator('[data-element="property-add"]').click(); await page.locator('[data-element="property-name"]').fill('TheBlock'); @@ -136,7 +135,7 @@ test.describe('BlockListEditorDocument', () => { await page.locator('[title="Select ' + blockListNameSecond + '"]').click(); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.submit)); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)); - + // Assert await expect(page.locator('.umb-notifications__notifications > .alert-success', {hasText: "Document Type saved"})).toBeVisible(); // Checks if the new block list is in the group @@ -147,4 +146,4 @@ test.describe('BlockListEditorDocument', () => { await umbracoApi.documentTypes.ensureNameNotExists(elementNameSecond); await umbracoApi.dataTypes.ensureNameNotExists(blockListNameSecond); }); -}); \ No newline at end of file +}); 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 e402f751e6..4793d98614 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/content.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/content.spec.ts @@ -13,7 +13,7 @@ test.describe('Content tests', () => { test.beforeEach(async ({page, umbracoApi}) => { await umbracoApi.login(); }); - + async function createSimpleMacro(name, umbracoApi: ApiHelpers){ const insertMacro = new PartialViewMacroBuilder() .withName(name) @@ -280,7 +280,7 @@ test.describe('Content tests', () => { await umbracoUi.clickElement(umbracoUi.getTreeItem("content", [initialNodeName])); const header = await page.locator('#headerName') - // Sadly playwright doesn't have a clear method for inputs :( + // Sadly playwright doesn't have a clear method for inputs :( // so we have to triple click to select all, and then hit backspace... await header.click({ clickCount: 3 }) await page.keyboard.press('Backspace'); @@ -388,7 +388,7 @@ test.describe('Content tests', () => { // Clean up (content is automatically deleted when document types are gone) await umbracoApi.documentTypes.ensureNameNotExists(rootDocTypeName); - }); + }); test('Preview draft', async ({ page, umbracoApi, umbracoUi }) => { const rootDocTypeName = "Test document type"; @@ -428,7 +428,7 @@ test.describe('Content tests', () => { // Clean up (content is automatically deleted when document types are gone) await umbracoApi.documentTypes.ensureNameNotExists(rootDocTypeName); - }); + }); test('Publish draft', async ({ page, umbracoApi, umbracoUi }) => { const rootDocTypeName = "Test document type"; @@ -554,8 +554,8 @@ test.describe('Content tests', () => { // Save and publish await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); // Added additional time because it could fail on pipeline because it's not saving fast enough - await umbracoUi.isSuccessNotificationVisible({timeout:20000}); - + await umbracoUi.isSuccessNotificationVisible(); + // Assert const expectedContent = '

Acceptance test

' await expect(await umbracoApi.content.verifyRenderedContent('/contentpickercontent', expectedContent, true)).toBeTruthy(); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/routing.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/routing.spec.ts index 14cfd99185..b2c6893226 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/routing.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/routing.spec.ts @@ -105,7 +105,7 @@ test.describe('Routing', () => { await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); // Pop-up with what cultures you want to publish shows, click it - await page.locator('.btn-success').last().click() + await umbracoUi.clickDataElementByElementName('button-overlaySubmit'); // Assert await umbracoUi.isSuccessNotificationVisible(); @@ -161,13 +161,13 @@ test.describe('Routing', () => { await expect(await page.locator('.umb-list')).toBeVisible(); await page.locator('.checkbox').last().click(); // Pop-up with what cultures you want to publish shows, click it - await page.locator('.btn-success').last().click() + await umbracoUi.clickDataElementByElementName('button-overlaySubmit'); // Assert - await expect(await umbracoUi.getSuccessNotification()).toHaveCount(2); + await expect(await umbracoUi.getSuccessNotification()).toHaveCount(2, {timeout: 20000}); await expect(await page.locator('.alert-warning')).toBeVisible(); }); - + test('Root node published in language A, Child node published in language A + B, Grandchild published in A + B', async ({page, umbracoApi, umbracoUi}) => { const rootDocType = new DocumentTypeBuilder() .withName(rootDocTypeName) @@ -239,7 +239,7 @@ test.describe('Routing', () => { await expect(await page.locator('.umb-list')).toBeVisible(); await page.locator('.checkbox').last().click(); - await page.locator('.btn-success').last().click() + await umbracoUi.clickDataElementByElementName('button-overlaySubmit'); await umbracoUi.clickMultiple(page.locator('.alert-success > .close')); await umbracoUi.clickElement(umbracoUi.getTreeItem("content", [nodeName, childNodeName, grandChildNodeName])); @@ -247,8 +247,8 @@ test.describe('Routing', () => { await expect(await page.locator('.umb-list')).toBeVisible(); await page.locator('.checkbox').last().click(); - await page.locator('.btn-success').last().click() + await umbracoUi.clickDataElementByElementName('button-overlaySubmit'); // Assert - await expect(await umbracoUi.getSuccessNotification()).toHaveCount(2); + await expect(await umbracoUi.getSuccessNotification()).toHaveCount(2, {timeout: 20000}); }) }); 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 808858ab01..cada9e7503 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataTypes/dataTypes.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataTypes/dataTypes.spec.ts @@ -103,7 +103,7 @@ test.describe('DataTypes', () => { // 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(); + await expect(await umbracoUi.getErrorNotification()).not.toBeVisible({timeout: 20000}); // Add char and assert errortext appears and can't save await page.locator('input[name="textbox"]').type('10'); // 1 char over max @@ -119,7 +119,6 @@ test.describe('DataTypes', () => { }); test('Test Url Picker', async ({page, umbracoApi, umbracoUi}) => { - const urlPickerDocTypeName = 'Url Picker Test'; const pickerDocTypeAlias = AliasHelper.toAlias(urlPickerDocTypeName); @@ -162,17 +161,17 @@ test.describe('DataTypes', () => { 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 - 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(); + await page.locator('[data-element="editor-container"]').locator('[data-element="tree-item-UrlPickerContent"]').click(); + await expect(page.locator('[alias="urlLinkPicker"]').locator('input[id="urlLinkPicker"]')).toHaveValue('/'); + await page.locator('.umb-editor-footer-content__right-side').locator('[label-key="' + ConstantHelper.buttons.submit + '"]').click(); + await expect(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(); + await expect(await umbracoUi.getErrorNotification()).not.toBeVisible({timeout: 20000}); // Testing if the edits match the expected results const expected = 'UrlPickerContent'; @@ -184,4 +183,4 @@ test.describe('DataTypes', () => { await umbracoApi.content.deleteAllContent(); await umbracoApi.templates.ensureNameNotExists(urlPickerDocTypeName); }); -}); \ No newline at end of file +}); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataTypes/textBoxVariation.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataTypes/textBoxVariation.spec.ts index 1cd66d12d2..d637b736d7 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataTypes/textBoxVariation.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataTypes/textBoxVariation.spec.ts @@ -7,7 +7,7 @@ test.describe('Vary by culture for TextBox', () => { test.beforeEach(async ({page, umbracoApi, umbracoUi}) => { await umbracoApi.login(); }); - + test('create documentType with vary by culture with UI with a textbox property which also has vary by culture', async ({page, umbracoApi, umbracoUi}) => { const documentTypeName = 'Test Document'; const textBoxPropertyName = 'TestBox'; @@ -36,7 +36,7 @@ test.describe('Vary by culture for TextBox', () => { await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)); // Assert - await expect(page.locator('.umb-notifications__notifications > .alert-success')).toBeVisible(); + await umbracoUi.isSuccessNotificationVisible(); // Clean await umbracoApi.documentTypes.ensureNameNotExists(documentTypeName); @@ -279,7 +279,7 @@ test.describe('Vary by culture for TextBox', () => { await expect(await umbracoApi.content.verifyRenderedContent(daEndpoint, daValue, true)).toBeTruthy(); await expect(await umbracoApi.content.verifyRenderedContent(enEndpoint, enValue, true)).toBeTruthy(); - // Clean + // Clean await umbracoApi.content.deleteAllContent(); await umbracoApi.documentTypes.ensureNameNotExists(documentName); await umbracoApi.languages.ensureCultureNotExists(languageDa); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Media/mediaSection.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Media/mediaSection.spec.ts index 19c69d6b9d..60891d4b47 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Media/mediaSection.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Media/mediaSection.spec.ts @@ -51,7 +51,7 @@ test.describe('Media', () => { } }); await page.locator('[label-key="actions_move"]').click(); - await page.locator('[data-element="editor-container"] >> "' + folderToMoveTooName + '"').click(); + await page.locator('[data-element="editor-container"]').locator('[data-element="tree-item-MoveHere"]').click(); await page.locator('[label-key="general_submit"]').click(); // Assert diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/ModelsBuilder/modelsbuilder.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/ModelsBuilder/modelsbuilder.spec.ts index 1ac6efc02e..c919912c55 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/ModelsBuilder/modelsbuilder.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/ModelsBuilder/modelsbuilder.spec.ts @@ -32,7 +32,7 @@ test.describe('Modelsbuilder tests', () => { .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; @@ -48,7 +48,7 @@ test.describe('Modelsbuilder tests', () => { // 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({timeout:10000}); + 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); @@ -80,7 +80,7 @@ test.describe('Modelsbuilder tests', () => { .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; @@ -116,7 +116,7 @@ test.describe('Modelsbuilder tests', () => { await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.submit)); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)); // Has a long timeout because it can sometimes take longer than 5 sec to save on the pipeline - await umbracoUi.isSuccessNotificationVisible({timeout:10000}); + 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) @@ -149,7 +149,7 @@ test.describe('Modelsbuilder tests', () => { .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; @@ -182,8 +182,8 @@ test.describe('Modelsbuilder tests', () => { // 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({timeout:10000}); + + await umbracoUi.isSuccessNotificationVisible(); await umbracoApi.content.verifyRenderedContent("/", "

" + propertyValue + "

Edited

", true); @@ -194,7 +194,7 @@ test.describe('Modelsbuilder tests', () => { test('Can update view and document type', async ({page, umbracoApi, umbracoUi}, testInfo) => { await testInfo.slow(); - + const docTypeName = "TestDocument"; const docTypeAlias = AliasHelper.toAlias(docTypeName); const propertyAlias = "title"; @@ -218,7 +218,7 @@ test.describe('Modelsbuilder tests', () => { .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; @@ -264,7 +264,7 @@ test.describe('Modelsbuilder tests', () => { // 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({timeout: 10000}); + await umbracoUi.isSuccessNotificationVisible(); await page.locator('span:has-text("×")').click(); // Navigate to the content section and update the content @@ -274,6 +274,8 @@ test.describe('Modelsbuilder tests', () => { await page.locator("#bod").type("Fancy body text"); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); + await page.waitForTimeout(2000); + await umbracoApi.content.verifyRenderedContent("/", "

" + propertyValue + "

Fancy body text

", true); await umbracoApi.content.deleteAllContent(); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/partialViewMacroFiles.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/partialViewMacroFiles.spec.ts index 94903f0a54..bcefbb60c5 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/partialViewMacroFiles.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/partialViewMacroFiles.spec.ts @@ -30,18 +30,18 @@ test.describe('Partial View Macro Files', () => { await page.locator('.menu-label localize[key="create_newPartialViewMacro"]').click(); - //Type name + // Type name await umbracoUi.setEditorHeaderName(name); - //Save + // Save await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)); //Assert - await umbracoUi.isSuccessNotificationVisible({timeout:10000}); + await umbracoUi.isSuccessNotificationVisible(); //Clean up await cleanup(umbracoApi, name); - }); + }); test('Create new partial view macro without macro', async ({page, umbracoApi, umbracoUi}) => { const name = "TestPartialMacrolessMacro"; @@ -54,16 +54,16 @@ test.describe('Partial View Macro Files', () => { // Type name await umbracoUi.setEditorHeaderName(name); - + // Save await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)); // Assert - await umbracoUi.isSuccessNotificationVisible({timeout:10000}); + await umbracoUi.isSuccessNotificationVisible(); // Clean await cleanup(umbracoApi, name); - }); + }); test('Create new partial view macro from snippet', async ({page, umbracoApi, umbracoUi}) => { const name = "TestPartialFromSnippet"; @@ -84,11 +84,11 @@ test.describe('Partial View Macro Files', () => { await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)); // Assert - await umbracoUi.isSuccessNotificationVisible({timeout:10000}); + await umbracoUi.isSuccessNotificationVisible(); // Clean await cleanup(umbracoApi, name); - }); + }); test('Delete partial view macro', async ({page, umbracoApi, umbracoUi}) => { const name = "TestDeletePartialViewMacro"; @@ -117,7 +117,7 @@ test.describe('Partial View Macro Files', () => { // Clean await cleanup(umbracoApi, name); - }); + }); test('Edit partial view macro', async ({page, umbracoApi, umbracoUi}) => { const name = "TestPartialViewMacroEditable"; @@ -139,12 +139,12 @@ test.describe('Partial View Macro Files', () => { // Type an edit await page.locator('.ace_text-input').type(" // test" ); - + // Save await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)); // Assert - await umbracoUi.isSuccessNotificationVisible({timeout:10000}); + await umbracoUi.isSuccessNotificationVisible(); await cleanup(umbracoApi, name); }); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/partialViews.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/partialViews.spec.ts index 64be19cd82..13ebb4c97d 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/partialViews.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/partialViews.spec.ts @@ -37,7 +37,7 @@ test.describe('Partial Views', () => { await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)); //Assert - await umbracoUi.isSuccessNotificationVisible({timeout: 30000}); + await umbracoUi.isSuccessNotificationVisible(); //Clean up await umbracoApi.partialViews.ensureNameNotExists('', fileName); @@ -63,7 +63,7 @@ test.describe('Partial Views', () => { await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)); // Assert - await umbracoUi.isSuccessNotificationVisible({timeout:20000}); + await umbracoUi.isSuccessNotificationVisible(); // Clean up await umbracoApi.partialViews.ensureNameNotExists('', fileName); @@ -135,9 +135,9 @@ test.describe('Partial Views', () => { await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.save)); // Assert - await umbracoUi.isSuccessNotificationVisible({timeout:20000}); + await umbracoUi.isSuccessNotificationVisible(); // Clean await umbracoApi.partialViews.ensureNameNotExists('', fileName); }); -}); \ No newline at end of file +}); From 7be18528271dd05355079fba5cad156353bb9deb Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Thu, 28 Sep 2023 13:25:11 +0200 Subject: [PATCH 2/4] Make sure to sign out external users if an error occurs during sign-in (#14867) --- .../Controllers/BackOfficeController.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs index 43e99622c1..911028912a 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs @@ -585,6 +585,11 @@ public class BackOfficeController : UmbracoController if (errors.Count > 0) { + // the external user might actually be signed in at this point, but certain errors (i.e. missing claims) + // prevents us from applying said user to a back-office session. make sure the sign-in manager does not + // report the user as being signed in for subsequent requests. + await _signInManager.SignOutAsync(); + ViewData.SetExternalSignInProviderErrors( new BackOfficeExternalLoginProviderErrors( loginInfo.LoginProvider, From 04b05714e572e226e1473e8946e776d3c3ab3d34 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Thu, 5 Oct 2023 14:39:00 +0200 Subject: [PATCH 3/4] Add notification state to "final" published notification when publishing with descendants (#14922) * Revert "V10/bugfix/14543 publish descendants (#14763)" This reverts commit f750bca453c12d4cc4321868eb1197c9916f8243. * Add notification state to "final" published notification when publishing with descendants --- src/Umbraco.Core/Services/ContentService.cs | 43 ++++++------------- .../ContentServicePublishBranchTests.cs | 12 +++--- 2 files changed, 19 insertions(+), 36 deletions(-) diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index e9d0f8f4fd..262598451a 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -1950,7 +1950,7 @@ public class ContentService : RepositoryService, IContentService cultures = new HashSet(); // empty means 'already published' } - if (isRoot || edited) + if (edited) { cultures.Add(c); // means 'republish this culture' } @@ -2105,13 +2105,11 @@ public class ContentService : RepositoryService, IContentService } // deal with the branch root - if it fails, abort - var rootPublishNotificationState = new Dictionary(); - PublishResult? rootResult = SaveAndPublishBranchItem(scope, document, shouldPublish, publishCultures, true, - publishedDocuments, eventMessages, userId, allLangs, rootPublishNotificationState); - if (rootResult != null) + PublishResult? result = SaveAndPublishBranchItem(scope, document, shouldPublish, publishCultures, true, publishedDocuments, eventMessages, userId, allLangs, out IDictionary notificationState); + if (result != null) { - results.Add(rootResult); - if (!rootResult.Success) + results.Add(result); + if (!result.Success) { return results; } @@ -2124,7 +2122,6 @@ public class ContentService : RepositoryService, IContentService int count; var page = 0; const int pageSize = 100; - PublishResult? result = null; do { count = 0; @@ -2143,8 +2140,7 @@ public class ContentService : RepositoryService, IContentService } // no need to check path here, parent has to be published here - result = SaveAndPublishBranchItem(scope, d, shouldPublish, publishCultures, false, - publishedDocuments, eventMessages, userId, allLangs,null); + result = SaveAndPublishBranchItem(scope, d, shouldPublish, publishCultures, false, publishedDocuments, eventMessages, userId, allLangs, out _); if (result != null) { results.Add(result); @@ -2168,12 +2164,7 @@ public class ContentService : RepositoryService, IContentService // (SaveAndPublishBranchOne does *not* do it) scope.Notifications.Publish( new ContentTreeChangeNotification(document, TreeChangeTypes.RefreshBranch, eventMessages)); - if (rootResult?.Success is true) - { - scope.Notifications.Publish( - new ContentPublishedNotification(rootResult!.Content!, eventMessages) - .WithState(rootPublishNotificationState)); - } + scope.Notifications.Publish(new ContentPublishedNotification(publishedDocuments, eventMessages).WithState(notificationState)); scope.Complete(); } @@ -2184,9 +2175,6 @@ public class ContentService : RepositoryService, IContentService // shouldPublish: a function determining whether the document has changes that need to be published // note - 'force' is handled by 'editing' // publishValues: a function publishing values (using the appropriate PublishCulture calls) - /// Only set this when processing a the root of the branch - /// Published notification will not be send when this property is set - /// private PublishResult? SaveAndPublishBranchItem( ICoreScope scope, IContent document, @@ -2198,8 +2186,9 @@ public class ContentService : RepositoryService, IContentService EventMessages evtMsgs, int userId, IReadOnlyCollection allLangs, - IDictionary? rootPublishingNotificationState) + out IDictionary notificationState) { + notificationState = new Dictionary(); HashSet? culturesToPublish = shouldPublish(document); // null = do not include @@ -2227,17 +2216,11 @@ public class ContentService : RepositoryService, IContentService return new PublishResult(PublishResultType.FailedPublishContentInvalid, evtMsgs, document); } - var notificationState = rootPublishingNotificationState ?? new Dictionary(); - PublishResult result = CommitDocumentChangesInternal(scope, document, evtMsgs, allLangs, notificationState, userId, true, isRoot); - if (!result.Success) + PublishResult result = CommitDocumentChangesInternal(scope, document, evtMsgs, allLangs, savingNotification.State, userId, true, isRoot); + if (result.Success) { - return result; - } - - publishedDocuments.Add(document); - if (rootPublishingNotificationState == null) - { - scope.Notifications.Publish(new ContentPublishedNotification(result.Content!, evtMsgs).WithState(notificationState)); + publishedDocuments.Add(document); + notificationState = savingNotification.State; } return result; diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentServicePublishBranchTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentServicePublishBranchTests.cs index bee4e7d045..83d51dbe8c 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentServicePublishBranchTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentServicePublishBranchTests.cs @@ -93,7 +93,7 @@ public class ContentServicePublishBranchTests : UmbracoIntegrationTest AssertPublishResults( r, x => x.Result, - PublishResultType.SuccessPublish, // During branch publishing, the change detection of the root branch runs AFTER the check to process the branchItem => root is always saved&Published as the intent requires it. + PublishResultType.SuccessPublishAlready, PublishResultType.SuccessPublishAlready, PublishResultType.SuccessPublishAlready); @@ -140,7 +140,7 @@ public class ContentServicePublishBranchTests : UmbracoIntegrationTest AssertPublishResults( r, x => x.Result, - PublishResultType.SuccessPublish, // During branch publishing, the change detection of the root branch runs AFTER the check to process the branchItem => root is always saved&Published as the intent requires it. + PublishResultType.SuccessPublishAlready, PublishResultType.SuccessPublishAlready, PublishResultType.SuccessPublishAlready, PublishResultType.SuccessPublish, @@ -185,7 +185,7 @@ public class ContentServicePublishBranchTests : UmbracoIntegrationTest var r = ContentService.SaveAndPublishBranch(vRoot, false) .ToArray(); // no culture specified so "*" is used, so all cultures - Assert.AreEqual(PublishResultType.SuccessPublishCulture, r[0].Result); // During branch publishing, the change detection of the root branch runs AFTER the check to process the branchItem => root is always saved&Published as the intent requires it. + Assert.AreEqual(PublishResultType.SuccessPublishAlready, r[0].Result); Assert.AreEqual(PublishResultType.SuccessPublishCulture, r[1].Result); } @@ -221,7 +221,7 @@ public class ContentServicePublishBranchTests : UmbracoIntegrationTest var saveResult = ContentService.Save(iv1); var r = ContentService.SaveAndPublishBranch(vRoot, false, "de").ToArray(); - Assert.AreEqual(PublishResultType.SuccessPublishCulture, r[0].Result); // During branch publishing, the change detection of the root branch runs AFTER the check to process the branchItem => root is always saved&Published as the intent requires it. + Assert.AreEqual(PublishResultType.SuccessPublishAlready, r[0].Result); Assert.AreEqual(PublishResultType.SuccessPublishCulture, r[1].Result); } @@ -381,7 +381,7 @@ public class ContentServicePublishBranchTests : UmbracoIntegrationTest AssertPublishResults( r, x => x.Result, - PublishResultType.SuccessPublish, // During branch publishing, the change detection of the root branch runs AFTER the check to process the branchItem => root is always saved&Published as the intent requires it. + PublishResultType.SuccessPublishAlready, PublishResultType.SuccessPublish, PublishResultType.SuccessPublishCulture); @@ -407,7 +407,7 @@ public class ContentServicePublishBranchTests : UmbracoIntegrationTest AssertPublishResults( r, x => x.Result, - PublishResultType.SuccessPublish, // During branch publishing, the change detection of the root branch runs AFTER the check to process the branchItem => root is always saved&Published as the intent requires it. + PublishResultType.SuccessPublishAlready, PublishResultType.SuccessPublish, PublishResultType.SuccessPublishCulture); From 132935c2d76a2e457113db6b4721a77f8c986035 Mon Sep 17 00:00:00 2001 From: Elitsa Marinovska <21998037+elit0451@users.noreply.github.com> Date: Mon, 9 Oct 2023 10:19:36 +0200 Subject: [PATCH 4/4] Handle corrupted index (#14889) --- .../ExamineManagementController.cs | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.BackOffice/Controllers/ExamineManagementController.cs b/src/Umbraco.Web.BackOffice/Controllers/ExamineManagementController.cs index 4ab0ccd072..e57f790fb0 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ExamineManagementController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ExamineManagementController.cs @@ -187,15 +187,41 @@ public class ExamineManagementController : UmbracoAuthorizedJsonController private ExamineIndexModel CreateModel(IIndex index) { var indexName = index.Name; - IIndexDiagnostics indexDiag = _indexDiagnosticsFactory.Create(index); - Attempt isHealth = indexDiag.IsHealthy(); + var healthResult = isHealth.Result; + + long documentCount; + int fieldCount; + + try + { + // This will throw if the index is corrupted - i.e. a file in the index folder cannot be found + // Which will break the UI and not give the possibility to rebuild the index + documentCount = indexDiag.GetDocumentCount(); + fieldCount = indexDiag.GetFieldNames().Count(); + } + catch (FileNotFoundException ex) + { + // Safe catch that will allow to rebuild a corrupted index + documentCount = 0; + fieldCount = 0; + + _logger.LogWarning(ex, "{name} is corrupted.", indexName); + + if (!string.IsNullOrWhiteSpace(healthResult)) + { + healthResult += " "; + } + + // Provide a useful message in the Examine dashboard + healthResult += $"It may not be possible to rebuild the index. Please try deleting the entire {indexName} folder and then attempt to rebuild it again."; + } var properties = new Dictionary { - ["DocumentCount"] = indexDiag.GetDocumentCount(), - ["FieldCount"] = indexDiag.GetFieldNames().Count() + ["DocumentCount"] = documentCount, + ["FieldCount"] = fieldCount }; foreach (KeyValuePair p in indexDiag.Metadata) @@ -206,7 +232,7 @@ public class ExamineManagementController : UmbracoAuthorizedJsonController var indexerModel = new ExamineIndexModel { Name = indexName, - HealthStatus = isHealth.Success ? isHealth.Result ?? "Healthy" : isHealth.Result ?? "Unhealthy", + HealthStatus = isHealth.Success ? healthResult ?? "Healthy" : healthResult ?? "Unhealthy", ProviderProperties = properties, CanRebuild = _indexRebuilder.CanRebuild(index.Name) };