diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Content/content.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Content/content.ts index 25d0b02e1dd6..b367ea124b95 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Content/content.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Content/content.ts @@ -766,7 +766,8 @@ context('Content', () => { // Click macro cy.get(':nth-child(4) > .umb-card-grid-item > :nth-child(1)').click(); // Select the macro - cy.get('.umb-card-grid-item').contains(macroName).click(); + cy.get(`.umb-card-grid-item[title='${macroName}']`).click('bottom'); + // Save and publish cy.umbracoButtonByLabelKey('buttons_saveAndPublish').click(); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/macropicker/macropicker.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/macropicker/macropicker.html index 49d40efffaa3..0e936e52c427 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/macropicker/macropicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/macropicker/macropicker.html @@ -28,12 +28,12 @@

diff --git a/tests/Umbraco.Tests.AcceptanceTest/cypress/integration/Tabs/tabs.ts b/tests/Umbraco.Tests.AcceptanceTest/cypress/integration/Tabs/tabs.ts new file mode 100644 index 000000000000..196a104518f7 --- /dev/null +++ b/tests/Umbraco.Tests.AcceptanceTest/cypress/integration/Tabs/tabs.ts @@ -0,0 +1,552 @@ +/// +import { + DocumentTypeBuilder, + AliasHelper + } from 'umbraco-cypress-testhelpers'; + + const tabsDocTypeName = 'Tabs Test Document'; + const tabsDocTypeAlias = AliasHelper.toAlias(tabsDocTypeName); + + context('Tabs', () => { + + beforeEach(() => { + cy.umbracoLogin(Cypress.env('username'), Cypress.env('password'), false); + }); + + afterEach(() => { + cy.umbracoEnsureDocumentTypeNameNotExists(tabsDocTypeName) + }); + + function OpenDocTypeFolder(){ + cy.umbracoSection('settings'); + cy.get('li .umb-tree-root:contains("Settings")').should("be.visible"); + cy.get('.umb-tree-item__inner > .umb-tree-item__arrow').eq(0).click(); + cy.get('.umb-tree-item__inner > .umb-tree-item__label').contains(tabsDocTypeName).click(); + } + + function CreateDocWithTabAndNavigate(){ + cy.umbracoEnsureDocumentTypeNameNotExists(tabsDocTypeName); + const tabsDocType = new DocumentTypeBuilder() + .withName(tabsDocTypeName) + .withAlias(tabsDocTypeAlias) + .withAllowAsRoot(true) + .withDefaultTemplate(tabsDocTypeAlias) + .addTab() + .withName('Tab 1') + .addGroup() + .withName('Tab group') + .addUrlPickerProperty() + .withAlias("urlPicker") + .done() + .done() + .done() + .build(); + cy.saveDocumentType(tabsDocType); + OpenDocTypeFolder(); + } + + it('Create tab', () => { + cy.umbracoEnsureDocumentTypeNameNotExists(tabsDocTypeName); + cy.deleteAllContent(); + const tabsDocType = new DocumentTypeBuilder() + .withName(tabsDocTypeName) + .withAlias(tabsDocTypeAlias) + .withAllowAsRoot(true) + .withDefaultTemplate(tabsDocTypeAlias) + .addGroup() + .withName('Tabs1Group') + .addUrlPickerProperty() + .withAlias('picker') + .done() + .done() + .build(); + cy.saveDocumentType(tabsDocType); + OpenDocTypeFolder(); + //Create a tab + cy.get('.umb-group-builder__tabs__add-tab').click(); + cy.get('ng-form.ng-invalid > .umb-group-builder__group-title-input').type('Tab 1'); + //Create a 2nd tab manually + cy.get('.umb-group-builder__tabs__add-tab').click(); + cy.get('ng-form.ng-invalid > .umb-group-builder__group-title-input').type('Tab 2'); + //Create a textstring property + cy.get('[aria-hidden="false"] > .umb-box-content > .umb-group-builder__group-add-property').click(); + cy.get('.editor-label').type('property name'); + cy.get('[data-element="editor-add"]').click(); + + //Search for textstring + cy.get('#datatype-search').type('Textstring'); + + // Choose first item + cy.get('[title="Textstring"]').closest("li").click(); + + // Save property + cy.get('.btn-success').last().click(); + cy.umbracoButtonByLabelKey('buttons_save').click(); + //Assert + cy.umbracoSuccessNotification().should('be.visible'); + cy.get('[title="tab1"]').should('be.visible'); + cy.get('[title="tab2"]').should('be.visible'); + }); + + it('Delete tabs', () => { + CreateDocWithTabAndNavigate(); + //Check if tab is there, else if it wasnt created, this test would always pass + cy.get('[title="aTab 1"]').should('be.visible'); + //Delete a tab + cy.get('.btn-reset > [icon="icon-trash"]').first().click(); + cy.get('.umb-button > .btn').last().click(); + cy.umbracoButtonByLabelKey('buttons_save').click(); + //Assert + cy.get('[title="aTab 1"]').should('not.exist'); + //Clean + cy.umbracoEnsureDocumentTypeNameNotExists(tabsDocTypeName); + }); + + it('Delete property in tab', () => { + cy.umbracoEnsureDocumentTypeNameNotExists(tabsDocTypeName); + const tabsDocType = new DocumentTypeBuilder() + .withName(tabsDocTypeName) + .withAlias(tabsDocTypeAlias) + .withAllowAsRoot(true) + .withDefaultTemplate(tabsDocTypeAlias) + .addTab() + .withName('Tab 1') + .addGroup() + .withName('Tab group') + .addUrlPickerProperty() + .withAlias("urlPicker") + .done() + .addContentPickerProperty() + .withAlias('picker') + .done() + .done() + .done() + .build(); + cy.saveDocumentType(tabsDocType); + OpenDocTypeFolder(); + cy.get('[aria-label="Delete property"]').last().click(); + cy.umbracoButtonByLabelKey('actions_delete').click(); + cy.umbracoButtonByLabelKey('buttons_save').click() + //Assert + cy.umbracoSuccessNotification().should('be.visible'); + cy.get('[title=urlPicker]').should('be.visible'); + cy.get('[title=picker]').should('not.exist'); + }); + + it('Delete group in tab', () => { + cy.umbracoEnsureDocumentTypeNameNotExists(tabsDocTypeName); + const tabsDocType = new DocumentTypeBuilder() + .withName(tabsDocTypeName) + .withAlias(tabsDocTypeAlias) + .withAllowAsRoot(true) + .withDefaultTemplate(tabsDocTypeAlias) + .addTab() + .withName('Tab 1') + .addGroup() + .withName('Tab group') + .addUrlPickerProperty() + .withAlias("urlPicker") + .done() + .done() + .addGroup() + .withName('Content Picker Group') + .addContentPickerProperty() + .withAlias('picker') + .done() + .done() + .done() + .build(); + cy.saveDocumentType(tabsDocType); + OpenDocTypeFolder(); + //Delete group + cy.get('.umb-group-builder__group-remove > [icon="icon-trash"]').eq(1).click(); + cy.umbracoButtonByLabelKey('actions_delete').click(); + cy.umbracoButtonByLabelKey('buttons_save').click() + //Assert + cy.umbracoSuccessNotification().should('be.visible'); + cy.get('[title=picker]').should('be.visible'); + cy.get('[title=urlPicker]').should('not.exist'); + }); + + it('Reorders tab', () => { + cy.umbracoEnsureDocumentTypeNameNotExists(tabsDocTypeName); + const tabsDocType = new DocumentTypeBuilder() + .withName(tabsDocTypeName) + .withAlias(tabsDocTypeAlias) + .withAllowAsRoot(true) + .withDefaultTemplate(tabsDocTypeAlias) + .addTab() + .withName('Tab 1') + .addGroup() + .withName('Tab group 1') + .addUrlPickerProperty() + .withLabel('Url picker 1') + .withAlias("urlPicker") + .done() + .done() + .done() + .addTab() + .withName('Tab 2') + .addGroup() + .withName('Tab group 2') + .addUrlPickerProperty() + .withLabel('Url picker 2') + .withAlias("pickerTab 2") + .done() + .done() + .done() + .addTab() + .withName('Tab 3') + .addGroup() + .withName('Tab group') + .addUrlPickerProperty() + .withLabel('Url picker 3') + .withAlias('pickerTab3') + .done() + .done() + .done() + .build(); + cy.saveDocumentType(tabsDocType); + OpenDocTypeFolder(); + //Check if there are any tabs + cy.get('ng-form.ng-valid-required > .umb-group-builder__group-title-input').should('be.visible'); + cy.get('[alias="reorder"]').click(); + //Type order in + cy.get('.umb-group-builder__tab-sort-order > .umb-property-editor-tiny').first().type('3'); + cy.get('[alias="reorder"]').click(); + //Assert + cy.get('.umb-group-builder__group-title-input').eq(0).invoke('attr', 'title').should('eq', 'aTab 2') + cy.get('.umb-group-builder__group-title-input').eq(1).invoke('attr', 'title').should('eq', 'aTab 3') + cy.get('.umb-group-builder__group-title-input').eq(2).invoke('attr', 'title').should('eq', 'aTab 1') + }); + + it('Reorders groups in a tab', () => { + cy.umbracoEnsureDocumentTypeNameNotExists(tabsDocTypeName); + const tabsDocType = new DocumentTypeBuilder() + .withName(tabsDocTypeName) + .withAlias(tabsDocTypeAlias) + .withAllowAsRoot(true) + .withDefaultTemplate(tabsDocTypeAlias) + .addTab() + .withName('Tab 1') + .addGroup() + .withName('Tab group 1') + .addUrlPickerProperty() + .withLabel('Url picker 1') + .withAlias("urlPicker") + .done() + .done() + .addGroup() + .withName('Tab group 2') + .addUrlPickerProperty() + .withLabel('Url picker 2') + .withAlias('urlPickerTwo') + .done() + .done() + .done() + .build(); + cy.saveDocumentType(tabsDocType); + OpenDocTypeFolder(); + cy.get('[alias="reorder"]').click(); + cy.get('.umb-property-editor-tiny').eq(2).type('1'); + + cy.get('[alias="reorder"]').click(); + cy.umbracoButtonByLabelKey('buttons_save').click(); + //Assert + cy.umbracoSuccessNotification().should('be.visible'); + cy.get('.umb-group-builder__group-title-input').eq(2) + .invoke('attr', 'title').should('eq', 'aTab 1/aTab group 2'); + }); + + it('Reorders properties in a tab', () => { + cy.umbracoEnsureDocumentTypeNameNotExists(tabsDocTypeName); + const tabsDocType = new DocumentTypeBuilder() + .withName(tabsDocTypeName) + .withAlias(tabsDocTypeAlias) + .withAllowAsRoot(true) + .withDefaultTemplate(tabsDocTypeAlias) + .addTab() + .withName('Tab 1') + .addGroup() + .withName('Tab group') + .addUrlPickerProperty() + .withLabel('PickerOne') + .withAlias("urlPicker") + .done() + .addUrlPickerProperty() + .withLabel('PickerTwo') + .withAlias('urlPickerTwo') + .done() + .done() + .done() + .build(); + cy.saveDocumentType(tabsDocType); + OpenDocTypeFolder(); + //Reorder + cy.get('[alias="reorder"]').click(); + cy.get('.umb-group-builder__group-sort-value').first().type('2'); + cy.get('[alias="reorder"]').click(); + cy.umbracoButtonByLabelKey('buttons_save').click(); + //Assert + cy.umbracoSuccessNotification().should('be.visible'); + cy.get('.umb-locked-field__input').last().invoke('attr', 'title').should('eq', 'urlPicker'); + }); + + it('Tab name cannot be empty', () => { + CreateDocWithTabAndNavigate(); + cy.get('.umb-group-builder__group-title-input').first().clear(); + cy.umbracoButtonByLabelKey('buttons_save').click(); + //Assert + cy.umbracoErrorNotification().should('be.visible'); + }); + + it('Two tabs cannot have the same name', () => { + cy.umbracoEnsureDocumentTypeNameNotExists(tabsDocTypeName); + const tabsDocType = new DocumentTypeBuilder() + .withName(tabsDocTypeName) + .withAlias(tabsDocTypeAlias) + .withAllowAsRoot(true) + .withDefaultTemplate(tabsDocTypeAlias) + .addTab() + .withName('Tab 1') + .addGroup() + .withName('Tab group') + .addUrlPickerProperty() + .withAlias("urlPicker") + .done() + .done() + .done() + .build(); + cy.saveDocumentType(tabsDocType); + OpenDocTypeFolder(); + //Create a 2nd tab manually + cy.get('.umb-group-builder__tabs__add-tab').click(); + cy.get('ng-form.ng-invalid > .umb-group-builder__group-title-input').type('Tab 1'); + cy.umbracoButtonByLabelKey('buttons_save').click(); + //Assert + cy.umbracoErrorNotification().should('be.visible'); + }); + + it('Group name cannot be empty', () => { + CreateDocWithTabAndNavigate(); + cy.get('.clearfix > .-placeholder').click(); + cy.umbracoButtonByLabelKey('buttons_save').click(); + //Assert + cy.umbracoErrorNotification().should('be.visible'); + }); + + it('Group name cannot have the same name', () => { + CreateDocWithTabAndNavigate(); + cy.get('.clearfix > .-placeholder').click(); + cy.get('.umb-group-builder__group-title-input').last().type('Tab group'); + cy.umbracoButtonByLabelKey('buttons_save').click(); + //Assert + cy.umbracoErrorNotification().should('be.visible'); + }); + + it('Drag a group into another tab', () => { + cy.umbracoEnsureDocumentTypeNameNotExists(tabsDocTypeName); + const tabsDocType = new DocumentTypeBuilder() + .withName(tabsDocTypeName) + .withAlias(tabsDocTypeAlias) + .withAllowAsRoot(true) + .withDefaultTemplate(tabsDocTypeAlias) + .addTab() + .withName('Tab 1') + .addGroup() + .withName('Tab group') + .addUrlPickerProperty() + .withAlias("urlPicker") + .done() + .done() + .done() + .addTab() + .withName('Tab 2') + .addGroup() + .withName('Tab group tab 2') + .addUrlPickerProperty() + .withAlias('urlPickerTabTwo') + .done() + .done() + .addGroup() + .withName('Tab group 2') + .addUrlPickerProperty() + .withAlias('urlPickerTwo') + .done() + .done() + .done() + .build(); + cy.saveDocumentType(tabsDocType); + OpenDocTypeFolder(); + cy.get('[alias="reorder"]').click(); + cy.get('body') + .then(($body) => { + while($body.find('.umb-group-builder__tabs-overflow--right > .caret').hasClass('active')){ + cy.click(); + } + }); + cy.get('.umb-group-builder__tab').last().click(); + cy.get('.umb-group-builder__group-title-icon').last().trigger('mousedown', { which: 1 }) + cy.get('.umb-group-builder__tab').eq(1).trigger('mousemove', {which: 1, force: true}); + cy.get('.umb-group-builder__tab').eq(1).should('have.class', 'is-active').trigger('mouseup', {force:true}); + cy.umbracoButtonByLabelKey('buttons_save').click(); + //Assert + cy.umbracoSuccessNotification().should('be.visible'); + cy.get('[title="aTab 1/aTab group 2"]').should('be.visible'); + }); + + it('Drag and drop reorders a tab', () => { + cy.umbracoEnsureDocumentTypeNameNotExists(tabsDocTypeName); + const tabsDocType = new DocumentTypeBuilder() + .withName(tabsDocTypeName) + .withAlias(tabsDocTypeAlias) + .withAllowAsRoot(true) + .withDefaultTemplate(tabsDocTypeAlias) + .addTab() + .withName('Tab 1') + .addGroup() + .withName('Tab group') + .addUrlPickerProperty() + .withAlias("urlPicker") + .done() + .done() + .done() + .addTab() + .withName('Tab 2') + .addGroup() + .withName('Tab group tab 2') + .addUrlPickerProperty() + .withAlias('urlPickerTabTwo') + .done() + .done() + .addGroup() + .withName('Tab group 2') + .addUrlPickerProperty() + .withAlias('urlPickerTwo') + .done() + .done() + .done() + .build(); + cy.saveDocumentType(tabsDocType); + OpenDocTypeFolder(); + cy.get('[alias="reorder"]').click(); + //Scroll right so we can see tab 2 + cy.get('body') + .then(($body) => { + while($body.find('.umb-group-builder__tabs-overflow--right > .caret').hasClass('active')){ + cy.click(); + } + }); + cy.get('.umb-group-builder__tab-title-icon').eq(1).trigger('mousedown', { which: 1 }) + cy.get('.umb-group-builder__tab').eq(1).trigger('mousemove', {which: 1, force: true}); + cy.get('.umb-group-builder__tab').eq(1).should('have.class', 'is-active').trigger('mouseup', {force:true}); + cy.get('[alias="reorder"]').click(); + cy.umbracoButtonByLabelKey('buttons_save').click(); + //Assert + cy.umbracoSuccessNotification().should('be.visible'); + cy.get('[title="aTab 2"]').should('be.visible'); + }); + + it('Drags and drops a property in a tab', () => { + cy.umbracoEnsureDocumentTypeNameNotExists(tabsDocTypeName); + const tabsDocType = new DocumentTypeBuilder() + .withName(tabsDocTypeName) + .withAlias(tabsDocTypeAlias) + .withAllowAsRoot(true) + .withDefaultTemplate(tabsDocTypeAlias) + .addTab() + .withName('Tab 1') + .addGroup() + .withName('Tab group') + .addUrlPickerProperty() + .withAlias("urlPicker") + .withLabel('UrlPickerOne') + .done() + .done() + .done() + .addTab() + .withName('Tab 2') + .addGroup() + .withName('Tab group tab 2') + .addUrlPickerProperty() + .withAlias('urlPickerTabTwo') + .withLabel('UrlPickerTabTwo') + .done() + .addUrlPickerProperty() + .withAlias('urlPickerTwo') + .withLabel('UrlPickerTwo') + .done() + .done() + .done() + .build(); + cy.saveDocumentType(tabsDocType); + OpenDocTypeFolder(); + cy.get('[alias="reorder"]').click(); + //Scroll so we are sure we see tab 2 + cy.get('body') + .then(($body) => { + while($body.find('.umb-group-builder__tabs-overflow--right > .caret').hasClass('active')){ + cy.click(); + } + }); + //Navigate to tab 2 + cy.get('.umb-group-builder__tab').last().click(); + cy.get('.umb-group-builder__property-meta > .flex > .icon').eq(1).trigger('mousedown', {which: 1}) + cy.get('.umb-group-builder__tab').eq(1).trigger('mousemove', {which: 1, force: true}); + cy.get('.umb-group-builder__tab').eq(1).should('have.class', 'is-active'); + cy.get('.umb-group-builder__property') + .first().trigger('mousemove', {which: 1, force: true}).trigger('mouseup', {which: 1, force:true}); + cy.get('[alias="reorder"]').click(); + cy.umbracoButtonByLabelKey('buttons_save').click(); + //Assert + cy.umbracoSuccessNotification().should('be.visible'); + cy.get('[title="urlPickerTabTwo"]').should('be.visible'); + }); + + it('Drags and drops a group and converts to tab', () => { + cy.umbracoEnsureDocumentTypeNameNotExists(tabsDocTypeName); + const tabsDocType = new DocumentTypeBuilder() + .withName(tabsDocTypeName) + .withAlias(tabsDocTypeAlias) + .withAllowAsRoot(true) + .withDefaultTemplate(tabsDocTypeAlias) + .addTab() + .withName('Tab 1') + .addGroup() + .withName('Tab group') + .addUrlPickerProperty() + .withAlias("urlPicker") + .withLabel('UrlPickerOne') + .done() + .done() + .addGroup() + .withName('Tab group 2') + .addUrlPickerProperty() + .withAlias('urlPickerTwo') + .withLabel('UrlPickerTwo') + .done() + .done() + .done() + .addTab() + .withName('Tab 2') + .addGroup() + .withName('Tab group tab 2') + .addUrlPickerProperty() + .withAlias('urlPickerTabTwo') + .withLabel('UrlPickerTabTwo') + .done() + .done() + .done() + .build(); + cy.saveDocumentType(tabsDocType); + OpenDocTypeFolder(); + cy.get('[alias="reorder"]').click(); + cy.get('.umb-group-builder__group-title-icon').eq(1).trigger('mousedown', {which: 1}) + cy.get('.umb-group-builder__convert-dropzone').trigger('mousemove', {which: 1, force: true}); + cy.get('.umb-group-builder__convert-dropzone').trigger('mouseup', {which: 1, force:true}); + cy.umbracoButtonByLabelKey('buttons_save').click(); + //Assert + cy.umbracoSuccessNotification().should('be.visible'); + cy.get('[title="tabGroup"]').should('be.visible'); + }); + });