Skip to content

Commit

Permalink
fix(tests): Move leftover acceptance tests for users from drone to cy…
Browse files Browse the repository at this point in the history
…press

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
  • Loading branch information
susnux committed Oct 21, 2023
1 parent 5c2610a commit 64839ed
Show file tree
Hide file tree
Showing 14 changed files with 417 additions and 551 deletions.
30 changes: 0 additions & 30 deletions .drone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1651,36 +1651,6 @@ trigger:
- pull_request
- push

---
kind: pipeline
name: acceptance-users

steps:
- name: submodules
image: ghcr.io/nextcloud/continuous-integration-alpine-git:latest
commands:
- git submodule update --init
- name: acceptance-users
image: ghcr.io/nextcloud/continuous-integration-acceptance-php8.0:latest
commands:
- tests/acceptance/run-local.sh --timeout-multiplier 10 --nextcloud-server-domain acceptance-users --selenium-server selenium:4444 allow-git-repository-modifications features/users.feature

services:
- name: selenium
image: ghcr.io/nextcloud/continuous-integration-selenium:3.141.59
environment:
# Reduce default log level for Selenium server (INFO) as it is too
# verbose.
JAVA_OPTS: -Dselenium.LOGGER.level=WARNING

trigger:
branch:
- master
- stable*
event:
- pull_request
- push

---
kind: pipeline
name: acceptance-apps
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/cypress.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:

steps:
- name: Checkout app
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v3.5.2
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0

- name: Check composer.json
id: check_composer
Expand All @@ -39,8 +39,8 @@ jobs:
uses: skjnldsv/read-package-engines-version-actions@8205673bab74a63eb9b8093402fd9e0e018663a1 # v2.2
id: versions
with:
fallbackNode: "^14"
fallbackNpm: "^7"
fallbackNode: "^20"
fallbackNpm: "^9"

- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1
Expand Down
6 changes: 6 additions & 0 deletions apps/settings/src/components/Users/UserRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@
<template v-if="editing">
<NcTextField class="user-row-text-field"
:class="{'icon-loading-small': loading.mailAddress}"
data-test-id="input-email"
:data-test-loading="`${loading.mailAddress}`"
:show-trailing-button="true"
:trailing-button-label="t('settings', 'Submit')"
:label="t('settings', 'Set new email address')"
Expand Down Expand Up @@ -179,6 +181,8 @@
<NcSelect v-model="editedUserQuota"
:close-on-select="true"
:create-option="validateQuota"
data-test-id="input-quota"
:data-test-loading="`${loading.quota}`"
:disabled="isLoadingField"
:loading="loading.quota"
:append-to-body="false"
Expand Down Expand Up @@ -253,6 +257,8 @@
</label>
<NcSelect v-model="currentManager"
class="select--fill"
data-test-id="input-manager"
:data-test-loading="`${loading.manager}`"
:input-id="'manager' + uniqueId"
:close-on-select="true"
:disabled="isLoadingField"
Expand Down
1 change: 0 additions & 1 deletion cypress/e2e/settings/usersUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ export function handlePasswordConfirmation(adminPassword = 'admin') {
const handleModal = (context: Cypress.Chainable) => {
return context.contains('.modal-container', 'Confirm your password')
.if()
.if('visible')
.within(() => {
cy.get('input[type="password"]').type(adminPassword)
cy.get('button').contains('Confirm').click()
Expand Down
182 changes: 161 additions & 21 deletions cypress/e2e/settings/users_groups.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,31 @@
*/

import { User } from '@nextcloud/cypress'
import { handlePasswordConfirmation } from './usersUtils'
import { getUserListRow, handlePasswordConfirmation } from './usersUtils'

// eslint-disable-next-line n/no-extraneous-import
import randomString from 'crypto-random-string'

const admin = new User('admin', 'admin')

describe('Settings: Create and delete groups', () => {
describe('Settings: Create groups', () => {
before(() => {
cy.login(admin)
// open the User settings
cy.visit('/settings/users')
})

it('Can create a group', () => {
const groupName = randomString(7)
// open the Create group menu
cy.get('button[aria-label="Create group"]').click()

cy.get('.action-item__popper ul[role="menu"]').within(() => {
// see that the group name is ""
cy.get('input[placeholder="Group name"]').should('exist').and('have.value', '')
// set the group name to foo
cy.get('input[placeholder="Group name"]').type('foo')
cy.get('input[placeholder="Group name"]').type(groupName)
// see that the group name is foo
cy.get('input[placeholder="Group name"]').should('have.value', 'foo')
cy.get('input[placeholder="Group name"]').should('have.value', groupName)
// submit the group name
cy.get('input[placeholder="Group name"] ~ button').click()
})
Expand All @@ -53,38 +56,175 @@ describe('Settings: Create and delete groups', () => {
// see that the created group is in the list
cy.get('ul.app-navigation__list').within(() => {
// see that the list of groups contains the group foo
cy.contains('foo').should('exist')
cy.contains(groupName).should('exist')
})
})
})

describe('Settings: Assign user to a group', { testIsolation: false }, () => {
const groupName = randomString(7)
let testUser: User

after(() => cy.deleteUser(testUser))
before(() => {
cy.createRandomUser().then((user) => {
testUser = user
})
cy.runOccCommand(`group:add '${groupName}'`)
cy.login(admin)
cy.visit('/settings/users')
})

it('see that the group is in the list', () => {
cy.get('ul.app-navigation__list').contains('li', groupName).should('exist')
cy.get('ul.app-navigation__list').contains('li', groupName).within(() => {
cy.get('.counter-bubble__counter')
.should('not.exist') // is hidden when 0
})
})

it('Can delete a group', () => {
// see that the group is in the list
it('see that the user is in the list', () => {
getUserListRow(testUser.userId)
.contains(testUser.userId)
.should('exist')
.scrollIntoView()
})

it('switch into user edit mode', () => {
getUserListRow(testUser.userId)
.find('[data-test-id="cell-actions"] button[aria-label="Edit"]')
.click({ force: true })
getUserListRow(testUser.userId)
.find('[data-test-id="cell-groups"] input')
.should('exist')
})

it('assign the group', () => {
// focus inside the input
getUserListRow(testUser.userId)
.find('[data-test-id="cell-groups"] input')
.click({ force: true })
// enter the group name
getUserListRow(testUser.userId)
.find('[data-test-id="cell-groups"] input')
.type(`${groupName.slice(0, 5)}`) // only type part as otherwise we would create a new one with the same name
cy.contains('li.vs__dropdown-option', groupName)
.click({ force: true })

handlePasswordConfirmation(admin.password)
})

it('leave the user edit mode', () => {
getUserListRow(testUser.userId)
.find('.row__cell--actions')
.find('button[aria-label="Done"]')
.click({ force: true })
})

it('see the group was successfully assigned', () => {
// see a new memeber
cy.get('ul.app-navigation__list')
.contains('li', groupName)
.find('.counter-bubble__counter')
.should('contain', '1')
})

it('validate the user was added on backend', () => {
cy.runOccCommand(`user:info --output=json '${testUser.userId}'`).then((output) => {
cy.wrap(output.code).should('eq', 0)
cy.wrap(JSON.parse(output.stdout)?.groups).should('include', groupName)
})
})
})

describe('Settings: Delete an empty group', { testIsolation: false }, () => {
const groupName = randomString(7)

before(() => {
cy.runOccCommand(`group:add '${groupName}'`)
cy.login(admin)
cy.visit('/settings/users')
})

it('see that the group is in the list', () => {
cy.get('ul.app-navigation__list').within(() => {
// see that the list of groups contains the group foo
cy.contains('foo').should('exist')
cy.contains(groupName).should('exist').scrollIntoView()
// open the actions menu for the group
cy.contains('li', 'foo').within(() => {
cy.get('button.action-item__menutoggle').click()
cy.contains('li', groupName).within(() => {
cy.get('button.action-item__menutoggle').click({ force: true })
})
})
})

it('can delete the group', () => {
// The "Remove group" action in the actions menu is shown and clicked
cy.get('.action-item__popper button').contains('Remove group').should('exist').click()
cy.get('.action-item__popper button').contains('Remove group').should('exist').click({ force: true })
// And confirmation dialog accepted
cy.get('.modal-container button').contains('Confirm').click()
cy.get('.modal-container button').contains('Confirm').click({ force: true })

// Make sure no confirmation modal is shown
cy.get('body').contains('.modal-container', 'Confirm your password')
.if('visible')
.then(($modal) => {
cy.wrap($modal).find('input[type="password"]').type(admin.password)
cy.wrap($modal).find('button').contains('Confirm').click()
})
handlePasswordConfirmation(admin.password)
})

// deleted group is not shown anymore
it('deleted group is not shown anymore', () => {
cy.get('ul.app-navigation__list').within(() => {
// see that the list of groups does not contain the group
cy.contains(groupName).should('not.exist')
})
// and also not in database
cy.runOccCommand('group:list --output=json').then(($response) => {
const groups: string[] = Object.keys(JSON.parse($response.stdout))
expect(groups).to.not.include(groupName)
})
})
})

describe('Settings: Delete a non empty group', () => {
let testUser: User
const groupName = randomString(7)

before(() => {
cy.runOccCommand(`group:add '${groupName}'`)
cy.createRandomUser().then(($user) => {
testUser = $user
cy.runOccCommand(`group:addUser '${groupName}' '${$user.userId}'`)
})
cy.login(admin)
cy.visit('/settings/users')
})
after(() => cy.deleteUser(testUser))

it('see that the group is in the list', () => {
// see that the list of groups contains the group
cy.get('ul.app-navigation__list').contains('li', groupName).should('exist').scrollIntoView()
})

it('can delete the group', () => {
// open the menu
cy.get('ul.app-navigation__list')
.contains('li', groupName)
.find('button.action-item__menutoggle')
.click({ force: true })

// The "Remove group" action in the actions menu is shown and clicked
cy.get('.action-item__popper button').contains('Remove group').should('exist').click({ force: true })
// And confirmation dialog accepted
cy.get('.modal-container button').contains('Confirm').click({ force: true })

// Make sure no confirmation modal is shown
handlePasswordConfirmation(admin.password)
})

it('deleted group is not shown anymore', () => {
cy.get('ul.app-navigation__list').within(() => {
// see that the list of groups does not contain the group foo
cy.contains('foo').should('not.exist')
cy.contains(groupName).should('not.exist')
})
// and also not in database
cy.runOccCommand('group:list --output=json').then(($response) => {
const groups: string[] = Object.keys(JSON.parse($response.stdout))
expect(groups).to.not.include(groupName)
})
})
})
Loading

0 comments on commit 64839ed

Please sign in to comment.