123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- /**
- * @copyright Copyright (c) 2022 John Molakvoæ <skjnldsv@protonmail.com>
- *
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- *
- * @license AGPL-3.0-or-later
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- // eslint-disable-next-line n/no-extraneous-import
- import type { AxiosResponse } from 'axios'
- import axios from '@nextcloud/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()
- // Register this file's custom commands types
- declare global {
- // eslint-disable-next-line @typescript-eslint/no-namespace
- namespace Cypress {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
- interface Chainable<Subject = any> {
- /**
- * Enable or disable a given user
- */
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- enableUser(user: User, enable?: boolean): Cypress.Chainable<Cypress.Response<any>>,
- /**
- * Upload a file from the fixtures folder to a given user storage.
- * **Warning**: Using this function will reset the previous session
- */
- uploadFile(user: User, fixture?: string, mimeType?: string, target?: string): Cypress.Chainable<void>,
- /**
- * Upload a raw content to a given user storage.
- * **Warning**: Using this function will reset the previous session
- */
- uploadContent(user: User, content: Blob, mimeType: string, target: string, mtime?: number): Cypress.Chainable<AxiosResponse>,
- /**
- * Create a new directory
- * **Warning**: Using this function will reset the previous session
- */
- mkdir(user: User, target: string): Cypress.Chainable<void>,
- /**
- * Set a file as favorite (or remove from favorite)
- */
- setFileAsFavorite(user: User, target: string, favorite?: boolean): Cypress.Chainable<void>,
- /**
- * Reset the admin theming entirely.
- * **Warning**: Using this function will reset the previous session
- */
- resetAdminTheming(): Cypress.Chainable<void>,
- /**
- * Reset the user theming settings.
- * If provided, will clear session and login as the given user.
- * **Warning**: Providing a user will reset the previous session.
- */
- resetUserTheming(user?: User): Cypress.Chainable<void>,
- /**
- * Run an occ command in the docker container.
- */
- runOccCommand(command: string, options?: Partial<Cypress.ExecOptions>): Cypress.Chainable<Cypress.Exec>,
- }
- }
- }
- const url = (Cypress.config('baseUrl') || '').replace(/\/index.php\/?$/g, '')
- Cypress.env('baseUrl', url)
- /**
- * Enable or disable a user
- * TODO: standardise 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: standardise 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(async file => {
- // convert the base64 string to a blob
- const blob = Cypress.Blob.base64StringToBlob(file, mimeType)
- 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
- 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)
- } catch (error) {
- cy.log('error', error)
- throw new Error('Unable to create directory')
- }
- })
- })
- /**
- * cy.uploadedContent - uploads a raw content
- * TODO: standardise 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('runOccCommand', (command: string, options?: Partial<Cypress.ExecOptions>) => {
- const env = Object.entries(options?.env ?? {}).map(([name, value]) => `-e '${name}=${value}'`).join(' ')
- return cy.exec(`docker exec --user www-data ${env} nextcloud-cypress-tests-server php ./occ ${command}`, options)
- })
|