Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9cf2852
In the fetchFaces method, remove the check if (Object.keys(this.faces…
Dymirt Jun 5, 2023
bf1e4cb
Minimize data processing
Dymirt Jun 5, 2023
d53e212
fix: use owner instead of owner_id to delete photos by owner
kesselb Jun 2, 2023
189635c
adding back check if (Object.keys(this.faces).length)
Dymirt Jun 5, 2023
02f8f61
enh(faces): Implement UnassignedFaces view
marcelklehr May 28, 2023
5c601dd
Compile assets
nextcloud-command May 30, 2023
2ed06e3
Add jest's types
artonge May 17, 2023
68bb0a4
Support browsers that do not support caches
artonge May 17, 2023
8381e79
Add test to test if a delete file break an album
artonge May 17, 2023
419f28c
Test if multiple collaborators work
artonge May 17, 2023
5118f2e
Add more shared albums tests
artonge May 24, 2023
41152ea
Remove user from collaborators when it is deleted
artonge May 24, 2023
7f5d4f2
Test adding files to a shared album from timeline
artonge May 24, 2023
5f81c01
Use NcSelect for collaborator form
artonge May 24, 2023
1bc4013
List shared albums in album picker
artonge May 24, 2023
c5f99a4
Test public links
artonge May 24, 2023
d3f5a0d
Prevent deletion when album is receive from group share
artonge May 24, 2023
3cbb580
Only run components testing in component CI step
artonge May 25, 2023
5574178
Do not retry tests
artonge Jun 6, 2023
7011d87
Compile assets
artonge May 25, 2023
a5adc50
Wait for some request to finish in tests
artonge May 31, 2023
7f81e1b
Increase timeout
artonge Jun 1, 2023
b8bb450
Only visit Photos' root view in 2e2 tests
artonge Jun 1, 2023
3dff2e8
Update cypress workflow
artonge Jun 5, 2023
cc98a9f
Update view when layout setting changes
artonge Jun 6, 2023
8839cb2
Fix(l10n): Update translations from Transifex
nextcloud-bot Jun 7, 2023
64a71b3
fixing Lint eslint / eslint errors
Dymirt Jun 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 19 additions & 9 deletions .github/workflows/cypress.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,20 @@ jobs:

steps:
- name: Checkout app
uses: actions/checkout@v3
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2

- name: Install server dependencies
run: composer install

- name: Read package.json node and npm engines version
uses: skjnldsv/read-package-engines-version-actions@v2.0
uses: skjnldsv/read-package-engines-version-actions@0ce2ed60f6df073a62a77c0a4958dd0fc68e32e7 # v2.1
id: versions
with:
fallbackNode: "^14"
fallbackNpm: "^7"

- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@v3
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
with:
cache: "npm"
node-version: ${{ steps.versions.outputs.nodeVersion }}
Expand All @@ -43,10 +43,10 @@ jobs:
npm ci
TESTING=true npm run build --if-present
- name: Save context
uses: actions/cache@v3
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
with:
key: cypress-context-${{ github.run_id }}
path: /home/runner/work/photos
path: ./

cypress:
runs-on: ubuntu-latest
Expand All @@ -62,14 +62,24 @@ jobs:

steps:
- name: Restore context
uses: actions/cache@v3
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
with:
fail-on-cache-miss: true
key: cypress-context-${{ github.run_id }}
path: /home/runner/work/photos
path: ./

- name: Set up node ${{ needs.init.outputs.nodeVersion }}
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
with:
cache: "npm"
node-version: ${{ needs.init.outputs.nodeVersion }}

- name: Set up npm ${{ needs.init.outputs.npmVersion }}
run: npm i -g npm@"${{ needs.init.outputs.npmVersion }}"

- name: Run ${{ matrix.containers == 'component' && 'component' || 'E2E' }} cypress tests

uses: cypress-io/github-action@v5
uses: cypress-io/github-action@db1693016f23ccf9043f4b2428f9b04e5d502a73 # v5.8.1
with:
record: true
parallel: true
Expand All @@ -87,7 +97,7 @@ jobs:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}

- name: Upload snapshots
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
if: always()
with:
name: snapshots_${{ matrix.containers }}
Expand Down
5 changes: 3 additions & 2 deletions cypress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ export default defineConfig({
viewportWidth: 1280,
viewportHeight: 720,

// Tries again 2 more times on failure
requestTimeout: 20000,

retries: {
runMode: 2,
runMode: 0,
// do not retry in `cypress open`
openMode: 0,
},
Expand Down
37 changes: 28 additions & 9 deletions cypress/e2e/albums.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@
*/
import {
addFilesToAlbumFromAlbum,
addFilesToAlbumFromAlbumFromHeader,
createAnAlbumFromAlbums,
deleteAnAlbumFromAlbumContent,
goToAlbum,
removeSelectionFromAlbum,
} from './albumsUtils'
import {
downloadSelection,
deleteSelection,
favoriteSelection,
selectMedia,
unfavoriteSelection,
Expand All @@ -43,9 +45,12 @@ Cypress.on('uncaught:exception', (err) => {
})

describe('Manage albums', () => {
let user = null

before(function() {
cy.createRandomUser()
.then((user) => {
.then(_user => {
user = _user
uploadTestMedia(user)
cy.login(user)
cy.visit('/apps/photos')
Expand All @@ -63,17 +68,21 @@ describe('Manage albums', () => {
cy.contains('There is no album yet!').click()
})

it('Add and remove a file to an album from an album', () => {
it('Create an album, populate it and delete it', () => {
cy.get('[data-test="media"]').should('have.length', 3)
})

it('Remove a file to an album from an album content view', () => {
selectMedia([0])
removeSelectionFromAlbum()
})

it('Add and remove multiple files to an album from an album', () => {
it('Remove multiple files to an album from an album content view', () => {
selectMedia([0, 1])
removeSelectionFromAlbum()
})

it('Favorite a file from an album', () => {
it('Favorite a file from an album content view', () => {
selectMedia([0])
favoriteSelection()
cy.get('[data-test="media"]').eq(0).find('[aria-label="The file is in the favorites"]')
Expand All @@ -82,7 +91,7 @@ describe('Manage albums', () => {
cy.get('[aria-label="The file is in the favorites"]').should('not.exist')
})

it('Favorite multiple files from an album', () => {
it('Favorite multiple files from an album content view', () => {
selectMedia([1, 2])
favoriteSelection()
cy.get('[data-test="media"]').eq(1).find('[aria-label="The file is in the favorites"]')
Expand All @@ -92,19 +101,19 @@ describe('Manage albums', () => {
cy.get('[aria-label="The file is in the favorites"]').should('not.exist')
})

// it('Download a file from an album', () => {
// it('Download a file from an album content view', () => {
// selectMedia([0])
// downloadSelection()
// unselectMedia([0])
// })

// it('Download multiple files from an album', () => {
// it('Download multiple files from an album content view', () => {
// selectMedia([1, 2])
// downloadSelection()
// unselectMedia([1, 2])
// })

// it('Download all files from an album', () => {
// it('Download all files from an album content view', () => {
// selectMedia([1, 2])
// downloadSelection()
// unselectMedia([1, 2])
Expand Down Expand Up @@ -145,4 +154,14 @@ describe('Manage albums', () => {
cy.get('form [name="location"]').clear()
cy.contains('Save').click()
})

it('Delete a file that was added to an album', () => {
addFilesToAlbumFromAlbumFromHeader('albums_test', [0])
cy.get('[data-test="media"]').should('have.length', 4)
cy.visit('/apps/photos')
selectMedia([3])
deleteSelection()
goToAlbum('albums_test')
cy.get('[data-test="media"]').should('have.length', 3)
})
})
54 changes: 52 additions & 2 deletions cypress/e2e/albumsUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*
*/

import { selectMedia } from "./photosUtils"
import { selectMedia } from './photosUtils'

export function createAnAlbumFromTimeline(albumName: string) {
cy.contains('Add').click()
Expand All @@ -30,9 +30,11 @@ export function createAnAlbumFromTimeline(albumName: string) {
}

export function createAnAlbumFromAlbums(albumName: string) {
cy.intercept({ times: 1, method: 'PROPFIND', url: `**/dav/photos/**/albums/${albumName}` }).as('propFind')
cy.contains('New album').click()
cy.get('form [name="name"]').type(albumName)
cy.contains('Create album').click()
cy.wait('@propFind')
}

export function deleteAnAlbumFromAlbumContent() {
Expand All @@ -41,32 +43,63 @@ export function deleteAnAlbumFromAlbumContent() {
}

export function addFilesToAlbumFromTimeline(albumName: string) {
cy.intercept({ times: 1, method: 'COPY', url: '**/dav/files/**' }).as('copy')
cy.intercept({ times: 1, method: 'PROPFIND', url: '**/dav/photos/**/albums/' }).as('propFindAlbums')
cy.intercept({ times: 1, method: 'PROPFIND', url: '**/dav/photos/**/sharedalbums/' }).as('propFindSharedAlbums')
cy.contains('Add to album').click()
cy.get('.album-picker ul').contains(albumName).click()
cy.wait('@copy')
cy.wait('@propFindAlbums')
cy.wait('@propFindSharedAlbums')
}

export function addFilesToAlbumFromAlbum(albumName: string, itemsIndex: number[]) {
cy.intercept({ times: 1, method: 'SEARCH', url: '**/dav/' }).as('search')
cy.get('[aria-label="Add photos to this album"]').click()
cy.wait('@search')
cy.get('.file-picker__file-list').within(() => {
selectMedia(itemsIndex)
})
cy.intercept({ times: itemsIndex.length, method: 'COPY', url: '**/dav/files/**' }).as('copy')
cy.intercept({ times: 1, method: 'PROPFIND', url: `**/dav/photos/**/albums/${albumName}` }).as('propFind')
cy.contains(`Add to ${albumName}`).click()
cy.wait('@copy')
cy.wait('@propFind')
}

export function addFilesToAlbumFromAlbumFromHeader(albumName: string, itemsIndex: number[]) {
cy.contains('Add').click()
cy.intercept({ times: 1, method: 'SEARCH', url: '**/dav/' }).as('search')
cy.contains('Add photos to this album').click()
cy.wait('@search')
cy.get('.file-picker__file-list').within(() => {
selectMedia(itemsIndex)
})
cy.intercept({ times: 1, method: 'PROPFIND', url: `**/dav/photos/**/albums/${albumName}` }).as('propFind')
cy.contains(`Add to ${albumName}`).click()
cy.wait('@propFind')
}

export function removeSelectionFromAlbum() {
cy.intercept({ times: 1, method: 'DELETE', url: '**/dav/photos/**' }).as('delete')
cy.get('[aria-label="Open actions menu"]').click()
cy.contains('Remove selection from album').click()
cy.wait('@delete')
}

export function goToAlbum(albumName: string) {
cy.intercept({ times: 1, method: 'PROPFIND', url: '**/dav/photos/**/albums' }).as('propFindAlbums')
cy.intercept({ times: 1, method: 'PROPFIND', url: `**/dav/photos/**/albums/${albumName}` }).as('propFindAlbumContent')
cy.get('.app-navigation__list').contains('Albums').click()
cy.wait('@propFindAlbums')
cy.get('ul.collections__list').contains(albumName).click()
cy.wait('@propFindAlbumContent')
}

export function addCollaborators(collaborators: string[]) {
cy.get('[aria-label="Manage collaborators for this album"]').click()
collaborators.forEach((collaborator: string) => {
cy.get('[aria-label="Search for collaborators"').type(collaborator)
cy.get('#sharing-search-input').type(collaborator)
cy.contains(collaborator).click()
})
cy.contains('Save').click()
Expand All @@ -85,3 +118,20 @@ export function removeCollaborators(collaborators: string[]) {
})
cy.contains('Save').click()
}

export function createPublicShare() {
cy.get('[aria-label="Manage collaborators for this album"]').click()
cy.intercept({ times: 1, method: 'PROPPATCH', url: '**/dav/photos/*/albums/*' }).as('patchCall')
cy.intercept({ times: 1, method: 'PROPFIND', url: '**/dav/photos/*/albums/*' }).as('propFind')
cy.get('[aria-label="Create public link share"]').click()
cy.wait('@patchCall')
cy.wait('@propFind')

return cy.get('[aria-label="Copy the public link"]')
.invoke('attr', 'title') as Cypress.Chainable<string>
}

export function deletePublicShare() {
cy.get('[aria-label="Manage collaborators for this album"]').click()
cy.get('[aria-label="Delete the public link"]').click()
}
14 changes: 2 additions & 12 deletions cypress/e2e/photosUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*
*/

import type { User } from "@nextcloud/cypress"
import type { User } from '@nextcloud/cypress'

export function uploadTestMedia(user: User) {
cy.exec('ls cypress/fixtures/media')
Expand Down Expand Up @@ -66,19 +66,9 @@ export function downloadAllFiles() {
}

export function deleteSelection() {
cy.intercept({ method: 'DELETE' }).as('deleteRequests')
cy.intercept({ times: 1, method: 'DELETE' }).as('deleteRequests')
cy.get('[aria-label="Open actions menu"]').click()
cy.contains('Delete selection')
.click()
.wait('@deleteRequests')
}

export function goToSharedAlbum(albumName: string) {
cy.get('.app-navigation__list').contains('Collaborative albums').click()
cy.get('ul.collections__list').contains(albumName).click()
}

export function removeSharedAlbums() {
cy.get('[aria-label="Open actions menu"]').click()
cy.contains('Delete album').click()
}
34 changes: 34 additions & 0 deletions cypress/e2e/sharedAlbumUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,46 @@
*
*/

import { selectMedia } from "./photosUtils"

export function goToSharedAlbum(albumName: string) {
cy.intercept({ times: 1, method: 'PROPFIND', url: '**/dav/photos/**/sharedalbums' }).as('propFindSharedAlbums')
cy.intercept({ times: 1, method: 'PROPFIND', url: `**/dav/photos/*/sharedalbums/${albumName}*/` }).as('propFindSharedAlbumContent')
cy.get('.app-navigation__list').contains('Collaborative albums').click()
cy.wait('@propFindSharedAlbums')
cy.get('ul.collections__list').contains(albumName).click()
cy.wait('@propFindSharedAlbumContent')
}

export function removeSharedAlbums() {
cy.get('[aria-label="Open actions menu"]').click()
cy.contains('Delete album').click()
}

export function addFilesToSharedAlbumFromSharedAlbumFromHeader(albumName: string, itemsIndex: number[]) {
cy.intercept({ times: 1, method: 'SEARCH', url: '**/dav/' }).as('search')
cy.contains('Add').click()
cy.wait('@search')
cy.get('.file-picker__file-list').within(() => {
selectMedia(itemsIndex)
})
cy.intercept({ times: itemsIndex.length, method: 'COPY', url: '**/dav/files/**' }).as('copy')
cy.intercept({ times: 1, method: 'PROPFIND', url: `**/dav/photos/*/sharedalbums/${albumName}*/` }).as('propFind')
cy.contains(`Add to ${albumName}`).click()
cy.wait('@copy')
cy.wait('@propFind')
}

export function addFilesToSharedAlbumFromAlbum(albumName: string, itemsIndex: number[]) {
cy.intercept({ times: 1, method: 'SEARCH', url: '**/dav/' }).as('search')
cy.get('[aria-label="Add photos to this album"]').click()
cy.wait('@search')
cy.get('.file-picker__file-list').within(() => {
selectMedia(itemsIndex)
})
cy.intercept({ times: itemsIndex.length, method: 'COPY', url: '**/dav/files/**' }).as('copy')
cy.intercept({ times: 1, method: 'PROPFIND', url: `**/dav/photos/*/sharedalbums/${albumName}*/` }).as('propFind')
cy.contains(`Add to ${albumName}`).click()
cy.wait('@copy')
cy.wait('@propFind')
}
Loading