aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorskjnldsv <skjnldsv@protonmail.com>2025-05-09 15:05:14 +0200
committerbackportbot[bot] <backportbot[bot]@users.noreply.github.com>2025-05-12 09:13:50 +0000
commit61e399f20d36c02dbc9ee048d850ea8e86c91834 (patch)
tree3449c90d47bd3dd427f0f818252efe37bd23a096
parente5a1b48f8a144342817ef79282127ead6cea57ad (diff)
downloadnextcloud-server-backport/52755/stable29.tar.gz
nextcloud-server-backport/52755/stable29.zip
chore(cypress): add setup testsbackport/52755/stable29
Signed-off-by: skjnldsv <skjnldsv@protonmail.com> [skip ci] [skip ci]
-rw-r--r--.github/workflows/cypress.yml46
-rw-r--r--core/src/components/setup/RecommendedApps.vue5
-rw-r--r--cypress.config.ts19
-rw-r--r--cypress/dockerNode.ts18
-rw-r--r--cypress/e2e/core/setup.ts114
5 files changed, 198 insertions, 4 deletions
diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml
index fe5aaba375e..c7c437cf4f8 100644
--- a/.github/workflows/cypress.yml
+++ b/.github/workflows/cypress.yml
@@ -82,6 +82,51 @@ jobs:
# Always aling this number with the total of e2e runners (max. index + 1)
total-containers: [6]
+ services:
+ mysql:
+ # Only start mysql if we are running the setup tests
+ image: ${{matrix.containers == 'setup' && 'ghcr.io/nextcloud/continuous-integration-mysql-8.4:latest' || ''}}
+ ports:
+ - '3306/tcp'
+ env:
+ MYSQL_ROOT_PASSWORD: rootpassword
+ MYSQL_USER: oc_autotest
+ MYSQL_PASSWORD: nextcloud
+ MYSQL_DATABASE: oc_autotest
+ options: --health-cmd="mysqladmin ping" --health-interval 5s --health-timeout 2s --health-retries 10
+
+ mariadb:
+ # Only start mariadb if we are running the setup tests
+ image: ${{matrix.containers == 'setup' && 'mariadb:11.4' || ''}}
+ ports:
+ - '3306/tcp'
+ env:
+ MYSQL_ROOT_PASSWORD: rootpassword
+ MYSQL_USER: oc_autotest
+ MYSQL_PASSWORD: nextcloud
+ MYSQL_DATABASE: oc_autotest
+ options: --health-cmd="mariadb-admin ping" --health-interval 5s --health-timeout 2s --health-retries 5
+
+ postgres:
+ # Only start postgres if we are running the setup tests
+ image: ${{matrix.containers == 'setup' && 'ghcr.io/nextcloud/continuous-integration-postgres-17:latest' || ''}}
+ ports:
+ - '5432/tcp'
+ env:
+ POSTGRES_USER: root
+ POSTGRES_PASSWORD: rootpassword
+ POSTGRES_DB: nextcloud
+ options: --mount type=tmpfs,destination=/var/lib/postgresql/data --health-cmd pg_isready --health-interval 5s --health-timeout 2s --health-retries 5
+
+ oracle:
+ # Only start oracle if we are running the setup tests
+ image: ${{matrix.containers == 'setup' && 'ghcr.io/gvenzl/oracle-free:23' || ''}}
+ ports:
+ - '1521'
+ env:
+ ORACLE_PASSWORD: oracle
+ options: --health-cmd healthcheck.sh --health-interval 20s --health-timeout 10s --health-retries 10
+
name: runner ${{ matrix.containers }}
steps:
@@ -119,6 +164,7 @@ jobs:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
SPLIT: ${{ matrix.total-containers }}
SPLIT_INDEX: ${{ matrix.containers == 'component' && 0 || matrix.containers }}
+ SETUP_TESTING: ${{ matrix.containers == 'setup' && 'true' || '' }}
- name: Upload snapshots
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
diff --git a/core/src/components/setup/RecommendedApps.vue b/core/src/components/setup/RecommendedApps.vue
index 472c011c762..4aaf6d2b34a 100644
--- a/core/src/components/setup/RecommendedApps.vue
+++ b/core/src/components/setup/RecommendedApps.vue
@@ -20,7 +20,7 @@
-->
<template>
- <div class="guest-box">
+ <div class="guest-box" data-cy-setup-recommended-apps>
<h2>{{ t('core', 'Recommended apps') }}</h2>
<p v-if="loadingApps" class="loading text-center">
{{ t('core', 'Loading apps …') }}
@@ -59,7 +59,8 @@
<NcButton v-if="showInstallButton"
type="tertiary"
role="link"
- :href="defaultPageUrl">
+ :href="defaultPageUrl"
+ data-cy-setup-recommended-apps-skip>
{{ t('core', 'Skip') }}
</NcButton>
diff --git a/cypress.config.ts b/cypress.config.ts
index 4b96e052df9..9f4ad8e9dc8 100644
--- a/cypress.config.ts
+++ b/cypress.config.ts
@@ -3,6 +3,13 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import type { Configuration } from 'webpack'
+import { defineConfig } from 'cypress'
+import { join } from 'path'
+import { removeDirectory } from 'cypress-delete-downloads-folder'
+
+import cypressSplit from 'cypress-split'
+import webpackPreprocessor from '@cypress/webpack-preprocessor'
+
import {
applyChangesToNextcloud,
configureNextcloud,
@@ -62,8 +69,6 @@ export default defineConfig({
// We've imported your old cypress plugins here.
// You may want to clean this up later by importing these.
async setupNodeEvents(on, config) {
- cypressSplit(on, config)
-
on('file:preprocessor', webpackPreprocessor({ webpackOptions: webpackConfig as Configuration }))
on('task', { removeDirectory })
@@ -106,6 +111,16 @@ export default defineConfig({
}
})
+ // Check if we are running the setup checks
+ if (process.env.SETUP_TESTING === 'true') {
+ console.log('Adding setup tests to specPattern 🧮')
+ config.specPattern = [join(__dirname, 'cypress/e2e/core/setup.ts')]
+ console.log('└─ Done')
+ } else {
+ // If we are not running the setup tests, we need to remove the setup tests from the specPattern
+ cypressSplit(on, config)
+ }
+
// Before the browser launches
// starting Nextcloud testing container
const ip = await startNextcloud(process.env.BRANCH)
diff --git a/cypress/dockerNode.ts b/cypress/dockerNode.ts
index 03c53c00c12..ba6a002c55b 100644
--- a/cypress/dockerNode.ts
+++ b/cypress/dockerNode.ts
@@ -290,3 +290,21 @@ const sleep = function(milliseconds: number) {
const getCurrentGitBranch = function() {
return execSync('git rev-parse --abbrev-ref HEAD').toString().trim() || 'master'
}
+
+/**
+ * Get the network name of the github actions network
+ * This is used to connect to the database services
+ * started by github actions
+ */
+const getGithubNetwork = async function(): Promise<string|undefined> {
+ console.log('├─ Looking for github actions network... 🔍')
+ const networks = await docker.listNetworks()
+ const network = networks.find((network) => network.Name.startsWith('github_network'))
+ if (network) {
+ console.log('│ └─ Found github actions network: ' + network.Name)
+ return network.Name
+ }
+
+ console.log('│ └─ No github actions network found')
+ return undefined
+}
diff --git a/cypress/e2e/core/setup.ts b/cypress/e2e/core/setup.ts
new file mode 100644
index 00000000000..01606a75617
--- /dev/null
+++ b/cypress/e2e/core/setup.ts
@@ -0,0 +1,114 @@
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+/**
+ * DO NOT RENAME THIS FILE to .cy.ts ⚠️
+ * This is not following the pattern of the other files in this folder
+ * because it is manually added to the tests by the cypress config.
+ */
+describe('Can install Nextcloud', { testIsolation: true, retries: 0 }, () => {
+ beforeEach(() => {
+ // Move the config file and data folder
+ cy.runCommand('rm /var/www/html/config/config.php', { failOnNonZeroExit: false })
+ cy.runCommand('rm /var/www/html/data/owncloud.db', { failOnNonZeroExit: false })
+ })
+
+ it('Sqlite', () => {
+ cy.visit('/')
+ cy.get('[data-cy-setup-form]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="adminlogin"]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="adminpass"]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="directory"]').should('have.value', '/var/www/html/data')
+
+ // Select the SQLite database
+ cy.get('[data-cy-setup-form-field="dbtype-sqlite"] input').check({ force: true })
+
+ sharedSetup()
+ })
+
+ it('MySQL', () => {
+ cy.visit('/')
+ cy.get('[data-cy-setup-form]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="adminlogin"]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="adminpass"]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="directory"]').should('have.value', '/var/www/html/data')
+
+ // Select the SQLite database
+ cy.get('[data-cy-setup-form-field="dbtype-mysql"] input').check({ force: true })
+
+ // Fill in the DB form
+ cy.get('[data-cy-setup-form-field="dbuser"]').type('{selectAll}oc_autotest')
+ cy.get('[data-cy-setup-form-field="dbpass"]').type('{selectAll}nextcloud')
+ cy.get('[data-cy-setup-form-field="dbname"]').type('{selectAll}oc_autotest')
+ cy.get('[data-cy-setup-form-field="dbhost"]').type('{selectAll}mysql:3306')
+
+ sharedSetup()
+ })
+
+ it('MariaDB', () => {
+ cy.visit('/')
+ cy.get('[data-cy-setup-form]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="adminlogin"]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="adminpass"]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="directory"]').should('have.value', '/var/www/html/data')
+
+ // Select the SQLite database
+ cy.get('[data-cy-setup-form-field="dbtype-mysql"] input').check({ force: true })
+
+ // Fill in the DB form
+ cy.get('[data-cy-setup-form-field="dbuser"]').type('{selectAll}oc_autotest')
+ cy.get('[data-cy-setup-form-field="dbpass"]').type('{selectAll}nextcloud')
+ cy.get('[data-cy-setup-form-field="dbname"]').type('{selectAll}oc_autotest')
+ cy.get('[data-cy-setup-form-field="dbhost"]').type('{selectAll}mariadb:3306')
+
+ sharedSetup()
+ })
+
+ it('PostgreSQL', () => {
+ cy.visit('/')
+ cy.get('[data-cy-setup-form]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="adminlogin"]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="adminpass"]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="directory"]').should('have.value', '/var/www/html/data')
+
+ // Select the SQLite database
+ cy.get('[data-cy-setup-form-field="dbtype-pgsql"] input').check({ force: true })
+
+ // Fill in the DB form
+ cy.get('[data-cy-setup-form-field="dbuser"]').type('{selectAll}root')
+ cy.get('[data-cy-setup-form-field="dbpass"]').type('{selectAll}rootpassword')
+ cy.get('[data-cy-setup-form-field="dbname"]').type('{selectAll}nextcloud')
+ cy.get('[data-cy-setup-form-field="dbhost"]').type('{selectAll}postgres:5432')
+
+ sharedSetup()
+ })
+
+})
+
+/**
+ * Shared admin setup function for the Nextcloud setup
+ */
+function sharedSetup() {
+ const randAdmin = 'admin-' + Math.random().toString(36).substring(2, 15)
+
+ // Fill in the form
+ cy.get('[data-cy-setup-form-field="adminlogin"]').type(randAdmin)
+ cy.get('[data-cy-setup-form-field="adminpass"]').type(randAdmin)
+
+ // Nothing more to do on sqlite, let's continue
+ cy.get('[data-cy-setup-form-submit]').click()
+
+ // Wait for the setup to finish
+ cy.location('pathname', { timeout: 10000 })
+ .should('include', '/core/apps/recommended')
+
+ // Skip the setup apps
+ cy.get('[data-cy-setup-recommended-apps]').should('be.visible')
+ cy.get('[data-cy-setup-recommended-apps-skip]').click()
+
+ // Go to files
+ cy.visit('/apps/files/')
+ cy.get('[data-cy-files-content]').should('be.visible')
+}