Add collaborators management views

Signed-off-by: Louis Chemineau <louis@chmn.me>
Signed-off-by: nextcloud-command <nextcloud-command@users.noreply.github.com>
This commit is contained in:
Louis Chemineau 2022-08-24 13:25:23 +02:00 committed by nextcloud-command
parent ac8c298b2e
commit 35af106097
214 changed files with 9027 additions and 2828 deletions

113
.github/workflows/cypress.yml vendored Normal file
View File

@ -0,0 +1,113 @@
name: Cypress
on:
pull_request:
push:
branches:
- master
- stable*
env:
APP_NAME: photos
BRANCH: ${{ github.base_ref }}
CYPRESS_baseUrl: http://127.0.0.1:8082/index.php
TESTING: true
jobs:
init:
runs-on: ubuntu-latest
steps:
- name: Checkout app
uses: actions/checkout@v3
- name: Read package.json node and npm engines version
uses: skjnldsv/read-package-engines-version-actions@v1.1
id: versions
with:
fallbackNode: '^12'
fallbackNpm: '^6'
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@v3
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}
- name: Set up npm ${{ steps.versions.outputs.npmVersion }}
run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}"
- name: Install dependencies & build app
run: |
npm ci
TESTING=true npm run build --if-present
- name: Save context
uses: actions/cache@v3
with:
key: cypress-context-${{ github.run_id }}
path: /home/runner/work/photos
cypress:
runs-on: ubuntu-latest
needs: init
strategy:
fail-fast: false
matrix:
# run multiple copies of the current job in parallel
containers: [1, 2, 3, 4, 5, 6, 7, 8]
name: runner ${{ matrix.containers }}
steps:
- name: Restore context
uses: actions/cache@v3
with:
key: cypress-context-${{ github.run_id }}
path: /home/runner/work/photos
- name: Setup server
run: |
cd cypress
docker-compose up -d
- name: Wait for server
run: npm run wait-on $CYPRESS_baseUrl
- name: Enable app & configure server
run: |
cd cypress
docker-compose exec --env APP_NAME=${{ env.APP_NAME }} --env BRANCH=${{ env.BRANCH }} -T nextcloud bash /initserver.sh
- name: Cypress run
uses: cypress-io/github-action@v4
with:
record: true
parallel: true
# cypress env
ci-build-id: ${{ github.sha }}-${{ github.run_number }}
tag: ${{ github.event_name }}
env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
# https://github.com/cypress-io/github-action/issues/124
COMMIT_INFO_MESSAGE: ${{ github.event.pull_request.title }}
TESTING: true
- name: Upload snapshots
uses: actions/upload-artifact@v3
if: always()
with:
name: snapshots
path: cypress/snapshots
summary:
runs-on: ubuntu-latest
needs: [init, cypress]
if: always()
name: cypress-summary
steps:
- name: Summary status
run: if ${{ needs.init.result != 'success' || ( needs.cypress.result != 'success' && needs.cypress.result != 'skipped' ) }}; then exit 1; fi

4
.gitignore vendored
View File

@ -19,3 +19,7 @@ coverage/
vendor
.php_cs.cache
.php-cs-fixer.cache
cypress/videos
cypress/snapshots
cypress/downloads

View File

@ -38,6 +38,14 @@ return [
'path' => '',
]
],
['name' => 'page#index', 'url' => '/sharedalbums/{path}', 'verb' => 'GET', 'postfix' => 'sharedalbums',
'requirements' => [
'path' => '.*',
],
'defaults' => [
'path' => '',
]
],
['name' => 'page#index', 'url' => '/folders/{path}', 'verb' => 'GET', 'postfix' => 'folders',
'requirements' => [
'path' => '.*',
@ -110,5 +118,14 @@ return [
'path' => '',
],
],
[
'name' => 'preview#index',
'url' => '/api/v1/preview/{fileId}',
'verb' => 'GET',
'requirements' => [
'fileId' => '.*',
]
],
]
];

26
cypress.config.js Normal file
View File

@ -0,0 +1,26 @@
const { defineConfig } = require("cypress");
const browserify = require('@cypress/browserify-preprocessor')
module.exports = defineConfig({
viewportWidth: 1280,
viewportHeight: 720,
defaultCommandTimeout: 6000,
retries: 1,
env: {
failSilently: false,
type: 'actual',
},
screenshotsFolder: 'cypress/snapshots/actual',
trashAssetsBeforeRuns: true,
e2e: {
baseUrl: 'http://localhost:8082/index.php',
setupNodeEvents(on, config) {
// Fix browserslist extend https://github.com/cypress-io/cypress/issues/2983#issuecomment-570616682
on('file:preprocessor', browserify())
},
},
});

11
cypress/.eslintrc.js Normal file
View File

@ -0,0 +1,11 @@
module.exports = {
env: {
'cypress/globals': true,
},
plugins: [
'cypress',
],
extends: [
'plugin:cypress/recommended',
],
};

View File

@ -0,0 +1,18 @@
version: '3.7'
services:
nextcloud:
image: ghcr.io/nextcloud/continuous-integration-shallow-server
ports:
- 8082:80
environment:
CYPRESS_baseUrl: "http://127.0.0.1:8082/index.php"
BRANCH: "${BRANCH:-master}"
volumes:
# Using fallback to make sure this script doesn't mess
# with the mounting if APP_NAME is not provided.
- ../:/var/www/html/apps/${APP_NAME:-photos}
- ./initserver.sh:/initserver.sh

102
cypress/e2e/albums.cy.js Normal file
View File

@ -0,0 +1,102 @@
/**
* @copyright Copyright (c) 2022 Louis Chmn <louis@chmn.me>
*
* @author Louis Chmn <louis@chmn.me>
*
* @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/>.
*
*/
import { randHash } from '../utils'
const randUser = randHash()
const resizeObserverLoopErrRe = /^[^(ResizeObserver loop limit exceeded)]/
Cypress.on('uncaught:exception', (err) => {
/* returning false here prevents Cypress from failing the test */
if (resizeObserverLoopErrRe.test(err.message)) {
return false
}
})
describe('Manage albums', () => {
before(function () {
cy.logout()
cy.nextcloudCreateUser(randUser, 'password')
cy.login(randUser, 'password')
cy.uploadTestMedia()
// wait a bit for things to be settled
cy.wait(1000)
})
beforeEach(() => {
cy.visit(`${Cypress.env('baseUrl')}/index.php/apps/photos/albums`)
cy.createAnAlbumFromAlbums('albums_test')
cy.addFilesToAlbumFromAlbum('albums_test', [0, 1, 2])
})
afterEach(() => {
cy.deleteAnAlbumFromAlbumContent()
cy.contains("There is no album yet!").click()
})
it('Add and remove a file to an album from an album', () => {
cy.selectMedia([0])
cy.removeSelectionFromAlbum()
})
it('Add and remove multiple files to an album from an album', () => {
cy.selectMedia([0, 1])
cy.removeSelectionFromAlbum()
})
it('Favorite a file from an album', () => {
cy.selectMedia([0])
cy.favoriteSelection()
cy.get('[data-test="media"]').eq(0).find('[aria-label="The file is in the favorites"]')
cy.unfavoriteSelection()
cy.unselectMedia([0])
cy.get('[aria-label="The file is in the favorites"]').should('not.exist')
})
it('Favorite multiple files from an album', () => {
cy.selectMedia([1, 2])
cy.favoriteSelection()
cy.get('[data-test="media"]').eq(1).find('[aria-label="The file is in the favorites"]')
cy.get('[data-test="media"]').eq(2).find('[aria-label="The file is in the favorites"]')
cy.unfavoriteSelection()
cy.unselectMedia([1, 2])
cy.get('[aria-label="The file is in the favorites"]').should('not.exist')
})
it('Download a file from an album', () => {
cy.selectMedia([0])
cy.downloadSelection()
cy.unselectMedia([0])
})
it('Download multiple files from an album', () => {
cy.selectMedia([1, 2])
cy.downloadSelection()
cy.unselectMedia([1, 2])
})
it('Download all files from an album', () => {
cy.selectMedia([1, 2])
cy.downloadSelection()
cy.unselectMedia([1, 2])
})
})

View File

