From a6f7ed645c46974e8b4d2b4d0566f5658d674942 Mon Sep 17 00:00:00 2001 From: Florian Barbin Date: Tue, 23 Jan 2024 11:09:35 +0100 Subject: [PATCH] [3015] Add Cypress tests for Lane editing in Deck Bug: https://github.com/eclipse-sirius/sirius-web/issues/3015 Signed-off-by: Florian Barbin --- .../cypress/e2e/project/deck/deck-card.cy.ts | 118 +++++++++++ .../cypress/e2e/project/deck/deck-lane.cy.ts | 69 +++++++ .../cypress/e2e/project/deck/deck.cy.ts | 185 ++---------------- integration-tests/cypress/workbench/Deck.ts | 81 ++++++++ 4 files changed, 285 insertions(+), 168 deletions(-) create mode 100644 integration-tests/cypress/e2e/project/deck/deck-card.cy.ts create mode 100644 integration-tests/cypress/e2e/project/deck/deck-lane.cy.ts diff --git a/integration-tests/cypress/e2e/project/deck/deck-card.cy.ts b/integration-tests/cypress/e2e/project/deck/deck-card.cy.ts new file mode 100644 index 0000000000..41832f5358 --- /dev/null +++ b/integration-tests/cypress/e2e/project/deck/deck-card.cy.ts @@ -0,0 +1,118 @@ +/******************************************************************************* + * Copyright (c) 2024 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ + +import { Deck } from '../../../workbench/Deck'; +import { Explorer } from '../../../workbench/Explorer'; +describe('Verify the Deck Representation cards selection and editing', () => { + let studioProjectId: string = ''; + let taskProjectId: string; + before(() => { + // We create the Deck View from the stereotype before executing the tests + new Deck().initDeckView().then((projectId) => { + studioProjectId = projectId; + }); + + new Deck() + .createTaskProjectAndDeckRepresentation('Daily Project Dev', 'New Daily Representation') + .then((projectId) => { + taskProjectId = projectId; + }); + }); + after(() => { + // We delete the created studio once all tests have been executed + cy.deleteProject(studioProjectId); + cy.deleteProject(taskProjectId); + }); + + beforeEach(() => { + new Deck().openDeckRepresentation(taskProjectId, 'Daily Project Dev', 'New Daily Representation'); + }); + + it('We verify the card selection.', () => { + const deck = new Deck(); + const explorer = new Explorer(); + deck.getCard('Monday', 'Idea').should('have.css', 'border', ''); + explorer.select('Idea'); + deck.getCard('Monday', 'Idea').should('have.css', 'border', '2px solid rgb(190, 26, 120)'); + deck.getCard('Monday', 'Specification').click(); + + // We verify that when selecting a card, the task is selected too in the model explorer. + explorer.getSelectedTreeItems(); + explorer.getSelectedTreeItems().should('have.length', 1); + explorer.getSelectedTreeItems().contains('Specification').should('exist'); + }); + + it('We verify the card direct edit.', () => { + const deck = new Deck(); + deck.getCard('Monday', 'Specification').click().trigger('keydown', { keyCode: 113, which: 113 }); // F2 key code + + //After having pressed F2, the focus should be on the title input field. + cy.getByTestId('card-input-title').get('input').should('have.focus'); + + //After having pressed Tab, the focus should be on the title input field. + deck.getCard('Monday', 'Specification').trigger('keydown', { keyCode: 9, which: 9 }); // Tab key code + cy.getByTestId('card-input-label').get('input').should('have.focus'); + deck.getCard('Monday', 'Specification').trigger('keydown', { keyCode: 9, which: 9 }); // Tab key code + cy.getByTestId('card-input-details').get('input').should('have.focus'); + }); + + it('We verify the card editing.', () => { + const deck = new Deck(); + deck.getCard('Monday', 'Specification').click().trigger('keydown', { keyCode: 113, which: 113 }); // F2 key code + + //We rename the title + cy.getByTestId('card-input-title').type('Specification_renamed{enter}'); + new Explorer().getTreeItemByLabel('Specification_renamed').should('exist'); + + //We edit the description + deck.getCard('Monday', 'Specification_renamed').click(); + cy.getByTestId('card-input-details').type('a description{enter}'); + + cy.getByTestId('input-Description').should('have.value', 'a description'); + }); + + it('We verify the card creation.', () => { + const deck = new Deck(); + const explorer = new Explorer(); + //We create a new Card + deck.getLane('Monday').find('a:contains("Click to add card")').click(); + deck.getLane('Monday').find('div[placeholder="title"]').click().type('myNewCard'); + deck.getLane('Monday').find('div[placeholder="description"]').click().type('my Card description'); + deck.getLane('Monday').get('button:contains("Add card")').click(); + + //We verify that the new task has been created + explorer.getTreeItemByLabel('myNewCard').should('exist'); + explorer.select('myNewCard'); + + //We check the values in the properties view. + cy.getByTestId('input-Name').should('have.value', 'myNewCard'); + cy.getByTestId('input-Description').should('have.value', 'my Card description'); + + //We check that the new card is visible in the deck representation. + deck.getCard('Monday', 'myNewCard').contains('my Card description'); + }); + + it('We verify the card deletion.', () => { + const deck = new Deck(); + const explorer = new Explorer(); + explorer.getTreeItemByLabel('Development').should('exist'); + deck.getCard('Tuesday', 'Development').click(); + + // We use the delete button + deck.getCard('Tuesday', 'Development').find('button[aria-label="deleteCard"]').click(); + + //The Task should be removed from the model explorer and the deck representation. + cy.getByTestId('card-Development').should('not.exist'); + explorer.getTreeItemByLabel('Development').should('not.exist'); + }); +}); diff --git a/integration-tests/cypress/e2e/project/deck/deck-lane.cy.ts b/integration-tests/cypress/e2e/project/deck/deck-lane.cy.ts new file mode 100644 index 0000000000..5cef003323 --- /dev/null +++ b/integration-tests/cypress/e2e/project/deck/deck-lane.cy.ts @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2024 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ + +import { Deck } from '../../../workbench/Deck'; +import { Details } from '../../../workbench/Details'; +import { Explorer } from '../../../workbench/Explorer'; +describe('Verify the Deck Representation lanes selection and editing', () => { + let studioProjectId: string = ''; + let taskProjectId: string; + before(() => { + // We create the Deck View from the stereotype before executing the tests + new Deck().initDeckView().then((projectId) => { + studioProjectId = projectId; + }); + + new Deck() + .createTaskProjectAndDeckRepresentation('Daily Project Dev', 'New Daily Representation') + .then((projectId) => { + taskProjectId = projectId; + }); + }); + after(() => { + // We delete the created studio once all tests have been executed + cy.deleteProject(studioProjectId); + cy.deleteProject(taskProjectId); + }); + + beforeEach(() => { + new Deck().openDeckRepresentation(taskProjectId, 'Daily Project Dev', 'New Daily Representation'); + }); + + it('We verify the lane selection.', () => { + const deck = new Deck(); + const explorer = new Explorer(); + deck.getLane('Monday').should('have.css', 'border-width', '0px'); + explorer.select('daily::Monday'); + deck.getLane('Monday').should('have.css', 'border', '2px solid rgb(190, 26, 120)'); + deck.getLane('Wednesday').click(); + + // We verify that when selecting a card, the task is selected too in the model explorer. + explorer.getSelectedTreeItems(); + explorer.getSelectedTreeItems().should('have.length', 1); + explorer.getSelectedTreeItems().contains('daily::Wednesday').should('exist'); + }); + + it.only('We verify the lane direct edit.', () => { + const deck = new Deck(); + deck.getLane('Monday').click('top').find('header').trigger('keydown', { keyCode: 113, which: 113 }); + cy.getByTestId('lane-input-title').get('input').should('have.focus'); + }); + + it('We verify the lane editing.', () => { + const deck = new Deck(); + deck.getLane('Monday').click('top').getByTestId('lane-input-title').click().type('Monday_renamed{enter}'); + new Explorer().getTreeItemByLabel('daily::Monday_renamed').should('exist'); + + new Details().getTextField('suffix').should('have.value', 'Monday_renamed'); + }); +}); diff --git a/integration-tests/cypress/e2e/project/deck/deck.cy.ts b/integration-tests/cypress/e2e/project/deck/deck.cy.ts index 62c62d35b3..aa9eca8147 100644 --- a/integration-tests/cypress/e2e/project/deck/deck.cy.ts +++ b/integration-tests/cypress/e2e/project/deck/deck.cy.ts @@ -11,30 +11,16 @@ * Obeo - initial API and implementation *******************************************************************************/ -import { Project } from '../../../pages/Project'; -import { Projects } from '../../../pages/Projects'; -import { isCreateProjectFromTemplateSuccessPayload } from '../../../support/server/createProjectFromTemplateCommand'; import { Deck } from '../../../workbench/Deck'; -import { Explorer } from '../../../workbench/Explorer'; import { Details } from '../../../workbench/Details'; +import { Explorer } from '../../../workbench/Explorer'; describe('Verify the Deck Representation', () => { let studioProjectId: string = ''; before(() => { // We create the Deck View from the stereotype before executing the tests - new Projects().visit(); - cy.createProjectFromTemplate('blank-studio-template').then((res) => { - const payload = res.body.data.createProjectFromTemplate; - if (isCreateProjectFromTemplateSuccessPayload(payload)) { - studioProjectId = payload.project.id; - - new Project().visit(studioProjectId); - cy.getByTestId('new-model').click(); - cy.getByTestId('name-input').type('Deck View'); - cy.getByTestId('stereotype').click(); - cy.get('li').filter(':contains("Deck View")').click(); - cy.getByTestId('create-document').click(); - } + new Deck().initDeckView().then((projectId) => { + studioProjectId = projectId; }); }); after(() => { @@ -44,27 +30,27 @@ describe('Verify the Deck Representation', () => { context('We first verify the creation of an empty deck representation', () => { it('We create the Deck Representation', () => { - createTaskProjectAndDeckRepresentation('Project Dev', 'New Daily Representation'); + const deck = new Deck(); + deck.createTaskProjectAndDeckRepresentation('Project Dev', 'New Daily Representation'); new Explorer().getSelectedTreeItems().contains('New Daily Representation').should('exist'); - new Deck().getDeckRepresentation().should('exist'); + deck.getDeckRepresentation().should('exist'); - deleteCurrentProject(); + deck.deleteCurrentProject(); }); }); context('We new verify the Deck Creation, Deletion and renaming', () => { let taskProjectId: string; before(() => { - createTaskProjectAndDeckRepresentation('Daily Project Dev', 'New Daily Representation').then(() => { - cy.url().then(($url) => { - const prefix = Cypress.config().baseUrl + '/projects/'; - taskProjectId = $url.substring(prefix.length, $url.indexOf('/', prefix.length + 1)); + new Deck() + .createTaskProjectAndDeckRepresentation('Daily Project Dev', 'New Daily Representation') + .then((projectId) => { + taskProjectId = projectId; }); - }); }); beforeEach(() => { - openDeckRepresentation(taskProjectId, 'Daily Project Dev', 'New Daily Representation'); + new Deck().openDeckRepresentation(taskProjectId, 'Daily Project Dev', 'New Daily Representation'); }); after(() => { @@ -113,16 +99,15 @@ describe('Verify the Deck Representation', () => { context('We now verify the Deck representation refresh', () => { let taskProjectId: string; before(() => { - createTaskProjectAndDeckRepresentation('Daily Project Dev', 'New Daily Representation').then(() => { - cy.url().then(($url) => { - const prefix = Cypress.config().baseUrl + '/projects/'; - taskProjectId = $url.substring(prefix.length, $url.indexOf('/', prefix.length + 1)); + new Deck() + .createTaskProjectAndDeckRepresentation('Daily Project Dev', 'New Daily Representation') + .then((projectId) => { + taskProjectId = projectId; }); - }); }); beforeEach(() => { - openDeckRepresentation(taskProjectId, 'Daily Project Dev', 'New Daily Representation'); + new Deck().openDeckRepresentation(taskProjectId, 'Daily Project Dev', 'New Daily Representation'); }); after(() => { @@ -163,140 +148,4 @@ describe('Verify the Deck Representation', () => { cy.getByTestId('card-Development').should('not.exist'); }); }); - - context('We now verify the Deck representation cards selection and editing', () => { - let taskProjectId: string; - before(() => { - createTaskProjectAndDeckRepresentation('Daily Project Dev', 'New Daily Representation').then(() => { - cy.url().then(($url) => { - const prefix = Cypress.config().baseUrl + '/projects/'; - taskProjectId = $url.substring(prefix.length, $url.indexOf('/', prefix.length + 1)); - }); - }); - }); - - beforeEach(() => { - openDeckRepresentation(taskProjectId, 'Daily Project Dev', 'New Daily Representation'); - }); - - after(() => { - cy.deleteProject(taskProjectId); - }); - it('We verify the card selection.', () => { - const deck = new Deck(); - const explorer = new Explorer(); - deck.getCard('Monday', 'Idea').should('have.css', 'border', ''); - explorer.select('Idea'); - deck.getCard('Monday', 'Idea').should('have.css', 'border', '2px solid rgb(190, 26, 120)'); - deck.getCard('Monday', 'Specification').click(); - - // We verify that when selecting a card, the task is selected too in the model explorer. - explorer.getSelectedTreeItems(); - explorer.getSelectedTreeItems().should('have.length', 1); - explorer.getSelectedTreeItems().contains('Specification').should('exist'); - }); - - it('We verify the card direct edit.', () => { - const deck = new Deck(); - deck.getCard('Monday', 'Specification').click().trigger('keydown', { keyCode: 113, which: 113 }); // F2 key code - - //After having pressed F2, the focus should be on the title input field. - cy.getByTestId('card-input-title').get('input').should('have.focus'); - - //After having pressed Tab, the focus should be on the title input field. - deck.getCard('Monday', 'Specification').trigger('keydown', { keyCode: 9, which: 9 }); // Tab key code - cy.getByTestId('card-input-label').get('input').should('have.focus'); - deck.getCard('Monday', 'Specification').trigger('keydown', { keyCode: 9, which: 9 }); // Tab key code - cy.getByTestId('card-input-details').get('input').should('have.focus'); - }); - - it('We verify the card editing.', () => { - const deck = new Deck(); - deck.getCard('Monday', 'Specification').click().trigger('keydown', { keyCode: 113, which: 113 }); // F2 key code - - //We rename the title - cy.getByTestId('card-input-title').type('Specification_renamed{enter}'); - new Explorer().getTreeItemByLabel('Specification_renamed').should('exist'); - - //We edit the description - deck.getCard('Monday', 'Specification_renamed').click(); - cy.getByTestId('card-input-details').type('a description{enter}'); - - cy.getByTestId('input-Description').should('have.value', 'a description'); - }); - - it('We verify the card creation.', () => { - const deck = new Deck(); - const explorer = new Explorer(); - //We create a new Card - deck.getLane('Monday').find('a:contains("Click to add card")').click(); - deck.getLane('Monday').find('div[placeholder="title"]').click().type('myNewCard'); - deck.getLane('Monday').find('div[placeholder="description"]').click().type('my Card description'); - deck.getLane('Monday').get('button:contains("Add card")').click(); - - //We verify that the new task has been created - explorer.getTreeItemByLabel('myNewCard').should('exist'); - explorer.select('myNewCard'); - - //We check the values in the properties view. - cy.getByTestId('input-Name').should('have.value', 'myNewCard'); - cy.getByTestId('input-Description').should('have.value', 'my Card description'); - - //We check that the new card is visible in the deck representation. - deck.getCard('Monday', 'myNewCard').contains('my Card description'); - }); - - it('We verify the card deletion.', () => { - const deck = new Deck(); - const explorer = new Explorer(); - explorer.getTreeItemByLabel('Development').should('exist'); - deck.getCard('Tuesday', 'Development').click(); - - // We use the delete button - deck.getCard('Tuesday', 'Development').find('button[aria-label="deleteCard"]').click(); - - //The Task should be removed from the model explorer and the deck representation. - cy.getByTestId('card-Development').should('not.exist'); - explorer.getTreeItemByLabel('Development').should('not.exist'); - }); - }); }); - -const createTaskProjectAndDeckRepresentation = (rootElementName: string, deckRepresentationName: string) => { - // We create the Task project from the template before each tests. - new Projects().visit(); - return cy.createProjectFromTemplate('task-template').then((res) => { - const payload = res.body.data.createProjectFromTemplate; - if (isCreateProjectFromTemplateSuccessPayload(payload)) { - const taskProjectId = payload.project.id; - new Project().visit(taskProjectId); - createDailyDeckRepresentation(rootElementName, deckRepresentationName); - } - }); -}; - -const createDailyDeckRepresentation = (rootElementName: string, deckRepresentationName) => { - const explorer = new Explorer(); - explorer.getTreeItemByLabel('Task Model').should('exist'); - explorer.expand('Task Model'); - explorer.expand('Company'); - explorer.createRepresentation(rootElementName, 'Deck Daily Representation', deckRepresentationName); -}; - -const deleteCurrentProject = () => { - cy.url().then(($url) => { - const prefix = Cypress.config().baseUrl + '/projects/'; - const projectId = $url.substring(prefix.length, $url.indexOf('/', prefix.length + 1)); - cy.deleteProject(projectId); - }); -}; - -function openDeckRepresentation(taskProjectId: string, projectName: string, representationName: string) { - new Projects().visit(); - new Project().visit(taskProjectId); - const explorer = new Explorer(); - explorer.expand('Task Model'); - explorer.expand('Company'); - explorer.expand(projectName); - new Explorer().getTreeItemByLabel(representationName).click(); -} diff --git a/integration-tests/cypress/workbench/Deck.ts b/integration-tests/cypress/workbench/Deck.ts index d55f27b8a9..439246af6a 100644 --- a/integration-tests/cypress/workbench/Deck.ts +++ b/integration-tests/cypress/workbench/Deck.ts @@ -11,6 +11,11 @@ * Obeo - initial API and implementation *******************************************************************************/ +import { Project } from '../pages/Project'; +import { Projects } from '../pages/Projects'; +import { isCreateProjectFromTemplateSuccessPayload } from '../support/server/createProjectFromTemplateCommand'; +import { Explorer } from './Explorer'; + export class Deck { public getDeckRepresentation(): Cypress.Chainable> { return cy.getByTestId('deck-representation'); @@ -23,4 +28,80 @@ export class Deck { public getCard(laneLabel: string, cardLabel): Cypress.Chainable> { return this.getLane(laneLabel).findByTestId(`card-${cardLabel}`); } + + public createDailyDeckRepresentation(rootElementName: string, deckRepresentationName) { + const explorer = new Explorer(); + explorer.getTreeItemByLabel('Task Model').should('exist'); + explorer.expand('Task Model'); + explorer.expand('Company'); + explorer.createRepresentation(rootElementName, 'Deck Daily Representation', deckRepresentationName); + } + + public deleteCurrentProject() { + cy.url().then(($url) => { + const prefix = Cypress.config().baseUrl + '/projects/'; + const projectId = $url.substring(prefix.length, $url.indexOf('/', prefix.length + 1)); + cy.deleteProject(projectId); + }); + } + + public openDeckRepresentation(taskProjectId: string, projectName: string, representationName: string) { + new Projects().visit(); + new Project().visit(taskProjectId); + const explorer = new Explorer(); + explorer.expand('Task Model'); + explorer.expand('Company'); + explorer.expand(projectName); + new Explorer().getTreeItemByLabel(representationName).click(); + } + + /** + * Creates the Deck view from the stereotype. + * @returns the created studio project id. + */ + public initDeckView(): Cypress.Chainable { + new Projects().visit(); + return cy.createProjectFromTemplate('blank-studio-template').then((res) => { + const payload = res.body.data.createProjectFromTemplate; + if (isCreateProjectFromTemplateSuccessPayload(payload)) { + const studioProjectId = payload.project.id; + new Project().visit(studioProjectId); + cy.getByTestId('new-model').click(); + cy.getByTestId('name-input').type('Deck View'); + cy.getByTestId('stereotype').click(); + cy.get('li').filter(':contains("Deck View")').click(); + cy.getByTestId('create-document').click(); + return cy.wrap(studioProjectId); + } + return cy.wrap(''); + }); + } + + /** + * Creates the Deck view from the stereotype. + * @returns the created studio project id. + */ + public createTaskProjectAndDeckRepresentation( + rootElementName: string, + deckRepresentationName: string + ): Cypress.Chainable { + new Projects().visit(); + return cy + .createProjectFromTemplate('task-template') + .then((res) => { + const payload = res.body.data.createProjectFromTemplate; + if (isCreateProjectFromTemplateSuccessPayload(payload)) { + const taskProjectId = payload.project.id; + new Project().visit(taskProjectId); + new Deck().createDailyDeckRepresentation(rootElementName, deckRepresentationName); + } + }) + .then(() => { + return cy.url().then(($url) => { + const prefix = Cypress.config().baseUrl + '/projects/'; + const taskProjectId = $url.substring(prefix.length, $url.indexOf('/', prefix.length + 1)); + return cy.wrap(taskProjectId); + }); + }); + } }