From 3b6e4a96f141b6fa3d053ece92543cd892d6b3b9 Mon Sep 17 00:00:00 2001 From: Nhu Dinh <150406148+nhudinh0309@users.noreply.github.com> Date: Sat, 26 Apr 2025 09:59:03 +0700 Subject: [PATCH] V15 QA Added acceptance tests for bulk trash dialog (#19125) * Added tests for bulk trash content dialog * Updated tests for trash content dialog * Added tests for trash and bulk trash media dialog * Moved trash content tests into a folder * Bumped version * Make trash tests run in the pipeline * Make trash tests run in the pipeline * Fixed comments * Reverted npm command --- .../package-lock.json | 20 ++-- .../Umbraco.Tests.AcceptanceTest/package.json | 4 +- .../TrashContent/BulkTrashContent.spec.ts | 93 +++++++++++++++++++ .../{ => TrashContent}/TrashContent.spec.ts | 2 +- .../tests/DefaultConfig/Media/Media.spec.ts | 78 ++++++++++++++++ 5 files changed, 183 insertions(+), 14 deletions(-) create mode 100644 tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/TrashContent/BulkTrashContent.spec.ts rename tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/{ => TrashContent}/TrashContent.spec.ts (99%) diff --git a/tests/Umbraco.Tests.AcceptanceTest/package-lock.json b/tests/Umbraco.Tests.AcceptanceTest/package-lock.json index b6ee78da3a..635fb500f2 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": "^2.0.31", - "@umbraco/playwright-testhelpers": "^15.0.44", + "@umbraco/json-models-builders": "^2.0.33", + "@umbraco/playwright-testhelpers": "^15.0.47", "camelize": "^1.0.0", "dotenv": "^16.3.1", "node-fetch": "^2.6.7" @@ -58,21 +58,19 @@ } }, "node_modules/@umbraco/json-models-builders": { - "version": "2.0.32", - "resolved": "https://registry.npmjs.org/@umbraco/json-models-builders/-/json-models-builders-2.0.32.tgz", - "integrity": "sha512-Aw7yBu8ePNxdjS7Q61j5KPFsiOS+IGCYxBX0H4KWbjXTdvL/PsB98KiqbDHHKFnp0fF1b2ffwJAI6jmvnxPBzg==", - "license": "MIT", + "version": "2.0.33", + "resolved": "https://registry.npmjs.org/@umbraco/json-models-builders/-/json-models-builders-2.0.33.tgz", + "integrity": "sha512-FAQxQIHoY6PGxWuodp4LSQxNufnOiqnaRNmtG8Ejn01r9lJJdA27CJKJ0bCs8U0W3cdN+Z+j7jBLd8H025/THw==", "dependencies": { "camelize": "^1.0.1" } }, "node_modules/@umbraco/playwright-testhelpers": { - "version": "15.0.44", - "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-15.0.44.tgz", - "integrity": "sha512-rbStBJG0bdVfs9pzEjAhArhcPoQbuvrUpvDJLbEMBcg54lRFH0I5nzcAimdZaY4UWh2r0i9ANfjv9E25NJxRUg==", - "license": "MIT", + "version": "15.0.47", + "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-15.0.47.tgz", + "integrity": "sha512-rYr3IU1O/mcOw74zHxXyqa7eRkxci2G6yMgWmTDKdYrB1jPFrElWvn5GQVVP6r9znH4z1VkzPT0rWmuPI8rP/w==", "dependencies": { - "@umbraco/json-models-builders": "2.0.32", + "@umbraco/json-models-builders": "2.0.33", "node-fetch": "^2.6.7" } }, diff --git a/tests/Umbraco.Tests.AcceptanceTest/package.json b/tests/Umbraco.Tests.AcceptanceTest/package.json index 524acec6eb..beffdfba62 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/package.json +++ b/tests/Umbraco.Tests.AcceptanceTest/package.json @@ -20,8 +20,8 @@ "typescript": "^4.8.3" }, "dependencies": { - "@umbraco/json-models-builders": "^2.0.31", - "@umbraco/playwright-testhelpers": "^15.0.44", + "@umbraco/json-models-builders": "^2.0.33", + "@umbraco/playwright-testhelpers": "^15.0.47", "camelize": "^1.0.0", "dotenv": "^16.3.1", "node-fetch": "^2.6.7" diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/TrashContent/BulkTrashContent.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/TrashContent/BulkTrashContent.spec.ts new file mode 100644 index 0000000000..957c330e65 --- /dev/null +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/TrashContent/BulkTrashContent.spec.ts @@ -0,0 +1,93 @@ +import {ConstantHelper, test} from '@umbraco/playwright-testhelpers'; +import {expect} from "@playwright/test"; + +let collectionId = ''; +const contentName = 'TestContent'; +const documentTypeName = 'TestDocumentTypeForContent'; +const childDocumentTypeName = 'TestChildDocumentType'; +const firstChildContentName = 'First Child Content'; +const secondChildContentName = 'Second Child Content'; +const collectionDataTypeName = 'List View - Content'; +const referenceHeadline = ConstantHelper.trashDeleteDialogMessage.bulkReferenceHeadline; +const documentPickerName = ['TestPicker', 'DocumentTypeForPicker']; + +test.beforeEach(async ({umbracoApi}) => { + await umbracoApi.documentType.ensureNameNotExists(documentTypeName); + await umbracoApi.document.ensureNameNotExists(contentName); + const collectionDataTypeData = await umbracoApi.dataType.getByName(collectionDataTypeName); + collectionId = collectionDataTypeData.id; +}); + +test.afterEach(async ({umbracoApi}) => { + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.documentType.ensureNameNotExists(documentTypeName); + await umbracoApi.documentType.ensureNameNotExists(childDocumentTypeName); + await umbracoApi.document.emptyRecycleBin(); +}); + +test('can bulk trash content nodes without a relation', async ({umbracoApi, umbracoUi}) => { + // Arrange + const childDocumentTypeId = await umbracoApi.documentType.createDefaultDocumentType(childDocumentTypeName); + const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithAllowedChildNodeAndCollectionId(documentTypeName, childDocumentTypeId, collectionId); + const contentId = await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); + await umbracoApi.document.createDefaultDocumentWithParent(firstChildContentName, childDocumentTypeId, contentId); + await umbracoApi.document.createDefaultDocumentWithParent(secondChildContentName, childDocumentTypeId, contentId); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.goToContentWithName(contentName); + await umbracoUi.content.selectContentWithNameInListView(firstChildContentName); + await umbracoUi.content.selectContentWithNameInListView(secondChildContentName); + await umbracoUi.content.clickTrashSelectedListItems(); + // Verify the references list not displayed + await umbracoUi.content.isReferenceHeadlineVisible(false); + await umbracoUi.content.clickConfirmTrashButton(); + + // // Assert + await umbracoUi.content.isSuccessNotificationVisible(); + expect(await umbracoApi.document.doesNameExist(firstChildContentName)).toBeFalsy(); + expect(await umbracoApi.document.doesNameExist(secondChildContentName)).toBeFalsy(); + await umbracoUi.content.isItemVisibleInRecycleBin(firstChildContentName); + await umbracoUi.content.isItemVisibleInRecycleBin(secondChildContentName); + expect(await umbracoApi.document.doesItemExistInRecycleBin(firstChildContentName)).toBeTruthy(); + expect(await umbracoApi.document.doesItemExistInRecycleBin(secondChildContentName)).toBeTruthy(); +}); + +test('can bulk trash content nodes with a relation', async ({umbracoApi, umbracoUi}) => { + // Arrange + const childDocumentTypeId = await umbracoApi.documentType.createDefaultDocumentType(childDocumentTypeName); + const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithAllowedChildNodeAndCollectionId(documentTypeName, childDocumentTypeId, collectionId); + const contentId = await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); + await umbracoApi.document.publish(contentId); + const firstChildContentId = await umbracoApi.document.createDefaultDocumentWithParent(firstChildContentName, childDocumentTypeId, contentId); + await umbracoApi.document.publish(firstChildContentId); + await umbracoApi.document.createDefaultDocumentWithParent(secondChildContentName, childDocumentTypeId, contentId); + // Create a document that has a document picker with firstChildContentName + await umbracoApi.document.createDefaultDocumentWithOneDocumentLink(documentPickerName[0], firstChildContentName, firstChildContentId, documentPickerName[1]); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.goToContentWithName(contentName); + await umbracoUi.content.selectContentWithNameInListView(firstChildContentName); + await umbracoUi.content.selectContentWithNameInListView(secondChildContentName); + await umbracoUi.content.clickTrashSelectedListItems(); + // Verify the references list + await umbracoUi.content.doesReferenceHeadlineHaveText(referenceHeadline); + await umbracoUi.content.doesReferenceItemsHaveCount(1); + await umbracoUi.content.isReferenceItemNameVisible(firstChildContentName); + await umbracoUi.content.clickConfirmTrashButton(); + + // // Assert + await umbracoUi.content.isSuccessNotificationVisible(); + expect(await umbracoApi.document.doesNameExist(firstChildContentName)).toBeFalsy(); + expect(await umbracoApi.document.doesNameExist(secondChildContentName)).toBeFalsy(); + await umbracoUi.content.isItemVisibleInRecycleBin(firstChildContentName); + await umbracoUi.content.isItemVisibleInRecycleBin(secondChildContentName); + expect(await umbracoApi.document.doesItemExistInRecycleBin(firstChildContentName)).toBeTruthy(); + expect(await umbracoApi.document.doesItemExistInRecycleBin(secondChildContentName)).toBeTruthy(); + + // Clean + await umbracoApi.documentType.ensureNameNotExists(documentPickerName[1]); +}); \ No newline at end of file diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/TrashContent.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/TrashContent/TrashContent.spec.ts similarity index 99% rename from tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/TrashContent.spec.ts rename to tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/TrashContent/TrashContent.spec.ts index c008ea38ba..4214ff691a 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/TrashContent.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/TrashContent/TrashContent.spec.ts @@ -6,7 +6,7 @@ const contentName = 'TestContent'; const documentTypeName = 'TestDocumentTypeForContent'; const dataTypeName = 'Textstring'; const contentText = 'This is test content text'; -const referenceHeadline = 'The following items depend on this'; +const referenceHeadline = ConstantHelper.trashDeleteDialogMessage.referenceHeadline; const documentPickerName = ['TestPicker', 'DocumentTypeForPicker']; test.beforeEach(async ({umbracoApi}) => { diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Media/Media.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Media/Media.spec.ts index 8e7f878166..8eaedb8313 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Media/Media.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Media/Media.spec.ts @@ -174,6 +174,8 @@ test('can trash a media item', async ({umbracoApi, umbracoUi}) => { // Act await umbracoUi.media.clickActionsMenuForName(mediaFileName); await umbracoUi.media.clickTrashButton(); + // Verify the references list not displayed + await umbracoUi.content.isReferenceHeadlineVisible(false); await umbracoUi.media.clickConfirmTrashButton(); // Assert @@ -245,3 +247,79 @@ test('can empty the recycle bin', async ({umbracoApi, umbracoUi}) => { expect(await umbracoApi.media.doesNameExist(mediaFileName)).toBeFalsy(); expect(await umbracoApi.media.doesMediaItemExistInRecycleBin(mediaFileName)).toBeFalsy(); }); + +test('can trash a media node with a relation', async ({umbracoApi, umbracoUi}) => { + // Arrange + const documentPickerName = ['TestPicker', 'DocumentTypeForPicker']; + await umbracoApi.media.emptyRecycleBin(); + await umbracoApi.media.createDefaultMediaFile(mediaFileName); + await umbracoApi.media.doesNameExist(mediaFileName); + // Create a document that have media picker is firstMediaFileName + await umbracoApi.document.createDefaultDocumentWithOneMediaLink(documentPickerName[0], mediaFileName, documentPickerName[1]); + await umbracoUi.media.goToSection(ConstantHelper.sections.media); + + // Act + await umbracoUi.media.clickActionsMenuForName(mediaFileName); + await umbracoUi.media.clickTrashButton(); + // Verify the references list + await umbracoUi.media.doesReferenceHeadlineHaveText(ConstantHelper.trashDeleteDialogMessage.referenceHeadline); + await umbracoUi.media.doesReferenceItemsHaveCount(1); + await umbracoUi.media.isReferenceItemNameVisible(documentPickerName[0]); + await umbracoUi.media.clickConfirmTrashButton(); + + // Assert + await umbracoUi.media.doesSuccessNotificationHaveText(NotificationConstantHelper.success.movedToRecycleBin); + await umbracoUi.media.isItemVisibleInRecycleBin(mediaFileName); + expect(await umbracoApi.media.doesNameExist(mediaFileName)).toBeFalsy(); + expect(await umbracoApi.media.doesMediaItemExistInRecycleBin(mediaFileName)).toBeTruthy(); + + // Clean + await umbracoApi.media.emptyRecycleBin(); + await umbracoApi.document.ensureNameNotExists(documentPickerName[0]); + await umbracoApi.documentType.ensureNameNotExists(documentPickerName[1]); +}); + +test('can bulk trash media nodes with a relation', async ({umbracoApi, umbracoUi}) => { + // Arrange + const firstMediaFileName = 'FirstMediaFile'; + const secondMediaFileName = 'SecondMediaFile'; + const documentPickerName1 = ['TestPicker1', 'DocumentTypeForPicker1']; + const documentPickerName2 = ['TestPicker2', 'DocumentTypeForPicker2']; + await umbracoApi.media.emptyRecycleBin(); + await umbracoApi.media.createDefaultMediaFile(firstMediaFileName); + await umbracoApi.media.createDefaultMediaFile(secondMediaFileName); + // Create a document that has a media picker with firstMediaFileName + await umbracoApi.document.createDefaultDocumentWithOneMediaLink(documentPickerName1[0], firstMediaFileName, documentPickerName1[1]); + // Create a document that has a media picker with secondMediaFileName + await umbracoApi.document.createDefaultDocumentWithOneMediaLink(documentPickerName2[0], secondMediaFileName, documentPickerName2[1]); + + // Act + await umbracoUi.media.goToSection(ConstantHelper.sections.media); + await umbracoUi.media.selectMediaWithName(firstMediaFileName); + await umbracoUi.media.selectMediaWithName(secondMediaFileName); + await umbracoUi.media.clickBulkTrashButton(); + // Verify the references list + await umbracoUi.media.doesReferenceHeadlineHaveText(ConstantHelper.trashDeleteDialogMessage.bulkReferenceHeadline); + await umbracoUi.media.doesReferenceItemsHaveCount(2); + await umbracoUi.media.isReferenceItemNameVisible(firstMediaFileName); + await umbracoUi.media.isReferenceItemNameVisible(secondMediaFileName); + await umbracoUi.media.clickConfirmTrashButton(); + + // Assert + await umbracoUi.media.isSuccessNotificationVisible(); + expect(await umbracoApi.media.doesNameExist(firstMediaFileName)).toBeFalsy(); + expect(await umbracoApi.media.doesNameExist(secondMediaFileName)).toBeFalsy(); + expect(await umbracoApi.media.doesMediaItemExistInRecycleBin(firstMediaFileName)).toBeTruthy(); + expect(await umbracoApi.media.doesMediaItemExistInRecycleBin(secondMediaFileName)).toBeTruthy(); + await umbracoUi.media.isItemVisibleInRecycleBin(firstMediaFileName); + await umbracoUi.media.isItemVisibleInRecycleBin(secondMediaFileName, true, false); + + // Clean + await umbracoApi.media.ensureNameNotExists(firstMediaFileName); + await umbracoApi.media.ensureNameNotExists(secondMediaFileName); + await umbracoApi.document.ensureNameNotExists(documentPickerName1[0]); + await umbracoApi.documentType.ensureNameNotExists(documentPickerName1[1]); + await umbracoApi.document.ensureNameNotExists(documentPickerName2[0]); + await umbracoApi.documentType.ensureNameNotExists(documentPickerName2[1]); + await umbracoApi.media.emptyRecycleBin(); +}); \ No newline at end of file