@ -0,0 +1,127 @@
/**
* @copyright Copyright (c) 2022 Louis Chmn <louis@chmn.me>
*
* @author Louis Chmn <louis@chmn.me>
*
* @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/>.
*
*/
import { randHash } from '../utils'
const randUser = randHash()
const randUser2 = randHash()
const resizeObserverLoopErrRe = /^[^(ResizeObserver loop limit exceeded)]/
Cypress.on('uncaught:exception', (err) => {
/* returning false here prevents Cypress from failing the test */
if (resizeObserverLoopErrRe.test(err.message)) {
return false
}
})
describe('Manage shared albums', () => {
before(() => {
cy.logout()
cy.nextcloudCreateUser(randUser, 'password')
cy.nextcloudCreateUser(randUser2, 'password')
cy.login(randUser, 'password')
cy.visit(`${Cypress.env('baseUrl')}/index.php/apps/photos/albums`)
cy.createAnAlbumFromAlbums('shared_album_test1')
cy.addCollaborators([randUser2])
cy.visit(`${Cypress.env('baseUrl')}/index.php/apps/photos/albums`)
cy.createAnAlbumFromAlbums('shared_album_test2')
cy.addCollaborators([randUser2])
cy.visit(`${Cypress.env('baseUrl')}/index.php/apps/photos/albums`)
cy.createAnAlbumFromAlbums('shared_album_test3')
cy.addCollaborators([randUser2])
cy.logout()
cy.login(randUser2, 'password')
cy.uploadTestMedia()
cy.visit(`${Cypress.env('baseUrl')}/index.php/apps/photos/sharedalbums`)
cy.goToSharedAlbum('shared_album_test2')
cy.addFilesToAlbumFromAlbum('shared_album_test2', [0, 1, 2])
// wait a bit for things to be settled
cy.wait(1000)
})
beforeEach(() => {
cy.visit(`${Cypress.env('baseUrl')}/index.php/apps/photos/sharedalbums`)
})
it('Add and remove a file to a shared album from a shared album', () => {
cy.goToSharedAlbum('shared_album_test1')
cy.get('[data-test="media"]').should('have.length', 0)
cy.addFilesToAlbumFromAlbum('shared_album_test1', [0])
cy.get('[data-test="media"]').should('have.length', 1)
cy.selectMedia([0])
cy.removeSelectionFromAlbum()
cy.get('[data-test="media"]').should('have.length', 0)
})
it('Add and remove multiple files to a shared album from a shared album', () => {
cy.goToSharedAlbum('shared_album_test1')
cy.get('[data-test="media"]').should('have.length', 0)
cy.addFilesToAlbumFromAlbum('shared_album_test1', [1, 2])
cy.get('[data-test="media"]').should('have.length', 2)
cy.selectMedia([0, 1])
cy.removeSelectionFromAlbum()
cy.get('[data-test="media"]').should('have.length', 0)
})
it('Download a file from a shared album', () => {
cy.goToSharedAlbum('shared_album_test2')
cy.selectMedia([0])
cy.downloadSelection()
cy.unselectMedia([0])
})
it('Download multiple files from a shared album', () => {
cy.goToSharedAlbum('shared_album_test2')
cy.selectMedia([1, 2])
cy.downloadSelection()
cy.unselectMedia([1, 2])
})
it('Download all files from a shared album', () => {
cy.goToSharedAlbum('shared_album_test2')
cy.downloadAllFiles()
})
it('Remove a file from a shared album', () => {
cy.goToSharedAlbum('shared_album_test2')
cy.get('[data-test="media"]').should('have.length', 3)
cy.goToSharedAlbum('shared_album_test2')
cy.selectMedia([0])
cy.removeSelectionFromAlbum()
cy.get('[data-test="media"]').should('have.length', 2)
})
it('Remove multiple files from a shared album', () => {
cy.goToSharedAlbum('shared_album_test2')
cy.get('[data-test="media"]').should('have.length', 2)
cy.goToSharedAlbum('shared_album_test2')
cy.selectMedia([0, 1])
cy.removeSelectionFromAlbum()
cy.get('[data-test="media"]').should('have.length', 0)
})
xit('Remove collaborator from an album', () => {
cy.goToSharedAlbum('shared_album_test3')
cy.removeSharedAlbums()
})
})

111
cypress/e2e/timelines.cy.js Normal file
View File

