aboutsummaryrefslogtreecommitdiffstats
path: root/cypress/support/commands.ts
diff options
context:
space:
mode:
Diffstat (limited to 'cypress/support/commands.ts')
-rw-r--r--cypress/support/commands.ts248
1 files changed, 248 insertions, 0 deletions
diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts
new file mode 100644
index 00000000000..ad486a8a8f7
--- /dev/null
+++ b/cypress/support/commands.ts
@@ -0,0 +1,248 @@
+/**
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+// eslint-disable-next-line n/no-extraneous-import
+import axios from 'axios'
+import { addCommands, User } from '@nextcloud/cypress'
+import { basename } from 'path'
+
+// Add custom commands
+import '@testing-library/cypress/add-commands'
+import 'cypress-if'
+import 'cypress-wait-until'
+addCommands()
+
+const url = (Cypress.config('baseUrl') || '').replace(/\/index.php\/?$/g, '')
+Cypress.env('baseUrl', url)
+
+/**
+ * Enable or disable a user
+ * TODO: standardize in @nextcloud/cypress
+ *
+ * @param {User} user the user to dis- / enable
+ * @param {boolean} enable True if the user should be enable, false to disable
+ */
+Cypress.Commands.add('enableUser', (user: User, enable = true) => {
+ const url = `${Cypress.config('baseUrl')}/ocs/v2.php/cloud/users/${user.userId}/${enable ? 'enable' : 'disable'}`.replace('index.php/', '')
+ return cy.request({
+ method: 'PUT',
+ url,
+ form: true,
+ auth: {
+ user: 'admin',
+ password: 'admin',
+ },
+ headers: {
+ 'OCS-ApiRequest': 'true',
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ }).then((response) => {
+ cy.log(`Enabled user ${user}`, response.status)
+ return cy.wrap(response)
+ })
+})
+
+/**
+ * cy.uploadedFile - uploads a file from the fixtures folder
+ * TODO: standardize in @nextcloud/cypress
+ *
+ * @param {User} user the owner of the file, e.g. admin
+ * @param {string} fixture the fixture file name, e.g. image1.jpg
+ * @param {string} mimeType e.g. image/png
+ * @param {string} [target] the target of the file relative to the user root
+ */
+Cypress.Commands.add('uploadFile', (user, fixture = 'image.jpg', mimeType = 'image/jpeg', target = `/${fixture}`) => {
+ // get fixture
+ return cy.fixture(fixture, 'base64')
+ .then((file) => (
+ // convert the base64 string to a blob
+ Cypress.Blob.base64StringToBlob(file, mimeType)
+ ))
+ .then((blob) => cy.uploadContent(user, blob, mimeType, target))
+})
+
+Cypress.Commands.add('setFileAsFavorite', (user: User, target: string, favorite = true) => {
+ // eslint-disable-next-line cypress/unsafe-to-chain-command
+ cy.clearAllCookies()
+ .then(async () => {
+ try {
+ const rootPath = `${Cypress.env('baseUrl')}/remote.php/dav/files/${encodeURIComponent(user.userId)}`
+ const filePath = target.split('/').map(encodeURIComponent).join('/')
+ const response = await axios({
+ url: `${rootPath}${filePath}`,
+ method: 'PROPPATCH',
+ auth: {
+ username: user.userId,
+ password: user.password,
+ },
+ headers: {
+ 'Content-Type': 'application/xml',
+ },
+ data: `<?xml version="1.0"?>
+ <d:propertyupdate xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns">
+ <d:set>
+ <d:prop>
+ <oc:favorite>${favorite ? 1 : 0}</oc:favorite>
+ </d:prop>
+ </d:set>
+ </d:propertyupdate>`,
+ })
+ cy.log(`Created directory ${target}`, response)
+ } catch (error) {
+ cy.log('error', error)
+ throw new Error('Unable to process fixture')
+ }
+ })
+})
+
+Cypress.Commands.add('mkdir', (user: User, target: string) => {
+ // eslint-disable-next-line cypress/unsafe-to-chain-command
+ return cy.clearCookies()
+ .then(async () => {
+ try {
+ const rootPath = `${Cypress.env('baseUrl')}/remote.php/dav/files/${encodeURIComponent(user.userId)}`
+ const filePath = target.split('/').map(encodeURIComponent).join('/')
+ const response = await axios({
+ url: `${rootPath}${filePath}`,
+ method: 'MKCOL',
+ auth: {
+ username: user.userId,
+ password: user.password,
+ },
+ })
+ cy.log(`Created directory ${target}`, response)
+ return response
+ } catch (error) {
+ cy.log('error', error)
+ throw new Error('Unable to create directory')
+ }
+ })
+})
+
+Cypress.Commands.add('rm', (user: User, target: string) => {
+ // eslint-disable-next-line cypress/unsafe-to-chain-command
+ cy.clearCookies()
+ .then(async () => {
+ try {
+ const rootPath = `${Cypress.env('baseUrl')}/remote.php/dav/files/${encodeURIComponent(user.userId)}`
+ const filePath = target.split('/').map(encodeURIComponent).join('/')
+ const response = await axios({
+ url: `${rootPath}${filePath}`,
+ method: 'DELETE',
+ auth: {
+ username: user.userId,
+ password: user.password,
+ },
+ })
+ cy.log(`delete file or directory ${target}`, response)
+ } catch (error) {
+ cy.log('error', error)
+ throw new Error('Unable to delete file or directory')
+ }
+ })
+})
+
+/**
+ * cy.uploadedContent - uploads a raw content
+ * TODO: standardize in @nextcloud/cypress
+ *
+ * @param {User} user the owner of the file, e.g. admin
+ * @param {Blob} blob the content to upload
+ * @param {string} mimeType e.g. image/png
+ * @param {string} target the target of the file relative to the user root
+ */
+Cypress.Commands.add('uploadContent', (user: User, blob: Blob, mimeType: string, target: string, mtime?: number) => {
+ cy.clearCookies()
+ return cy.then(async () => {
+ const fileName = basename(target)
+
+ // Process paths
+ const rootPath = `${Cypress.env('baseUrl')}/remote.php/dav/files/${encodeURIComponent(user.userId)}`
+ const filePath = target.split('/').map(encodeURIComponent).join('/')
+ try {
+ const file = new File([blob], fileName, { type: mimeType })
+ const response = await axios({
+ url: `${rootPath}${filePath}`,
+ method: 'PUT',
+ data: file,
+ headers: {
+ 'Content-Type': mimeType,
+ 'X-OC-MTime': mtime ? `${mtime}` : undefined,
+ },
+ auth: {
+ username: user.userId,
+ password: user.password,
+ },
+ })
+ cy.log(`Uploaded content as ${fileName}`, response)
+ return response
+ } catch (error) {
+ cy.log('error', error)
+ throw new Error('Unable to process fixture')
+ }
+ })
+})
+
+/**
+ * Reset the admin theming entirely
+ */
+Cypress.Commands.add('resetAdminTheming', () => {
+ const admin = new User('admin', 'admin')
+
+ cy.clearCookies()
+ cy.login(admin)
+
+ // Clear all settings
+ cy.request('/csrftoken').then(({ body }) => {
+ const requestToken = body.token
+
+ axios({
+ method: 'POST',
+ url: '/index.php/apps/theming/ajax/undoAllChanges',
+ headers: {
+ requesttoken: requestToken,
+ },
+ })
+ })
+
+ // Clear admin session
+ cy.clearCookies()
+})
+
+/**
+ * Reset the current or provided user theming settings
+ * It does not reset the theme config as it is enforced in the
+ * server config for cypress testing.
+ */
+Cypress.Commands.add('resetUserTheming', (user?: User) => {
+ if (user) {
+ cy.clearCookies()
+ cy.login(user)
+ }
+
+ // Reset background config
+ cy.request('/csrftoken').then(({ body }) => {
+ const requestToken = body.token
+
+ cy.request({
+ method: 'POST',
+ url: '/apps/theming/background/default',
+ headers: {
+ requesttoken: requestToken,
+ },
+ })
+ })
+
+ if (user) {
+ // Clear current session
+ cy.clearCookies()
+ }
+})
+
+Cypress.Commands.add('userFileExists', (user: string, path: string) => {
+ user.replaceAll('"', '\\"')
+ path.replaceAll('"', '\\"').replaceAll(/^\/+/gm, '')
+ return cy.runCommand(`stat --printf="%s" "data/${user}/files/${path}"`, { failOnNonZeroExit: true })
+ .then((exec) => Number.parseInt(exec.stdout || '0'))
+})