diff --git a/tests/Umbraco.Tests.AcceptanceTest/lib/builders/dataTypes/blockGridBuilder/blockGridAreaBuilder.ts b/tests/Umbraco.Tests.AcceptanceTest/lib/builders/dataTypes/blockGridBuilder/blockGridAreaBuilder.ts index 71ad3b086e43..4bf3900778eb 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/lib/builders/dataTypes/blockGridBuilder/blockGridAreaBuilder.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/lib/builders/dataTypes/blockGridBuilder/blockGridAreaBuilder.ts @@ -94,7 +94,7 @@ export class BlockGridAreaBuilder { } if (this.blockGridSpecifiedAllowanceBuilder && this.blockGridSpecifiedAllowanceBuilder.length > 0) { - values.specifiedAllowances = this.blockGridSpecifiedAllowanceBuilder.map((builder) => { + values.specifiedAllowance = this.blockGridSpecifiedAllowanceBuilder.map((builder) => { return builder.getValues(); }); } diff --git a/tests/Umbraco.Tests.AcceptanceTest/lib/helpers/DataTypeApiHelper.ts b/tests/Umbraco.Tests.AcceptanceTest/lib/helpers/DataTypeApiHelper.ts index 2efaa9af05b5..50d202b6ed8e 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/lib/helpers/DataTypeApiHelper.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/lib/helpers/DataTypeApiHelper.ts @@ -602,6 +602,96 @@ export class DataTypeApiHelper { return await this.save(blockGrid); } + async createBlockGridWithAnAreaWithSpecifiedAllowanceInABlock(blockGridName: string, contentElementTypeId: string, specifiedAllowanceElementTypeId: string, areaAlias: string = 'area', createLabel: string = 'CreateLabel', columnSpan: number = 6, rowSpan: number = 1) { + await this.ensureNameNotExists(blockGridName); + + const blockGrid = new BlockGridDataTypeBuilder() + .withName(blockGridName) + .addBlock() + .withContentElementTypeKey(contentElementTypeId) + .withAllowAtRoot(true) + .addArea() + .withAlias(areaAlias) + .withCreateLabel(createLabel) + .withColumnSpan(columnSpan) + .withRowSpan(rowSpan) + .addSpecifiedAllowance() + .withElementTypeKey(specifiedAllowanceElementTypeId) + .done() + .done() + .done() + .addBlock() + .withContentElementTypeKey(specifiedAllowanceElementTypeId) + .withAllowInAreas(true) + .done() + .build(); + + return await this.save(blockGrid); + } + + async createBlockGridWithAnAreaWithSpecifiedAllowanceWithMinMaxInABlock(blockGridName: string, contentElementTypeId: string, specifiedAllowanceElementTypeId: string, minAllowed: number, maxAllowed: number, areaAlias: string = 'area', createLabel: string = 'CreateLabel', columnSpan: number = 6, rowSpan: number = 1) { + await this.ensureNameNotExists(blockGridName); + + const blockGrid = new BlockGridDataTypeBuilder() + .withName(blockGridName) + .addBlock() + .withContentElementTypeKey(contentElementTypeId) + .withAllowAtRoot(true) + .addArea() + .withAlias(areaAlias) + .withCreateLabel(createLabel) + .withColumnSpan(columnSpan) + .withRowSpan(rowSpan) + .addSpecifiedAllowance() + .withElementTypeKey(specifiedAllowanceElementTypeId) + .withMinAllowed(minAllowed) + .withMaxAllowed(maxAllowed) + .done() + .done() + .done() + .addBlock() + .withContentElementTypeKey(specifiedAllowanceElementTypeId) + .withAllowInAreas(true) + .done() + .build(); + + return await this.save(blockGrid); + } + + async createBlockGridWithAnAreaWithTwoSpecifiedAllowancesInABlock(blockGridName: string, contentElementTypeId: string, firstSpecifiedAllowanceElementTypeId: string, secondSpecifiedAllowanceElementTypeId: string, areaAlias: string = 'area', createLabel: string = 'CreateLabel', columnSpan: number = 6, rowSpan: number = 1) { + await this.ensureNameNotExists(blockGridName); + + const blockGrid = new BlockGridDataTypeBuilder() + .withName(blockGridName) + .addBlock() + .withContentElementTypeKey(contentElementTypeId) + .withAllowAtRoot(true) + .addArea() + .withAlias(areaAlias) + .withCreateLabel(createLabel) + .withColumnSpan(columnSpan) + .withRowSpan(rowSpan) + .addSpecifiedAllowance() + .withElementTypeKey(firstSpecifiedAllowanceElementTypeId) + .done() + .addSpecifiedAllowance() + .withElementTypeKey(secondSpecifiedAllowanceElementTypeId) + .done() + .done() + .done() + .addBlock() + .withContentElementTypeKey(firstSpecifiedAllowanceElementTypeId) + .withAllowInAreas(true) + .done() + .addBlock() + .withContentElementTypeKey(secondSpecifiedAllowanceElementTypeId) + .withAllowInAreas(true) + .done() + .build(); + + return await this.save(blockGrid); + } + async createBlockGridWithAnAreaInABlockWithAllowInAreas(blockGridName: string, contentElementTypeId: string, areaAlias: string = 'area', allowInAreas = false, createButtonLabel :string = 'CreateLabel', columnSpan: number = 6, rowSpan: number = 1, minAllowed: number = 0, maxAllowed: number = 2) { await this.ensureNameNotExists(blockGridName); @@ -939,11 +1029,35 @@ export class DataTypeApiHelper { } async doesBlockEditorBlockContainAreaWithSpecifiedAllowance(blockGridName: string, elementTypeKey: string, areaAlias: string = 'area') { - const block = await this.getBlockWithContentElementTypeId(blockGridName, elementTypeKey); - const area = block.areas.find(area => area.alias === areaAlias); + const area = await this.getBlockAreaByAlias(blockGridName, elementTypeKey, areaAlias); return area && area.specifiedAllowance && area.specifiedAllowance.length > 0; } + async doesBlockGridBlockContainAreaWithSpecifiedAllowanceForElementType(blockGridName: string, elementTypeKey: string, specifiedAllowanceElementTypeKey: string, areaAlias: string = 'area') { + const area = await this.getBlockAreaByAlias(blockGridName, elementTypeKey, areaAlias); + return area && area.specifiedAllowance && area.specifiedAllowance.some(sa => sa.elementTypeKey === specifiedAllowanceElementTypeKey); + } + + async doesBlockGridBlockContainAreaWithSpecifiedAllowanceCount(blockGridName: string, elementTypeKey: string, count: number, areaAlias: string = 'area') { + const area = await this.getBlockAreaByAlias(blockGridName, elementTypeKey, areaAlias); + return area && area.specifiedAllowance && area.specifiedAllowance.length === count; + } + + async doesBlockGridBlockContainAreaWithSpecifiedAllowanceMinMax(blockGridName: string, elementTypeKey: string, specifiedAllowanceElementTypeKey: string, minAllowed: number, maxAllowed: number, areaAlias: string = 'area') { + const area = await this.getBlockAreaByAlias(blockGridName, elementTypeKey, areaAlias); + return area && area.specifiedAllowance && + area.specifiedAllowance.some(sa => + sa.elementTypeKey === specifiedAllowanceElementTypeKey && + sa.minAllowed === minAllowed && + sa.maxAllowed === maxAllowed + ); + } + + private async getBlockAreaByAlias(blockGridName: string, elementTypeKey: string, areaAlias: string) { + const block = await this.getBlockWithContentElementTypeId(blockGridName, elementTypeKey); + return block.areas.find(area => area.alias === areaAlias); + } + async doesBlockEditorBlockContainStylesheet(blockGridName: string, elementTypeKey: string, stylesheetPath: string) { const block = await this.getBlockWithContentElementTypeId(blockGridName, elementTypeKey); const encodedSecondStylesheetPath = await this.api.stylesheet.encodeStylesheetPath(stylesheetPath); diff --git a/tests/Umbraco.Tests.AcceptanceTest/lib/helpers/DataTypeUiHelper.ts b/tests/Umbraco.Tests.AcceptanceTest/lib/helpers/DataTypeUiHelper.ts index 42253a0bc208..85d658ad2515 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/lib/helpers/DataTypeUiHelper.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/lib/helpers/DataTypeUiHelper.ts @@ -146,6 +146,8 @@ export class DataTypeUiHelper extends UiBaseLocators { private readonly dynamicRootOriginPickerModal: Locator; private readonly dynamicRootQueryStepPickerModal: Locator; private readonly closeDynamicRootOriginPickerModalBtn: Locator; + private readonly specifiedAllowance: Locator; + private readonly specifiedAllowanceItems: Locator; constructor(page: Page) { super(page); @@ -297,13 +299,15 @@ export class DataTypeUiHelper extends UiBaseLocators { this.createLabelTxt = this.page.locator('[alias="createLabel"]').locator('#input'); this.minAllowedTxt = this.page.locator('#container').getByLabel('Low value'); this.maxAllowedTxt = this.page.locator('#container').getByLabel('High value'); - this.addSpecifiedAllowanceBtn = this.page.locator('[alias="specifiedAllowance"]').getByLabel('Add'); this.advancedTabBtn = this.page.getByRole('tab', {name: 'Advanced'}); this.allowBlockAtRootToggle = this.page.getByTestId('property:allowAtRoot').locator('#toggle'); this.allowInAreasToggle = this.page.getByTestId('property:allowInAreas').locator('#toggle'); this.expandChildItemsForMediaBtn = this.page.getByLabel('Expand child items for media', {exact: true}); this.chooseCustomStylesheetBtn = this.page.locator('[label="Custom stylesheet"]').getByLabel('Choose'); this.blockThumbnailRemoveBtn = this.page.getByTestId('property:thumbnail').getByLabel('Remove', {exact: true}); + this.specifiedAllowance = this.page.getByTestId('property:specifiedAllowance'); + this.addSpecifiedAllowanceBtn = this.specifiedAllowance.getByLabel('Add'); + this.specifiedAllowanceItems = this.specifiedAllowance.locator('.permission-setting'); // Tiptap this.tiptapToolbarConfiguration = this.page.locator('umb-property-editor-ui-tiptap-toolbar-configuration'); @@ -835,7 +839,7 @@ export class DataTypeUiHelper extends UiBaseLocators { } async goToBlockWithName(name: string) { - await this.click(this.page.getByRole('link', {name: name})); + await this.click(this.page.getByRole('link', {name: name, exact: true})); } async enterBlockLabelText(label: string) { @@ -1058,6 +1062,41 @@ export class DataTypeUiHelper extends UiBaseLocators { await this.click(this.addSpecifiedAllowanceBtn); } + async clickSpecifiedAllowanceComboboxByIndex(index: number = 0) { + const combobox = this.specifiedAllowanceItems.nth(index).locator('uui-combobox'); + await this.click(combobox); + } + + async selectSpecifiedAllowanceOptionByName(elementTypeName: string) { + const option = this.specifiedAllowanceItems.locator('uui-combobox-list-option').filter({hasText: elementTypeName}); + await this.click(option); + } + + async clickRemoveSpecifiedAllowanceByIndex(index: number = 0) { + const removeBtn = this.specifiedAllowanceItems.nth(index).locator('uui-button[label="Remove"]'); + await this.click(removeBtn); + } + + async enterSpecifiedAllowanceMinByIndex(value: number | undefined, index: number = 0) { + const minInput = this.specifiedAllowanceItems.nth(index).locator('uui-input[type="number"]').first().locator('input'); + if (value === undefined) { + await this.focus(minInput); // Focus is needed + await this.clearText(minInput); + return; + } + await this.enterText(minInput, value.toString()); + } + + async enterSpecifiedAllowanceMaxByIndex(value: number | undefined, index: number = 0) { + const maxInput = this.specifiedAllowanceItems.nth(index).locator('uui-input[type="number"]').nth(1).locator('input'); + if (value === undefined) { + await this.focus(maxInput); // Focus is needed + await this.clearText(maxInput); + return; + } + await this.enterText(maxInput, value.toString()); + } + async goToBlockAdvancedTab() { await this.click(this.advancedTabBtn); } diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockGrid/BlockGridArea.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockGrid/BlockGridArea.spec.ts index ed642eef7b16..7124110478c4 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockGrid/BlockGridArea.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockGrid/BlockGridArea.spec.ts @@ -12,6 +12,7 @@ const contentName = 'TestContent'; const firstElementTypeName = 'FirstBlockGridElement'; let firstElementTypeId = null; const secondElementTypeName = 'SecondBlockGridElement'; +const thirdElementTypeName = 'ThirdBlockGridElement'; // Block Grid Data Type const blockGridDataTypeName = 'BlockGridTester'; @@ -20,29 +21,26 @@ const firstAreaName = 'FirstArea'; const areaCreateLabel = 'CreateLabel'; const toAllowInAreas = true; -test.beforeEach(async ({umbracoApi}) => { - await umbracoApi.documentType.ensureNameNotExists(documentTypeName); - await umbracoApi.documentType.ensureNameNotExists(firstElementTypeName); - await umbracoApi.documentType.ensureNameNotExists(secondElementTypeName); +test.beforeEach(async ({umbracoApi, umbracoUi}) => { await umbracoApi.document.ensureNameNotExists(contentName); - await umbracoApi.dataType.ensureNameNotExists(blockGridDataTypeName); + firstElementTypeId = await umbracoApi.documentType.createEmptyElementType(firstElementTypeName); + await umbracoUi.goToBackOffice(); }); test.afterEach(async ({umbracoApi}) => { await umbracoApi.documentType.ensureNameNotExists(documentTypeName); await umbracoApi.documentType.ensureNameNotExists(firstElementTypeName); await umbracoApi.documentType.ensureNameNotExists(secondElementTypeName); + await umbracoApi.documentType.ensureNameNotExists(thirdElementTypeName); await umbracoApi.document.ensureNameNotExists(contentName); await umbracoApi.dataType.ensureNameNotExists(blockGridDataTypeName); }); test('can create content with a block grid with an empty block in a area', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => { // Arrange - firstElementTypeId = await umbracoApi.documentType.createEmptyElementType(firstElementTypeName); blockGridDataTypeId = await umbracoApi.dataType.createBlockGridWithAnAreaInABlockWithAllowInAreas(blockGridDataTypeName, firstElementTypeId, firstAreaName, toAllowInAreas, areaCreateLabel); documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, blockGridDataTypeName, blockGridDataTypeId); await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); - await umbracoUi.goToBackOffice(); await umbracoUi.content.goToSection(ConstantHelper.sections.content); await umbracoUi.content.goToContentWithName(contentName); @@ -61,11 +59,9 @@ test('can create content with a block grid with an empty block in a area', {tag: test('can create content with a block grid with two empty blocks in a area', async ({umbracoApi, umbracoUi}) => { // Arrange - firstElementTypeId = await umbracoApi.documentType.createEmptyElementType(firstElementTypeName); blockGridDataTypeId = await umbracoApi.dataType.createBlockGridWithAnAreaInABlockWithAllowInAreas(blockGridDataTypeName, firstElementTypeId, firstAreaName, toAllowInAreas, areaCreateLabel); documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, blockGridDataTypeName, blockGridDataTypeId); await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); - await umbracoUi.goToBackOffice(); await umbracoUi.content.goToSection(ConstantHelper.sections.content); await umbracoUi.content.goToContentWithName(contentName); @@ -92,12 +88,10 @@ test('can create content with a block grid with two empty blocks in a area', asy test('can create content with block grid area with a create label', async ({umbracoApi, umbracoUi}) => { // Arrange - firstElementTypeId = await umbracoApi.documentType.createEmptyElementType(firstElementTypeName); const createLabel = 'ThisIsACreateLabel'; blockGridDataTypeId = await umbracoApi.dataType.createBlockGridWithAnAreaInABlockWithACreateLabel(blockGridDataTypeName, firstElementTypeId, createLabel, firstAreaName); documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, blockGridDataTypeName, blockGridDataTypeId); await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); - await umbracoUi.goToBackOffice(); await umbracoUi.content.goToSection(ConstantHelper.sections.content); await umbracoUi.content.goToContentWithName(contentName); @@ -112,12 +106,10 @@ test('can create content with block grid area with a create label', async ({umbr test('can create content with block grid area with column span', async ({umbracoApi, umbracoUi}) => { // Arrange - firstElementTypeId = await umbracoApi.documentType.createEmptyElementType(firstElementTypeName); const columnSpan = 2; blockGridDataTypeId = await umbracoApi.dataType.createBlockGridWithAnAreaInABlockWithColumnSpanAndRowSpan(blockGridDataTypeName, firstElementTypeId, columnSpan, 1, firstAreaName, areaCreateLabel); documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, blockGridDataTypeName, blockGridDataTypeId); await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); - await umbracoUi.goToBackOffice(); await umbracoUi.content.goToSection(ConstantHelper.sections.content); await umbracoUi.content.goToContentWithName(contentName); @@ -132,12 +124,10 @@ test('can create content with block grid area with column span', async ({umbraco test('can create content with block grid area with row span', async ({umbracoApi, umbracoUi}) => { // Arrange - firstElementTypeId = await umbracoApi.documentType.createEmptyElementType(firstElementTypeName); const rowSpan = 4; blockGridDataTypeId = await umbracoApi.dataType.createBlockGridWithAnAreaInABlockWithColumnSpanAndRowSpan(blockGridDataTypeName, firstElementTypeId, 12, rowSpan, firstAreaName, areaCreateLabel); documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, blockGridDataTypeName, blockGridDataTypeId); await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); - await umbracoUi.goToBackOffice(); await umbracoUi.content.goToSection(ConstantHelper.sections.content); await umbracoUi.content.goToContentWithName(contentName); @@ -152,13 +142,11 @@ test('can create content with block grid area with row span', async ({umbracoApi test('can create content with block grid area with min allowed', async ({umbracoApi, umbracoUi}) => { // Arrange - firstElementTypeId = await umbracoApi.documentType.createEmptyElementType(firstElementTypeName); const secondElementTypeId = await umbracoApi.documentType.createEmptyElementType(secondElementTypeName); const minAllowed = 2; blockGridDataTypeId = await umbracoApi.dataType.createBlockGridWithAnAreaInABlockWithMinAndMaxAllowed(blockGridDataTypeName, firstElementTypeId, secondElementTypeId, minAllowed, 10, firstAreaName, areaCreateLabel); documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, blockGridDataTypeName, blockGridDataTypeId); await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); - await umbracoUi.goToBackOffice(); await umbracoUi.content.goToSection(ConstantHelper.sections.content); await umbracoUi.content.goToContentWithName(contentName); @@ -186,13 +174,11 @@ test('can create content with block grid area with min allowed', async ({umbraco test('can create content with block grid area with max allowed', async ({umbracoApi, umbracoUi}) => { // Arrange - firstElementTypeId = await umbracoApi.documentType.createEmptyElementType(firstElementTypeName); const secondElementTypeId = await umbracoApi.documentType.createEmptyElementType(secondElementTypeName); const maxAllowed = 0; blockGridDataTypeId = await umbracoApi.dataType.createBlockGridWithAnAreaInABlockWithMinAndMaxAllowed(blockGridDataTypeName, firstElementTypeId, secondElementTypeId, 0, maxAllowed, firstAreaName, areaCreateLabel); documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, blockGridDataTypeName, blockGridDataTypeId); await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); - await umbracoUi.goToBackOffice(); await umbracoUi.content.goToSection(ConstantHelper.sections.content); await umbracoUi.content.goToContentWithName(contentName); @@ -217,3 +203,105 @@ test('can create content with block grid area with max allowed', async ({umbraco // Clean await umbracoApi.documentType.ensureNameNotExists(secondElementTypeName); }); + +test('can create content with a block grid area with specified allowance', async ({umbracoApi, umbracoUi}) => { + // Arrange + const secondElementTypeId = await umbracoApi.documentType.createEmptyElementType(secondElementTypeName); + blockGridDataTypeId = await umbracoApi.dataType.createBlockGridWithAnAreaWithSpecifiedAllowanceInABlock(blockGridDataTypeName, firstElementTypeId, secondElementTypeId, firstAreaName, areaCreateLabel); + documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, blockGridDataTypeName, blockGridDataTypeId); + await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + await umbracoUi.content.goToContentWithName(contentName); + + // Act + await umbracoUi.content.clickAddBlockGridElementWithName(firstElementTypeName); + await umbracoUi.content.clickSelectBlockElementWithName(firstElementTypeName); + await umbracoUi.content.clickLinkWithName(areaCreateLabel); + await umbracoUi.content.clickSelectBlockElementInAreaWithName(secondElementTypeName); + await umbracoUi.content.clickSaveAndPublishButtonAndWaitForContentToBePublished(); + + // Assert + await umbracoUi.content.doesBlockContainBlockInAreaWithName(firstElementTypeName, firstAreaName, secondElementTypeName); + await umbracoUi.content.doesBlockContainBlockCountInArea(firstElementTypeName, firstAreaName, 1); +}); + +test('can create content with a block grid area with specified allowance with min allowed', async ({umbracoApi, umbracoUi}) => { + // Arrange + const secondElementTypeId = await umbracoApi.documentType.createEmptyElementType(secondElementTypeName); + const minAllowed = 2; + const warningMessage = secondElementTypeName + ' must be present at least ' + minAllowed + ' time(s).'; + blockGridDataTypeId = await umbracoApi.dataType.createBlockGridWithAnAreaWithSpecifiedAllowanceWithMinMaxInABlock(blockGridDataTypeName, firstElementTypeId, secondElementTypeId, minAllowed, 10, firstAreaName, areaCreateLabel); + documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, blockGridDataTypeName, blockGridDataTypeId); + await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + await umbracoUi.content.goToContentWithName(contentName); + + // Act + await umbracoUi.content.clickAddBlockGridElementWithName(firstElementTypeName); + await umbracoUi.content.clickSelectBlockElementWithName(firstElementTypeName); + await umbracoUi.content.clickLinkWithName(areaCreateLabel); + await umbracoUi.content.clickSelectBlockElementInAreaWithName(secondElementTypeName); + await umbracoUi.content.isTextWithExactNameVisible(warningMessage); + await umbracoUi.content.clickSaveAndPublishButton(); + await umbracoUi.content.doesErrorNotificationHaveText(NotificationConstantHelper.error.documentCouldNotBePublished); + await umbracoUi.content.clickInlineAddToAreaButton(firstElementTypeName, firstAreaName, 0, 1); + await umbracoUi.content.clickSelectBlockElementInAreaWithName(secondElementTypeName); + await umbracoUi.content.clickSaveAndPublishButtonAndWaitForContentToBePublished(); + + // Assert + await umbracoUi.content.doesBlockContainBlockCountInArea(firstElementTypeName, firstAreaName, 2); +}); + +test('can create content with a block grid area with specified allowance with max allowed', async ({umbracoApi, umbracoUi}) => { + // Arrange + const secondElementTypeId = await umbracoApi.documentType.createEmptyElementType(secondElementTypeName); + const maxAllowed = 1; + const warningMessage = secondElementTypeName + ' must maximum be present ' + maxAllowed + ' time(s).'; + blockGridDataTypeId = await umbracoApi.dataType.createBlockGridWithAnAreaWithSpecifiedAllowanceWithMinMaxInABlock(blockGridDataTypeName, firstElementTypeId, secondElementTypeId, 0, maxAllowed, firstAreaName, areaCreateLabel); + documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, blockGridDataTypeName, blockGridDataTypeId); + await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + await umbracoUi.content.goToContentWithName(contentName); + + // Act + await umbracoUi.content.clickAddBlockGridElementWithName(firstElementTypeName); + await umbracoUi.content.clickSelectBlockElementWithName(firstElementTypeName); + await umbracoUi.content.clickLinkWithName(areaCreateLabel); + await umbracoUi.content.clickSelectBlockElementInAreaWithName(secondElementTypeName); + await umbracoUi.content.clickInlineAddToAreaButton(firstElementTypeName, firstAreaName, 0, 1); + await umbracoUi.content.clickSelectBlockElementInAreaWithName(secondElementTypeName); + await umbracoUi.content.isTextWithExactNameVisible(warningMessage); + await umbracoUi.content.clickSaveAndPublishButton(); + await umbracoUi.content.doesErrorNotificationHaveText(NotificationConstantHelper.error.documentCouldNotBePublished); + await umbracoUi.content.removeBlockFromArea(firstElementTypeName, firstAreaName, secondElementTypeName); + await umbracoUi.content.clickConfirmToDeleteButton(); + await umbracoUi.content.clickSaveAndPublishButtonAndWaitForContentToBePublished(); + + // Assert + await umbracoUi.content.doesBlockContainBlockCountInArea(firstElementTypeName, firstAreaName, 1); +}); + +test('can create content with a block grid area with multiple specified allowances', async ({umbracoApi, umbracoUi}) => { + // Arrange + const secondElementTypeId = await umbracoApi.documentType.createEmptyElementType(secondElementTypeName); + const thirdElementTypeId = await umbracoApi.documentType.createEmptyElementType(thirdElementTypeName); + blockGridDataTypeId = await umbracoApi.dataType.createBlockGridWithAnAreaWithTwoSpecifiedAllowancesInABlock(blockGridDataTypeName, firstElementTypeId, secondElementTypeId, thirdElementTypeId, firstAreaName, areaCreateLabel); + documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, blockGridDataTypeName, blockGridDataTypeId); + await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + await umbracoUi.content.goToContentWithName(contentName); + + // Act + await umbracoUi.content.clickAddBlockGridElementWithName(firstElementTypeName); + await umbracoUi.content.clickSelectBlockElementWithName(firstElementTypeName); + await umbracoUi.content.clickLinkWithName(areaCreateLabel); + await umbracoUi.content.clickSelectBlockElementInAreaWithName(secondElementTypeName); + await umbracoUi.content.clickInlineAddToAreaButton(firstElementTypeName, firstAreaName, 0, 1); + await umbracoUi.content.clickSelectBlockElementInAreaWithName(thirdElementTypeName); + await umbracoUi.content.clickSaveAndPublishButtonAndWaitForContentToBePublished(); + + // Assert + await umbracoUi.content.doesBlockContainBlockInAreaWithName(firstElementTypeName, firstAreaName, secondElementTypeName); + await umbracoUi.content.doesBlockContainBlockInAreaWithName(firstElementTypeName, firstAreaName, thirdElementTypeName); + await umbracoUi.content.doesBlockContainBlockCountInArea(firstElementTypeName, firstAreaName, 2); +}); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/BlockGrid/Block/BlockGridBlockAreas.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/BlockGrid/Block/BlockGridBlockAreas.spec.ts index 0922d8533493..dd158e8629a9 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/BlockGrid/Block/BlockGridBlockAreas.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/BlockGrid/Block/BlockGridBlockAreas.spec.ts @@ -3,6 +3,7 @@ import {expect} from "@playwright/test"; const blockGridEditorName = 'TestBlockGridEditor'; const elementTypeName = 'BlockGridElement'; +const secondElementTypeName = 'SecondBlockElement'; const dataTypeName = 'Textstring'; const groupName = 'testGroup'; let contentElementTypeId = ''; @@ -17,6 +18,7 @@ test.beforeEach(async ({umbracoUi, umbracoApi}) => { test.afterEach(async ({umbracoApi}) => { await umbracoApi.dataType.ensureNameNotExists(blockGridEditorName); await umbracoApi.documentType.ensureNameNotExists(elementTypeName); + await umbracoApi.documentType.ensureNameNotExists(secondElementTypeName); }); test('can update grid columns for areas for a block', async ({umbracoApi, umbracoUi}) => { @@ -291,22 +293,119 @@ test('can add specified allowance for an area in a block', async ({umbracoApi, u expect(await umbracoApi.dataType.doesBlockEditorBlockContainAreaWithSpecifiedAllowance(blockGridEditorName, contentElementTypeId, areaAlias)).toBeTruthy(); }); -test.fixme('can update specified allowance for an area in a block', async ({umbracoApi, umbracoUi}) => { - // TODO: Implement it later +test('can update specified allowance for an area in a block', async ({umbracoApi, umbracoUi}) => { + // Arrange + const areaAlias = 'TestArea'; + const textStringData = await umbracoApi.dataType.getByName(dataTypeName); + const secondContentElementTypeId = await umbracoApi.documentType.createDefaultElementType(secondElementTypeName, groupName, dataTypeName, textStringData.id); + await umbracoApi.dataType.createBlockGridWithAnAreaWithSpecifiedAllowanceInABlock(blockGridEditorName, contentElementTypeId, secondContentElementTypeId, areaAlias); + expect(await umbracoApi.dataType.doesBlockGridBlockContainAreaWithSpecifiedAllowanceForElementType(blockGridEditorName, contentElementTypeId, secondContentElementTypeId, areaAlias)).toBeTruthy(); + + // Act + await umbracoUi.dataType.goToDataType(blockGridEditorName); + await umbracoUi.dataType.goToBlockWithName(elementTypeName); + await umbracoUi.dataType.goToBlockAreasTab(); + await umbracoUi.dataType.goToAreaByAlias(areaAlias); + await umbracoUi.dataType.clickSpecifiedAllowanceComboboxByIndex(0); + await umbracoUi.dataType.selectSpecifiedAllowanceOptionByName(elementTypeName); + await umbracoUi.dataType.clickAreaSubmitButton(); + await umbracoUi.dataType.clickSubmitButton(); + await umbracoUi.dataType.clickSaveButtonAndWaitForDataTypeToBeUpdated(); + + // Assert + expect(await umbracoApi.dataType.doesBlockGridBlockContainAreaWithSpecifiedAllowanceForElementType(blockGridEditorName, contentElementTypeId, contentElementTypeId, areaAlias)).toBeTruthy(); + expect(await umbracoApi.dataType.doesBlockGridBlockContainAreaWithSpecifiedAllowanceForElementType(blockGridEditorName, contentElementTypeId, secondContentElementTypeId, areaAlias)).toBeFalsy(); }); -test.fixme('can remove specified allowance for an area in a block', async ({umbracoApi, umbracoUi}) => { - // TODO: Implement it later +test('can remove specified allowance for an area in a block', async ({umbracoApi, umbracoUi}) => { + // Arrange + const areaAlias = 'TestArea'; + const textStringData = await umbracoApi.dataType.getByName(dataTypeName); + const secondContentElementTypeId = await umbracoApi.documentType.createDefaultElementType(secondElementTypeName, groupName, dataTypeName, textStringData.id); + await umbracoApi.dataType.createBlockGridWithAnAreaWithSpecifiedAllowanceInABlock(blockGridEditorName, contentElementTypeId, secondContentElementTypeId, areaAlias); + expect(await umbracoApi.dataType.doesBlockEditorBlockContainAreaWithSpecifiedAllowance(blockGridEditorName, contentElementTypeId, areaAlias)).toBeTruthy(); + + // Act + await umbracoUi.dataType.goToDataType(blockGridEditorName); + await umbracoUi.dataType.goToBlockWithName(elementTypeName); + await umbracoUi.dataType.goToBlockAreasTab(); + await umbracoUi.dataType.goToAreaByAlias(areaAlias); + await umbracoUi.dataType.clickRemoveSpecifiedAllowanceByIndex(0); + await umbracoUi.dataType.clickAreaSubmitButton(); + await umbracoUi.dataType.clickSubmitButton(); + await umbracoUi.dataType.clickSaveButtonAndWaitForDataTypeToBeUpdated(); + + // Assert + expect(await umbracoApi.dataType.doesBlockEditorBlockContainAreaWithSpecifiedAllowance(blockGridEditorName, contentElementTypeId, areaAlias)).toBeFalsy(); }); -test.fixme('can add multiple specified allowances for an area in a block', async ({umbracoApi, umbracoUi}) => { - // TODO: Implement it later +test('can add multiple specified allowances for an area in a block', async ({umbracoApi, umbracoUi}) => { + // Arrange + const areaAlias = 'TestArea'; + const textStringData = await umbracoApi.dataType.getByName(dataTypeName); + const secondContentElementTypeId = await umbracoApi.documentType.createDefaultElementType(secondElementTypeName, groupName, dataTypeName, textStringData.id); + await umbracoApi.dataType.createBlockGridWithAnAreaWithSpecifiedAllowanceInABlock(blockGridEditorName, contentElementTypeId, secondContentElementTypeId, areaAlias); + expect(await umbracoApi.dataType.doesBlockGridBlockContainAreaWithSpecifiedAllowanceCount(blockGridEditorName, contentElementTypeId, 1, areaAlias)).toBeTruthy(); + + // Act + await umbracoUi.dataType.goToDataType(blockGridEditorName); + await umbracoUi.dataType.goToBlockWithName(elementTypeName); + await umbracoUi.dataType.goToBlockAreasTab(); + await umbracoUi.dataType.goToAreaByAlias(areaAlias); + await umbracoUi.dataType.clickAddSpecifiedAllowanceButton(); + await umbracoUi.dataType.clickAreaSubmitButton(); + await umbracoUi.dataType.clickSubmitButton(); + await umbracoUi.dataType.clickSaveButtonAndWaitForDataTypeToBeUpdated(); + + // Assert + expect(await umbracoApi.dataType.doesBlockGridBlockContainAreaWithSpecifiedAllowanceCount(blockGridEditorName, contentElementTypeId, 2, areaAlias)).toBeTruthy(); }); -test.fixme('can add specified allowance with min and max for an area in a block', async ({umbracoApi, umbracoUi}) => { - // TODO: Implement it later +test('can add specified allowance with min and max for an area in a block', async ({umbracoApi, umbracoUi}) => { + // Arrange + const areaAlias = 'TestArea'; + const minAllowed = 2; + const maxAllowed = 5; + const textStringData = await umbracoApi.dataType.getByName(dataTypeName); + const secondContentElementTypeId = await umbracoApi.documentType.createDefaultElementType(secondElementTypeName, groupName, dataTypeName, textStringData.id); + await umbracoApi.dataType.createBlockGridWithAnAreaWithSpecifiedAllowanceInABlock(blockGridEditorName, contentElementTypeId, secondContentElementTypeId, areaAlias); + + // Act + await umbracoUi.dataType.goToDataType(blockGridEditorName); + await umbracoUi.dataType.goToBlockWithName(elementTypeName); + await umbracoUi.dataType.goToBlockAreasTab(); + await umbracoUi.dataType.goToAreaByAlias(areaAlias); + await umbracoUi.dataType.enterSpecifiedAllowanceMinByIndex(minAllowed, 0); + await umbracoUi.dataType.enterSpecifiedAllowanceMaxByIndex(maxAllowed, 0); + await umbracoUi.dataType.clickAreaSubmitButton(); + await umbracoUi.dataType.clickSubmitButton(); + await umbracoUi.dataType.clickSaveButtonAndWaitForDataTypeToBeUpdated(); + + // Assert + expect(await umbracoApi.dataType.doesBlockGridBlockContainAreaWithSpecifiedAllowanceMinMax(blockGridEditorName, contentElementTypeId, secondContentElementTypeId, minAllowed, maxAllowed, areaAlias)).toBeTruthy(); }); -test.fixme('can remove min and max from specified allowance for an area in a block', async ({umbracoApi, umbracoUi}) => { - // TODO: Implement it later +test('can remove min and max from specified allowance for an area in a block', async ({umbracoApi, umbracoUi}) => { + // Arrange + const areaAlias = 'TestArea'; + const minAllowed = 3; + const maxAllowed = 8; + const textStringData = await umbracoApi.dataType.getByName(dataTypeName); + const secondContentElementTypeId = await umbracoApi.documentType.createDefaultElementType(secondElementTypeName, groupName, dataTypeName, textStringData.id); + await umbracoApi.dataType.createBlockGridWithAnAreaWithSpecifiedAllowanceWithMinMaxInABlock(blockGridEditorName, contentElementTypeId, secondContentElementTypeId, minAllowed, maxAllowed, areaAlias); + expect(await umbracoApi.dataType.doesBlockGridBlockContainAreaWithSpecifiedAllowanceMinMax(blockGridEditorName, contentElementTypeId, secondContentElementTypeId, minAllowed, maxAllowed, areaAlias)).toBeTruthy(); + + // Act + await umbracoUi.dataType.goToDataType(blockGridEditorName); + await umbracoUi.dataType.goToBlockWithName(elementTypeName); + await umbracoUi.dataType.goToBlockAreasTab(); + await umbracoUi.dataType.goToAreaByAlias(areaAlias); + await umbracoUi.dataType.enterSpecifiedAllowanceMinByIndex(undefined, 0); + await umbracoUi.dataType.enterSpecifiedAllowanceMaxByIndex(undefined, 0); + await umbracoUi.dataType.clickAreaSubmitButton(); + await umbracoUi.dataType.clickSubmitButton(); + await umbracoUi.dataType.clickSaveButtonAndWaitForDataTypeToBeUpdated(); + + // Assert + expect(await umbracoApi.dataType.doesBlockGridBlockContainAreaWithSpecifiedAllowanceMinMax(blockGridEditorName, contentElementTypeId, secondContentElementTypeId, minAllowed, maxAllowed, areaAlias)).toBeFalsy(); });