@ -0,0 +1,111 @@
/**
* @copyright Copyright (c) 2022 Louis Chmn <louis@chmn.me>
*
* @author Louis Chmn <louis@chmn.me>
*
* @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/>.
*
*/
import { randHash } from '../utils'
const randUser = randHash()
const resizeObserverLoopErrRe = /^[^(ResizeObserver loop limit exceeded)]/
Cypress.on('uncaught:exception', (err) => {
/* returning false here prevents Cypress from failing the test */
if (resizeObserverLoopErrRe.test(err.message)) {
return false
}
})
describe('View list of photos in the main timeline', () => {
before(() => {
cy.logout()
cy.nextcloudCreateUser(randUser, 'password')
cy.login(randUser, 'password')
cy.uploadTestMedia()
// wait a bit for things to be settled
cy.wait(1000)
})
beforeEach(() => {
cy.visit(`${Cypress.env('baseUrl')}/index.php/apps/photos`)
})
it('Favorite a file from a timeline', () => {
cy.selectMedia([0])
cy.favoriteSelection()
cy.get('[data-test="media"]').eq(0).find('[aria-label="The file is in the favorites"]')
cy.unfavoriteSelection()
cy.unselectMedia([0])
cy.get('[aria-label="The file is in the favorites"]').should('not.exist')
})
it('Favorite multiple files from a timeline', () => {
cy.selectMedia([1, 2])
cy.favoriteSelection()
cy.get('[data-test="media"]').eq(1).find('[aria-label="The file is in the favorites"]')
cy.get('[data-test="media"]').eq(2).find('[aria-label="The file is in the favorites"]')
cy.unfavoriteSelection()
cy.unselectMedia([1, 2])
cy.get('[aria-label="The file is in the favorites"]').should('not.exist')
})
it('Download a file from a timeline', () => {
cy.selectMedia([0])
cy.downloadSelection()
cy.unselectMedia([0])
})
it('Download multiple files from a timeline', () => {
cy.selectMedia([1, 2])
cy.downloadSelection()
cy.unselectMedia([1, 2])
})
it('Add file to an album from a timeline', () => {
cy.createAnAlbumFromTimeline('timeline_test_single')
cy.selectMedia([0])
cy.addFilesToAlbumFromTimeline('timeline_test_single')
cy.goToAlbum('timeline_test_single')
cy.get('[data-test="media"]').should('have.length', 1)
cy.deleteAnAlbumFromAlbumContent()
})
it('Add multiple files to an album from a timeline', () => {
cy.createAnAlbumFromTimeline('timeline_test_multiple')
cy.selectMedia([1, 2])
cy.addFilesToAlbumFromTimeline('timeline_test_multiple')
cy.goToAlbum('timeline_test_multiple')
cy.get('[data-test="media"]').should('have.length', 2)
cy.deleteAnAlbumFromAlbumContent()
})
it('Delete a file from photos', () => {
cy.get('[data-test="media"]').should('have.length', 5)
cy.selectMedia([0])
cy.deleteSelection()
cy.get('[data-test="media"]').should('have.length', 4)
})
it('Delete multiple files from photos', () => {
cy.get('[data-test="media"]').should('have.length', 4)
cy.selectMedia([1, 2])
cy.deleteSelection()
cy.get('[data-test="media"]').should('have.length', 2)
})
})

View File

@ -0,0 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 KiB

16
cypress/initserver.sh Executable file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env bash
echo "APP_NAME: $APP_NAME"
echo "BRANCH: $BRANCH"
chown -R www-data:www-data /var/www/html/data
su www-data -c "
php occ config:system:set force_language --value en
php occ config:system:set enforce_theme --value light
php occ app:enable $APP_NAME
php occ app:list
"
cd apps
git clone --depth 1 https://github.com/nextcloud/viewer.git

18
cypress/start.sh Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env bash
# RUN THIS SCRIPT FROM THE ROOT FOLDER OF YOUR APP
APP_NAME=${PWD##*/}
CYPRESS_baseUrl=http://127.0.0.1:8082/index.php
if [[ $APP_NAME == "cypress" ]]
then
echo "Please run this app from your app root folder."
else
echo "Launching docker server for the $APP_NAME app"
cd cypress
docker-compose pull
docker-compose up -d --force-recreate
npm run wait-on $CYPRESS_baseUrl
echo "Nextcloud successfully installed"
docker-compose exec --env APP_NAME=$APP_NAME -T nextcloud bash /initserver.sh
echo "Nextcloud successfully configured"
fi

12
cypress/stop.sh Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
# RUN THIS SCRIPT FROM THE ROOT FOLDER OF YOUR APP
appname=${PWD##*/}
if [[ $appname == "cypress" ]]
then
echo "Please run this app from your app root folder."
else
echo "Killing server for the $appname app"
cd cypress
docker-compose stop
fi

244
cypress/support/commands.js Normal file
View File

@ -0,0 +1,244 @@
/**
* @copyright Copyright (c) 2019 John Molakvoæ <skjnldsv@protonmail.com>
*
* @author John Molakvoæ <skjnldsv@protonmail.com>
* @author Louis Chmn <louis@chmn.me>
*
* @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/>.
*
*/
/// <reference types="Cypress" />
const url = Cypress.config('baseUrl').replace(/\/index.php\/?$/g, '')
Cypress.env('baseUrl', url)
Cypress.Commands.add('login', (user, password, route = '/apps/files') => {
cy.clearCookies()
Cypress.Cookies.defaults({
preserve: /^(oc|nc)/,
})
cy.visit(route)
cy.get('input[name=user]').type(user)
cy.get('input[name=password]').type(password)
cy.get('form[name=login] [type=submit]').click()
cy.url().should('include', route)
})
Cypress.Commands.add('logout', () => {
cy.visit('')
cy.getCookies()
.then(cookies => {
if (cookies.length === 0) {
cy.log('Not logged, skipping logout...')
return
}
return cy.get("body")
.then($body => {
const logout = $body.find('#expanddiv li[data-id="logout"] a')
if (logout.length > 0) {
cy.log('Loging out...')
cy.visit(logout[0].href)
} else {
cy.log('Nothing')
}
})
})
})
Cypress.Commands.add('nextcloudCreateUser', (user, password) => {
cy.clearCookies()
cy.visit('/')
cy.request({
method: 'POST',
url: `${Cypress.env('baseUrl')}/ocs/v1.php/cloud/users?format=json`,
form: true,
body: {
userid: user,
password,
},
auth: { user: 'admin', pass: 'admin' },
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'OCS-ApiRequest': 'true',
Authorization: `Basic ${Buffer.from('admin:admin').toString('base64')}`,
},
})
})
Cypress.Commands.add('uploadTestMedia', () => {
cy.exec('ls cypress/fixtures/media')
.then((result) => {
for (const fileName of result.stdout.split('\n')) {
cy.uploadFile(`media/${fileName}`, 'image/png', '', fileName)
}
})
})
/**
* cy.uploadedFile - uploads a file from the fixtures folder
*
* @param {string} fixtureFileName
* @param {string} mimeType eg. image/png
* @param {string} path to the folder in which this file should be uploaded
* @param {string} uploadedFileName alternative name to give the file while uploading
*/
Cypress.Commands.add('uploadFile', (fixtureFileName, mimeType, path = '', uploadedFileName = null) => {
if (uploadedFileName === null) {
uploadedFileName = fixtureFileName;
}
let file = null
return cy.fixture(fixtureFileName, 'base64')
.then(fileBase64 => {
// convert the logo base64 string to a blob
const blob = Cypress.Blob.base64StringToBlob(fileBase64, mimeType)
file = new File([blob], uploadedFileName, { type: mimeType })
return cy.window()
})
.then(window => {
const encodedPath = path.split("/")
.map(encodeURIComponent)
.join("/")
const url = `${Cypress.env('baseUrl')}/remote.php/webdav${encodedPath}/${encodeURIComponent(uploadedFileName)}`
return cy.request({
method: 'PUT',
url,
body: file,
encoding: 'binary',
headers: {
'Content-Type': mimeType,
requesttoken: window.OC.requestToken,
},
})
})
})
Cypress.Commands.add('selectMedia', (indexes) => {
indexes.forEach(index => {
cy.get('[data-test="media"]').eq(index)
.find('a').focus()
.parent().find('input').check({ force: true })
})
})
Cypress.Commands.add('unselectMedia', indexes => {
indexes.forEach(index => {
cy.get('[data-test="media"]').eq(index)
.find('a').focus()
.parent().find('input').uncheck({ force: true })
})
})
Cypress.Commands.add('favoriteSelection', () => {
cy.get('[aria-label="Open actions menu"]').click()
cy.get('[aria-label="Mark selection as favorite"]').click()
})
Cypress.Commands.add('unfavoriteSelection', () => {
cy.get('[aria-label="Open actions menu"]').click()
cy.get('[aria-label="Remove selection from favorites"]').click()
})
Cypress.Commands.add('downloadSelection', () => {
cy.get('[aria-label="Open actions menu"]').click()
cy.get('[aria-label="Download selected files"]').trigger('click')
})
Cypress.Commands.add('downloadAllFiles', () => {
cy.get('[aria-label="Open actions menu"]').click()
cy.get('[aria-label="Download all files in album"]').trigger('click')
})
Cypress.Commands.add('createAnAlbumFromTimeline', albumName => {
cy.contains('Add').click()
cy.contains('Create new album').click()
cy.get('form [name="name"]').type(albumName)
cy.contains('Create album').click()
})
Cypress.Commands.add('createAnAlbumFromAlbums', albumName => {
cy.contains('New album').click()
cy.get('form [name="name"]').type(albumName)
cy.contains('Create album').click()
})
Cypress.Commands.add('deleteAnAlbumFromAlbumContent', albumName => {
cy.get('[aria-label="Open actions menu"]').click()
cy.contains('Delete album').click()
})
Cypress.Commands.add('addFilesToAlbumFromTimeline', albumName => {
cy.contains('Add to album').click()
cy.get('.album-picker ul').contains(albumName).click()
})
Cypress.Commands.add('addFilesToAlbumFromAlbum', (albumName, itemsIndex) => {
cy.get('[aria-label="Add photos to this album"]').click()
cy.get('.file-picker__file-list').within(() => {
cy.selectMedia(itemsIndex)
})
cy.contains(`Add to ${albumName}`).click()
})
Cypress.Commands.add('deleteSelection', () => {
cy.intercept({ method: 'DELETE' }).as("deleteRequests");
cy.get('[aria-label="Open actions menu"]').click()
cy.contains("Delete selection")
.click()
.wait('@deleteRequests')
})
Cypress.Commands.add('removeSelectionFromAlbum', () => {
cy.get('[aria-label="Open actions menu"]').click()
cy.contains("Remove selection from album").click()
})
Cypress.Commands.add('goToAlbum', albumName => {
cy.get('.app-navigation__list').contains('Albums').click()
cy.get('ul.collections__list').contains(albumName).click()
})
Cypress.Commands.add('goToSharedAlbum', albumName => {
cy.get('.app-navigation__list').contains('Collaborative albums').click()
cy.get('ul.collections__list').contains(albumName).click()
})
Cypress.Commands.add('addCollaborators', collaborators => {
cy.get('[aria-label="Manage collaborators for this album"]').click()
collaborators.forEach((collaborator) => {
cy.get('[aria-label="Search for collaborators"').type(collaborator)
cy.contains(collaborator).click()
})
cy.contains('Save').click()
})
Cypress.Commands.add('removeCollaborators', collaborators => {
cy.get('[aria-label="Manage collaborators for this album"]').click()
collaborators.forEach((collaborator) => {
cy.get('[aria-label="Search for collaborators"').type(collaborator)
cy.contains(collaborator).click()
})
cy.contains('Save').click()
})
Cypress.Commands.add('removeSharedAlbums', collaborators => {
cy.get('[aria-label="Open actions menu"]').click()
cy.contains("Remove selection from album").click()
})

17
cypress/support/e2e.js Normal file
View File

@ -0,0 +1,17 @@
// ***********************************************************
// This example support/e2e.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands.js'

33
cypress/utils/index.js Normal file
View File

@ -0,0 +1,33 @@
/**
* @copyright Copyright (c) 2019 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/>.
*
*/
export const getSearchParams = url => {
return url
.split(/[?&]/)
.reduce((acc, cur) => {
const parts = cur.split('=')
parts[1] && (acc[parts[0]] = parts[1])
return acc
}, {})
}
export const randHash = () => Math.random().toString(36).replace(/[^a-z]+/g, '').slice(0, 10)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More