mirror of
https://github.com/nextcloud/server.git
synced 2026-06-06 15:23:17 -04:00
fix(cypress): Test using data-test-id attributes rather than private classes
Makes the test more resilant to inner component changes of the `@nextcloud/vue` library. Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
This commit is contained in:
parent
add1d922ba
commit
3f83ae145f
11 changed files with 93 additions and 61 deletions
|
|
@ -45,6 +45,7 @@
|
|||
:data-component="UserRow"
|
||||
:data-sources="filteredUsers"
|
||||
data-key="id"
|
||||
data-test-id="userList"
|
||||
:item-height="rowHeight"
|
||||
:style="style"
|
||||
:extra-props="{
|
||||
|
|
|
|||
|
|
@ -36,11 +36,12 @@
|
|||
:user="user.id" />
|
||||
</td>
|
||||
|
||||
<td class="row__cell row__cell--displayname">
|
||||
<td class="row__cell row__cell--displayname" data-test-id="cell-displayname">
|
||||
<template v-if="editing && user.backendCapabilities.setDisplayName">
|
||||
<NcTextField ref="displayNameField"
|
||||
data-test="displayNameField"
|
||||
class="user-row-text-field"
|
||||
data-test-id="input-displayName"
|
||||
:data-test-loading="`${loading.displayName}`"
|
||||
:trailing-button-label="t('settings', 'Submit')"
|
||||
:class="{ 'icon-loading-small': loading.displayName }"
|
||||
:show-trailing-button="true"
|
||||
|
|
@ -63,10 +64,13 @@
|
|||
</template>
|
||||
</td>
|
||||
|
||||
<td class="row__cell"
|
||||
<td data-test-id="cell-password"
|
||||
class="row__cell"
|
||||
:class="{ 'row__cell--obfuscated': hasObfuscated }">
|
||||
<template v-if="editing && settings.canChangePassword && user.backendCapabilities.setPassword">
|
||||
<NcTextField class="user-row-text-field"
|
||||
data-test-id="input-password"
|
||||
:data-test-loading="`${loading.password}`"
|
||||
:trailing-button-label="t('settings', 'Submit')"
|
||||
:class="{'icon-loading-small': loading.password}"
|
||||
:show-trailing-button="true"
|
||||
|
|
@ -89,7 +93,7 @@
|
|||
</span>
|
||||
</td>
|
||||
|
||||
<td class="row__cell">
|
||||
<td class="row__cell" data-test-id="cell-email">
|
||||
<template v-if="editing">
|
||||
<NcTextField class="user-row-text-field"
|
||||
:class="{'icon-loading-small': loading.mailAddress}"
|
||||
|
|
@ -100,7 +104,7 @@
|
|||
trailing-button-icon="arrowRight"
|
||||
:value.sync="editedMail"
|
||||
autocapitalize="off"
|
||||
autocomplete="new-password"
|
||||
autocomplete="email"
|
||||
autocorrect="off"
|
||||
spellcheck="false"
|
||||
type="email"
|
||||
|
|
@ -112,7 +116,7 @@
|
|||
</span>
|
||||
</td>
|
||||
|
||||
<td class="row__cell row__cell--large row__cell--multiline">
|
||||
<td class="row__cell row__cell--large row__cell--multiline" data-test-id="cell-groups">
|
||||
<template v-if="editing">
|
||||
<label class="hidden-visually"
|
||||
:for="'groups' + uniqueId">
|
||||
|
|
@ -142,6 +146,7 @@
|
|||
</td>
|
||||
|
||||
<td v-if="subAdminsGroups.length > 0 && settings.isAdmin"
|
||||
data-test-id="cell-subadmins"
|
||||
class="row__cell row__cell--large row__cell--multiline">
|
||||
<template v-if="editing && settings.isAdmin && subAdminsGroups.length > 0">
|
||||
<label class="hidden-visually"
|
||||
|
|
@ -168,7 +173,7 @@
|
|||
</span>
|
||||
</td>
|
||||
|
||||
<td class="row__cell">
|
||||
<td class="row__cell" data-test-id="cell-quota">
|
||||
<template v-if="editing">
|
||||
<label class="hidden-visually"
|
||||
:for="'quota' + uniqueId">
|
||||
|
|
@ -200,7 +205,7 @@
|
|||
|
||||
<td v-if="showConfig.showLanguages"
|
||||
class="row__cell row__cell--large"
|
||||
data-test="language">
|
||||
data-test-id="cell-language">
|
||||
<template v-if="editing">
|
||||
<label class="hidden-visually"
|
||||
:for="'language' + uniqueId">
|
||||
|
|
@ -224,6 +229,7 @@
|
|||
</td>
|
||||
|
||||
<td v-if="showConfig.showUserBackend || showConfig.showStoragePath"
|
||||
data-test-id="cell-storageLocation"
|
||||
class="row__cell row__cell--large">
|
||||
<template v-if="!isObfuscated">
|
||||
<span v-if="showConfig.showUserBackend">{{ user.backend }}</span>
|
||||
|
|
@ -238,11 +244,11 @@
|
|||
<td v-if="showConfig.showLastLogin"
|
||||
:title="userLastLoginTooltip"
|
||||
class="row__cell"
|
||||
data-test="lastLogin">
|
||||
data-test-id="cell-lastLogin">
|
||||
<span v-if="!isObfuscated">{{ userLastLogin }}</span>
|
||||
</td>
|
||||
|
||||
<td class="row__cell row__cell--large row__cell--fill">
|
||||
<td class="row__cell row__cell--large row__cell--fill" data-test-id="cell-manager">
|
||||
<template v-if="editing">
|
||||
<label class="hidden-visually"
|
||||
:for="'manager' + uniqueId">
|
||||
|
|
@ -268,7 +274,7 @@
|
|||
</span>
|
||||
</td>
|
||||
|
||||
<td class="row__cell row__cell--actions">
|
||||
<td class="row__cell row__cell--actions" data-test-id="cell-actions">
|
||||
<UserRowActions v-if="visible && !isObfuscated && canEdit && !loading.all"
|
||||
:actions="userActions"
|
||||
:disabled="isLoadingField"
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@
|
|||
<NcActions :aria-label="t('settings', 'Toggle user actions menu')"
|
||||
:disabled="disabled"
|
||||
:inline="1">
|
||||
<NcActionButton :disabled="disabled"
|
||||
<NcActionButton data-test-id="button-toggleEdit"
|
||||
:data-test="`${edit}`"
|
||||
:disabled="disabled"
|
||||
@click="toggleEdit">
|
||||
{{ edit ? t('settings', 'Done') : t('settings', 'Edit') }}
|
||||
<template #icon>
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
*/
|
||||
/// <reference types="cypress-if" />
|
||||
import { User } from '@nextcloud/cypress'
|
||||
import { getUserListRow, handlePasswordConfirmation } from './usersUtils'
|
||||
|
||||
const admin = new User('admin', 'admin')
|
||||
const jdoe = new User('jdoe', 'jdoe')
|
||||
|
|
@ -106,10 +107,10 @@ describe('Settings: Create and delete users', function() {
|
|||
handlePasswordConfirmation(admin.password)
|
||||
|
||||
// see that the created user is in the list
|
||||
cy.get('tbody.user-list__body tr[data-test="john"]').within(() => {
|
||||
getUserListRow('john')
|
||||
// see that the list of users contains the user john
|
||||
cy.contains('john').should('exist')
|
||||
})
|
||||
.contains('john')
|
||||
.should('exist')
|
||||
})
|
||||
|
||||
it('Can delete a user', function() {
|
||||
|
|
|
|||
|
|
@ -22,16 +22,35 @@
|
|||
|
||||
/**
|
||||
* Assert that `element` does not exist or is not visible
|
||||
*
|
||||
* Useful in cases such as when NcModal is opened/closed rapidly
|
||||
* @param element Element that is inspected
|
||||
*/
|
||||
export function assertNotExistOrNotVisible(element: JQuery<HTMLElement>) {
|
||||
const doesNotExist = element.length === 0
|
||||
const isNotVisible = !element.is(':visible')
|
||||
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
expect(doesNotExist || isNotVisible, 'does not exist or is not visible').to.be.true
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the settings users list
|
||||
* @return Cypress chainable object
|
||||
*/
|
||||
export function getUserList() {
|
||||
return cy.get('[data-test-id="userList"]')
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the row entry for given userId within the settings users list
|
||||
*
|
||||
* @param userId the user to query
|
||||
* @return Cypress chainable object
|
||||
*/
|
||||
export function getUserListRow(userId: string) {
|
||||
return getUserList().find(`tr[data-test="${userId}"]`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the confirm password dialog (if needed)
|
||||
* @param adminPassword The admin password for the dialog
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
*/
|
||||
|
||||
import { User } from '@nextcloud/cypress'
|
||||
import { assertNotExistOrNotVisible } from './usersUtils.js'
|
||||
import { assertNotExistOrNotVisible, getUserList } from './usersUtils.js'
|
||||
|
||||
const admin = new User('admin', 'admin')
|
||||
|
||||
|
|
@ -77,8 +77,8 @@ describe('Settings: Show and hide columns', function() {
|
|||
})
|
||||
|
||||
// see that the language column is in all user rows
|
||||
cy.get('tbody.user-list__body tr').each(($row) => {
|
||||
cy.wrap($row).get('[data-test="language"]').should('exist')
|
||||
getUserList().find('tbody tr').each(($row) => {
|
||||
cy.wrap($row).get('[data-test-id="cell-language"]').should('exist')
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -89,8 +89,8 @@ describe('Settings: Show and hide columns', function() {
|
|||
})
|
||||
|
||||
// see that the last login column is in all user rows
|
||||
cy.get('tbody.user-list__body tr').each(($row) => {
|
||||
cy.wrap($row).get('[data-test="lastLogin"]').should('exist')
|
||||
getUserList().find('tbody tr').each(($row) => {
|
||||
cy.wrap($row).get('[data-test-id="cell-lastLogin"]').should('exist')
|
||||
})
|
||||
|
||||
// open the settings dialog
|
||||
|
|
@ -112,8 +112,8 @@ describe('Settings: Show and hide columns', function() {
|
|||
})
|
||||
|
||||
// see that the last login column is not in all user rows
|
||||
cy.get('tbody.user-list__body tr').each(($row) => {
|
||||
cy.wrap($row).get('[data-test="lastLogin"]').should('not.exist')
|
||||
getUserList().find('tbody tr').each(($row) => {
|
||||
cy.wrap($row).get('[data-test-id="cell-lastLogin"]').should('not.exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
*/
|
||||
|
||||
import { User } from '@nextcloud/cypress'
|
||||
import { getUserListRow, handlePasswordConfirmation } from './usersUtils'
|
||||
|
||||
const admin = new User('admin', 'admin')
|
||||
const jdoe = new User('jdoe', 'jdoe')
|
||||
|
|
@ -34,16 +35,14 @@ describe('Settings: Change user properties', function() {
|
|||
})
|
||||
|
||||
beforeEach(function() {
|
||||
cy.get(`tbody.user-list__body tr[data-test="${jdoe.userId}"]`).within(() => {
|
||||
// reset edit mode for the user jdoe
|
||||
cy.get('td.row__cell--actions .action-items > button:first-of-type')
|
||||
.invoke('attr', 'title')
|
||||
.then((title) => {
|
||||
if (title === 'Done') {
|
||||
cy.get('td.row__cell--actions .action-items > button:first-of-type').click()
|
||||
}
|
||||
})
|
||||
})
|
||||
// reset to read-only mode: try to find the edit button and click it if set to editing
|
||||
getUserListRow(jdoe.userId)
|
||||
.find('[data-test-id="cell-actions"]')
|
||||
// replace with following (more error resilent) with nextcloud-vue 8
|
||||
// find('[data-test-id="button-toggleEdit"][data-test="true"]')
|
||||
.find('button[aria-label="Done"]')
|
||||
.if()
|
||||
.click({ force: true })
|
||||
})
|
||||
|
||||
after(() => {
|
||||
|
|
@ -51,41 +50,45 @@ describe('Settings: Change user properties', function() {
|
|||
})
|
||||
|
||||
it('Can change the display name', function() {
|
||||
cy.get(`tbody.user-list__body tr[data-test="${jdoe.userId}"]`).within(() => {
|
||||
// see that the list of users contains the user jdoe
|
||||
cy.contains(jdoe.userId).should('exist')
|
||||
// see that the list of users contains the user jdoe
|
||||
getUserListRow(jdoe.userId).should('exist')
|
||||
// toggle the edit mode for the user jdoe
|
||||
cy.get('td.row__cell--actions .action-items > button:first-of-type').click()
|
||||
})
|
||||
.find('[data-test-id="cell-actions"]')
|
||||
.find('button[aria-label="Edit"]')
|
||||
// replace with following (more error resilent) with nextcloud-vue 8
|
||||
// find('[data-test-id="button-toggleEdit"]')
|
||||
.click({ force: true })
|
||||
|
||||
cy.get(`tbody.user-list__body tr[data-test="${jdoe.userId}"]`).within(() => {
|
||||
getUserListRow(jdoe.userId).within(() => {
|
||||
// set the display name
|
||||
cy.get('input[data-test="displayNameField"]').should('exist').and('have.value', 'jdoe')
|
||||
cy.get('input[data-test="displayNameField"]').clear()
|
||||
cy.get('input[data-test="displayNameField"]').type('John Doe')
|
||||
cy.get('input[data-test="displayNameField"]').should('have.value', 'John Doe')
|
||||
cy.get('input[data-test="displayNameField"] ~ button').click()
|
||||
cy.get('input[data-test-id="input-displayName"]').should('exist').and('have.value', 'jdoe')
|
||||
cy.get('input[data-test-id="input-displayName"]').clear()
|
||||
cy.get('input[data-test-id="input-displayName"]').type('John Doe')
|
||||
cy.get('input[data-test-id="input-displayName"]').should('have.value', 'John Doe')
|
||||
cy.get('input[data-test-id="input-displayName"] ~ button').click()
|
||||
|
||||
// Make sure no confirmation modal is shown
|
||||
handlePasswordConfirmation(admin.password)
|
||||
|
||||
// see that the display name cell is done loading
|
||||
cy.get('.user-row-text-field.icon-loading-small').should('exist')
|
||||
cy.waitUntil(() => cy.get('.user-row-text-field.icon-loading-small').should('not.exist'), { timeout: 10000 })
|
||||
cy.get('[data-test-id="input-displayName"]').should('have.attr', 'data-test-loading', 'true')
|
||||
cy.waitUntil(() => cy.get('[data-test-id="input-displayName"]').should('have.attr', 'data-test-loading', 'false'), { timeout: 10000 })
|
||||
})
|
||||
// Success message is shown
|
||||
cy.get('.toastify.toast-success').contains(/Display.+name.+was.+successfully.+changed/i).should('exist')
|
||||
})
|
||||
|
||||
it('Can change the password', function() {
|
||||
cy.get(`tbody.user-list__body tr[data-test="${jdoe.userId}"]`).within(() => {
|
||||
// see that the list of users contains the user jdoe
|
||||
cy.contains(jdoe.userId).should('exist')
|
||||
// see that the list of users contains the user jdoe
|
||||
getUserListRow(jdoe.userId).should('exist')
|
||||
// toggle the edit mode for the user jdoe
|
||||
cy.get('td.row__cell--actions .action-items > button:first-of-type').click()
|
||||
})
|
||||
.find('[data-test-id="cell-actions"]')
|
||||
.find('button[aria-label="Edit"]')
|
||||
// replace with following (more error resilent) with nextcloud-vue 8
|
||||
// find('[data-test-id="button-toggleEdit"]')
|
||||
.click({ force: true })
|
||||
|
||||
cy.get(`tbody.user-list__body tr[data-test="${jdoe.userId}"]`).within(() => {
|
||||
getUserListRow(jdoe.userId).within(() => {
|
||||
// see that the password of user0 is ""
|
||||
cy.get('input[type="password"]').should('exist').and('have.value', '')
|
||||
// set the password for user0 to 123456
|
||||
|
|
@ -98,10 +101,10 @@ describe('Settings: Change user properties', function() {
|
|||
handlePasswordConfirmation(admin.password)
|
||||
|
||||
// see that the password cell for user user0 is done loading
|
||||
cy.get('.user-row-text-field.icon-loading-small').should('exist')
|
||||
cy.waitUntil(() => cy.get('.user-row-text-field.icon-loading-small').should('not.exist'), { timeout: 10000 })
|
||||
cy.get('[data-test-id="input-password"]').should('have.attr', 'data-test-loading', 'true')
|
||||
cy.waitUntil(() => cy.get('[data-test-id="input-password"]').should('have.attr', 'data-test-loading', 'false'), { timeout: 10000 })
|
||||
// password input is emptied on change
|
||||
cy.get('input[type="password"]').should('have.value', '')
|
||||
cy.get('[data-test-id="input-password"]').should('have.value', '')
|
||||
})
|
||||
// Success message is shown
|
||||
cy.get('.toastify.toast-success').contains(/Password.+successfully.+changed/i).should('exist')
|
||||
|
|
|
|||
4
dist/settings-users-8351.js
vendored
4
dist/settings-users-8351.js
vendored
File diff suppressed because one or more lines are too long
2
dist/settings-users-8351.js.map
vendored
2
dist/settings-users-8351.js.map
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue