mirror of
https://github.com/nextcloud/server.git
synced 2026-02-18 18:28:50 -05:00
chore(cypress): add setup tests
Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
This commit is contained in:
parent
0b354efb22
commit
3dbc479239
7 changed files with 207 additions and 16 deletions
48
.github/workflows/cypress.yml
vendored
48
.github/workflows/cypress.yml
vendored
|
|
@ -94,11 +94,56 @@ jobs:
|
|||
matrix:
|
||||
# Run multiple copies of the current job in parallel
|
||||
# Please increase the number or runners as your tests suite grows (0 based index for e2e tests)
|
||||
containers: ["component", '0', '1', '2', '3', '4', '5', '6', '7']
|
||||
containers: ['component', 'setup', '0', '1', '2', '3', '4', '5', '6', '7']
|
||||
# Hack as strategy.job-total includes the component and GitHub does not allow math expressions
|
||||
# Always align this number with the total of e2e runners (max. index + 1)
|
||||
total-containers: [8]
|
||||
|
||||
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:
|
||||
|
|
@ -141,6 +186,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 and videos
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
|
|
|
|||
|
|
@ -4,7 +4,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 …') }}
|
||||
|
|
@ -40,13 +40,15 @@
|
|||
<NcButton v-if="showInstallButton && !installingApps"
|
||||
type="tertiary"
|
||||
role="link"
|
||||
:href="defaultPageUrl">
|
||||
:href="defaultPageUrl"
|
||||
data-cy-setup-recommended-apps-skip>
|
||||
{{ t('core', 'Skip') }}
|
||||
</NcButton>
|
||||
|
||||
<NcButton v-if="showInstallButton"
|
||||
type="primary"
|
||||
:disabled="installingApps || !isAnyAppSelected"
|
||||
data-cy-setup-recommended-apps-install>
|
||||
@click.stop.prevent="installApps">
|
||||
{{ installingApps ? t('core', 'Installing apps …') : t('core', 'Install recommended apps') }}
|
||||
</NcButton>
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -10,11 +17,6 @@ import {
|
|||
stopNextcloud,
|
||||
waitOnNextcloud,
|
||||
} from './cypress/dockerNode'
|
||||
import { defineConfig } from 'cypress'
|
||||
import cypressSplit from 'cypress-split'
|
||||
import { removeDirectory } from 'cypress-delete-downloads-folder'
|
||||
import webpackPreprocessor from '@cypress/webpack-preprocessor'
|
||||
|
||||
import webpackConfig from './webpack.config.js'
|
||||
|
||||
export default defineConfig({
|
||||
|
|
@ -62,8 +64,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 +106,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)
|
||||
|
|
|
|||
|
|
@ -94,6 +94,9 @@ export const startNextcloud = async function(branch: string = getCurrentGitBranc
|
|||
HostPort: '8083',
|
||||
}],
|
||||
},
|
||||
// If running the setup tests, let's bind to host
|
||||
// to communicate with the github actions DB services
|
||||
NetworkMode: process.env.SETUP_TESTING === 'true' ? await getGithubNetwork() : undefined,
|
||||
},
|
||||
Env: [
|
||||
`BRANCH=${branch}`,
|
||||
|
|
@ -106,9 +109,6 @@ export const startNextcloud = async function(branch: string = getCurrentGitBranc
|
|||
await runExec(container, ['chown', '-R', 'www-data:www-data', '/var/www/html/data'], false, 'root')
|
||||
await runExec(container, ['chmod', '0770', '/var/www/html/data'], false, 'root')
|
||||
|
||||
// Init Nextcloud
|
||||
// await runExec(container, ['initnc.sh'], true, 'root')
|
||||
|
||||
// Get container's IP
|
||||
const ip = await getContainerIP(container)
|
||||
|
||||
|
|
@ -252,6 +252,7 @@ export const getContainerIP = async function(
|
|||
if (err) {
|
||||
throw err
|
||||
}
|
||||
|
||||
if (data?.HostConfig.PortBindings?.['80/tcp']?.[0]?.HostPort) {
|
||||
ip = `localhost:${data.HostConfig.PortBindings['80/tcp'][0].HostPort}`
|
||||
} else {
|
||||
|
|
@ -335,3 +336,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
|
||||
}
|
||||
|
|
|
|||
114
cypress/e2e/core/setup.ts
Normal file
114
cypress/e2e/core/setup.ts
Normal file
|
|
@ -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')
|
||||
}
|
||||
4
dist/core-recommendedapps.js
vendored
4
dist/core-recommendedapps.js
vendored
File diff suppressed because one or more lines are too long
2
dist/core-recommendedapps.js.map
vendored
2
dist/core-recommendedapps.js.map
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue