chore: migrate Cypress to @nextcloud/e2e-test-server
- chore: use vite preprocessor for Cypress Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
This commit is contained in:
19
.github/workflows/cypress.yml
vendored
19
.github/workflows/cypress.yml
vendored
@@ -205,20 +205,19 @@ jobs:
|
||||
cypress/snapshots
|
||||
cypress/videos
|
||||
|
||||
- name: Extract NC logs
|
||||
- name: Show logs
|
||||
if: failure() && matrix.containers != 'component'
|
||||
run: docker logs nextcloud-cypress-tests_${{ env.APP_NAME }} > nextcloud.log
|
||||
|
||||
- name: Upload NC logs
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
if: failure() && matrix.containers != 'component'
|
||||
with:
|
||||
name: nc_logs_${{ matrix.containers }}
|
||||
path: nextcloud.log
|
||||
run: |
|
||||
for id in $(docker ps -aq); do
|
||||
docker container inspect "$id" --format '=== Logs for container {{.Name}} ==='
|
||||
docker logs "$id" >> nextcloud.log
|
||||
done
|
||||
echo '=== Nextcloud server logs ==='
|
||||
docker exec nextcloud-e2e-test-server_${{ env.APP_NAME }} cat data/nextcloud.log
|
||||
|
||||
- name: Create data dir archive
|
||||
if: failure() && matrix.containers != 'component'
|
||||
run: docker exec nextcloud-cypress-tests_${{ env.APP_NAME }} tar -cvjf - data > data.tar
|
||||
run: docker exec nextcloud-e2e-test-server_${{ env.APP_NAME }} tar -cvjf - data > data.tar
|
||||
|
||||
- name: Upload data dir archive
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
|
||||
@@ -57,7 +57,6 @@ $expectedFiles = [
|
||||
'cron.php',
|
||||
'custom.d.ts',
|
||||
'cypress.config.ts',
|
||||
'cypress.d.ts',
|
||||
'cypress',
|
||||
'dist',
|
||||
'eslint.config.mjs',
|
||||
|
||||
@@ -4,21 +4,20 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { Configuration } from 'webpack'
|
||||
|
||||
import webpackPreprocessor from '@cypress/webpack-preprocessor'
|
||||
import { configureNextcloud, docker, getContainer, getContainerName, runExec, runOcc, startNextcloud, stopNextcloud, waitOnNextcloud } from '@nextcloud/e2e-test-server'
|
||||
import { defineConfig } from 'cypress'
|
||||
import { removeDirectory } from 'cypress-delete-downloads-folder'
|
||||
import cypressSplit from 'cypress-split'
|
||||
import { join } from 'path'
|
||||
import {
|
||||
applyChangesToNextcloud,
|
||||
configureNextcloud,
|
||||
startNextcloud,
|
||||
stopNextcloud,
|
||||
waitOnNextcloud,
|
||||
} from './cypress/dockerNode.ts'
|
||||
import webpackConfig from './webpack.config.js'
|
||||
import vitePreprocessor from 'cypress-vite'
|
||||
import { existsSync } from 'node:fs'
|
||||
import { dirname, join, resolve } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { nodePolyfills } from 'vite-plugin-node-polyfills'
|
||||
|
||||
if (!globalThis.__dirname) {
|
||||
// Cypress has their own weird parser
|
||||
globalThis.__dirname = dirname(fileURLToPath(new URL(import.meta.url)))
|
||||
}
|
||||
|
||||
export default defineConfig({
|
||||
projectId: '37xpdh',
|
||||
@@ -65,13 +64,15 @@ 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) {
|
||||
on('file:preprocessor', webpackPreprocessor({ webpackOptions: webpackConfig as Configuration }))
|
||||
on('file:preprocessor', vitePreprocessor({
|
||||
plugins: [nodePolyfills()],
|
||||
}))
|
||||
|
||||
on('task', { removeDirectory })
|
||||
|
||||
// This allows to store global data (e.g. the name of a snapshot)
|
||||
// because Cypress.env() and other options are local to the current spec file.
|
||||
const data = {}
|
||||
const data: Record<string, unknown> = {}
|
||||
on('task', {
|
||||
setVariable({ key, value }) {
|
||||
data[key] = value
|
||||
@@ -117,21 +118,82 @@ export default defineConfig({
|
||||
cypressSplit(on, config)
|
||||
}
|
||||
|
||||
const mounts = {
|
||||
'3rdparty': resolve(__dirname, './3rdparty'),
|
||||
apps: resolve(__dirname, './apps'),
|
||||
core: resolve(__dirname, './core'),
|
||||
cypress: resolve(__dirname, './cypress'),
|
||||
dist: resolve(__dirname, './dist'),
|
||||
lib: resolve(__dirname, './lib'),
|
||||
ocs: resolve(__dirname, './ocs'),
|
||||
'ocs-provider': resolve(__dirname, './ocs-provider'),
|
||||
resources: resolve(__dirname, './resources'),
|
||||
tests: resolve(__dirname, './tests'),
|
||||
'console.php': resolve(__dirname, './console.php'),
|
||||
'cron.php': resolve(__dirname, './cron.php'),
|
||||
'index.php': resolve(__dirname, './index.php'),
|
||||
occ: resolve(__dirname, './occ'),
|
||||
'public.php': resolve(__dirname, './public.php'),
|
||||
'remote.php': resolve(__dirname, './remote.php'),
|
||||
'status.php': resolve(__dirname, './status.php'),
|
||||
'version.php': resolve(__dirname, './version.php'),
|
||||
} as Record<string, string>
|
||||
|
||||
for (const [key, path] of Object.entries(mounts)) {
|
||||
if (!existsSync(path)) {
|
||||
delete mounts[key]
|
||||
}
|
||||
}
|
||||
|
||||
// Before the browser launches
|
||||
// starting Nextcloud testing container
|
||||
const ip = await startNextcloud(process.env.BRANCH)
|
||||
|
||||
const port = 8042
|
||||
const ip = await startNextcloud(process.env.BRANCH, false, {
|
||||
mounts,
|
||||
exposePort: port,
|
||||
})
|
||||
// Setting container's IP as base Url
|
||||
config.baseUrl = `http://${ip}/index.php`
|
||||
config.baseUrl = `http://localhost:${port}/index.php`
|
||||
// if needed for the setup tests, connect to the actions network
|
||||
await connectToActionsNetwork()
|
||||
// make sure not to write into apps but use a local apps folder
|
||||
runExec(['mkdir', 'apps-cypress'])
|
||||
runExec(['cp', 'cypress/fixtures/app.config.php', 'config'])
|
||||
// now wait until Nextcloud is ready and configure it
|
||||
await waitOnNextcloud(ip)
|
||||
await configureNextcloud()
|
||||
// additionally we do not want to DoS the app store
|
||||
runOcc(['config:system:set', 'appstoreenabled', '--value', 'false', '--type', 'boolean'])
|
||||
|
||||
if (!process.env.CI) {
|
||||
await applyChangesToNextcloud()
|
||||
}
|
||||
// for later use in tests save the container name
|
||||
// @ts-expect-error we are adding a custom property
|
||||
config.dockerContainerName = getContainerName()
|
||||
|
||||
// IMPORTANT: return the config otherwise cypress-split will not work
|
||||
return config
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* Connect the running test container to the GitHub Actions network
|
||||
*/
|
||||
async function connectToActionsNetwork() {
|
||||
if (process.env.SETUP_TESTING !== 'true') {
|
||||
console.log('├─ Not running setup tests, skipping actions network connection 🌐')
|
||||
return
|
||||
}
|
||||
|
||||
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('│ └─ No actions network found ⚠️')
|
||||
return
|
||||
}
|
||||
|
||||
console.log('│ |─ Found actions network: ' + network.Name)
|
||||
await docker.getNetwork(network.Id)
|
||||
.connect({ Container: getContainer().id })
|
||||
console.log('│ └─ Connected to actions network 🌐')
|
||||
}
|
||||
|
||||
32
cypress.d.ts
vendored
32
cypress.d.ts
vendored
@@ -1,32 +0,0 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
/* eslint-disable */
|
||||
import { mount } from '@cypress/vue2'
|
||||
|
||||
type MountParams = Parameters<typeof mount>;
|
||||
type OptionsParam = MountParams[1];
|
||||
|
||||
declare global {
|
||||
namespace Cypress {
|
||||
interface Chainable {
|
||||
mount: typeof mount;
|
||||
/**
|
||||
* Mock an initial state for component testing
|
||||
*
|
||||
* @param app App name of the initial state
|
||||
* @param key Key of the initial state
|
||||
* @param value The mocked value of the initial state
|
||||
*/
|
||||
mockInitialState: (app: string, key: string, value: any) => void
|
||||
/**
|
||||
* Unmock all initial states or one defined by app and key
|
||||
*
|
||||
* @param app app name of the initial state
|
||||
* @param key the key of the initial state
|
||||
*/
|
||||
unmockInitialState: (app?: string, key?: string) => void
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,375 +0,0 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { execSync } from 'child_process'
|
||||
import Docker from 'dockerode'
|
||||
import { existsSync } from 'fs'
|
||||
import path, { basename } from 'path'
|
||||
import { c as createTar } from 'tar'
|
||||
import waitOn from 'wait-on'
|
||||
|
||||
export const docker = new Docker()
|
||||
|
||||
const CONTAINER_NAME = `nextcloud-cypress-tests_${basename(process.cwd()).replace(' ', '')}`
|
||||
const SERVER_IMAGE = 'ghcr.io/nextcloud/continuous-integration-shallow-server'
|
||||
|
||||
/**
|
||||
* Start the testing container
|
||||
*
|
||||
* @param branch the branch of your current work
|
||||
*/
|
||||
export async function startNextcloud(branch: string = getCurrentGitBranch()): Promise<any> {
|
||||
try {
|
||||
try {
|
||||
// Pulling images
|
||||
console.log('\nPulling images... ⏳')
|
||||
await new Promise((resolve, reject): any => docker.pull(SERVER_IMAGE, (err, stream) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
}
|
||||
if (stream === null) {
|
||||
reject(new Error('Could not connect to docker, ensure docker is running.'))
|
||||
return
|
||||
}
|
||||
|
||||
// https://github.com/apocas/dockerode/issues/357
|
||||
docker.modem.followProgress(stream, onFinished)
|
||||
|
||||
/**
|
||||
*
|
||||
* @param err
|
||||
*/
|
||||
function onFinished(err) {
|
||||
if (!err) {
|
||||
resolve(true)
|
||||
return
|
||||
}
|
||||
reject(err)
|
||||
}
|
||||
}))
|
||||
|
||||
const digest = await (await docker.getImage(SERVER_IMAGE).inspect()).RepoDigests.at(0)
|
||||
const sha = digest?.split('@').at(1)
|
||||
console.log('├─ Using image ' + sha)
|
||||
console.log('└─ Done')
|
||||
} catch (e) {
|
||||
console.log('└─ Failed to pull images')
|
||||
throw e
|
||||
}
|
||||
|
||||
// Remove old container if exists
|
||||
console.log('\nChecking running containers... 🔍')
|
||||
try {
|
||||
const oldContainer = docker.getContainer(CONTAINER_NAME)
|
||||
const oldContainerData = await oldContainer.inspect()
|
||||
if (oldContainerData) {
|
||||
console.log('├─ Existing running container found')
|
||||
console.log('├─ Removing... ⏳')
|
||||
// Forcing any remnants to be removed just in case
|
||||
await oldContainer.remove({ force: true })
|
||||
console.log('└─ Done')
|
||||
}
|
||||
} catch {
|
||||
console.log('└─ None found!')
|
||||
}
|
||||
|
||||
// Starting container
|
||||
console.log('\nStarting Nextcloud container... 🚀')
|
||||
console.log(`├─ Using branch '${branch}'`)
|
||||
const container = await docker.createContainer({
|
||||
Image: SERVER_IMAGE,
|
||||
name: CONTAINER_NAME,
|
||||
HostConfig: {
|
||||
Mounts: [{
|
||||
Target: '/var/www/html/data',
|
||||
Source: '',
|
||||
Type: 'tmpfs',
|
||||
ReadOnly: false,
|
||||
}],
|
||||
PortBindings: {
|
||||
'80/tcp': [{
|
||||
HostIP: '0.0.0.0',
|
||||
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}`,
|
||||
'APCU=1',
|
||||
],
|
||||
})
|
||||
await container.start()
|
||||
|
||||
// Set proper permissions for the data folder
|
||||
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')
|
||||
|
||||
// Get container's IP
|
||||
const ip = await getContainerIP(container)
|
||||
|
||||
console.log(`├─ Nextcloud container's IP is ${ip} 🌏`)
|
||||
return ip
|
||||
} catch (err) {
|
||||
console.log('└─ Unable to start the container 🛑')
|
||||
console.log('\n', err, '\n')
|
||||
stopNextcloud()
|
||||
throw new Error('Unable to start the container')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure Nextcloud
|
||||
*/
|
||||
export async function configureNextcloud() {
|
||||
console.log('\nConfiguring nextcloud...')
|
||||
const container = docker.getContainer(CONTAINER_NAME)
|
||||
await runExec(container, ['php', 'occ', '--version'], true)
|
||||
|
||||
// Be consistent for screenshots
|
||||
await runExec(container, ['php', 'occ', 'config:system:set', 'default_language', '--value', 'en'], true)
|
||||
await runExec(container, ['php', 'occ', 'config:system:set', 'force_language', '--value', 'en'], true)
|
||||
await runExec(container, ['php', 'occ', 'config:system:set', 'default_locale', '--value', 'en_US'], true)
|
||||
await runExec(container, ['php', 'occ', 'config:system:set', 'force_locale', '--value', 'en_US'], true)
|
||||
await runExec(container, ['php', 'occ', 'config:system:set', 'enforce_theme', '--value', 'light'], true)
|
||||
|
||||
// Speed up test and make them less flaky. If a cron execution is needed, it can be triggered manually.
|
||||
await runExec(container, ['php', 'occ', 'background:cron'], true)
|
||||
|
||||
// Checking apcu
|
||||
const distributed = await runExec(container, ['php', 'occ', 'config:system:get', 'memcache.distributed'])
|
||||
const local = await runExec(container, ['php', 'occ', 'config:system:get', 'memcache.local'])
|
||||
const hashing = await runExec(container, ['php', 'occ', 'config:system:get', 'hashing_default_password'])
|
||||
|
||||
console.log('├─ Checking APCu configuration... 👀')
|
||||
if (!distributed.trim().includes('Memcache\\APCu')
|
||||
|| !local.trim().includes('Memcache\\APCu')
|
||||
|| !hashing.trim().includes('true')) {
|
||||
console.log('└─ APCu is not properly configured 🛑')
|
||||
throw new Error('APCu is not properly configured')
|
||||
}
|
||||
console.log('│ └─ OK !')
|
||||
|
||||
// Saving DB state
|
||||
console.log('├─ Creating init DB snapshot...')
|
||||
await runExec(container, ['cp', '/var/www/html/data/owncloud.db', '/var/www/html/data/owncloud.db-init'], true)
|
||||
console.log('├─ Creating init data backup...')
|
||||
await runExec(container, ['tar', 'cf', 'data-init.tar', 'admin'], true, undefined, '/var/www/html/data')
|
||||
|
||||
console.log('└─ Nextcloud is now ready to use 🎉')
|
||||
}
|
||||
|
||||
/**
|
||||
* Applying local changes to the container
|
||||
* Only triggered if we're not in CI. Otherwise the
|
||||
* continuous-integration-shallow-server image will
|
||||
* already fetch the proper branch.
|
||||
*/
|
||||
export async function applyChangesToNextcloud() {
|
||||
console.log('\nApply local changes to nextcloud...')
|
||||
|
||||
const htmlPath = '/var/www/html'
|
||||
const folderPaths = [
|
||||
'./3rdparty',
|
||||
'./apps',
|
||||
'./core',
|
||||
'./dist',
|
||||
'./lib',
|
||||
'./ocs',
|
||||
'./ocs-provider',
|
||||
'./resources',
|
||||
'./tests',
|
||||
'./console.php',
|
||||
'./cron.php',
|
||||
'./index.php',
|
||||
'./occ',
|
||||
'./public.php',
|
||||
'./remote.php',
|
||||
'./status.php',
|
||||
'./version.php',
|
||||
].filter((folderPath) => {
|
||||
const fullPath = path.resolve(__dirname, '..', folderPath)
|
||||
|
||||
if (existsSync(fullPath)) {
|
||||
console.log(`├─ Copying ${folderPath}`)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
// Don't try to apply changes, when there are none. Otherwise we
|
||||
// still execute the 'chown' command, which is not needed.
|
||||
if (folderPaths.length === 0) {
|
||||
console.log('└─ No local changes found to apply')
|
||||
return
|
||||
}
|
||||
|
||||
const container = docker.getContainer(CONTAINER_NAME)
|
||||
|
||||
// Tar-streaming the above folders into the container
|
||||
const serverTar = createTar({ gzip: false }, folderPaths)
|
||||
await container.putArchive(serverTar, {
|
||||
path: htmlPath,
|
||||
})
|
||||
|
||||
// Making sure we have the proper permissions
|
||||
await runExec(container, ['chown', '-R', 'www-data:www-data', htmlPath], false, 'root')
|
||||
|
||||
console.log('└─ Changes applied successfully 🎉')
|
||||
}
|
||||
|
||||
/**
|
||||
* Force stop the testing container
|
||||
*/
|
||||
export async function stopNextcloud() {
|
||||
try {
|
||||
const container = docker.getContainer(CONTAINER_NAME)
|
||||
console.log('Stopping Nextcloud container...')
|
||||
container.remove({ force: true })
|
||||
console.log('└─ Nextcloud container removed 🥀')
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the testing container's IP
|
||||
*
|
||||
* @param container the container to get the IP from
|
||||
*/
|
||||
export async function getContainerIP(container = docker.getContainer(CONTAINER_NAME)): Promise<string> {
|
||||
let ip = ''
|
||||
let tries = 0
|
||||
while (ip === '' && tries < 10) {
|
||||
tries++
|
||||
|
||||
container.inspect(function(err, data) {
|
||||
if (err) {
|
||||
throw err
|
||||
}
|
||||
|
||||
if (data?.HostConfig.PortBindings?.['80/tcp']?.[0]?.HostPort) {
|
||||
ip = `localhost:${data.HostConfig.PortBindings['80/tcp'][0].HostPort}`
|
||||
} else {
|
||||
ip = data?.NetworkSettings?.IPAddress || ''
|
||||
}
|
||||
})
|
||||
|
||||
if (ip !== '') {
|
||||
break
|
||||
}
|
||||
|
||||
await sleep(1000 * tries)
|
||||
}
|
||||
|
||||
return ip
|
||||
}
|
||||
|
||||
// Would be simpler to start the container from cypress.config.ts,
|
||||
// but when checking out different branches, it can take a few seconds
|
||||
// Until we can properly configure the baseUrl retry intervals,
|
||||
// We need to make sure the server is already running before cypress
|
||||
// https://github.com/cypress-io/cypress/issues/22676
|
||||
/**
|
||||
*
|
||||
* @param ip
|
||||
*/
|
||||
export async function waitOnNextcloud(ip: string) {
|
||||
console.log('├─ Waiting for Nextcloud to be ready... ⏳')
|
||||
await waitOn({
|
||||
resources: [`http://${ip}/index.php`],
|
||||
// wait for nextcloud to be up and return any non error status
|
||||
validateStatus: (status) => status >= 200 && status < 400,
|
||||
// timout in ms
|
||||
timeout: 5 * 60 * 1000,
|
||||
// timeout for a single HTTP request
|
||||
httpTimeout: 60 * 1000,
|
||||
})
|
||||
console.log('└─ Done')
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param container
|
||||
* @param command
|
||||
* @param verbose
|
||||
* @param user
|
||||
* @param workdir
|
||||
*/
|
||||
async function runExec(
|
||||
container: Docker.Container,
|
||||
command: string[],
|
||||
verbose = false,
|
||||
user = 'www-data',
|
||||
workdir?: string,
|
||||
): Promise<string> {
|
||||
const exec = await container.exec({
|
||||
Cmd: command,
|
||||
WorkingDir: workdir,
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
User: user,
|
||||
})
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let output = ''
|
||||
exec.start({}, (err, stream) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
}
|
||||
if (stream) {
|
||||
stream.setEncoding('utf-8')
|
||||
stream.on('data', (str) => {
|
||||
str = str.trim()
|
||||
// Remove non printable characters
|
||||
// eslint-disable-next-line no-control-regex
|
||||
.replace(/[^\x0A\x0D\x20-\x7E]+/g, '')
|
||||
// Remove non alphanumeric leading characters
|
||||
.replace(/^[^a-z]/gi, '')
|
||||
output += str
|
||||
if (verbose && str !== '') {
|
||||
console.log(`├─ ${str.replace(/\n/gi, '\n├─ ')}`)
|
||||
}
|
||||
})
|
||||
stream.on('end', () => resolve(output))
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param milliseconds
|
||||
*/
|
||||
function sleep(milliseconds: number) {
|
||||
return new Promise((resolve) => setTimeout(resolve, milliseconds))
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function getCurrentGitBranch() {
|
||||
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
|
||||
*/
|
||||
async function getGithubNetwork(): 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
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { User } from '@nextcloud/cypress'
|
||||
import { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
import { clearState, getNextcloudUserMenu, getNextcloudUserMenuToggle } from '../../support/commonUtils.ts'
|
||||
|
||||
const admin = new User('admin', 'admin')
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { User } from '@nextcloud/cypress'
|
||||
import randomString from 'crypto-random-string'
|
||||
import { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
import { clearState, getNextcloudHeader } from '../../support/commonUtils.ts'
|
||||
import { randomString } from '../../support/utils/randomString.ts'
|
||||
|
||||
const admin = new User('admin', 'admin')
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { randomString } from '../../support/utils/randomString.ts'
|
||||
|
||||
/**
|
||||
* DO NOT RENAME THIS FILE to .cy.ts ⚠️
|
||||
* This is not following the pattern of the other files in this folder
|
||||
@@ -110,7 +112,7 @@ describe('Can install Nextcloud', { testIsolation: true, retries: 0 }, () => {
|
||||
* Shared admin setup function for the Nextcloud setup
|
||||
*/
|
||||
function sharedSetup() {
|
||||
const randAdmin = 'admin-' + Math.random().toString(36).substring(2, 15)
|
||||
const randAdmin = 'admin-' + randomString(10)
|
||||
|
||||
// mock appstore
|
||||
cy.intercept('**/settings/apps/list', { fixture: 'appstore/apps.json' })
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { ACTION_COPY_MOVE } from '../../../apps/files/src/actions/moveOrCopyAction.ts'
|
||||
const ACTION_COPY_MOVE = 'move-copy'
|
||||
|
||||
export const getRowForFileId = (fileid: number) => cy.get(`[data-cy-files-list-row-fileid="${fileid}"]`)
|
||||
export const getRowForFile = (filename: string) => cy.get(`[data-cy-files-list-row-name="${CSS.escape(filename)}"]`)
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { randomString } from '../../support/utils/randomString.ts'
|
||||
|
||||
type SetupInfo = {
|
||||
snapshot: string
|
||||
@@ -72,7 +74,7 @@ export function setupLivePhotos(): Cypress.Chainable<SetupInfo> {
|
||||
} else {
|
||||
let requesttoken: string
|
||||
|
||||
setupInfo.fileName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10)
|
||||
setupInfo.fileName = randomString(10)
|
||||
|
||||
cy.createRandomUser().then((_user) => {
|
||||
setupInfo.user = _user
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { getActionButtonForFile, getRowForFile, triggerActionForFile } from './FilesUtils.ts'
|
||||
|
||||
|
||||
@@ -3,14 +3,15 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { FileAction } from '@nextcloud/files'
|
||||
import { ACTION_DELETE } from '../../../apps/files/src/actions/deleteAction.ts'
|
||||
import { ACTION_COPY_MOVE } from '../../../apps/files/src/actions/moveOrCopyAction.ts'
|
||||
import { ACTION_DETAILS } from '../../../apps/files/src/actions/sidebarAction.ts'
|
||||
import { getActionButtonForFileId, getActionEntryForFileId, getRowForFile, getSelectionActionButton, getSelectionActionEntry, selectRowForFile } from './FilesUtils.ts'
|
||||
|
||||
const ACTION_DELETE = 'delete'
|
||||
const ACTION_COPY_MOVE = 'move-copy'
|
||||
const ACTION_DETAILS = 'details'
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
_nc_fileactions: FileAction[]
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { getRowForFile, navigateToFolder, selectAllFiles, triggerActionForFile } from './FilesUtils.ts'
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import randomString from 'crypto-random-string'
|
||||
import { deleteDownloadsFolderBeforeEach } from 'cypress-delete-downloads-folder'
|
||||
import { zipFileContains } from '../../support/utils/assertions.ts'
|
||||
import { randomString } from '../../support/utils/randomString.ts'
|
||||
import { getRowForFile, navigateToFolder, triggerActionForFile } from './FilesUtils.ts'
|
||||
|
||||
describe('files: Download files using file actions', { testIsolation: true }, () => {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { FilesFilterPage } from '../../pages/FilesFilters.ts'
|
||||
import { FilesNavigationPage } from '../../pages/FilesNavigation.ts'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { getRowForFile, navigateToFolder } from './FilesUtils.ts'
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { calculateViewportHeight, createFolder, getRowForFile, haveValidity, renameFile, triggerActionForFile } from './FilesUtils.ts'
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { deselectAllFiles, selectAllFiles, selectRowForFile } from './FilesUtils.ts'
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { getRowForFile } from './FilesUtils.ts'
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { assertNotExistOrNotVisible } from '../settings/usersUtils.ts'
|
||||
import { getRowForFile, navigateToFolder, triggerActionForFile } from './FilesUtils.ts'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import {
|
||||
clickOnBreadcrumbs,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { getRowForFile, triggerActionForFile } from './FilesUtils.ts'
|
||||
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { join } from 'path'
|
||||
import { joinPaths as join } from '@nextcloud/paths'
|
||||
import { getRowForFileId } from './FilesUtils.ts'
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { FilesNavigationPage } from '../../pages/FilesNavigation.ts'
|
||||
import { getRowForFile, navigateToFolder } from './FilesUtils.ts'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
export type StorageConfig = {
|
||||
[key: string]: string
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { getRowForFile } from '../files/FilesUtils.ts'
|
||||
import { AuthBackend, createStorageWithConfig, StorageBackend } from './StorageUtils.ts'
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { ACTION_CREDENTIALS_EXTERNAL_STORAGE } from '../../../apps/files_external/src/actions/enterCredentialsAction.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'
|
||||
|
||||
describe('Files user credentials', { testIsolation: true }, () => {
|
||||
let user1: User
|
||||
let user2: User
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { AuthBackend, createStorageWithConfig, deleteAllExternalStorages, setStorageMountOptions, StorageBackend } from './StorageUtils.ts'
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { closeSidebar } from '../files/FilesUtils.ts'
|
||||
import { createShare, openSharingDetails, openSharingPanel, updateShare } from './FilesSharingUtils.ts'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { createFolder, getRowForFile, navigateToFolder } from '../files/FilesUtils.ts'
|
||||
import { createFileRequest } from './FilesSharingUtils.ts'
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
|
||||
import { ACTION_COPY_MOVE } from '../../../apps/files/src/actions/moveOrCopyAction.ts'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import {
|
||||
copyFile,
|
||||
getRowForFile,
|
||||
@@ -13,6 +13,8 @@ import {
|
||||
} from '../files/FilesUtils.ts'
|
||||
import { createShare } from './FilesSharingUtils.ts'
|
||||
|
||||
const ACTION_COPY_MOVE = 'move-copy'
|
||||
|
||||
export function copyFileForbidden(fileName: string, dirPath: string) {
|
||||
getRowForFile(fileName).should('be.visible')
|
||||
triggerActionForFile(fileName, ACTION_COPY_MOVE)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import {
|
||||
getActionButtonForFile,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { getRowForFile } from '../files/FilesUtils.ts'
|
||||
import { createShare } from './FilesSharingUtils.ts'
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { randomString } from '../../support/utils/randomString.ts'
|
||||
import { createShare } from './FilesSharingUtils.ts'
|
||||
|
||||
describe('Limit to sharing to people in the same group', () => {
|
||||
@@ -17,11 +18,11 @@ describe('Limit to sharing to people in the same group', () => {
|
||||
let randomGroupName3 = ''
|
||||
|
||||
before(() => {
|
||||
randomFileName1 = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + '.txt'
|
||||
randomFileName2 = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + '.txt'
|
||||
randomGroupName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10)
|
||||
randomGroupName2 = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10)
|
||||
randomGroupName3 = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10)
|
||||
randomFileName1 = randomString(10) + '.txt'
|
||||
randomFileName2 = randomString(10) + '.txt'
|
||||
randomGroupName = randomString(10)
|
||||
randomGroupName2 = randomString(10)
|
||||
randomGroupName3 = randomString(10)
|
||||
|
||||
cy.runOccCommand('config:app:set core shareapi_only_share_with_group_members --value yes')
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { navigateToFolder } from '../files/FilesUtils.ts'
|
||||
import { createShare, openSharingPanel } from './FilesSharingUtils.ts'
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
import type { ShareOptions } from '../ShareOptionsType.ts'
|
||||
|
||||
import { openSharingPanel } from '../FilesSharingUtils.ts'
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { getRowForFile } from '../../files/FilesUtils.ts'
|
||||
import { createLinkShare, setupData } from './PublicShareUtils.ts'
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
|
||||
/*!
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
import type { ShareContext } from './PublicShareUtils.ts'
|
||||
|
||||
// @ts-expect-error The package is currently broken - but works...
|
||||
import { deleteDownloadsFolderBeforeEach } from 'cypress-delete-downloads-folder'
|
||||
import { zipFileContains } from '../../../support/utils/assertions.ts'
|
||||
import { getRowForFile, getRowForFileId, triggerActionForFile, triggerActionForFileId } from '../../files/FilesUtils.ts'
|
||||
import {
|
||||
type ShareContext,
|
||||
|
||||
createLinkShare, getShareUrl, openLinkShareDetails, setupPublicShare,
|
||||
} from './PublicShareUtils.ts'
|
||||
import { createLinkShare, getShareUrl, openLinkShareDetails, setupPublicShare } from './PublicShareUtils.ts'
|
||||
|
||||
describe('files_sharing: Public share - downloading files', { testIsolation: true }, () => {
|
||||
// in general there is no difference except downloading
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { createLinkShare, openLinkShareDetails } from './PublicShareUtils.ts'
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { closeSidebar, enableGridMode, getActionButtonForFile, getInlineActionEntryForFile, getRowForFile } from '../files/FilesUtils.ts'
|
||||
import { createShare } from './FilesSharingUtils.ts'
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { deleteFileWithRequest, triggerFileListAction } from '../files/FilesUtils.ts'
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
// @ts-expect-error package has wrong typings
|
||||
import { deleteDownloadsFolderBeforeEach } from 'cypress-delete-downloads-folder'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
import type { ShareSetting } from '../files_sharing/FilesSharingUtils.ts'
|
||||
|
||||
import { createShare } from '../files_sharing/FilesSharingUtils.ts'
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { randomString } from '../../support/utils/randomString.ts'
|
||||
import { openVersionsPanel, uploadThreeVersions } from './filesVersionsUtils.ts'
|
||||
|
||||
describe('Versions creation', () => {
|
||||
let randomFileName = ''
|
||||
|
||||
before(() => {
|
||||
randomFileName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + '.txt'
|
||||
randomFileName = randomString(10) + '.txt'
|
||||
|
||||
cy.createRandomUser()
|
||||
.then((user) => {
|
||||
|
||||
@@ -3,32 +3,12 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { randomString } from '../../support/utils/randomString.ts'
|
||||
import { clickOnBreadcrumbs, closeSidebar, copyFile, moveFile, navigateToFolder } from '../files/FilesUtils.ts'
|
||||
import { assertVersionContent, nameVersion, openVersionsPanel, setupTestSharedFileFromUser, uploadThreeVersions } from './filesVersionsUtils.ts'
|
||||
|
||||
/**
|
||||
*
|
||||
* @param filePath
|
||||
*/
|
||||
function assertVersionsContent(filePath: string) {
|
||||
const path = filePath.split('/').slice(0, -1).join('/')
|
||||
|
||||
clickOnBreadcrumbs('All files')
|
||||
|
||||
if (path !== '') {
|
||||
navigateToFolder(path)
|
||||
}
|
||||
|
||||
openVersionsPanel(filePath)
|
||||
|
||||
cy.get('[data-files-versions-version]').should('have.length', 3)
|
||||
assertVersionContent(0, 'v3')
|
||||
assertVersionContent(1, 'v2')
|
||||
assertVersionContent(2, 'v1')
|
||||
}
|
||||
|
||||
describe('Versions cross share move and copy', () => {
|
||||
let randomSharedFolderName = ''
|
||||
let randomFileName = ''
|
||||
@@ -37,7 +17,7 @@ describe('Versions cross share move and copy', () => {
|
||||
let bob: User
|
||||
|
||||
before(() => {
|
||||
randomSharedFolderName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10)
|
||||
randomSharedFolderName = randomString(10)
|
||||
|
||||
cy.createRandomUser()
|
||||
.then((user) => {
|
||||
@@ -49,7 +29,7 @@ describe('Versions cross share move and copy', () => {
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
randomFileName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + '.txt'
|
||||
randomFileName = randomString(10) + '.txt'
|
||||
randomFilePath = `${randomSharedFolderName}/${randomFileName}`
|
||||
uploadThreeVersions(alice, randomFilePath)
|
||||
|
||||
@@ -78,8 +58,8 @@ describe('Versions cross share move and copy', () => {
|
||||
let randomSubSubFolderName
|
||||
|
||||
beforeEach(() => {
|
||||
randomSubFolderName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10)
|
||||
randomSubSubFolderName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10)
|
||||
randomSubFolderName = randomString(10)
|
||||
randomSubSubFolderName = randomString(10)
|
||||
clickOnBreadcrumbs('All files')
|
||||
cy.mkdir(bob, `/${randomSharedFolderName}/${randomSubFolderName}`)
|
||||
cy.mkdir(bob, `/${randomSharedFolderName}/${randomSubFolderName}/${randomSubSubFolderName}`)
|
||||
@@ -101,3 +81,23 @@ describe('Versions cross share move and copy', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* @param filePath
|
||||
*/
|
||||
function assertVersionsContent(filePath: string) {
|
||||
const path = filePath.split('/').slice(0, -1).join('/')
|
||||
|
||||
clickOnBreadcrumbs('All files')
|
||||
|
||||
if (path !== '') {
|
||||
navigateToFolder(path)
|
||||
}
|
||||
|
||||
openVersionsPanel(filePath)
|
||||
|
||||
cy.get('[data-files-versions-version]').should('have.length', 3)
|
||||
assertVersionContent(0, 'v3')
|
||||
assertVersionContent(1, 'v2')
|
||||
assertVersionContent(2, 'v1')
|
||||
}
|
||||
|
||||
@@ -3,14 +3,15 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { randomString } from '../../support/utils/randomString.ts'
|
||||
import { getRowForFile, navigateToFolder } from '../files/FilesUtils.ts'
|
||||
import { deleteVersion, doesNotHaveAction, openVersionsPanel, setupTestSharedFileFromUser, uploadThreeVersions } from './filesVersionsUtils.ts'
|
||||
|
||||
describe('Versions restoration', () => {
|
||||
const folderName = 'shared_folder'
|
||||
const randomFileName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + '.txt'
|
||||
const randomFileName = randomString(10) + '.txt'
|
||||
const randomFilePath = `/${folderName}/${randomFileName}`
|
||||
let user: User
|
||||
let versionCount = 0
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { randomString } from '../../support/utils/randomString.ts'
|
||||
import { getRowForFile } from '../files/FilesUtils.ts'
|
||||
import { assertVersionContent, doesNotHaveAction, openVersionsPanel, setupTestSharedFileFromUser, uploadThreeVersions } from './filesVersionsUtils.ts'
|
||||
|
||||
@@ -13,7 +14,7 @@ describe('Versions download', () => {
|
||||
let user: User
|
||||
|
||||
before(() => {
|
||||
randomFileName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + '.txt'
|
||||
randomFileName = randomString(10) + '.txt'
|
||||
|
||||
cy.runOccCommand('config:app:set --value no core shareapi_allow_view_without_download')
|
||||
cy.createRandomUser()
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { randomString } from '../../support/utils/randomString.ts'
|
||||
import { assertVersionContent, nameVersion, openVersionsPanel, uploadThreeVersions } from './filesVersionsUtils.ts'
|
||||
|
||||
describe('Versions expiration', () => {
|
||||
let randomFileName = ''
|
||||
|
||||
beforeEach(() => {
|
||||
randomFileName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + '.txt'
|
||||
randomFileName = randomString(10) + '.txt'
|
||||
|
||||
cy.createRandomUser()
|
||||
.then((user) => {
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { randomString } from '../../support/utils/randomString.ts'
|
||||
import { getRowForFile } from '../files/FilesUtils.ts'
|
||||
import { doesNotHaveAction, nameVersion, openVersionsPanel, setupTestSharedFileFromUser, uploadThreeVersions } from './filesVersionsUtils.ts'
|
||||
|
||||
@@ -13,7 +14,7 @@ describe('Versions naming', () => {
|
||||
let user: User
|
||||
|
||||
before(() => {
|
||||
randomFileName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + '.txt'
|
||||
randomFileName = randomString(10) + '.txt'
|
||||
|
||||
cy.createRandomUser()
|
||||
.then((_user) => {
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { randomString } from '../../support/utils/randomString.ts'
|
||||
import { getRowForFile } from '../files/FilesUtils.ts'
|
||||
import { assertVersionContent, doesNotHaveAction, openVersionsPanel, restoreVersion, setupTestSharedFileFromUser, uploadThreeVersions } from './filesVersionsUtils.ts'
|
||||
|
||||
@@ -13,7 +14,7 @@ describe('Versions restoration', () => {
|
||||
let user: User
|
||||
|
||||
before(() => {
|
||||
randomFileName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + '.txt'
|
||||
randomFileName = randomString(10) + '.txt'
|
||||
|
||||
cy.createRandomUser()
|
||||
.then((_user) => {
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { randomString } from '../../support/utils/randomString.ts'
|
||||
import { navigateToFolder, triggerActionForFile } from '../files/FilesUtils.ts'
|
||||
import { setupTestSharedFileFromUser, uploadThreeVersions } from './filesVersionsUtils.ts'
|
||||
|
||||
describe('Versions on shares', () => {
|
||||
const randomSharedFolderName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10)
|
||||
const randomFileName = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 10) + '.txt'
|
||||
const randomSharedFolderName = randomString(10)
|
||||
const randomFileName = randomString(10) + '.txt'
|
||||
const randomFilePath = `${randomSharedFolderName}/${randomFileName}`
|
||||
let alice: User
|
||||
let bob: User
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { getNextcloudUserMenu, getNextcloudUserMenuToggle } from '../../support/commonUtils.ts'
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
interface IChromeVirtualAuthenticator {
|
||||
authenticatorId: string
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { User } from '@nextcloud/cypress'
|
||||
import { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
import { clearState, getNextcloudUserMenu, getNextcloudUserMenuToggle } from '../../support/commonUtils.ts'
|
||||
|
||||
const admin = new User('admin', 'admin')
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { User } from '@nextcloud/cypress'
|
||||
import { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
import { handlePasswordConfirmation } from './usersUtils.ts'
|
||||
|
||||
const admin = new User('admin', 'admin')
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { handlePasswordConfirmation } from './usersUtils.ts'
|
||||
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
/// <reference types="cypress-if" />
|
||||
|
||||
import { User } from '@nextcloud/cypress'
|
||||
import randomString from 'crypto-random-string'
|
||||
import { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
import { randomString } from '../../support/utils/randomString.ts'
|
||||
import { getUserListRow, handlePasswordConfirmation } from './usersUtils.ts'
|
||||
|
||||
const admin = new User('admin', 'admin')
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
/// <reference types="cypress-if" />
|
||||
|
||||
import { User } from '@nextcloud/cypress'
|
||||
import { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
import { getUserListRow, handlePasswordConfirmation } from './usersUtils.ts'
|
||||
|
||||
const admin = new User('admin', 'admin')
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
/**
|
||||
* Assert that `element` does not exist or is not visible
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { User } from '@nextcloud/cypress'
|
||||
import { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
import { assertNotExistOrNotVisible, getUserList } from './usersUtils.js'
|
||||
|
||||
const admin = new User('admin', 'admin')
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { User } from '@nextcloud/cypress'
|
||||
import { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
import { clearState } from '../../support/commonUtils.ts'
|
||||
import { getUserListRow } from './usersUtils.ts'
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { User } from '@nextcloud/cypress'
|
||||
import randomString from 'crypto-random-string'
|
||||
import { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
import { randomString } from '../../support/utils/randomString.ts'
|
||||
import { assertNotExistOrNotVisible, getUserListRow, handlePasswordConfirmation, toggleEditButton } from './usersUtils.ts'
|
||||
|
||||
const admin = new User('admin', 'admin')
|
||||
@@ -16,6 +16,8 @@ describe('Settings: Create groups', () => {
|
||||
})
|
||||
|
||||
it('Can create a group', () => {
|
||||
cy.intercept('POST', '**/ocs/v2.php/cloud/groups').as('createGroups')
|
||||
|
||||
const groupName = randomString(7)
|
||||
// open the Create group menu
|
||||
cy.get('button[aria-label="Create group"]').click()
|
||||
@@ -33,6 +35,7 @@ describe('Settings: Create groups', () => {
|
||||
|
||||
// Make sure no confirmation modal is shown
|
||||
handlePasswordConfirmation(admin.password)
|
||||
cy.wait('@createGroups').its('response.statusCode').should('eq', 200)
|
||||
|
||||
// see that the created group is in the list
|
||||
cy.get('ul[data-cy-users-settings-navigation-groups="custom"]').within(() => {
|
||||
@@ -108,7 +111,7 @@ describe('Settings: Assign user to a group', { testIsolation: false }, () => {
|
||||
|
||||
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(output.exitCode).should('eq', 0)
|
||||
cy.wrap(JSON.parse(output.stdout)?.groups).should('include', groupName)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { User } from '@nextcloud/cypress'
|
||||
import { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
import { clearState } from '../../support/commonUtils.ts'
|
||||
import { getUserListRow, handlePasswordConfirmation, toggleEditButton, waitLoading } from './usersUtils.ts'
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { User } from '@nextcloud/cypress'
|
||||
import { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
import { clearState } from '../../support/commonUtils.ts'
|
||||
import { getUserListRow, handlePasswordConfirmation, toggleEditButton, waitLoading } from './usersUtils.ts'
|
||||
|
||||
@@ -140,7 +140,7 @@ describe('Settings: Change user properties', function() {
|
||||
|
||||
// I see that the quota was set on the backend
|
||||
cy.runOccCommand(`user:info --output=json '${user.userId}'`).then(($result) => {
|
||||
expect($result.code).to.equal(0)
|
||||
expect($result.exitCode).to.equal(0)
|
||||
const info = JSON.parse($result.stdout)
|
||||
expect(info?.quota).to.equal('5 GB')
|
||||
})
|
||||
@@ -176,7 +176,7 @@ describe('Settings: Change user properties', function() {
|
||||
|
||||
// I see that the quota was set on the backend
|
||||
cy.runOccCommand(`user:info --output=json '${user.userId}'`).then(($result) => {
|
||||
expect($result.code).to.equal(0)
|
||||
expect($result.exitCode).to.equal(0)
|
||||
// TODO: Enable this after the file size handling is fixed!!!!!!
|
||||
// const info = JSON.parse($result.stdout)
|
||||
// expect(info?.quota).to.equal('4 MB')
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { User } from '@nextcloud/cypress'
|
||||
import { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
const admin = new User('admin', 'admin')
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { randomBytes } from 'crypto'
|
||||
import { getRowForFile, selectAllFiles, selectRowForFile, triggerSelectionAction } from '../files/FilesUtils.ts'
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { randomBytes } from 'crypto'
|
||||
import { closeSidebar, getRowForFile, triggerActionForFile } from '../files/FilesUtils.ts'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { randomBytes } from 'crypto'
|
||||
import { getRowForFile, triggerActionForFile } from '../files/FilesUtils.ts'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { randomBytes } from 'crypto'
|
||||
import { closeSidebar, getRowForFile, getRowForFileId, triggerActionForFile } from '../files/FilesUtils.ts'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { User } from '@nextcloud/cypress'
|
||||
import { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
import { NavigationHeader } from '../../pages/NavigationHeader.ts'
|
||||
import {
|
||||
defaultBackground,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { User } from '@nextcloud/cypress'
|
||||
import { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
import { NavigationHeader } from '../../pages/NavigationHeader.ts'
|
||||
|
||||
const admin = new User('admin', 'admin')
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
import { User } from '@nextcloud/cypress'
|
||||
import { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
const admin = new User('admin', 'admin')
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import type { User } from '@nextcloud/cypress'
|
||||
import type { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
|
||||
import { NavigationHeader } from '../../pages/NavigationHeader.ts'
|
||||
import { installTestApp, uninstallTestApp } from '../../support/commonUtils.ts'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { User } from '@nextcloud/cypress'
|
||||
import { User } from '@nextcloud/e2e-test-server/cypress'
|
||||
import { NavigationHeader } from '../../pages/NavigationHeader.ts'
|
||||
import { defaultBackground, defaultPrimary, validateBodyThemingCss } from './themingUtils.ts'
|
||||
|
||||
|
||||
20
cypress/fixtures/app.config.php
Normal file
20
cypress/fixtures/app.config.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
$CONFIG = [
|
||||
'apps_paths' => [
|
||||
[
|
||||
'path' => '/var/www/html/apps',
|
||||
'url' => '/apps',
|
||||
'writable' => false,
|
||||
],
|
||||
[
|
||||
'path' => '/var/www/html/apps-cypress',
|
||||
'url' => '/apps-cypress',
|
||||
'writable' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
@@ -3,9 +3,9 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { addCommands, User } from '@nextcloud/cypress'
|
||||
import { addCommands, User } from '@nextcloud/e2e-test-server/cypress'
|
||||
import { basename } from '@nextcloud/paths'
|
||||
import axios from 'axios'
|
||||
import { basename } from 'path'
|
||||
|
||||
// Add custom commands
|
||||
import '@testing-library/cypress/add-commands'
|
||||
@@ -18,7 +18,7 @@ Cypress.env('baseUrl', url)
|
||||
|
||||
/**
|
||||
* Enable or disable a user
|
||||
* TODO: standardize in @nextcloud/cypress
|
||||
* TODO: standardize in @nextcloud/e2e-test-server
|
||||
*
|
||||
* @param {User} user the user to dis- / enable
|
||||
* @param {boolean} enable True if the user should be enable, false to disable
|
||||
@@ -45,7 +45,7 @@ Cypress.Commands.add('enableUser', (user: User, enable = true) => {
|
||||
|
||||
/**
|
||||
* cy.uploadedFile - uploads a file from the fixtures folder
|
||||
* TODO: standardize in @nextcloud/cypress
|
||||
* TODO: standardize in @nextcloud/e2e-test-server
|
||||
*
|
||||
* @param {User} user the owner of the file, e.g. admin
|
||||
* @param {string} fixture the fixture file name, e.g. image1.jpg
|
||||
@@ -142,7 +142,7 @@ Cypress.Commands.add('rm', (user: User, target: string) => {
|
||||
|
||||
/**
|
||||
* cy.uploadedContent - uploads a raw content
|
||||
* TODO: standardize in @nextcloud/cypress
|
||||
* TODO: standardize in @nextcloud/e2e-test-server
|
||||
*
|
||||
* @param {User} user the owner of the file, e.g. admin
|
||||
* @param {Blob} blob the content to upload
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { basename } from 'path'
|
||||
|
||||
/**
|
||||
* Get the header navigation bar
|
||||
*/
|
||||
@@ -49,14 +47,14 @@ export function clearState() {
|
||||
export function installTestApp() {
|
||||
const testAppPath = 'cypress/fixtures/testapp'
|
||||
cy.runOccCommand('-V').then((output) => {
|
||||
// @ts-expect-error we added this property in cypress.config.ts
|
||||
const containerName = Cypress.config('dockerContainerName')
|
||||
const version = output.stdout.match(/(\d\d+)\.\d+\.\d+/)?.[1]
|
||||
cy.wrap(version).should('not.be.undefined')
|
||||
getContainerName()
|
||||
.then((containerName) => {
|
||||
cy.exec(`docker cp '${testAppPath}' ${containerName}:/var/www/html/apps`, { log: true })
|
||||
cy.exec(`docker exec --workdir /var/www/html ${containerName} chown -R www-data:www-data /var/www/html/apps/testapp`)
|
||||
})
|
||||
cy.runCommand(`sed -i -e 's|-version=\\"[0-9]\\+|-version=\\"${version}|g' apps/testapp/appinfo/info.xml`)
|
||||
|
||||
cy.exec(`docker cp '${testAppPath}' ${containerName}:/var/www/html/apps-cypress`, { log: true })
|
||||
cy.exec(`docker exec --workdir /var/www/html ${containerName} chown -R www-data:www-data /var/www/html/apps-cypress/testapp`)
|
||||
cy.runCommand(`sed -i -e 's|-version=\\"[0-9]\\+|-version=\\"${version}|g' apps-cypress/testapp/appinfo/info.xml`)
|
||||
cy.runOccCommand('app:enable --force testapp')
|
||||
})
|
||||
}
|
||||
@@ -66,15 +64,5 @@ export function installTestApp() {
|
||||
*/
|
||||
export function uninstallTestApp() {
|
||||
cy.runOccCommand('app:remove testapp', { failOnNonZeroExit: false })
|
||||
cy.runCommand('rm -fr apps/testapp/appinfo/info.xml')
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export function getContainerName(): Cypress.Chainable<string> {
|
||||
return cy.exec('pwd')
|
||||
.then(({ stdout }) => {
|
||||
return cy.wrap(`nextcloud-cypress-tests_${basename(stdout).replace(' ', '')}`)
|
||||
})
|
||||
cy.runCommand('rm -fr apps-cypress/testapp')
|
||||
}
|
||||
|
||||
19
cypress/support/utils/randomString.ts
Normal file
19
cypress/support/utils/randomString.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
/*!
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
export function randomString(length: number) {
|
||||
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
|
||||
const alphaNumeric = characters + '0123456789'
|
||||
let result = ''
|
||||
for (let i = 0; i < length; i++) {
|
||||
// Ensure the first character is alphabetic
|
||||
if (i === 0) {
|
||||
result += characters.charAt(Math.floor(Math.random() * characters.length))
|
||||
continue
|
||||
}
|
||||
result += alphaNumeric.charAt(Math.floor(Math.random() * alphaNumeric.length))
|
||||
}
|
||||
return result
|
||||
}
|
||||
547
package-lock.json
generated
547
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
11
package.json
11
package.json
@@ -126,9 +126,8 @@
|
||||
"@babel/plugin-transform-private-methods": "^7.27.1",
|
||||
"@babel/preset-typescript": "^7.27.1",
|
||||
"@codecov/webpack-plugin": "^1.9.1",
|
||||
"@cypress/webpack-preprocessor": "^7.0.0",
|
||||
"@nextcloud/babel-config": "^1.2.0",
|
||||
"@nextcloud/cypress": "^1.0.0-beta.15",
|
||||
"@nextcloud/e2e-test-server": "^0.4.0",
|
||||
"@nextcloud/eslint-config": "^9.0.0-rc.5",
|
||||
"@nextcloud/stylelint-config": "^3.1.0",
|
||||
"@nextcloud/typings": "^1.9.1",
|
||||
@@ -149,15 +148,16 @@
|
||||
"babel-plugin-module-resolver": "^5.0.2",
|
||||
"browserslist": "^4.26.3",
|
||||
"colord": "^2.9.3",
|
||||
"cypress": "^13.17.0",
|
||||
"cypress": "^15.5.0",
|
||||
"cypress-axe": "^1.7.0",
|
||||
"cypress-delete-downloads-folder": "^0.0.6",
|
||||
"cypress-if": "^1.13.2",
|
||||
"cypress-split": "^1.24.24",
|
||||
"cypress-split": "^1.24.25",
|
||||
"cypress-vite": "^1.8.0",
|
||||
"cypress-wait-until": "^3.0.2",
|
||||
"dockerode": "^4.0.9",
|
||||
"eslint": "^9.36.0",
|
||||
"eslint-plugin-cypress": "^5.1.1",
|
||||
"eslint-plugin-cypress": "^5.2.0",
|
||||
"eslint-plugin-no-only-tests": "^3.3.0",
|
||||
"exports-loader": "^5.0.0",
|
||||
"file-loader": "^6.2.0",
|
||||
@@ -171,7 +171,6 @@
|
||||
"sass": "^1.93.2",
|
||||
"stylelint": "^16.24.0",
|
||||
"stylelint-use-logical": "^2.1.2",
|
||||
"tar": "^7.5.1",
|
||||
"ts-node": "^10.9.2",
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.9.2",
|
||||
|
||||
Reference in New Issue
Block a user