From ed30b1922ffa8aeb1ed92925891f1ff2f9ed95b3 Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Tue, 28 Apr 2026 22:32:36 +0200 Subject: [PATCH] test(appstore): adjust cypress tests for app split Signed-off-by: Ferdinand Thiessen --- cypress/e2e/appstore/apps.cy.ts | 199 +++++++++++++----- .../files-user-credentials.cy.ts | 2 +- cypress/e2e/files_external/settings.cy.ts | 2 +- cypress/e2e/settings/personal-info.cy.ts | 2 +- cypress/e2e/settings/users-group-admin.cy.ts | 3 +- cypress/e2e/settings/users.cy.ts | 3 +- cypress/e2e/settings/usersUtils.ts | 2 - cypress/e2e/settings/users_groups.cy.ts | 3 +- cypress/e2e/settings/users_manager.cy.ts | 3 +- cypress/e2e/settings/users_modify.cy.ts | 3 +- 10 files changed, 157 insertions(+), 65 deletions(-) diff --git a/cypress/e2e/appstore/apps.cy.ts b/cypress/e2e/appstore/apps.cy.ts index 31252e69186..391ab163f9a 100644 --- a/cypress/e2e/appstore/apps.cy.ts +++ b/cypress/e2e/appstore/apps.cy.ts @@ -1,5 +1,5 @@ -/** - * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors +/* + * SPDX-FileCopyrightText: 2023-2026 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ @@ -19,7 +19,7 @@ describe('Settings: App management', { testIsolation: true }, () => { cy.login(admin) // Intercept the apps list request - cy.intercept('GET', '**/ocs/v2.php/apps/appstore/api/v1/apps').as('fetchAppsList') + cy.intercept('GET', '/ocs/v2.php/apps/appstore/api/v1/apps').as('fetchAppsList') // I open the Apps management cy.visit('/settings/apps/installed') @@ -29,70 +29,96 @@ describe('Settings: App management', { testIsolation: true }, () => { }) it('Can enable an installed app', () => { - cy.intercept('POST', '**/ocs/v2.php/apps/appstore/api/v1/apps/enable').as('enableApp') - cy.get('#apps-list').should('exist') + cy.intercept('POST', '/ocs/v2.php/apps/appstore/api/v1/apps/enable').as('enableApp') + + cy.findByRole('table').should('exist') // Wait for the app list to load .contains('tr', 'QA testing', { timeout: 10000 }) .should('exist') + .findByRole('button', { name: 'Enable' }) // I enable the "QA testing" app - .contains('button', 'Enable') .click({ force: true }) handlePasswordConfirmation(admin.password) + cy.wait('@enableApp') // Wait until we see the disable button for the app - cy.get('#apps-list').should('exist') + cy.findByRole('table').should('exist') .contains('tr', 'QA testing') .should('exist') // I see the disable button for the app - .contains('button', 'Disable', { timeout: 10000 }) + .findByRole('button', { name: 'Disable' }) + .should('be.visible') // Change to enabled apps view - cy.get('#app-category-enabled a').click({ force: true }) + cy.findByRole('navigation', { name: 'Appstore categories' }) + .within(() => { + cy.findByRole('link', { name: 'Active apps' }) + .should('be.visible') + .click({ force: true }) + }) + cy.url().should('match', /settings\/apps\/enabled$/) // I see that the "QA testing" app has been enabled - cy.get('#apps-list').contains('tr', 'QA testing') + cy.findByRole('table') + .contains('tr', 'QA testing') }) it('Can disable an installed app', () => { - cy.intercept('POST', '**/ocs/v2.php/apps/appstore/api/v1/apps/disable').as('disableApp') - cy.get('#apps-list') + cy.intercept('POST', '/ocs/v2.php/apps/appstore/api/v1/apps/disable').as('disableApp') + + cy.findByRole('table') .should('exist') // Wait for the app list to load .contains('tr', 'Update notification', { timeout: 10000 }) .should('exist') // I disable the "Update notification" app - .contains('button', 'Disable') + .findByRole('button', { name: 'Disable' }) .click({ force: true }) handlePasswordConfirmation(admin.password) cy.wait('@disableApp') // Wait until we see the disable button for the app - cy.get('#apps-list').should('exist') + cy.findByRole('table').should('exist') .contains('tr', 'Update notification') .should('exist') // I see the enable button for the app - .contains('button', 'Enable', { timeout: 10000 }) + .findByRole('button', { name: 'Enable' }) + .should('exist') // Change to disabled apps view - cy.get('#app-category-disabled a').click({ force: true }) + cy.findByRole('navigation', { name: 'Appstore categories' }) + .within(() => { + cy.findByRole('link', { name: 'Disabled apps' }).click({ force: true }) + }) cy.url().should('match', /settings\/apps\/disabled$/) + // I see that the "Update notification" app has been disabled - cy.get('#apps-list').contains('tr', 'Update notification') + cy.findByRole('table') + .contains('tr', 'Update notification') }) it('Browse enabled apps', () => { // When I open the "Active apps" section - cy.get('#app-category-enabled a') - .should('contain', 'Active apps') - .click({ force: true }) + cy.findByRole('navigation', { name: 'Appstore categories' }) + .within(() => { + cy.findByRole('link', { name: 'Active apps' }) + .should('be.visible') + .click({ force: true }) + }) + // Then I see that the current section is "Active apps" cy.url().should('match', /settings\/apps\/enabled$/) - cy.get('#app-category-enabled').find('.active').should('exist') + cy.findByRole('navigation', { name: 'Appstore categories' }) + .within(() => { + cy.findByRole('link', { name: 'Active apps', current: 'page' }) + .should('be.visible') + }) + // I see that there are only enabled apps - cy.get('#apps-list') + cy.findByRole('table') .should('exist') .find('tr button') .each(($action) => { @@ -101,15 +127,27 @@ describe('Settings: App management', { testIsolation: true }, () => { }) it('Browse disabled apps', () => { - // When I open the "Active apps" section - cy.get('#app-category-disabled a') - .should('contain', 'Disabled apps') - .click({ force: true }) - // Then I see that the current section is "Active apps" + // When I open the "Active Disabled" section + cy.findByRole('navigation', { name: 'Appstore categories' }) + .within(() => { + cy.findByRole('link', { name: 'Disabled apps' }) + .as('disabledAppsLink') + .should('be.visible') + .and('not.have.attr', 'aria-current') + cy.get('@disabledAppsLink') + .click({ force: true }) + }) + + // Then I see that the current section is "Disabled apps" cy.url().should('match', /settings\/apps\/disabled$/) - cy.get('#app-category-disabled').find('.active').should('exist') + cy.findByRole('navigation', { name: 'Appstore categories' }) + .within(() => { + cy.findByRole('link', { name: 'Disabled apps', current: 'page' }) + .should('be.visible') + }) + // I see that there are only disabled apps - cy.get('#apps-list') + cy.findByRole('table') .should('exist') .find('tr button') .each(($action) => { @@ -119,61 +157,112 @@ describe('Settings: App management', { testIsolation: true }, () => { it('Browse app bundles', () => { // When I open the "App bundles" section - cy.get('#app-category-your-bundles a') - .should('contain', 'App bundles') - .click({ force: true }) + cy.findByRole('navigation', { name: 'Appstore categories' }) + .within(() => { + cy.findByRole('link', { name: 'App bundles' }) + .as('appBundlesLink') + .should('be.visible') + .and('not.have.attr', 'aria-current') + cy.get('@appBundlesLink') + .click({ force: true }) + }) + // Then I see that the current section is "App bundles" - cy.url().should('match', /settings\/apps\/app-bundles$/) - cy.get('#app-category-your-bundles').find('.active').should('exist') + cy.url().should('match', /settings\/apps\/bundles$/) + cy.findByRole('navigation', { name: 'Appstore categories' }) + .within(() => { + cy.findByRole('link', { name: 'App bundles', current: 'page' }) + .should('be.visible') + }) + // I see the app bundles - cy.get('#apps-list').contains('tr', 'Enterprise bundle') - cy.get('#apps-list').contains('tr', 'Education bundle') - // I see that the "Enterprise bundle" is disabled - cy.get('#apps-list').contains('tr', 'Enterprise bundle').contains('button', 'Download and enable all') + cy.findByRole('heading', { name: 'Enterprise bundle' }) + .should('be.visible') + cy.findByRole('heading', { name: 'Education bundle' }) + .should('be.visible') }) it('View app details', () => { // When I click on the "QA testing" app - cy.get('#apps-list').contains('a', 'QA testing').click({ force: true }) + cy.findByRole('table') + .contains('a', 'QA testing') + .click({ force: true }) // I see that the app details are shown cy.get('#app-sidebar-vue') .should('be.visible') .find('.app-sidebar-header__info') .should('contain', 'QA testing') cy.get('#app-sidebar-vue').contains('a', 'View in store').should('exist') - cy.get('#app-sidebar-vue').findByRole('button', { name: 'Enable' }).should('be.visible') + cy.get('#app-sidebar-vue') + .findByRole('button', { name: 'Enable' }) + .should('be.visible') + cy.get('#app-sidebar-vue') + .findByRole('button', { name: 'Remove' }) + .should('be.visible') cy.get('#app-sidebar-vue').contains(/Version \d+\.\d+\.\d+/).should('be.visible') }) - it.skip('Limit app usage to group', () => { + it('Limit app usage to group', () => { // When I open the "Active apps" section - cy.get('#app-category-enabled a') - .should('contain', 'Active apps') - .click({ force: true }) + cy.findByRole('navigation', { name: 'Appstore categories' }) + .within(() => { + cy.findByRole('link', { name: 'Active apps' }) + .should('be.visible') + .click({ force: true }) + }) + // Then I see that the current section is "Active apps" cy.url().should('match', /settings\/apps\/enabled$/) - cy.get('#app-category-enabled').find('.active').should('exist') + // Then I select the app - cy.get('#apps-list') + cy.findByRole('table') .should('exist') - .contains('tr', 'Dashboard', { timeout: 10000 }) + .contains('tr a', 'Dashboard', { timeout: 10000 }) .click() + // Then I enable "limit app to group" - cy.get('[for="groups_enable_dashboard"]').click() + cy.findByRole('button', { name: 'Limit to groups' }) + .click() + // Then I select a group - cy.get('#limitToGroups').click() - cy.get('ul[role="listbox"]') - .find('span') - .contains('admin') + cy.findByRole('dialog') + .should('be.visible') + .within(() => { + cy.get('input') + .should('be.focused') + .type('admin') + }) + cy.findByRole('option', { name: /admin/ }) + .click() + cy.findByRole('button', { name: 'Save' }) .click() handlePasswordConfirmation(admin.password) - cy.get('span.name-parts__first') - .contains('admin') + cy.get('#app-sidebar-vue') + .findByRole('list', { name: 'Limited to groups' }) + .findByRole('listitem', { name: /admin/ }) .should('be.visible') + // Then I disable the group limitation - cy.get('button[title="Deselect admin"]').click() + cy.get('#app-sidebar-vue') + .findByRole('button', { name: 'Limit to groups' }) + .click() + cy.findByRole('dialog') + .should('be.visible') + .within(() => { + cy.findByRole('button', { name: 'Deselect admin' }) + .should('be.visible') + .click() + cy.findByRole('button', { name: 'Save' }) + .click() + }) + + handlePasswordConfirmation(admin.password) + + cy.get('#app-sidebar-vue') + .findByRole('list', { name: 'Limited to groups' }) + .should('not.exist') }) /* diff --git a/cypress/e2e/files_external/files-user-credentials.cy.ts b/cypress/e2e/files_external/files-user-credentials.cy.ts index a6d52015b36..ac44cdb0c4f 100644 --- a/cypress/e2e/files_external/files-user-credentials.cy.ts +++ b/cypress/e2e/files_external/files-user-credentials.cy.ts @@ -5,8 +5,8 @@ import type { User } from '@nextcloud/e2e-test-server/cypress' +import { handlePasswordConfirmation } from '../core-utils.ts' import { getInlineActionEntryForFile, getRowForFile, navigateToFolder, triggerInlineActionForFile } from '../files/FilesUtils.ts' -import { handlePasswordConfirmation } from '../settings/usersUtils.ts' import { AuthBackend, createStorageWithConfig, StorageBackend } from './StorageUtils.ts' const ACTION_CREDENTIALS_EXTERNAL_STORAGE = 'credentials-external-storage' diff --git a/cypress/e2e/files_external/settings.cy.ts b/cypress/e2e/files_external/settings.cy.ts index ce9e3e71a3c..a7850b83de5 100644 --- a/cypress/e2e/files_external/settings.cy.ts +++ b/cypress/e2e/files_external/settings.cy.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -import { handlePasswordConfirmation } from '../settings/usersUtils.ts' +import { handlePasswordConfirmation } from '../core-utils.ts' describe('files_external settings', () => { before(() => { diff --git a/cypress/e2e/settings/personal-info.cy.ts b/cypress/e2e/settings/personal-info.cy.ts index 5be6290f717..068af94aec9 100644 --- a/cypress/e2e/settings/personal-info.cy.ts +++ b/cypress/e2e/settings/personal-info.cy.ts @@ -5,7 +5,7 @@ import type { User } from '@nextcloud/e2e-test-server/cypress' -import { handlePasswordConfirmation } from './usersUtils.ts' +import { handlePasswordConfirmation } from '../core-utils.ts' let user: User diff --git a/cypress/e2e/settings/users-group-admin.cy.ts b/cypress/e2e/settings/users-group-admin.cy.ts index 932e699d0dc..68dddac2e05 100644 --- a/cypress/e2e/settings/users-group-admin.cy.ts +++ b/cypress/e2e/settings/users-group-admin.cy.ts @@ -5,7 +5,8 @@ import { User } from '@nextcloud/e2e-test-server/cypress' import { randomString } from '../../support/utils/randomString.ts' -import { getUserListRow, handlePasswordConfirmation } from './usersUtils.ts' +import { handlePasswordConfirmation } from '../core-utils.ts' +import { getUserListRow } from './usersUtils.ts' const admin = new User('admin', 'admin') const john = new User('john', '123456') diff --git a/cypress/e2e/settings/users.cy.ts b/cypress/e2e/settings/users.cy.ts index ec4123bf77b..615455bc302 100644 --- a/cypress/e2e/settings/users.cy.ts +++ b/cypress/e2e/settings/users.cy.ts @@ -5,7 +5,8 @@ /// import { User } from '@nextcloud/e2e-test-server/cypress' -import { getUserListRow, handlePasswordConfirmation } from './usersUtils.ts' +import { handlePasswordConfirmation } from '../core-utils.ts' +import { getUserListRow } from './usersUtils.ts' const admin = new User('admin', 'admin') const john = new User('john', '123456') diff --git a/cypress/e2e/settings/usersUtils.ts b/cypress/e2e/settings/usersUtils.ts index 868c4656d44..c9bc7800fd1 100644 --- a/cypress/e2e/settings/usersUtils.ts +++ b/cypress/e2e/settings/usersUtils.ts @@ -72,5 +72,3 @@ export function saveEditDialog() { // Wait for dialog to close cy.get('.edit-dialog').should('not.exist') } - -export { handlePasswordConfirmation } from '../core-utils.ts' diff --git a/cypress/e2e/settings/users_groups.cy.ts b/cypress/e2e/settings/users_groups.cy.ts index 36339c6b4b7..f9f29059884 100644 --- a/cypress/e2e/settings/users_groups.cy.ts +++ b/cypress/e2e/settings/users_groups.cy.ts @@ -6,7 +6,8 @@ import { User } from '@nextcloud/e2e-test-server/cypress' import { clearState } from '../../support/commonUtils.ts' import { randomString } from '../../support/utils/randomString.ts' -import { assertNotExistOrNotVisible, getUserListRow, handlePasswordConfirmation, openEditDialog, saveEditDialog } from './usersUtils.ts' +import { handlePasswordConfirmation } from '../core-utils.ts' +import { assertNotExistOrNotVisible, getUserListRow, openEditDialog, saveEditDialog } from './usersUtils.ts' const admin = new User('admin', 'admin') diff --git a/cypress/e2e/settings/users_manager.cy.ts b/cypress/e2e/settings/users_manager.cy.ts index 429b2beab55..68b453b1c9b 100644 --- a/cypress/e2e/settings/users_manager.cy.ts +++ b/cypress/e2e/settings/users_manager.cy.ts @@ -5,7 +5,8 @@ import { User } from '@nextcloud/e2e-test-server/cypress' import { clearState } from '../../support/commonUtils.ts' -import { handlePasswordConfirmation, openEditDialog, saveEditDialog } from './usersUtils.ts' +import { handlePasswordConfirmation } from '../core-utils.ts' +import { openEditDialog, saveEditDialog } from './usersUtils.ts' const admin = new User('admin', 'admin') diff --git a/cypress/e2e/settings/users_modify.cy.ts b/cypress/e2e/settings/users_modify.cy.ts index abe04b73c05..7a3147124d5 100644 --- a/cypress/e2e/settings/users_modify.cy.ts +++ b/cypress/e2e/settings/users_modify.cy.ts @@ -5,7 +5,8 @@ import { User } from '@nextcloud/e2e-test-server/cypress' import { clearState } from '../../support/commonUtils.ts' -import { handlePasswordConfirmation, openEditDialog, saveEditDialog } from './usersUtils.ts' +import { handlePasswordConfirmation } from '../core-utils.ts' +import { openEditDialog, saveEditDialog } from './usersUtils.ts' const admin = new User('admin', 'admin')