From 4ab70617a53bf3f33dc46d4bc65337869f65e269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Mon, 2 Jan 2023 11:53:21 +0100 Subject: [PATCH] test(Cypress): Add e2e tests for sharing basics and navigation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- cypress/e2e/boardFeatures.js | 17 +++++++- cypress/e2e/cardFeatures.js | 34 +++++---------- cypress/e2e/deckDashboard.js | 1 - cypress/e2e/sharingFeatures.js | 50 ++++++++++++++++++++++ cypress/e2e/stackFeatures.js | 3 +- cypress/support/commands.js | 32 ++++++++------ cypress/support/component-index.html | 12 ++++++ cypress/support/component.js | 27 ++++++++++++ cypress/utils/sampleBoard.js | 37 ++++++++++++++++ src/components/board/SharingTabSidebar.vue | 27 +++++++++--- src/components/board/Stack.vue | 2 +- 11 files changed, 195 insertions(+), 47 deletions(-) create mode 100644 cypress/e2e/sharingFeatures.js create mode 100644 cypress/support/component-index.html create mode 100644 cypress/support/component.js create mode 100644 cypress/utils/sampleBoard.js diff --git a/cypress/e2e/boardFeatures.js b/cypress/e2e/boardFeatures.js index acf37ac34..ab47289c5 100644 --- a/cypress/e2e/boardFeatures.js +++ b/cypress/e2e/boardFeatures.js @@ -1,10 +1,12 @@ import { randUser } from '../utils/index.js' const user = randUser() +const recipient = randUser() describe('Board', function() { before(function() { cy.createUser(user) + cy.createUser(recipient) }) beforeEach(function() { @@ -21,7 +23,6 @@ describe('Board', function() { }).as('createBoardRequest') // Click "Add board" - cy.openLeftSidebar() cy.get('#app-navigation-vue .app-navigation__list .app-navigation-entry') .eq(3).find('a').first().click({ force: true }) @@ -38,4 +39,18 @@ describe('Board', function() { cy.get('.app-navigation__list .app-navigation-entry__children .app-navigation-entry') .contains(board).should('be.visible') }) + + it('Shows and hides the navigation', () => { + cy.get('#app-navigation-vue .app-navigation__list .app-navigation-entry') + .contains('Upcoming cards') + .should('be.visible') + cy.openLeftSidebar() + cy.get('#app-navigation-vue .app-navigation__list .app-navigation-entry') + .contains('Upcoming cards') + .should('not.be.visible') + cy.openLeftSidebar() + cy.get('#app-navigation-vue .app-navigation__list .app-navigation-entry') + .contains('Upcoming cards') + .should('be.visible') + }) }) diff --git a/cypress/e2e/cardFeatures.js b/cypress/e2e/cardFeatures.js index fbc994978..7cc1aae4a 100644 --- a/cypress/e2e/cardFeatures.js +++ b/cypress/e2e/cardFeatures.js @@ -1,40 +1,29 @@ import { randUser } from '../utils/index.js' -const user = randUser() +import { sampleBoard } from '../utils/sampleBoard' -const testBoardData = { - title: 'MyBoardTest', - color: '00ff00', - stacks: [ - { - title: 'TestList', - cards: [ - { - title: 'Hello world', - }, - ], - }, - ], -} +const user = randUser() +const boardData = sampleBoard() describe('Card', function() { + let boardId before(function() { cy.createUser(user) cy.login(user) cy.createExampleBoard({ - user: user.userId, - password: user.password, - board: testBoardData, + user, + board: boardData, + }).then((board) => { + boardId = board.id }) }) beforeEach(function() { cy.login(user) - cy.visit('/apps/deck') + cy.visit(`/apps/deck/#/board/${boardId}`) }) it('Can show card details modal', function() { - cy.openLeftSidebar() - cy.getNavigationEntry(testBoardData.title) + cy.getNavigationEntry(boardData.title) .first().click({ force: true }) cy.get('.board .stack').eq(0).within(() => { @@ -48,8 +37,7 @@ describe('Card', function() { it('Can add a card', function() { const newCardTitle = 'Write some cypress tests' - cy.openLeftSidebar() - cy.getNavigationEntry(testBoardData.title) + cy.getNavigationEntry(boardData.title) .first().click({ force: true }) cy.get('.board .stack').eq(0).within(() => { diff --git a/cypress/e2e/deckDashboard.js b/cypress/e2e/deckDashboard.js index 6cd65b6c4..f48f289da 100644 --- a/cypress/e2e/deckDashboard.js +++ b/cypress/e2e/deckDashboard.js @@ -20,7 +20,6 @@ describe('Deck dashboard', function() { it('Can see the default "Personal Board" created for user by default', function() { const defaultBoard = 'Personal' - cy.openLeftSidebar() cy.get('.app-navigation-entry-wrapper[icon=icon-deck]') .find('ul.app-navigation-entry__children .app-navigation-entry:contains(' + defaultBoard + ')') .first() diff --git a/cypress/e2e/sharingFeatures.js b/cypress/e2e/sharingFeatures.js new file mode 100644 index 000000000..634af242b --- /dev/null +++ b/cypress/e2e/sharingFeatures.js @@ -0,0 +1,50 @@ +import { randUser } from '../utils/index.js' +import { sampleBoard } from '../utils/sampleBoard' +const user = randUser() +const recipient = randUser() + +describe('Board', function() { + before(function() { + cy.createUser(user) + cy.createUser(recipient) + }) + + beforeEach(function() { + cy.login(user) + }) + + it('Share a board to a user', function() { + const board = sampleBoard('Read only board') + cy.createExampleBoard({ user, board }).then((board) => { + const boardId = board.id + cy.visit(`/apps/deck/#/board/${boardId}`) + cy.get('.board-title').contains(board.title) + + cy.shareBoardWithUi(recipient.userId) + + cy.login(recipient) + cy.visit(`/apps/deck/#/board/${boardId}`) + cy.get('.board-title').contains(board.title) + cy.get('.button-vue[aria-label*="Add card"]') + .should('not.exist') + }) + }) + + it('Share a board to a user as writable', function() { + const board = sampleBoard('Editable board') + cy.createExampleBoard({ user, board }).then((board) => { + const boardId = board.id + cy.visit(`/apps/deck/#/board/${boardId}`) + cy.get('.board-title').contains(board.title) + + cy.shareBoardWithUi(recipient.userId) + cy.get(`[data-cy="acl-participant:${recipient.userId}"]`).find('[data-cy="action:permission-edit"]').click() + + cy.login(recipient) + cy.visit(`/apps/deck/#/board/${boardId}`) + cy.get('.board-title').contains(board.title) + cy.get('.button-vue[aria-label*="Add card"]') + .first().click() + }) + }) +}) diff --git a/cypress/e2e/stackFeatures.js b/cypress/e2e/stackFeatures.js index 81f5dc721..7eb514f1f 100644 --- a/cypress/e2e/stackFeatures.js +++ b/cypress/e2e/stackFeatures.js @@ -16,8 +16,7 @@ describe('Stack', function() { cy.createUser(user) cy.login(user) cy.createExampleBoard({ - user: user.userId, - password: user.password, + user, board: testBoardData, }) }) diff --git a/cypress/support/commands.js b/cypress/support/commands.js index f81ad73d4..070cbc7c2 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -63,14 +63,15 @@ Cypress.Commands.add('deckCreateList', ({ user, password }, title) => { cy.get('#stack-add form input[type=submit]').first().click() }) -Cypress.Commands.add('createExampleBoard', ({ user, password, board }) => { +Cypress.Commands.add('createExampleBoard', ({ user, board }) => { + const auth = { + user: user.userId, + password: user.password, + } cy.request({ method: 'POST', url: `${Cypress.env('baseUrl')}/index.php/apps/deck/api/v1.0/boards`, - auth: { - user, - password, - }, + auth, body: { title: board.title, color: board.color ?? 'ff0000' }, }).then((boardResponse) => { expect(boardResponse.status).to.eq(200) @@ -80,10 +81,7 @@ Cypress.Commands.add('createExampleBoard', ({ user, password, board }) => { cy.request({ method: 'POST', url: `${Cypress.env('baseUrl')}/index.php/apps/deck/api/v1.0/boards/${boardData.id}/stacks`, - auth: { - user, - password, - }, + auth, body: { title: stack.title, order: 0 }, }).then((stackResponse) => { const stackData = stackResponse.body @@ -92,15 +90,13 @@ Cypress.Commands.add('createExampleBoard', ({ user, password, board }) => { cy.request({ method: 'POST', url: `${Cypress.env('baseUrl')}/index.php/apps/deck/api/v1.0/boards/${boardData.id}/stacks/${stackData.id}/cards`, - auth: { - user, - password, - }, + auth, body: { title: card.title }, }) } }) } + cy.wrap(boardData) }) }) @@ -109,3 +105,13 @@ Cypress.Commands.add('getNavigationEntry', (boardTitle) => { .find('ul.app-navigation-entry__children .app-navigation-entry:contains(' + boardTitle + ')') .find('a.app-navigation-entry-link') }) + +Cypress.Commands.add('shareBoardWithUi', (userId) => { + cy.get('[aria-label="Open details"]').click() + cy.get('.app-sidebar').should('be.visible') + cy.get('.multiselect__input').type(`${userId}`) + cy.get('.multiselect__content .multiselect__element').first().contains(userId) + cy.get('.multiselect__input').type('{enter}') + + cy.get('.shareWithList').contains(userId) +}) diff --git a/cypress/support/component-index.html b/cypress/support/component-index.html new file mode 100644 index 000000000..ac6e79fd8 --- /dev/null +++ b/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + Components App + + +
+ + \ No newline at end of file diff --git a/cypress/support/component.js b/cypress/support/component.js new file mode 100644 index 000000000..3d1a3d225 --- /dev/null +++ b/cypress/support/component.js @@ -0,0 +1,27 @@ +// *********************************************************** +// This example support/component.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') + +import { mount } from 'cypress/vue2' + +Cypress.Commands.add('mount', mount) + +// Example use: +// cy.mount(MyComponent) diff --git a/cypress/utils/sampleBoard.js b/cypress/utils/sampleBoard.js new file mode 100644 index 000000000..e0019012e --- /dev/null +++ b/cypress/utils/sampleBoard.js @@ -0,0 +1,37 @@ +/* + * @copyright Copyright (c) 2022 Julius Härtl + * + * @author Julius Härtl + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +export const sampleBoard = (title = 'MyTestBoard') => { + return { + title: title, + color: '00ff00', + stacks: [ + { + title: 'TestList', + cards: [ + { + title: 'Hello world', + }, + ], + }, + ], + } +} diff --git a/src/components/board/SharingTabSidebar.vue b/src/components/board/SharingTabSidebar.vue index f5707c106..de2f720a9 100644 --- a/src/components/board/SharingTabSidebar.vue +++ b/src/components/board/SharingTabSidebar.vue @@ -31,7 +31,7 @@ -
  • +
  • @@ -41,20 +41,35 @@ {{ t('deck', '(Circle)') }} - + {{ t('deck', 'Can edit') }} - + {{ t('deck', 'Can share') }} - + {{ t('deck', 'Can manage') }} - + {{ t('deck', 'Owner') }} - + {{ t('deck', 'Delete') }} diff --git a/src/components/board/Stack.vue b/src/components/board/Stack.vue index dd7a18339..0decc0a77 100644 --- a/src/components/board/Stack.vue +++ b/src/components/board/Stack.vue @@ -74,7 +74,7 @@ - + {{ t('deck', 'Add card') }}