diff --git a/.github/workflows/cypress-snapshot-update.yml b/.github/workflows/cypress-snapshot-update.yml deleted file mode 100644 index cec2d5a8a..000000000 --- a/.github/workflows/cypress-snapshot-update.yml +++ /dev/null @@ -1,73 +0,0 @@ -# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors -# SPDX-License-Identifier: MIT -name: Cypress snapshot update - -on: - workflow_dispatch: - schedule: - # At 2:30 on Sundays - - cron: '20 1 * * 0' - -permissions: - contents: read - issues: write - -jobs: - update: - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - branches: ["master", "stable31", "stable32"] - - name: cypress-snapshot-update-${{ matrix.branches }} - - steps: - - name: Checkout app - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - ref: ${{ matrix.branches }} - - - name: Read package.json node and npm engines version - uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3 - id: versions - with: - fallbackNode: "^20" - fallbackNpm: "^10" - - - name: Set up node ${{ steps.versions.outputs.nodeVersion }} - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - 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 node dependencies & build app - run: | - npm ci - npm run build --if-present - - - name: Snapshot update - run: npm run cypress:update-snapshots - - - name: Create Pull Request - if: always() - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 - with: - token: ${{ secrets.COMMAND_BOT_PAT }} - commit-message: "chore(deps): cypress snapshot update" - committer: GitHub - author: nextcloud-command - signoff: true - branch: automated/noid/${{ matrix.branches }}-cypress-snapshot-update - title: "[${{ matrix.branches }}] Update cypress snapshots" - body: | - Auto-generated update of cypress snapshots - labels: | - dependencies - 3. to review - add-paths: | - cypress/snapshots diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml deleted file mode 100644 index 26819dde9..000000000 --- a/.github/workflows/cypress.yml +++ /dev/null @@ -1,171 +0,0 @@ -# This workflow is provided via the organization template repository -# -# https://github.com/nextcloud/.github -# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization -# -# SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors -# SPDX-License-Identifier: MIT - -name: Cypress - -on: pull_request - -concurrency: - group: cypress-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -env: - # Adjust APP_NAME if your repository name is different - APP_NAME: ${{ github.event.repository.name }} - - # This represents the server branch to checkout. - # Usually it's the base branch of the PR, but for pushes it's the branch itself. - # e.g. 'main', 'stable27' or 'feature/my-feature' - # n.b. server will use head_ref, as we want to test the PR branch. - BRANCH: ${{ github.base_ref || github.ref_name }} - - -permissions: - contents: read - -jobs: - init: - runs-on: ubuntu-latest - outputs: - nodeVersion: ${{ steps.versions.outputs.nodeVersion }} - npmVersion: ${{ steps.versions.outputs.npmVersion }} - - env: - PUPPETEER_SKIP_DOWNLOAD: true - - steps: - - name: Disabled on forks - if: ${{ github.event.pull_request.head.repo.full_name != github.repository }} - run: | - echo 'Can not run cypress on forks' - exit 1 - - - name: Checkout app - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - - - name: Check composer.json - id: check_composer - uses: andstor/file-existence-action@558493d6c74bf472d87c84eab196434afc2fa029 # v3.1.0 - with: - files: 'composer.json' - - - name: Install composer dependencies - if: steps.check_composer.outputs.files_exists == 'true' - run: composer install --no-dev - - - name: Read package.json node and npm engines version - uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3 - id: versions - with: - fallbackNode: '^24' - fallbackNpm: '^11.3' - - - name: Set up node ${{ steps.versions.outputs.nodeVersion }} - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - 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 node dependencies & build app - run: | - npm ci - TESTING=true npm run build --if-present - - - name: Save context - uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 - with: - key: cypress-context-${{ github.run_id }} - path: ./ - - cypress: - runs-on: ubuntu-latest - needs: init - - strategy: - fail-fast: false - matrix: - # Please increase the number or runners as your tests suite grows (0 based index for e2e tests) - containers: [0, 1, 2, 3, 4, 5, 6, 7] - # Hack as strategy.job-total includes the component and GitHub does not allow math expressions - # Always align this number with the total of e2e runners (max. index + 1) - total-containers: [8] - - name: runner ${{ matrix.containers }} - - steps: - - name: Restore context - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 - with: - fail-on-cache-miss: true - key: cypress-context-${{ github.run_id }} - path: ./ - - - name: Set up node ${{ needs.init.outputs.nodeVersion }} - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version: ${{ needs.init.outputs.nodeVersion }} - - - name: Set up npm ${{ needs.init.outputs.npmVersion }} - run: npm i -g 'npm@${{ needs.init.outputs.npmVersion }}' - - - name: Install cypress - run: ./node_modules/cypress/bin/cypress install - - - name: Run ${{ matrix.containers == 'component' && 'component' || 'E2E' }} cypress tests - uses: cypress-io/github-action@b7a7441d775af8f8b9d19945c10dd689a51dba68 # v7.2.0 - with: - # We already installed the dependencies in the init job - install: false - # cypress run type - component: ${{ matrix.containers == 'component' }} - # Do not add Cypress record key config as this conflicts with cypress-split - # Cypress again tries to force users to buy their dashboard... - env: - # Needs to be prefixed with CYPRESS_ - CYPRESS_BRANCH: ${{ env.BRANCH }} - # https://github.com/cypress-io/github-action/issues/124 - COMMIT_INFO_MESSAGE: ${{ github.event.pull_request.title }} - # Needed for some specific code workarounds - TESTING: true - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SPLIT: ${{ matrix.total-containers }} - SPLIT_INDEX: ${{ matrix.containers == 'component' && 0 || matrix.containers }} - - - name: Upload snapshots - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 - if: always() - with: - name: snapshots_${{ matrix.containers }} - path: cypress/snapshots - - - name: Extract NC 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@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 - if: failure() && matrix.containers != 'component' - with: - name: nc_logs_${{ matrix.containers }} - path: nextcloud.log - - summary: - runs-on: ubuntu-latest-low - 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 diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 000000000..347a869d4 --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,106 @@ +# SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: MIT + +name: Playwright + +on: pull_request + +concurrency: + group: playwright-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read + +env: + APP_NAME: ${{ github.event.repository.name }} + BRANCH: ${{ github.base_ref || github.ref_name }} + +jobs: + playwright: + runs-on: ubuntu-latest + + name: Playwright E2E tests + + steps: + - name: Disabled on forks + if: ${{ github.event.pull_request.head.repo.full_name != github.repository }} + run: | + echo 'Can not run Playwright on forks' + exit 1 + + - name: Checkout app + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Check composer.json + id: check_composer + uses: andstor/file-existence-action@558493d6c74bf472d87c84eab196434afc2fa029 # v3.1.0 + with: + files: 'composer.json' + + - name: Install composer dependencies + if: steps.check_composer.outputs.files_exists == 'true' + run: composer install --no-dev + + - name: Read package.json node and npm engines version + uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3 + id: versions + with: + fallbackNode: '^24' + fallbackNpm: '^11' + + - name: Set up node ${{ steps.versions.outputs.nodeVersion }} + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + 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: Install Playwright browsers + run: npx playwright install chromium --with-deps + + - name: Run Playwright tests + run: npx playwright test + env: + BRANCH: ${{ env.BRANCH }} + CI: true + + - name: Show Nextcloud logs on failure + if: failure() + run: | + docker exec nextcloud-e2e-test-server_${{ env.APP_NAME }} cat data/nextcloud.log || true + + - name: Upload Playwright report + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + if: ${{ !cancelled() }} + with: + name: playwright-report + path: playwright-report/ + retention-days: 7 + if-no-files-found: ignore + + - name: Upload Playwright traces + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + if: failure() + with: + name: playwright-traces + path: test-results/ + retention-days: 7 + if-no-files-found: ignore + + summary: + runs-on: ubuntu-latest-low + needs: playwright + if: always() + name: playwright-summary + steps: + - name: Summary status + run: if ${{ needs.playwright.result != 'success' && needs.playwright.result != 'skipped' }}; then exit 1; fi diff --git a/.gitignore b/.gitignore index feb19e486..1200c39ab 100644 --- a/.gitignore +++ b/.gitignore @@ -26,14 +26,12 @@ coverage/ vendor .php_cs.cache -# Cypress files +# Playwright files js/*roboto* -cypress/downloads -cypress/screenshots -cypress/snapshots -cypress/videos -cypress/snapshots/actual -cypress/snapshots/diff +playwright-report/ +test-results/ +blob-report/ +playwright/.cache/ # RelativeCI webpack bundle stats webpack-stats.json diff --git a/README.md b/README.md index 176f1f028..a1889eb6e 100644 --- a/README.md +++ b/README.md @@ -22,12 +22,19 @@ Show your latest holiday photos and videos like in the movies. Show a glimpse of ### 🧙 Advanced development stuff To build the Javascript whenever you make changes, you can also run `npm run dev` for development builds. -### 📷 Running cypress tests -To run e2e cypress tests, execute `npm run cypress`. +### 📷 Running Playwright tests +The end-to-end tests use [Playwright](https://playwright.dev/) and a disposable Nextcloud Docker container. -The `visual-regression` tests require additional care as they depend on installation of fonts in the application. To achieve repeatable results run the tests using `npm run cypress:visual-regression`. This will build the app with the required fonts and run the tests. +Build the app once, then run the tests: -If changes are required to the reference (base) screenshots used by the `visual-regression` tests, run `cypress:update-snapshots` and commit the updated screenshots. +```sh +npm ci +npx playwright install chromium +TESTING=true npm run build +npm run test:e2e +``` + +`npm run test:e2e:ui` opens the interactive UI. The Nextcloud container is started automatically by `playwright/start-server.mjs` (port 8081) and reused between local runs; set `PLAYWRIGHT_BASE_URL` to target an existing instance instead. ## API diff --git a/REUSE.toml b/REUSE.toml index 6a7e9678e..8b02d3eca 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -12,7 +12,7 @@ SPDX-FileCopyrightText = "2019 Nextcloud GmbH and Nextcloud contributors" SPDX-License-Identifier = "AGPL-3.0-or-later" [[annotations]] -path = ["cypress/fixtures/image.gif", "cypress/fixtures/image.ico", "cypress/fixtures/image.svg", "cypress/fixtures/image-small.png", "cypress/fixtures/image-apng.png"] +path = ["playwright/fixtures/image.gif", "playwright/fixtures/image.ico", "playwright/fixtures/image.svg", "playwright/fixtures/image-small.png", "playwright/fixtures/image-apng.png"] precedence = "aggregate" SPDX-FileCopyrightText = "2019 Nextcloud GmbH" SPDX-License-Identifier = "LicenseRef-NextcloudTrademarks" @@ -24,7 +24,7 @@ SPDX-FileCopyrightText = "2020 Nextcloud GmbH and Nextcloud contributors" SPDX-License-Identifier = "AGPL-3.0-or-later" [[annotations]] -path = ["psalm.xml", "tsconfig.json", "tests/psalm-baseline.xml", "cypress/tsconfig.json"] +path = ["psalm.xml", "tsconfig.json", "tests/psalm-baseline.xml", "playwright/tsconfig.json"] precedence = "aggregate" SPDX-FileCopyrightText = "2022 Nextcloud GmbH and Nextcloud contributors" SPDX-License-Identifier = "AGPL-3.0-or-later" @@ -36,7 +36,7 @@ SPDX-FileCopyrightText = "2023 Nextcloud GmbH and Nextcloud contributors" SPDX-License-Identifier = "AGPL-3.0-or-later" [[annotations]] -path = [".eslintrc.json", "cypress/.eslintrc.json", "cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/image.png", "cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/image2.png", "cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/non-dav.png", "cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/video.png"] +path = [".eslintrc.json"] precedence = "aggregate" SPDX-FileCopyrightText = "2024 Nextcloud GmbH and Nextcloud contributors" SPDX-License-Identifier = "AGPL-3.0-or-later" @@ -60,55 +60,55 @@ SPDX-FileCopyrightText = "2019 Nextcloud translators { - if (browser.family === 'chromium' && browser.name !== 'electron') { - launchOptions.preferences.default['browser.enable_spellchecking'] = false - return launchOptions - } - - if (browser.family === 'firefox') { - launchOptions.preferences['layout.spellcheckDefault'] = 0 - return launchOptions - } - - if (browser.name === 'electron') { - launchOptions.preferences.spellcheck = false - return launchOptions - } - }) - - if (process.env.CYPRESS_baseUrl) { - return config - } - - // Remove container after run - on('after:run', () => { - if (!process.env.CI) { - stopNextcloud() - } - }) - - // Before the browser launches - // starting Nextcloud testing container - const ip = await startNextcloud(process.env.BRANCH) - // Setting container's IP as base Url - config.baseUrl = `http://${ip}/index.php` - await waitOnNextcloud(ip) - await configureNextcloud([]) // pass empty array as WE are already the viewer - return config - }, - }, -}) diff --git a/cypress/.eslintrc.json b/cypress/.eslintrc.json deleted file mode 100644 index fb78972d2..000000000 --- a/cypress/.eslintrc.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "env": { - "cypress/globals": true - }, - "plugins": [ - "cypress" - ], - "extends": [ - "plugin:cypress/recommended" - ] -} diff --git a/cypress/e2e/a11y.cy.ts b/cypress/e2e/a11y.cy.ts deleted file mode 100644 index de1415c0b..000000000 --- a/cypress/e2e/a11y.cy.ts +++ /dev/null @@ -1,83 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ -describe('A11y tests', function() { - before(function() { - // Init user - cy.createRandomUser().then(user => { - // Upload test files - cy.uploadFile(user, 'image1.jpg', 'image/jpeg') - cy.uploadFile(user, 'image2.jpg', 'image/jpeg') - cy.uploadFile(user, 'video1.mp4', 'video/mp4') - - // Visit nextcloud - cy.login(user) - cy.visit('/apps/files') - }) - }) - - after(function() { - cy.logout() - }) - - it('See files in the list', function() { - cy.getFile('image1.jpg', { timeout: 10000 }) - .should('contain', 'image1 .jpg') - cy.getFile('image2.jpg', { timeout: 10000 }) - .should('contain', 'image2 .jpg') - cy.getFile('video1.mp4', { timeout: 10000 }) - .should('contain', 'video1 .mp4') - }) - - it('Open the viewer on file click', function() { - cy.openFile('image2.jpg') - cy.get('body > .viewer').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('See the title on the viewer header', function() { - cy.get('body > .viewer .modal-header__name').should('contain', 'image2.jpg') - }) - - it('Should have rendered the previous video and the next image', function() { - // There are buttons to navigate to the previous and next image - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - // The previous and the next image - cy.get('body > .viewer .modal-container img').should('have.length', 2) - // The next video - cy.get('body > .viewer .modal-container video').should('have.length', 1) - }) - - it('Should make the previous and the next slides hidden for assistive technologies', function() { - // Cypress doesn't respect aria-hidden in should.be.visible - cy.get('body > .viewer .modal-container .viewer__file:not(.viewer__file--active) video') - .parents('[aria-hidden="true"]') - .should('exist') - cy.get('body > .viewer .modal-container .viewer__file:not(.viewer__file--active) video') - .parents('[inert]') - .should('exist') - cy.get('body > .viewer .modal-container .viewer__file:not(.viewer__file--active) img') - .parents('[aria-hidden="true"]') - .should('exist') - cy.get('body > .viewer .modal-container .viewer__file:not(.viewer__file--active) img') - .parents('[inert]') - .should('exist') - }) - - it('Should make vido controls on the next slide not focusable', function() { - cy.get('body > .viewer .modal-container .viewer__file:not(.viewer__file--active):has(video) button') - .first() - .focus() - cy.get('body > .viewer .modal-container .viewer__file:not(.viewer__file--active):has(video) button') - .first() - .should('not.have.focus') - }) -}) diff --git a/cypress/e2e/actions/delete.cy.ts b/cypress/e2e/actions/delete.cy.ts deleted file mode 100644 index 099ea885e..000000000 --- a/cypress/e2e/actions/delete.cy.ts +++ /dev/null @@ -1,56 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -describe('Delete image.png in viewer', function() { - before(function() { - // Init user - cy.createRandomUser().then(user => { - // Upload test files - cy.uploadFile(user, 'image.png', 'image/png') - - // Visit nextcloud - cy.login(user) - cy.visit('/apps/files') - }) - }) - after(function() { - cy.logout() - }) - - it('See image.png in the list', function() { - cy.getFile('image.png', { timeout: 10000 }) - .should('contain', 'image .png') - }) - - it('Open the viewer on file click', function() { - cy.openFile('image.png') - cy.get('body > .viewer').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('Delete the image and close viewer', function() { - // open the menu - cy.get('body > .viewer .modal-header button.action-item__menutoggle').click() - // delete the file - cy.get('.action-button:contains(\'Delete\')').click() - }) - - it('Does not see the viewer anymore', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('not.exist') - }) - - it('Does not see image.png in the list anymore', function() { - cy.visit('/apps/files') - cy.getFile('image.png', { timeout: 10000 }) - .should('not.exist') - }) -}) diff --git a/cypress/e2e/actions/download.cy.ts b/cypress/e2e/actions/download.cy.ts deleted file mode 100644 index 6a61dc457..000000000 --- a/cypress/e2e/actions/download.cy.ts +++ /dev/null @@ -1,67 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import * as path from 'path' - -const fileName = 'image.png' - -describe(`Download ${fileName} in viewer`, function() { - before(function() { - // Init user - cy.createRandomUser().then(user => { - // Upload test files - cy.uploadFile(user, fileName, 'image/png') - - // Visit nextcloud - cy.login(user) - cy.visit('/apps/files') - }) - }) - - after(function() { - cy.logout() - }) - - it(`See "${fileName}" in the list`, function() { - cy.getFile(fileName, { timeout: 10000 }) - .should('contain', fileName.replace(/(.*)\./, '$1 .')) - }) - - it('Open the viewer on file click', function() { - cy.openFile(fileName) - cy.get('body > .viewer').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('Download the image', function() { - // open the menu - cy.get('body > .viewer .modal-header button.action-item__menutoggle').click() - // download the - cy.findByRole('menuitem', { name: 'Download' }).click() - }) - - it('Compare downloaded file with asset by size', function() { - const downloadsFolder = Cypress.config('downloadsFolder') - const fixturesFolder = Cypress.config('fixturesFolder') - - const downloadedFilePath = path.join(downloadsFolder, fileName) - const fixtureFilePath = path.join(fixturesFolder, fileName) - - cy.readFile(fixtureFilePath, 'binary', { timeout: 5000 }).then(fixtureBuffer => { - cy.readFile(downloadedFilePath, 'binary', { timeout: 5000 }) - .should(downloadedBuffer => { - if (downloadedBuffer.length !== fixtureBuffer.length) { - throw new Error(`File size ${downloadedBuffer.length} is not ${fixtureBuffer.length}`) - } - }) - }) - }) -}) diff --git a/cypress/e2e/actions/edit.cy.ts b/cypress/e2e/actions/edit.cy.ts deleted file mode 100644 index 2e9f48511..000000000 --- a/cypress/e2e/actions/edit.cy.ts +++ /dev/null @@ -1,44 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -describe('Open the new saved as image', function() { - before(function() { - cy.createRandomUser().then(user => { - cy.uploadFile(user, 'image1.jpg', 'image/jpeg') - cy.login(user) - cy.visit('/apps/files') - }) - }) - after(function() { - cy.logout() - }) - - it('See images in the list', function() { - cy.getFile('image1.jpg', { timeout: 10000 }) - .should('contain', 'image1 .jpg') - }) - it('Open the viewer on file click', function() { - cy.openFile('image1.jpg') - cy.get('body > .viewer').should('be.visible') - }) - it('open the image editor', function() { - cy.get('button[aria-label="Edit"]').click() - }) - it('Save the image', function() { - cy.get('.FIE_topbar-save-button').click() - cy.get('input[type="text"].SfxInput-Base').clear() - cy.get('input[type="text"].SfxInput-Base').type('imageSave') - cy.get('.SfxModal-Container button[color="primary"].SfxButton-root').contains('Save').click() - cy.get('.FIE_topbar-close-button').click() - cy.get('.modal-header__name').should('contain', 'imageSave.jpg') - cy.get('.modal-header button[aria-label="Close"]').click() - }) - it('See the new saved image in the list', function() { - - cy.getFile('imageSave.jpg', { timeout: 10000 }) - .should('contain', 'imageSave .jpg') - }) - -}) diff --git a/cypress/e2e/actions/sidebar.cy.ts b/cypress/e2e/actions/sidebar.cy.ts deleted file mode 100644 index ceb20974f..000000000 --- a/cypress/e2e/actions/sidebar.cy.ts +++ /dev/null @@ -1,127 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -describe('Open the sidebar from the viewer and open viewer with sidebar already opened', function() { - before(function() { - // Init user - cy.createRandomUser().then(user => { - // Upload test files - cy.uploadFile(user, 'image1.jpg', 'image/jpeg') - cy.uploadFile(user, 'image2.jpg', 'image/jpeg') - cy.uploadFile(user, 'image3.jpg', 'image/jpeg') - cy.uploadFile(user, 'image4.jpg', 'image/jpeg') - - // Visit nextcloud - cy.login(user) - cy.visit('/apps/files') - }) - }) - after(function() { - cy.logout() - }) - - it('See images in the list', function() { - cy.getFile('image1.jpg', { timeout: 10000 }) - .should('contain', 'image1 .jpg') - cy.getFile('image2.jpg', { timeout: 10000 }) - .should('contain', 'image2 .jpg') - cy.getFile('image3.jpg', { timeout: 10000 }) - .should('contain', 'image3 .jpg') - cy.getFile('image4.jpg', { timeout: 10000 }) - .should('contain', 'image4 .jpg') - }) - - it('Open the viewer on file click', function() { - cy.openFile('image1.jpg') - cy.get('body > .viewer').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('See the menu icon and title on the viewer header', function() { - cy.get('body > .viewer .modal-header__name').should('contain', 'image1.jpg') - cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') - cy.get('body > .viewer .modal-header button.header-close').should('be.visible') - }) - - it('Open the sidebar', function() { - // open the menu - cy.get('body > .viewer .modal-header button.action-item__menutoggle').click() - // open the sidebar - cy.findByRole('menuitem', { name: 'Open sidebar' }).click() - cy.get('aside.app-sidebar').should('be.visible') - // we hide the sidebar button if opened - cy.get('.action-button__icon.icon-menu-sidebar').should('not.exist') - // check the sidebar is opened for the correct file - cy.get('aside.app-sidebar .app-sidebar-header .app-sidebar-header__mainname').should('contain', 'image1.jpg') - }) - - it('Change to next image with sidebar open', function() { - cy.get('aside.app-sidebar').should('be.visible') - - // check the sidebar is opened for the correct file - cy.get('aside.app-sidebar .app-sidebar-header .app-sidebar-header__mainname').should('contain', 'image1.jpg') - - // open the next file (image2.png) using the arrow - cy.get('body > .viewer .button-vue.next').click() - cy.get('aside.app-sidebar .app-sidebar-header .app-sidebar-header__mainname').should('contain', 'image2.jpg') - }) - - it('Change to previous image with sidebar open', function() { - cy.get('aside.app-sidebar').should('be.visible') - - // check the sidebar is opened for the correct file - cy.get('aside.app-sidebar .app-sidebar-header .app-sidebar-header__mainname').should('contain', 'image2.jpg') - - // open the previous file (image1.png) using the arrow - cy.get('body > .viewer .button-vue.prev').click() - cy.get('aside.app-sidebar .app-sidebar-header .app-sidebar-header__mainname').should('contain', 'image1.jpg') - }) - - it('Close the sidebar', function() { - cy.get('aside.app-sidebar .app-sidebar-header .app-sidebar__close').click() - cy.get('aside.app-sidebar').should('not.be.visible') - cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') - cy.get('body > .viewer .modal-header button.action-item__menutoggle').click() - // The button to show the sidebar is shown again - cy.findByRole('menuitem', { name: 'Open sidebar' }).should('be.visible') - }) - - it('Open the viewer with the sidebar open', function() { - cy.get('body > .viewer .modal-header button.header-close').click() - cy.get('body > .viewer').should('not.exist') - - // open the sidebar without viewer open - cy.getFile('image1.jpg') - .find('[data-cy-files-list-row-mtime]') - .click() - cy.get('aside.app-sidebar').should('be.visible') - cy.url().should('contain', 'opendetails=true') - - // eslint-disable-next-line - cy.wait(500) - - cy.openFile('image1.jpg') - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - - // eslint-disable-next-line - cy.wait(500) - - // close the sidebar again - cy.get('aside.app-sidebar') - .findByRole('button', { name: 'Close sidebar' }) - .click() - cy.get('aside.app-sidebar').should('not.be.visible') - cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') - }) -}) diff --git a/cypress/e2e/audios/audio.mpeg.cy.ts b/cypress/e2e/audios/audio.mpeg.cy.ts deleted file mode 100644 index 38b37d798..000000000 --- a/cypress/e2e/audios/audio.mpeg.cy.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import audioTest from '../mixins/audio' - -describe('Open audio.mp3 in viewer', function() { - audioTest('audio.mp3', 'audio/mpeg') -}) diff --git a/cypress/e2e/audios/audio.ogg.cy.ts b/cypress/e2e/audios/audio.ogg.cy.ts deleted file mode 100644 index f5a0ffc2f..000000000 --- a/cypress/e2e/audios/audio.ogg.cy.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ -import audioTest from '../mixins/audio' - -describe('Open audio.ogg in viewer', function() { - audioTest('audio.ogg', 'audio/ogg') -}) diff --git a/cypress/e2e/audios/audios.cy.ts b/cypress/e2e/audios/audios.cy.ts deleted file mode 100644 index 16c777d4d..000000000 --- a/cypress/e2e/audios/audios.cy.ts +++ /dev/null @@ -1,83 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -describe('Open mp3 and ogg audio in viewer', function() { - let randUser - - before(function() { - // Init user - cy.createRandomUser().then(user => { - randUser = user - - // Upload test files - cy.uploadFile(user, 'audio.mp3', 'audio/mpeg') - cy.uploadFile(user, 'audio.ogg', 'audio/ogg') - - // Visit nextcloud - cy.login(user) - cy.visit('/apps/files') - }) - }) - after(function() { - cy.logout() - }) - - it('See audios in the list', function() { - cy.getFile('audio.mp3', { timeout: 10000 }) - .should('contain', 'audio .mp3') - cy.getFile('audio.ogg', { timeout: 10000 }) - .should('contain', 'audio .ogg') - }) - - it('Open the viewer on file click', function() { - cy.openFile('audio.mp3') - cy.get('body > .viewer').should('be.visible') - }) - - it('See the menu icon and title on the viewer header', function() { - cy.get('body > .viewer .modal-header__name').should('contain', 'audio.mp3') - cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') - cy.get('body > .viewer .modal-header button.header-close').should('be.visible') - }) - - it('Does see next navigation arrows', function() { - cy.get('body > .viewer .modal-container audio').should('have.length', 2) - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('The audio source is the remote url', function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active audio') - .should('have.attr', 'src') - .and('contain', `/remote.php/dav/files/${randUser.userId}/audio.mp3`) - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('Show audio.ogg on next', function() { - cy.get('body > .viewer button.next').click() - cy.get('body > .viewer .modal-container audio').should('have.length', 2) - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('The audio source is the remote url', function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active audio') - .should('have.attr', 'src') - .and('contain', `/remote.php/dav/files/${randUser.userId}/audio.ogg`) - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) -}) diff --git a/cypress/e2e/download-forbidden.cy.ts b/cypress/e2e/download-forbidden.cy.ts deleted file mode 100644 index 2822a8e50..000000000 --- a/cypress/e2e/download-forbidden.cy.ts +++ /dev/null @@ -1,69 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import type { User } from '@nextcloud/cypress' -import { ShareType } from '@nextcloud/sharing' - -describe('Disable download button if forbidden', { testIsolation: true }, () => { - let sharee: User - - before(() => { - cy.createRandomUser().then((user) => { sharee = user }) - cy.createRandomUser().then((user) => { - // Upload test files - cy.createFolder(user, '/Photos') - cy.uploadFile(user, 'image1.jpg', 'image/jpeg', '/Photos/image1.jpg') - - cy.login(user) - cy.createShare('/Photos', - { shareWith: sharee.userId, shareType: ShareType.User, attributes: [{ scope: 'permissions', key: 'download', value: false }] }, - ) - cy.logout() - }) - }) - - beforeEach(() => { - cy.login(sharee) - cy.visit('/apps/files') - cy.openFile('Photos') - }) - - it('See the shared folder and images in files list', () => { - cy.getFile('image1.jpg', { timeout: 10000 }) - .should('contain', 'image1 .jpg') - }) - - // TODO: Fix no-download files on server - it.skip('See the image can be shown', () => { - cy.getFile('image1.jpg').should('be.visible') - cy.openFile('image1.jpg') - cy.get('body > .viewer').should('be.visible') - - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('See the title on the viewer header but not the Download nor the menu button', () => { - cy.getFile('image1.jpg').should('be.visible') - // eslint-disable-next-line - cy.wait(250) - cy.openFile('image1.jpg') - cy.get('body > .viewer .modal-header__name').should('contain', 'image1.jpg') - - cy.get('[role="dialog"]') - .should('be.visible') - .find('button[aria-label="Actions"]') - .click() - - cy.get('[role="menu"]:visible') - .find('button') - .should('have.length', 2) - .each(($el) => { - expect($el.text()).to.match(/(Full screen|Open sidebar)/i) - }) - }) -}) diff --git a/cypress/e2e/files.cy.ts b/cypress/e2e/files.cy.ts deleted file mode 100644 index 6354bced2..000000000 --- a/cypress/e2e/files.cy.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import { User } from '@nextcloud/cypress' - -describe('Files default view', function() { - const user = new User('admin', 'admin') - - before(function() { - cy.login(user) - }) - - after(function() { - cy.logout() - }) - - it('See the default files list', function() { - cy.visit('/apps/files') - cy.getFile('welcome.txt').should('contain', 'welcome .txt') - }) - - it('Take screenshot', function() { - cy.screenshot() - }) -}) diff --git a/cypress/e2e/images/image-apng.cy.ts b/cypress/e2e/images/image-apng.cy.ts deleted file mode 100644 index 935ccf1f6..000000000 --- a/cypress/e2e/images/image-apng.cy.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import imageTest from '../mixins/image' - -describe('Open image-apng.png in viewer', function() { - imageTest('image-apng.png', 'image/png') -}) diff --git a/cypress/e2e/images/image-small.png.cy.ts b/cypress/e2e/images/image-small.png.cy.ts deleted file mode 100644 index 92437d08b..000000000 --- a/cypress/e2e/images/image-small.png.cy.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import imageTest from '../mixins/image' - -describe('Open image-small.png in viewer', function() { - imageTest('image-small.png', 'image/png') -}) diff --git a/cypress/e2e/images/image.gif.cy.ts b/cypress/e2e/images/image.gif.cy.ts deleted file mode 100644 index db7d42e23..000000000 --- a/cypress/e2e/images/image.gif.cy.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ -import imageTest from '../mixins/image' - -describe('Open image.gif in viewer', function() { - imageTest('image.gif', 'image/gif', '/remote.php/dav/files') -}) diff --git a/cypress/e2e/images/image.ico.cy.ts b/cypress/e2e/images/image.ico.cy.ts deleted file mode 100644 index c02764a1a..000000000 --- a/cypress/e2e/images/image.ico.cy.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import imageTest from '../mixins/image' - -describe('Open image.ico in viewer', function() { - imageTest('image.ico', 'image/x-icon', '/remote.php/dav/files') -}) diff --git a/cypress/e2e/images/image.png.cy.ts b/cypress/e2e/images/image.png.cy.ts deleted file mode 100644 index cb8dcb407..000000000 --- a/cypress/e2e/images/image.png.cy.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import imageTest from '../mixins/image' - -describe('Open image.png in viewer', function() { - imageTest('image.png', 'image/png') -}) diff --git a/cypress/e2e/images/image.svg.cy.ts b/cypress/e2e/images/image.svg.cy.ts deleted file mode 100644 index 81ceaccc8..000000000 --- a/cypress/e2e/images/image.svg.cy.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import imageTest from '../mixins/image' - -describe('Open image.svg in viewer', function() { - imageTest('image.svg', 'image/svg+xml', 'data:image/svg+xml;base64') -}) diff --git a/cypress/e2e/images/image.webp.cy.ts b/cypress/e2e/images/image.webp.cy.ts deleted file mode 100644 index 2c5822679..000000000 --- a/cypress/e2e/images/image.webp.cy.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import imageTest from '../mixins/image' - -describe('Open image.webp in viewer', function() { - imageTest('image.webp', 'image/webp') -}) diff --git a/cypress/e2e/images/images-custom-list-loadmore.cy.ts b/cypress/e2e/images/images-custom-list-loadmore.cy.ts deleted file mode 100644 index b7314d25b..000000000 --- a/cypress/e2e/images/images-custom-list-loadmore.cy.ts +++ /dev/null @@ -1,201 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -describe('Open custom list of images in viewer with pagination', function() { - before(function() { - // Init user - cy.createRandomUser().then(user => { - // Upload test files - cy.uploadFile(user, 'image1.jpg', 'image/jpeg') - cy.uploadFile(user, 'image2.jpg', 'image/jpeg') - cy.uploadFile(user, 'image3.jpg', 'image/jpeg') - cy.uploadFile(user, 'image4.jpg', 'image/jpeg') - - // Visit nextcloud - cy.login(user) - cy.visit('/apps/files') - }) - }) - after(function() { - cy.logout() - }) - - it('See images in the list', function() { - cy.getFile('image1.jpg', { timeout: 10000 }) - .should('contain', 'image1 .jpg') - cy.getFile('image2.jpg', { timeout: 10000 }) - .should('contain', 'image2 .jpg') - cy.getFile('image3.jpg', { timeout: 10000 }) - .should('contain', 'image3 .jpg') - cy.getFile('image4.jpg', { timeout: 10000 }) - .should('contain', 'image4 .jpg') - }) - - it('Open the viewer with a specific list', function() { - // make sure we only loadMore once - let loaded = false - - // get the files fileids - cy.getFileId('image1.jpg').then(fileID1 => { - cy.getFileId('image2.jpg').then(fileID2 => { - cy.getFileId('image3.jpg').then(fileID3 => { - cy.getFileId('image4.jpg').then(fileID4 => { - - // open the viewer with custom list of fileinfo - cy.window().then((win) => { - win.OCA.Viewer.open({ - path: '/image1.jpg', - list: [ - { - basename: 'image1.jpg', - filename: '/image1.jpg', - hasPreview: true, - fileid: parseInt(fileID1), - mime: 'image/jpeg', - permissions: 'RWD', - etag: 'etag123', - }, - { - basename: 'image2.jpg', - filename: '/image2.jpg', - hasPreview: true, - fileid: parseInt(fileID2), - mime: 'image/jpeg', - permissions: 'RWD', - etag: 'etag456', - }, - ], - // This will be triggered when we get to the end of the list - loadMore() { - // make sure we only loadMore once - if (loaded) { - return [] - } - - loaded = true - return [ - { - basename: 'image3.jpg', - filename: '/image3.jpg', - hasPreview: true, - fileid: parseInt(fileID3), - mime: 'image/jpeg', - permissions: 'RWD', - etag: 'etag123', - }, - { - basename: 'image4.jpg', - filename: '/image4.jpg', - hasPreview: true, - fileid: parseInt(fileID4), - mime: 'image/jpeg', - permissions: 'RWD', - etag: 'etag456', - }, - ] - }, - }) - }) - }) - }) - }) - }) - cy.get('body > .viewer').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('See the menu icon and title on the viewer header', function() { - cy.get('body > .viewer .modal-header__name').should('contain', 'image1.jpg') - cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') - cy.get('body > .viewer .modal-header button.header-close').should('be.visible') - }) - - it('Does see next navigation arrows', function() { - cy.get('body > .viewer .modal-container img').should('have.length', 2) - cy.get('body > .viewer .modal-container img').should('have.attr', 'src') - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('Show image2 on next', function() { - cy.get('body > .viewer button.next').click() - cy.get('body > .viewer .modal-container img').should('have.length', 2) - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('The image source is the preview url', function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active img') - .should('have.attr', 'src') - .and('contain', '/index.php/core/preview') - }) - - it('Show image3 on next', function() { - cy.get('body > .viewer button.next').click() - cy.get('body > .viewer .modal-container img').should('have.length', 3) - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('Show image4 on next', function() { - cy.get('body > .viewer button.next').click() - cy.get('body > .viewer .modal-container img').should('have.length', 2) - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('The image source is the preview url', function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active img') - .should('have.attr', 'src') - .and('contain', '/index.php/core/preview') - }) - - it('Show image1 again on next', function() { - cy.get('body > .viewer button.next').click() - cy.get('body > .viewer .modal-container img').should('have.length', 2) - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('The image source is the preview url', function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active img') - .should('have.attr', 'src') - .and('contain', '/index.php/core/preview') - }) -}) diff --git a/cypress/e2e/images/images-custom-list.cy.ts b/cypress/e2e/images/images-custom-list.cy.ts deleted file mode 100644 index 36b2494d9..000000000 --- a/cypress/e2e/images/images-custom-list.cy.ts +++ /dev/null @@ -1,156 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -describe('Open custom images list in viewer', function() { - before(function() { - // Init user - cy.createRandomUser().then(user => { - // Upload test files - cy.uploadFile(user, 'image1.jpg', 'image/jpeg') - cy.uploadFile(user, 'image2.jpg', 'image/jpeg') - cy.uploadFile(user, 'image3.jpg', 'image/jpeg') - cy.uploadFile(user, 'image4.jpg', 'image/jpeg') - - // Visit nextcloud - cy.login(user) - cy.visit('/apps/files') - }) - }) - after(function() { - cy.logout() - }) - - it('See images in the list', function() { - cy.getFile('image1.jpg', { timeout: 10000 }) - .should('contain', 'image1 .jpg') - cy.getFile('image2.jpg', { timeout: 10000 }) - .should('contain', 'image2 .jpg') - cy.getFile('image3.jpg', { timeout: 10000 }) - .should('contain', 'image3 .jpg') - cy.getFile('image4.jpg', { timeout: 10000 }) - .should('contain', 'image4 .jpg') - }) - - it('Open the viewer with a specific list', function() { - // get the two files fileids - cy.getFileId('image1.jpg').then(fileID1 => { - cy.getFileId('image3.jpg').then(fileID3 => { - - // open the viewer with custom list of fileinfo - cy.window().then((win) => { - win.OCA.Viewer.open({ - path: '/image1.jpg', - list: [ - { - basename: 'image1.jpg', - filename: '/image1.jpg', - hasPreview: true, - fileid: parseInt(fileID1), - permissions: 'RWD', - mime: 'image/jpeg', - etag: '123456789', - }, - { - basename: 'image3.jpg', - filename: '/image3.jpg', - hasPreview: true, - fileid: parseInt(fileID3), - permissions: 'R', - mime: 'image/jpeg', - etag: '987654321', - }, - ], - }) - }) - - }) - }) - cy.get('body > .viewer').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('See the menu icon and title on the viewer header', function() { - cy.get('body > .viewer .modal-header__name').should('contain', 'image1.jpg') - cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') - cy.get('body > .viewer .modal-header button.header-close').should('be.visible') - }) - - it('Does see next navigation arrows', function() { - cy.get('body > .viewer .modal-container img').should('have.length', 2) - cy.get('body > .viewer .modal-container img').should('have.attr', 'src') - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('The image source is the preview url', function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active img') - .should('have.attr', 'src') - .and('contain', '/index.php/core/preview') - }) - - it('Show image3 on next', function() { - cy.get('body > .viewer button.next').click() - cy.get('body > .viewer .modal-container img').should('have.length', 2) - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('The image source is the preview url', function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active img') - .should('have.attr', 'src') - .and('contain', '/index.php/core/preview') - }) - - it('See the menu icon and title on the viewer header', function() { - cy.get('body > .viewer .modal-header__name').should('contain', 'image3.jpg') - cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') - cy.get('body > .viewer .modal-header button.header-close').should('be.visible') - }) - - it('Show image1 on next', function() { - cy.get('body > .viewer button.next').click() - cy.get('body > .viewer .modal-container img').should('have.length', 2) - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('The image source is the preview url', function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active img') - .should('have.attr', 'src') - .and('contain', '/index.php/core/preview') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('See the menu icon and title on the viewer header', function() { - cy.get('body > .viewer .modal-header__name').should('contain', 'image1.jpg') - cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') - cy.get('body > .viewer .modal-header button.header-close').should('be.visible') - }) - - it('The image source is the preview url', function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active img') - .should('have.attr', 'src') - .and('contain', '/index.php/core/preview') - }) -}) diff --git a/cypress/e2e/images/images.cy.ts b/cypress/e2e/images/images.cy.ts deleted file mode 100644 index d23f0ab69..000000000 --- a/cypress/e2e/images/images.cy.ts +++ /dev/null @@ -1,148 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -describe('Open images in viewer', function() { - before(function() { - // Init user - cy.createRandomUser().then(user => { - // Upload test files - cy.uploadFile(user, 'image1.jpg', 'image/jpeg') - cy.uploadFile(user, 'image2.jpg', 'image/jpeg') - cy.uploadFile(user, 'image3.jpg', 'image/jpeg') - cy.uploadFile(user, 'image4.jpg', 'image/jpeg') - - // Visit nextcloud - cy.login(user) - cy.visit('/apps/files') - }) - }) - after(function() { - cy.logout() - }) - - it('See images in the list', function() { - cy.getFile('image1.jpg', { timeout: 10000 }) - .should('contain', 'image1 .jpg') - cy.getFile('image2.jpg', { timeout: 10000 }) - .should('contain', 'image2 .jpg') - cy.getFile('image3.jpg', { timeout: 10000 }) - .should('contain', 'image3 .jpg') - cy.getFile('image4.jpg', { timeout: 10000 }) - .should('contain', 'image4 .jpg') - }) - - it('Open the viewer on file click', function() { - cy.openFile('image1.jpg') - cy.get('body > .viewer').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('The image source is the preview url', function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active img') - .should('have.attr', 'src') - .and('contain', '/index.php/core/preview') - }) - - it('See the menu icon and title on the viewer header', function() { - cy.get('body > .viewer .modal-header__name').should('contain', 'image1.jpg') - cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') - cy.get('body > .viewer .modal-header button.header-close').should('be.visible') - }) - - it('Does see next navigation arrows', function() { - // only 2 because we don't know if we're at the end of the slideshow, current img and next one - cy.get('body > .viewer .modal-container img').should('have.length', 2) - cy.get('body > .viewer .modal-container img').should('have.attr', 'src') - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('Show image2 on next', function() { - cy.get('body > .viewer button.next').click() - cy.get('body > .viewer .modal-container img').should('have.length', 3) - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('The image source is the preview url', function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active img') - .should('have.attr', 'src') - .and('contain', '/index.php/core/preview') - }) - - it('Show image3 on next', function() { - cy.get('body > .viewer button.next').click() - cy.get('body > .viewer .modal-container img').should('have.length', 3) - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('The image source is the preview url', function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active img') - .should('have.attr', 'src') - .and('contain', '/index.php/core/preview') - }) - - it('Show image4 on next', function() { - cy.get('body > .viewer button.next').click() - // only 2 because we don't know if we're at the end of the slideshow, current img and previous one - cy.get('body > .viewer .modal-container img').should('have.length', 2) - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('The image source is the preview url', function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active img') - .should('have.attr', 'src') - .and('contain', '/index.php/core/preview') - }) - - it('Show image1 again on next', function() { - cy.get('body > .viewer button.next').click() - cy.get('body > .viewer .modal-container img').should('have.length', 2) - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('The image source is the preview url', function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active img') - .should('have.attr', 'src') - .and('contain', '/index.php/core/preview') - }) -}) diff --git a/cypress/e2e/mixins/audio.ts b/cypress/e2e/mixins/audio.ts deleted file mode 100644 index 03462f091..000000000 --- a/cypress/e2e/mixins/audio.ts +++ /dev/null @@ -1,69 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -/** - * Generate an audio cypress test - * - * @param {string} fileName the audio to upload and test against - * @param {string} mimeType the audio mime type - */ -export default function(fileName = 'audio.ogg', mimeType = 'audio/ogg') { - let randUser - - before(function() { - // Init user - cy.createRandomUser().then(user => { - randUser = user - - // Upload test files - cy.uploadFile(user, fileName, mimeType) - - // Visit nextcloud - cy.login(user) - cy.visit('/apps/files') - }) - }) - after(function() { - cy.logout() - }) - - it(`See ${fileName} in the list`, function() { - cy.getFile(fileName, { timeout: 10000 }) - .should('contain', fileName.replace(/(.*)\./, '$1 .')) - }) - - it('Open the viewer on file click and wait for loading to end', function() { - // Match audio request - cy.intercept('GET', `/remote.php/dav/files/${randUser.userId}/${fileName}`).as('source') - - // Open the file and check Viewer existence - cy.openFile(fileName) - cy.get('body > .viewer').should('be.visible') - - // Make sure loading is finished - cy.wait('@source').its('response.statusCode').should('eq', 206) - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('See the menu icon and title on the viewer header', function() { - cy.get('body > .viewer .modal-header__name').should('contain', fileName) - cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') - cy.get('body > .viewer .modal-header button.header-close').should('be.visible') - }) - - it('Does not see navigation arrows', function() { - cy.get('body > .viewer button.prev').should('not.be.visible') - cy.get('body > .viewer button.next').should('not.be.visible') - }) - - it('The audio source is the remote url', function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active audio') - .should('have.attr', 'src') - .and('contain', `/remote.php/dav/files/${randUser.userId}/${fileName}`) - }) -} diff --git a/cypress/e2e/mixins/image.ts b/cypress/e2e/mixins/image.ts deleted file mode 100644 index 9f7b79e67..000000000 --- a/cypress/e2e/mixins/image.ts +++ /dev/null @@ -1,71 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -/** - * Generate an image cypress test - * - * @param {string} fileName the image to upload and test against - * @param {string} mimeType the image mime type - * @param {string} source the optional custom source to check against - */ -export default function(fileName = 'image1.jpg', mimeType = 'image/jpeg', source = null) { - before(function() { - // Init user - cy.createRandomUser().then(user => { - // Upload test files - cy.uploadFile(user, fileName, mimeType) - - // Visit nextcloud - cy.login(user) - cy.visit('/apps/files') - }) - }) - after(function() { - cy.logout() - }) - - it(`See ${fileName} in the list`, function() { - cy.getFile(fileName, { timeout: 10000 }) - .should('contain', fileName.replace(/(.*)\./, '$1 .')) - }) - - it('Open the viewer on file click and wait for loading to end', function() { - // Match image request - cy.getFileId(fileName).then(fileId => { - const matchRoute = source - ? `/remote.php/dav/files/*/${fileName}` - : `/index.php/core/preview*fileId=${fileId}*` - cy.intercept('GET', matchRoute).as('image') - }) - - // Open the file and check Viewer existence - cy.openFile(fileName) - cy.get('body > .viewer').should('be.visible') - - // Make sure loading is finished - cy.wait('@image').its('response.statusCode').should('eq', 200) - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('See the menu icon and title on the viewer header', function() { - cy.get('body > .viewer .modal-header__name').should('contain', fileName) - cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') - cy.get('body > .viewer .modal-header button.header-close').should('be.visible') - }) - - it('Does not see navigation arrows', function() { - cy.get('body > .viewer button.prev').should('not.be.visible') - cy.get('body > .viewer button.next').should('not.be.visible') - }) - - it(`The image source is the ${source ? 'remote' : 'preview'} url`, function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active img') - .should('have.attr', 'src') - .and('contain', source ?? '/index.php/core/preview') - }) -} diff --git a/cypress/e2e/mixins/oddname.ts b/cypress/e2e/mixins/oddname.ts deleted file mode 100644 index 60023a7d9..000000000 --- a/cypress/e2e/mixins/oddname.ts +++ /dev/null @@ -1,141 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -/** - * Make a name aimed to break the viewer in case of escaping errors - * - * @param {string} realName the file original name - * @return {string} a name for the file to be uploaded as - */ -function naughtyFileName(realName) { - const ext = realName.split('.').pop() - return ( - '~⛰️ shot of a $[big} mountain`, ' - + "realy #1's " - + '" #_+="%2520%27%22%60%25%21%23 was this called ' - + realName - + 'in the' - + '☁️' - + '👩‍💻' - + '? :* .' - + ext.toUpperCase() - ) -} - -let failsLeft = 5 -Cypress.on('fail', (error) => { - failsLeft-- - throw error // throw error to have test still fail -}) - -/** - * - * @param file - * @param type - * @param sidebar - */ -export default function(file, type, sidebar = false) { - const placedName = naughtyFileName(file) - - const folderName - = 'Nextcloud "%27%22%60%25%21%23" >`⛰️<' + file + "><` e*'rocks!#?#%~" - - describe(`Open ${file} in viewer with a naughty name ${sidebar ? 'with sidebar' : ''}`, function() { - before(function() { - // fail fast - if (failsLeft < 0) { - throw new Error('Too many previous tests failed') - } - - // Init user - cy.createRandomUser().then(user => { - // Upload test files - cy.createFolder(user, `/${folderName}`) - cy.uploadFile(user, file, type, `/${folderName}/${placedName}`) - - // Visit nextcloud - cy.login(user) - cy.visit('/apps/files') - }) - - // wait a bit for things to be settled - cy.openFile(folderName) - }) - - /** - * - */ - function noLoadingAnimation() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - } - - /** - * - */ - function menuOk() { - cy.get('body > .viewer .icon-error').should('not.exist') - cy.get('body > .viewer .modal-header__name').should('contain', placedName) - cy.get('body > .viewer .modal-header button.header-close').should( - 'be.visible', - ) - } - - /** - * - */ - function arrowsOK() { - cy.get('body > .viewer button.prev').should('not.be.visible') - cy.get('body > .viewer button.next').should('not.be.visible') - } - - it(`See ${file} as ${placedName} in the list`, function() { - // cy.getFile will escape all the characters in the name to match it with css - cy.getFile(placedName, { timeout: 10000 }) - .should('contain', placedName.replace(/(.*)\./, '$1 .')) - }) - - it('Open the viewer on file click', function() { - cy.openFile(placedName) - cy.get('body > .viewer').should('be.visible') - }) - - it('Does not see a loading animation', noLoadingAnimation) - it('See the menu icon and title on the viewer header', menuOk) - it('Does not see navigation arrows', arrowsOK) - - if (sidebar) { - it('Open the sidebar', function() { - // open the menu - cy.get('body > .viewer .modal-header button.action-item__menutoggle').click() - // open the sidebar - cy.findByRole('menuitem', { name: 'Open sidebar' }).should('be.visible').click() - cy.get('aside.app-sidebar').should('be.visible') - // we hide the sidebar button if opened - cy.get('.action-button__icon.icon-menu-sidebar').should('not.exist') - // check the sidebar is opened for the correct file - cy.get('aside.app-sidebar .app-sidebar-header .app-sidebar-header__mainname').should('contain', placedName) - }) - } - - it('Share the folder with a share link and access the share link', function() { - cy.createLinkShare(folderName).then((token) => { - cy.logout() - cy.visit(`/s/${token}`) - }) - }) - - it('Open the viewer on file click (public)', function() { - cy.openFile(placedName) - cy.get('body > .viewer').should('be.visible') - }) - - it('Does not see a loading animation (public)', noLoadingAnimation) - it('See the menu icon and title on the viewer header (public)', menuOk) - it('Does not see navigation arrows (public)', arrowsOK) - }) -} diff --git a/cypress/e2e/mixins/video.ts b/cypress/e2e/mixins/video.ts deleted file mode 100644 index f5a59929d..000000000 --- a/cypress/e2e/mixins/video.ts +++ /dev/null @@ -1,69 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -/** - * Generate a video cypress test - * - * @param {string} fileName the video to upload and test against - * @param {string} mimeType the video mime type - */ -export default function(fileName = 'image1.jpg', mimeType = 'image/jpeg') { - let randUser - - before(function() { - // Init user - cy.createRandomUser().then(user => { - randUser = user - - // Upload test files - cy.uploadFile(user, fileName, mimeType) - - // Visit nextcloud - cy.login(user) - cy.visit('/apps/files') - }) - }) - after(function() { - cy.logout() - }) - - it(`See ${fileName} in the list`, function() { - cy.getFile(fileName, { timeout: 10000 }) - .should('contain', fileName.replace(/(.*)\./, '$1 .')) - }) - - it('Open the viewer on file click and wait for loading to end', function() { - // Match audio request - cy.intercept('GET', `/remote.php/dav/files/${randUser.userId}/${fileName}`).as('source') - - // Open the file and check Viewer existence - cy.openFile(fileName) - cy.get('body > .viewer').should('be.visible') - - // Make sure loading is finished - cy.wait('@source').its('response.statusCode').should('eq', 206) - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('See the menu icon and title on the viewer header', function() { - cy.get('body > .viewer .modal-header__name').should('contain', fileName) - cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') - cy.get('body > .viewer .modal-header button.header-close').should('be.visible') - }) - - it('Does not see navigation arrows', function() { - cy.get('body > .viewer button.prev').should('not.be.visible') - cy.get('body > .viewer button.next').should('not.be.visible') - }) - - it('The video source is the remote url', function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active video') - .should('have.attr', 'src') - .and('contain', `/remote.php/dav/files/${randUser.userId}/${fileName}`) - }) -} diff --git a/cypress/e2e/navigation.cy.ts b/cypress/e2e/navigation.cy.ts deleted file mode 100644 index f5dc1d3c6..000000000 --- a/cypress/e2e/navigation.cy.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -describe('Browser navigation', function() { - before(function() { - // Init user - cy.createRandomUser().then(user => { - // Upload test files - cy.uploadFile(user, 'image.png', 'image/png', '/image1.png') - - // Visit nextcloud - cy.login(user) - cy.visit('/apps/files') - }) - }) - after(function() { - cy.logout() - }) - - it('Navigating back to the files overview', function() { - cy.getFile('image1.png', { timeout: 10000 }) - cy.openFile('image1.png') - cy.get('body > .viewer').should('be.visible') - cy.go('back') - cy.get('body > .viewer').should('not.exist') - }) -}) diff --git a/cypress/e2e/non-dav-files.cy.ts b/cypress/e2e/non-dav-files.cy.ts deleted file mode 100644 index 0bb5764ea..000000000 --- a/cypress/e2e/non-dav-files.cy.ts +++ /dev/null @@ -1,74 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import { basename as pathBasename } from '@nextcloud/paths' - -const source = '/apps/theming/img/background/anatoly-mikhaltsov-butterfly-wing-scale.jpg' -const basename = pathBasename(source) - -describe('Open non-dav files in viewer', function() { - before(function() { - // Init user - cy.createRandomUser().then(user => { - // Upload test files - cy.uploadFile(user, 'test-card.mp4', 'video/mp4') - - // Visit nextcloud - cy.login(user) - cy.visit('/apps/files') - }) - }) - after(function() { - cy.logout() - }) - - it('Open background', function() { - const fileInfo = { - filename: source, - basename, - mime: 'image/jpeg', - source, - etag: 'abc', - hasPreview: false, - fileid: 123, - } - - cy.window().then((win) => { - win.OCA.Viewer.open({ - fileInfo, - list: [fileInfo], - }) - }) - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('See the title and close button on the viewer header', function() { - cy.get('body > .viewer .modal-header__name').should('contain', basename) - cy.get('body > .viewer .modal-header button.header-close').should('be.visible') - }) - - it('Does not see navigation arrows', function() { - cy.get('body > .viewer button.prev').should('not.be.visible') - cy.get('body > .viewer button.next').should('not.be.visible') - }) - - it('See the menu but does not see the sidebar button', function() { - // Menu exists - cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') - cy.get('.action-button__icon.icon-menu-sidebar').should('not.exist') - }) - - it('The image source is the remote url', function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active img') - .should('have.attr', 'src') - .and('contain', source) - }) -}) diff --git a/cypress/e2e/oddname/oddname-audio.cy.ts b/cypress/e2e/oddname/oddname-audio.cy.ts deleted file mode 100644 index f293e6356..000000000 --- a/cypress/e2e/oddname/oddname-audio.cy.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ -import runTest from '../mixins/oddname' - -for (const [file, type] of [ - ['audio.mp3', 'audio/mpeg'], - ['audio.ogg', 'audio/ogg'], -]) { - runTest(file, type) -} diff --git a/cypress/e2e/oddname/oddname-image.cy.ts b/cypress/e2e/oddname/oddname-image.cy.ts deleted file mode 100644 index 238614ee7..000000000 --- a/cypress/e2e/oddname/oddname-image.cy.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ -import runTest from '../mixins/oddname' - -for (const [file, type] of [ - ['image1.jpg', 'image/jpeg'], - ['image.gif', 'image/gif'], - ['image.png', 'image/png'], - ['image-small.png', 'image/png'], - ['image.svg', 'image/svg'], -]) { - runTest(file, type) -} diff --git a/cypress/e2e/oddname/oddname-sidebar.cy.ts b/cypress/e2e/oddname/oddname-sidebar.cy.ts deleted file mode 100644 index 2672a7e73..000000000 --- a/cypress/e2e/oddname/oddname-sidebar.cy.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ -import runTest from '../mixins/oddname' - -runTest('image.png', 'image/png', true) diff --git a/cypress/e2e/oddname/oddname-video.cy.ts b/cypress/e2e/oddname/oddname-video.cy.ts deleted file mode 100644 index 6d1b3973d..000000000 --- a/cypress/e2e/oddname/oddname-video.cy.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ -import runTest from '../mixins/oddname' - -for (const [file, type] of [ - ['video1.mp4', 'video/mp4'], - ['video.mkv', 'video/mkv'], - ['video.ogv', 'video/ogv'], - ['video.webm', 'video/webm'], -]) { - runTest(file, type) -} diff --git a/cypress/e2e/sharing/download-share-disabled.cy.ts b/cypress/e2e/sharing/download-share-disabled.cy.ts deleted file mode 100644 index af4c8f516..000000000 --- a/cypress/e2e/sharing/download-share-disabled.cy.ts +++ /dev/null @@ -1,110 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -const fileName = 'image1.jpg' - -describe(`Download ${fileName} in viewer`, function() { - before(function() { - // Init user - cy.createRandomUser().then(user => { - // Upload test files - cy.createFolder(user, '/Photos') - cy.uploadFile(user, 'image1.jpg', 'image/jpeg', '/Photos/image1.jpg') - cy.uploadFile(user, 'image2.jpg', 'image/jpeg', '/Photos/image2.jpg') - - // Visit nextcloud - cy.login(user) - cy.visit('/apps/files') - }) - }) - - it('See the default files list', function() { - cy.getFile('welcome.txt').should('contain', 'welcome .txt') - cy.getFile('Photos').should('contain', 'Photos') - }) - - it('See shared files in the list', function() { - cy.openFile('Photos') - cy.getFile('image1.jpg', { timeout: 10000 }) - .should('contain', 'image1 .jpg') - cy.getFile('image2.jpg', { timeout: 10000 }) - .should('contain', 'image2 .jpg') - }) - - it('Share the Photos folder with a share link, disable download and access the share link', function() { - cy.createLinkShare('/Photos').then((token: string) => { - cy.intercept('GET', '**/apps/files_sharing/api/v1/shares*').as('sharingAPI') - - // Open the sidebar from the breadcrumbs - cy.findByRole('navigation', { name: 'Current directory path' }) - .findByRole('button', { name: 'Photos' }) - .click() - cy.findByRole('menuitem', { name: 'Share' }).click() - cy.get('aside.app-sidebar').should('be.visible') - - // Wait for the sidebar to be done loading - cy.wait('@sharingAPI', { timeout: 10000 }) - - // Open the share menu - cy.get('.sharing-link-list > .sharing-entry button[aria-label*="Actions for "]').click() - cy.get('.action-button:contains(\'Customize link\')').click() - cy.findByRole('button', { name: 'Advanced settings' }).click() - - cy.get('.checkbox-radio-switch-checkbox').contains('Hide download').as('hideDownloadBtn') - // click the label - cy.get('@hideDownloadBtn').get('span').contains('Hide download').click() - cy.get('@hideDownloadBtn').get('input[type=checkbox]').should('be.checked') - - cy.intercept('PUT', '/ocs/v2.php/apps/files_sharing/api/v1/shares/*').as('updateShare') - cy.contains('button', 'Update share').click() - cy.wait('@updateShare') - - // Log out and access link share - cy.logout() - cy.visit(`/s/${token}`) - }) - }) - - it('See only view action', () => { - for (const file of ['image1.jpg', 'image2.jpg']) { - cy.get(`[data-cy-files-list-row-name="${CSS.escape(file)}"]`) - .find('[data-cy-files-list-row-actions]') - .find('button') - .click() - // Only view action - cy.get('[role="menu"]:visible') - .find('button') - .should('have.length', 1) - .first() - .should('contain.text', 'View') - cy.get(`[data-cy-files-list-row-name="${CSS.escape(file)}"]`) - .find('[data-cy-files-list-row-actions]') - .find('button') - .click() - } - }) - - it('Open the viewer on file click', function() { - cy.openFile('image1.jpg') - cy.get('body > .viewer').should('be.visible') - }) - - // TODO: FIX DOWNLOAD DISABLED SHARES - it.skip('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - // TODO: FIX DOWNLOAD DISABLED SHARES - it.skip('See the title on the viewer header but not the Download nor the menu button', function() { - cy.get('body > .viewer .modal-header__name').should('contain', 'image1.jpg') - cy.get('body a[download="image1.jpg"]').should('not.exist') - cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('not.exist') - cy.get('body > .viewer .modal-header button.header-close').should('be.visible') - }) - -}) diff --git a/cypress/e2e/sharing/download-share.cy.ts b/cypress/e2e/sharing/download-share.cy.ts deleted file mode 100644 index 6a04b81e4..000000000 --- a/cypress/e2e/sharing/download-share.cy.ts +++ /dev/null @@ -1,101 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import * as path from 'path' - -const fileName = 'image1.jpg' - -describe(`Download ${fileName} from viewer in link share`, function() { - let token = null - - before(function() { - // Init user - cy.createRandomUser().then(user => { - // Upload test files - cy.createFolder(user, '/Photos') - cy.uploadFile(user, 'image1.jpg', 'image/jpeg', '/Photos/image1.jpg') - cy.uploadFile(user, 'image2.jpg', 'image/jpeg', '/Photos/image2.jpg') - - // Visit nextcloud - cy.login(user) - cy.visit('/apps/files') - }) - }) - after(function() { - // already logged out after visiting share link - // cy.logout() - }) - - it('See the default files list', function() { - cy.getFile('welcome.txt').should('contain', 'welcome .txt') - cy.getFile('Photos').should('contain', 'Photos') - }) - - it('See shared files in the list', function() { - cy.openFile('Photos') - cy.getFile('image1.jpg', { timeout: 10000 }) - .should('contain', 'image1 .jpg') - cy.getFile('image2.jpg', { timeout: 10000 }) - .should('contain', 'image2 .jpg') - }) - - it('Share the Photos folder with a share link and access the share link', function() { - cy.createLinkShare('/Photos').then(newToken => { - token = newToken - cy.logout() - cy.visit(`/s/${token}`) - }) - }) - - it('Open the viewer on file click', function() { - cy.openFile('image1.jpg') - cy.get('body > .viewer').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('See the title and the close icon on the viewer header', function() { - cy.get('body > .viewer .modal-header__name').should('contain', 'image1.jpg') - cy.get('body > .viewer .modal-header button.header-close').should('be.visible') - }) - - it('See the menu on the viewer header and open it', function() { - cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible').click() - }) - - it('See the full screen and download icons in the menu', function() { - cy.findByRole('menuitem', { name: 'Full screen' }).should('be.visible') - cy.findByRole('menuitem', { name: 'Download' }).should('be.visible') - }) - - it('Download the image', function() { - // https://github.com/cypress-io/cypress/issues/14857 - cy.window().then((win) => { setTimeout(() => { win.location.reload() }, 5000) }) - // download the file - cy.findByRole('menuitem', { name: 'Download' }).click() - }) - - it('Compare downloaded file with asset by size', function() { - const downloadsFolder = Cypress.config('downloadsFolder') - const fixturesFolder = Cypress.config('fixturesFolder') - - const downloadedFilePath = path.join(downloadsFolder, fileName) - const fixtureFilePath = path.join(fixturesFolder, fileName) - - cy.readFile(fixtureFilePath, 'binary', { timeout: 5000 }).then(fixtureBuffer => { - cy.readFile(downloadedFilePath, 'binary', { timeout: 5000 }) - .should(downloadedBuffer => { - if (downloadedBuffer.length !== fixtureBuffer.length) { - throw new Error(`File size ${downloadedBuffer.length} is not ${fixtureBuffer.length}`) - } - }) - }) - }) -}) diff --git a/cypress/e2e/sharing/files-shares.cy.ts b/cypress/e2e/sharing/files-shares.cy.ts deleted file mode 100644 index f07c5fc19..000000000 --- a/cypress/e2e/sharing/files-shares.cy.ts +++ /dev/null @@ -1,150 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -describe('See shared folder with link share', function() { - before(function() { - // Init user - cy.createRandomUser().then(user => { - // Upload test files - cy.createFolder(user, '/Photos') - cy.uploadFile(user, 'image1.jpg', 'image/jpeg', '/Photos/image1.jpg') - cy.uploadFile(user, 'image2.jpg', 'image/jpeg', '/Photos/image2.jpg') - cy.uploadFile(user, 'image3.jpg', 'image/jpeg', '/Photos/image3.jpg') - cy.uploadFile(user, 'image4.jpg', 'image/jpeg', '/Photos/image4.jpg') - cy.uploadFile(user, 'video1.mp4', 'video/mp4', '/Photos/video1.mp4') - - // Visit nextcloud - cy.login(user) - cy.visit('/apps/files') - }) - }) - after(function() { - // already logged out after visiting share link - // cy.logout() - }) - - it('See the default files list', function() { - cy.getFile('welcome.txt').should('contain', 'welcome .txt') - cy.getFile('Photos').should('contain', 'Photos') - }) - - it('See shared files in the list', function() { - cy.openFile('Photos') - cy.getFile('image1.jpg', { timeout: 10000 }) - .should('contain', 'image1 .jpg') - cy.getFile('image2.jpg', { timeout: 10000 }) - .should('contain', 'image2 .jpg') - cy.getFile('image3.jpg', { timeout: 10000 }) - .should('contain', 'image3 .jpg') - cy.getFile('image4.jpg', { timeout: 10000 }) - .should('contain', 'image4 .jpg') - cy.getFile('video1.mp4', { timeout: 10000 }) - .should('contain', 'video1 .mp4') - }) - - it('Share the Photos folder with a share link and access the share link', function() { - cy.createLinkShare('/Photos').then(token => { - cy.logout() - cy.visit(`/s/${token}`) - }) - }) - - it('Open the viewer on file click', function() { - cy.openFile('image1.jpg') - cy.get('body > .viewer').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('See the menu icon and title on the viewer header', function() { - cy.get('body > .viewer .modal-header__name').should('contain', 'image1.jpg') - cy.get('body > .viewer .modal-header button.header-close').should('be.visible') - }) - - it('Does see next navigation arrows', function() { - cy.get('body > .viewer .modal-container img').should('have.length', 2) - cy.get('body > .viewer .modal-container img').should('have.attr', 'src') - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('Show image2 on next', function() { - cy.get('body > .viewer button.next').click() - cy.get('body > .viewer .modal-container img').should('have.length', 3) - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('Show image3 on next', function() { - cy.get('body > .viewer button.next').click() - cy.get('body > .viewer .modal-container img').should('have.length', 3) - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('Show image4 on next', function() { - cy.get('body > .viewer button.next').click() - cy.get('body > .viewer .modal-container img').should('have.length', 2) - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('Show video1 on next', function() { - cy.get('body > .viewer button.next').click() - // only 2 because we don't know if we're at the end of the slideshow, current vid and prev img - cy.get('body > .viewer .modal-container img').should('have.length', 1) - cy.get('body > .viewer .modal-container video').should('have.length', 1) - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - cy.get('body > .viewer .modal-header__name').should('contain', 'video1.mp4') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('Show image1 again on next', function() { - cy.get('body > .viewer button.next').click() - cy.get('body > .viewer .modal-container img').should('have.length', 2) - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) -}) diff --git a/cypress/e2e/sharing/single-file-share.cy.ts b/cypress/e2e/sharing/single-file-share.cy.ts deleted file mode 100644 index 1b5a99efe..000000000 --- a/cypress/e2e/sharing/single-file-share.cy.ts +++ /dev/null @@ -1,81 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -describe('See shared folder with link share', function() { - let imageToken - let videoToken - - before(function() { - // Init user - cy.createRandomUser().then(user => { - // Upload test files - cy.uploadFile(user, 'image1.jpg', 'image/jpeg') - cy.uploadFile(user, 'video1.mp4', 'video/mp4') - - // Visit nextcloud - cy.login(user) - cy.visit('/apps/files') - - // Create shares - cy.createLinkShare('/image1.jpg').then(token => { imageToken = token }) - cy.createLinkShare('/video1.mp4').then(token => { videoToken = token }) - - // Done - cy.logout() - }) - }) - - it('Opens the shared image in the viewer', function() { - cy.visit(`/s/${imageToken}`) - - cy.contains('image1.jpg').should('be.visible') - - cy.intercept('GET', '**/apps/files_sharing/publicpreview/**').as('getImage') - cy.openFileInSingleShare() - cy.wait('@getImage') - .its('response.statusCode') - .should('eq', 200) - - // Make sure loading is finished - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - - // The image source is the preview url - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active img') - .should('have.attr', 'src') - .and('contain', '/apps/files_sharing/publicpreview/') - - // See the menu icon and close button - cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') - cy.get('body > .viewer .modal-header button.header-close').should('be.visible') - }) - - it('Opens the shared video in the viewer', function() { - cy.visit(`/s/${videoToken}`) - - cy.contains('video1.mp4').should('be.visible') - - cy.intercept('GET', '**/public.php/dav/files/**').as('loadVideo') - cy.openFileInSingleShare() - cy.wait('@loadVideo') - - // Make sure loading is finished - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - - // The video source is the preview url - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active video') - .should('have.attr', 'src') - .and('contain', `/public.php/dav/files/${videoToken}`) - - // See the menu icon and close button - cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') - cy.get('body > .viewer .modal-header button.header-close').should('be.visible') - }) -}) diff --git a/cypress/e2e/videos/video.mkv.cy.ts b/cypress/e2e/videos/video.mkv.cy.ts deleted file mode 100644 index 2adfb4916..000000000 --- a/cypress/e2e/videos/video.mkv.cy.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import videoTest from '../mixins/video' - -describe('Open video.mkv in viewer', function() { - videoTest('video.mkv', 'image/mkv') -}) diff --git a/cypress/e2e/videos/video.mp4.cy.ts b/cypress/e2e/videos/video.mp4.cy.ts deleted file mode 100644 index 88ed4b9c1..000000000 --- a/cypress/e2e/videos/video.mp4.cy.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import videoTest from '../mixins/video' - -describe('Open video1.mp4 in viewer', function() { - videoTest('video1.mp4', 'video/mp4') -}) diff --git a/cypress/e2e/videos/video.ogv.cy.ts b/cypress/e2e/videos/video.ogv.cy.ts deleted file mode 100644 index c0e9b74fa..000000000 --- a/cypress/e2e/videos/video.ogv.cy.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import videoTest from '../mixins/video' - -describe('Open video.ogv in viewer', function() { - videoTest('video.ogv', 'video/ogv') -}) diff --git a/cypress/e2e/videos/video.webm.cy.ts b/cypress/e2e/videos/video.webm.cy.ts deleted file mode 100644 index 228448d59..000000000 --- a/cypress/e2e/videos/video.webm.cy.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import videoTest from '../mixins/video' - -describe('Open video.webm in viewer', function() { - videoTest('video.webm', 'video/webm') -}) diff --git a/cypress/e2e/videos/videos.cy.ts b/cypress/e2e/videos/videos.cy.ts deleted file mode 100644 index 0c54dc668..000000000 --- a/cypress/e2e/videos/videos.cy.ts +++ /dev/null @@ -1,83 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -describe('Open mp4 videos in viewer', function() { - let randUser - - before(function() { - // Init user - cy.createRandomUser().then(user => { - randUser = user - - // Upload test files - cy.uploadFile(user, 'video1.mp4', 'video/mp4') - cy.uploadFile(user, 'video2.mp4', 'video/mp4') - - // Visit nextcloud - cy.login(user) - cy.visit('/apps/files') - }) - }) - after(function() { - cy.logout() - }) - - it('See videos in the list', function() { - cy.getFile('video1.mp4', { timeout: 10000 }) - .should('contain', 'video1 .mp4') - cy.getFile('video2.mp4', { timeout: 10000 }) - .should('contain', 'video2 .mp4') - }) - - it('Open the viewer on file click', function() { - cy.openFile('video1.mp4') - cy.get('body > .viewer').should('be.visible') - }) - - it('See the menu icon and title on the viewer header', function() { - cy.get('body > .viewer .modal-header__name').should('contain', 'video1.mp4') - cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') - cy.get('body > .viewer .modal-header button.header-close').should('be.visible') - }) - - it('Does see next navigation arrows', function() { - cy.get('body > .viewer .modal-container video').should('have.length', 2) - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('The video source is the remote url', function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active video') - .should('have.attr', 'src') - .and('contain', `/remote.php/dav/files/${randUser.userId}/video1.mp4`) - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('Show video 2 on next', function() { - cy.get('body > .viewer button.next').click() - cy.get('body > .viewer .modal-container video').should('have.length', 2) - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('The video source is the remote url', function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active video') - .should('have.attr', 'src') - .and('contain', `/remote.php/dav/files/${randUser.userId}/video2.mp4`) - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) -}) diff --git a/cypress/e2e/visual-regression.cy.ts b/cypress/e2e/visual-regression.cy.ts deleted file mode 100644 index a2e6529ee..000000000 --- a/cypress/e2e/visual-regression.cy.ts +++ /dev/null @@ -1,163 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -describe('Visual regression tests', function() { - let randUser - - before(function() { - // Init user - cy.createRandomUser().then(user => { - randUser = user - - // Upload test files - cy.uploadFile(user, 'test-card.mp4', 'video/mp4') - cy.uploadFile(user, 'test-card.png', 'image/png') - - // Visit nextcloud - cy.login(user) - cy.visit('/apps/files') - }) - - cy.window().then((win) => { - // Load roboto font for visual regression consistency - win.loadRoboto = true - win.document.body.style.setProperty('--font-face', 'Roboto') - win.document.body.style.setProperty('font-family', 'Roboto') - }) - }) - - it('See files in the list', function() { - cy.getFile('test-card.mp4', { timeout: 10000 }) - .should('contain', 'test-card .mp4') - cy.getFile('test-card.png', { timeout: 10000 }) - .should('contain', 'test-card .png') - }) - - it('Open the viewer on file click', function() { - cy.intercept('GET', '**/viewer/css/fonts/roboto-*').as('roboto-font') - cy.intercept('GET', '**/core/preview*').as('image1') - cy.intercept('GET', '/remote.php/dav/files/*/test-card.mp4').as('video') - cy.openFile('test-card.mp4') - cy.wait('@roboto-font') - cy.wait('@video') - // We preload images, so we can check its loading here and not when clicking next - cy.wait('@image1') - cy.get('body > .viewer').should('be.visible') - }) - - it('See the menu icon and title on the viewer header', function() { - cy.get('body > .viewer .modal-header__name').should('contain', 'test-card.mp4') - cy.get('body > .viewer .modal-header button.action-item__menutoggle').should('be.visible') - cy.get('body > .viewer .modal-header button.header-close').should('be.visible') - }) - - it('Does see next navigation arrows', function() { - cy.get('body > .viewer .modal-container video').should('have.length', 1) - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active video') - .should('have.attr', 'src') - .and('contain', `/remote.php/dav/files/${randUser.userId}/test-card.mp4`) - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('Take test-card.mp4 screenshot', { retries: 0 }, function() { - cy.get('body > .viewer .modal-container .viewer__file.viewer__file--active video').then(video => { - video.get(0).pause() - video.get(0).currentTime = 1 - }) - // wait a bit for things to be settled - // eslint-disable-next-line - cy.wait(250) - cy.compareSnapshot('video', 0.02) - }) - - it('Show second file on next', function() { - cy.get('body > .viewer button.next').click() - cy.get('body > .viewer .modal-container img').should('have.length', 1) - cy.get('body > .viewer .modal-container img').should('have.attr', 'src') - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('Take test-card.png screenshot', { retries: 0 }, function() { - cy.compareSnapshot('image') - }) - - it('Close and open image again', function() { - cy.get('body > .viewer button.header-close').click() - cy.get('body > .viewer').should('not.exist') - - // No need to intercept the request again, it's cached - cy.openFile('test-card.png') - - cy.get('body > .viewer').should('be.visible') - cy.get('body > .viewer .modal-header__name').should('contain', 'test-card.png') - cy.get('body > .viewer .modal-container img').should('have.length', 1) - cy.get('body > .viewer .modal-container img').should('have.attr', 'src') - cy.get('body > .viewer button.prev').should('be.visible') - cy.get('body > .viewer button.next').should('be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('Take test-card.png screenshot 2', { retries: 0 }, function() { - cy.compareSnapshot('image2') - }) - - it('Open non-dav image', function() { - const fileInfo = { - filename: '/core/img/favicon.png', - basename: 'favicon.png', - mime: 'image/png', - source: '/core/img/favicon.png', - etag: 'abc', - hasPreview: false, - fileid: 123, - } - cy.intercept('GET', '/core/img/favicon.png').as('favicon') - cy.window().then((win) => { - win.OCA.Viewer.open({ - fileInfo, - list: [fileInfo], - }) - }) - cy.wait('@favicon') - - cy.get('body > .viewer .modal-container img').should('have.length', 1) - cy.get('body > .viewer .modal-container img').should('have.attr', 'src') - cy.get('body > .viewer button.prev').should('not.be.visible') - cy.get('body > .viewer button.next').should('not.be.visible') - }) - - it('Does not see a loading animation', function() { - cy.get('body > .viewer', { timeout: 10000 }) - .should('be.visible') - .and('have.class', 'modal-mask') - .and('not.have.class', 'icon-loading') - }) - - it('Take non-dav logo.png screenshot', { retries: 0 }, function() { - cy.compareSnapshot('non-dav') - }) -}) diff --git a/cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/image.png b/cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/image.png deleted file mode 100644 index ba2d88803..000000000 Binary files a/cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/image.png and /dev/null differ diff --git a/cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/image2.png b/cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/image2.png deleted file mode 100644 index 1bcd211a5..000000000 Binary files a/cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/image2.png and /dev/null differ diff --git a/cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/non-dav.png b/cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/non-dav.png deleted file mode 100644 index c437bd908..000000000 Binary files a/cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/non-dav.png and /dev/null differ diff --git a/cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/video.png b/cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/video.png deleted file mode 100644 index b1127ff85..000000000 Binary files a/cypress/snapshots/base/cypress/e2e/visual-regression.cy.ts/video.png and /dev/null differ diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts deleted file mode 100644 index 5eefac18f..000000000 --- a/cypress/support/commands.ts +++ /dev/null @@ -1,174 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import { addCommands } from '@nextcloud/cypress' -import { Permission } from '@nextcloud/files' -import { ShareType } from '@nextcloud/sharing' -import { addCompareSnapshotCommand } from 'cypress-visual-regression/dist/command' -import { basename } from 'path' - -import '@testing-library/cypress/add-commands' - -addCommands() -addCompareSnapshotCommand({ - errorThreshold: 0.01, -}) - -const url = Cypress.config('baseUrl')!.replace(/\/index.php\/?$/g, '') -Cypress.env('baseUrl', url) - -/** - * cy.uploadedFile - uploads a file from the fixtures folder - * - * @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, mimeType, target = `/${fixture}`) => { - cy.clearCookies() - - // get fixture - return cy.fixture(fixture, 'binary').then(file => { - // convert the binary to a blob - const blob = Cypress.Blob.binaryStringToBlob(file, mimeType) - - const fileName = basename(target) - const rootPath = `${Cypress.env('baseUrl')}/remote.php/dav/files/${encodeURIComponent(user.userId)}` - const filePath = target.split('/').map(encodeURIComponent).join('/') - - cy.request({ - url: `${rootPath}${filePath}`, - method: 'PUT', - body: blob, - headers: { - 'Content-Type': mimeType, - }, - auth: { - username: user.userId, - password: user.password, - }, - }).then(response => { - cy.log(`Uploaded file ${fileName}`, response) - }) - }) -}) - -Cypress.Commands.add('createFolder', (user, target) => { - cy.clearCookies() - - const dirName = basename(target) - const rootPath = `${Cypress.env('baseUrl')}/remote.php/dav/files/${encodeURIComponent(user.userId)}` - const dirPath = target.split('/').map(encodeURIComponent).join('/') - - cy.request({ - url: `${rootPath}${dirPath}`, - method: 'MKCOL', - auth: { - username: user.userId, - password: user.password, - }, - }).then(response => { - cy.log(`Created folder ${dirName}`, response) - }) -}) - -Cypress.Commands.add('getFile', fileName => { - return cy.get(`[data-cy-files-list] tr[data-cy-files-list-row-name="${CSS.escape(fileName)}"]`) -}) - -Cypress.Commands.add('openFile', fileName => { - cy.getFile(fileName) - .find('button') - .first() - .should('be.visible') - .click() - // eslint-disable-next-line - cy.wait(250) -}) - -Cypress.Commands.add('openFileInSingleShare', () => { - cy.get('tr[data-cy-files-list-row-name]') - .should('have.length', 1) - // eslint-disable-next-line - cy.wait(250) -}) - -Cypress.Commands.add('getFileId', fileName => { - return cy.getFile(fileName) - .should('have.attr', 'data-cy-files-list-row-fileid') -}) - -Cypress.Commands.add('deleteFile', fileName => { - cy.getFile(fileName).clickAction('delete') -}) - -Cypress.Commands.add('reloadCurrentFilesList', () => { - cy.get('[data-cy-files-content-breadcrumbs] a[title="Reload current directory"]').click() -}) - -Cypress.Commands.add( - 'clickAction', - { prevSubject: 'element' }, - (subject, action) => { - subject.find('[data-cy-files-list-row-actions] button').click() - cy.get(`[data-cy-files-list-row-action="${action}"]`).click() - }, -) - -interface ShareOptions { - shareType: number - shareWith?: string - permissions: number - attributes?: { value: boolean, key: string, scope: string}[] -} - -Cypress.Commands.add('createShare', (path: string, shareOptions?: ShareOptions) => { - return cy.request('/csrftoken').then(({ body }) => { - const requesttoken = body.token - - return cy.request({ - method: 'POST', - url: '../ocs/v2.php/apps/files_sharing/api/v1/shares?format=json', - headers: { - requesttoken, - }, - body: { - path, - permissions: Permission.READ, - ...shareOptions, - attributes: shareOptions?.attributes && JSON.stringify(shareOptions.attributes), - }, - }).then(({ body }) => { - const shareToken = body.ocs?.data?.token - if (shareToken === undefined) { - throw new Error('Invalid OCS response') - } - cy.log('Share link created', shareToken) - return cy.wrap(shareToken) - }) - }) -}) - -/** - * Create a share link and return the share url - * - * @param {string} path the file/folder path - * @return {string} the share link url - */ -Cypress.Commands.add('createLinkShare', path => { - return cy.createShare(path, { shareType: ShareType.Link }) -}) - -Cypress.Commands.overwrite('compareSnapshot', (originalFn, subject, name, options) => { - // hide avatar because random colour break the visual regression tests - cy.window().then(window => { - const avatarDiv = window.document.querySelector('.avatardiv') - if (avatarDiv) { - avatarDiv.remove() - } - }) - return originalFn(subject, name, options) -}) diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts deleted file mode 100644 index 0a5f71f43..000000000 --- a/cypress/support/e2e.ts +++ /dev/null @@ -1,25 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ -// *********************************************************** -// This example support/index.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' - -Cypress.on('uncaught:exception', () => { - return false -}) diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json deleted file mode 100644 index 8e156cf39..000000000 --- a/cypress/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../tsconfig.json", - "include": ["../*.ts", "."], - "compilerOptions": { - "rootDir": "..", - "types": [ - "@testing-library/cypress", - "cypress", - "dockerode", - "node" - ] - } -} diff --git a/js/NcActionButton-Em4cBvPi.chunk.mjs b/js/NcActionButton-DK3gSVD8.chunk.mjs similarity index 92% rename from js/NcActionButton-Em4cBvPi.chunk.mjs rename to js/NcActionButton-DK3gSVD8.chunk.mjs index 8b2cb9e4b..01bdf2d17 100644 --- a/js/NcActionButton-Em4cBvPi.chunk.mjs +++ b/js/NcActionButton-DK3gSVD8.chunk.mjs @@ -1,2 +1,2 @@ -import{N as i,m as s,b as a}from"./NcIconSvgWrapper-Bui9PhAS-CGu-pMgA.chunk.mjs";import{A as n}from"./actionText-BMig9Egt-DrBqWVOB.chunk.mjs";import{n as o}from"./_plugin-vue2_normalizer-DU4iP6Vu-CHYf0Z4t.chunk.mjs";import"./previewUtils-iDIXNuD0.chunk.mjs";const l={name:"NcActionButton",components:{NcIconSvgWrapper:i},mixins:[n],inject:{isInSemanticMenu:{from:"NcActions:isSemanticMenu",default:!1}},props:{ariaHidden:{type:Boolean,default:null},disabled:{type:Boolean,default:!1},isMenu:{type:Boolean,default:!1},type:{type:String,default:"button",validator:t=>["button","checkbox","radio","reset","submit"].includes(t)},modelValue:{type:[Boolean,String],default:null},value:{type:String,default:null},description:{type:String,default:""}},setup(){return{mdiCheck:a,mdiChevronRight:s}},computed:{isFocusable(){return!this.disabled},isChecked(){return this.type==="radio"&&typeof this.modelValue!="boolean"?this.modelValue===this.value:this.modelValue},nativeType(){return this.type==="submit"||this.type==="reset"?this.type:"button"},buttonAttributes(){const t={};return this.isInSemanticMenu?(t.role="menuitem",this.type==="radio"?(t.role="menuitemradio",t["aria-checked"]=this.isChecked?"true":"false"):(this.type==="checkbox"||this.nativeType==="button"&&this.modelValue!==null)&&(t.role="menuitemcheckbox",t["aria-checked"]=this.modelValue===null?"mixed":this.modelValue?"true":"false")):this.modelValue!==null&&this.nativeType==="button"&&(t["aria-pressed"]=this.modelValue?"true":"false"),t}},methods:{handleClick(t){this.onClick(t),(this.modelValue!==null||this.type!=="button")&&(this.type==="radio"?typeof this.modelValue!="boolean"?this.isChecked||this.$emit("update:modelValue",this.value):this.$emit("update:modelValue",!this.isChecked):this.$emit("update:modelValue",!this.isChecked))}}};var c=function(){var t=this,e=t._self._c;return e("li",{staticClass:"action",class:{"action--disabled":t.disabled},attrs:{role:t.isInSemanticMenu&&"presentation"}},[e("button",t._b({staticClass:"action-button button-vue",class:{"action-button--active":t.isChecked,focusable:t.isFocusable},attrs:{"aria-label":t.ariaLabel,disabled:t.disabled,title:t.title,type:t.nativeType},on:{click:t.handleClick}},"button",t.buttonAttributes,!1),[t._t("icon",function(){return[e("span",{staticClass:"action-button__icon",class:[t.isIconUrl?"action-button__icon--url":t.icon],style:{backgroundImage:t.isIconUrl?`url(${t.icon})`:null},attrs:{"aria-hidden":"true"}})]}),e("span",{staticClass:"action-button__longtext-wrapper"},[t.name?e("strong",{staticClass:"action-button__name"},[t._v(" "+t._s(t.name)+" ")]):t._e(),t.isLongText?e("span",{staticClass:"action-button__longtext",domProps:{textContent:t._s(t.text)}}):e("span",{staticClass:"action-button__text"},[t._v(" "+t._s(t.text)+" ")]),t.description?e("span",{staticClass:"action-button__description",domProps:{textContent:t._s(t.description)}}):t._e()]),t.isMenu?e("NcIconSvgWrapper",{staticClass:"action-button__menu-icon",attrs:{directional:"",path:t.mdiChevronRight}}):t.isChecked?e("NcIconSvgWrapper",{staticClass:"action-button__pressed-icon",attrs:{path:t.mdiCheck}}):t.isChecked===!1?e("span",{staticClass:"action-button__pressed-icon material-design-icon"}):t._e(),t._e()],2)])},u=[],r=o(l,c,u,!1,null,"5b4c6c71");const b=r.exports;export{b as default}; -//# sourceMappingURL=NcActionButton-Em4cBvPi.chunk.mjs.map +import{N as i,m as s,b as a}from"./NcIconSvgWrapper-Bui9PhAS-CzrbGJe-.chunk.mjs";import{A as n}from"./actionText-BMig9Egt-DrBqWVOB.chunk.mjs";import{n as o}from"./_plugin-vue2_normalizer-DU4iP6Vu-CHYf0Z4t.chunk.mjs";import"./previewUtils-2CV10zJE.chunk.mjs";const l={name:"NcActionButton",components:{NcIconSvgWrapper:i},mixins:[n],inject:{isInSemanticMenu:{from:"NcActions:isSemanticMenu",default:!1}},props:{ariaHidden:{type:Boolean,default:null},disabled:{type:Boolean,default:!1},isMenu:{type:Boolean,default:!1},type:{type:String,default:"button",validator:t=>["button","checkbox","radio","reset","submit"].includes(t)},modelValue:{type:[Boolean,String],default:null},value:{type:String,default:null},description:{type:String,default:""}},setup(){return{mdiCheck:a,mdiChevronRight:s}},computed:{isFocusable(){return!this.disabled},isChecked(){return this.type==="radio"&&typeof this.modelValue!="boolean"?this.modelValue===this.value:this.modelValue},nativeType(){return this.type==="submit"||this.type==="reset"?this.type:"button"},buttonAttributes(){const t={};return this.isInSemanticMenu?(t.role="menuitem",this.type==="radio"?(t.role="menuitemradio",t["aria-checked"]=this.isChecked?"true":"false"):(this.type==="checkbox"||this.nativeType==="button"&&this.modelValue!==null)&&(t.role="menuitemcheckbox",t["aria-checked"]=this.modelValue===null?"mixed":this.modelValue?"true":"false")):this.modelValue!==null&&this.nativeType==="button"&&(t["aria-pressed"]=this.modelValue?"true":"false"),t}},methods:{handleClick(t){this.onClick(t),(this.modelValue!==null||this.type!=="button")&&(this.type==="radio"?typeof this.modelValue!="boolean"?this.isChecked||this.$emit("update:modelValue",this.value):this.$emit("update:modelValue",!this.isChecked):this.$emit("update:modelValue",!this.isChecked))}}};var c=function(){var t=this,e=t._self._c;return e("li",{staticClass:"action",class:{"action--disabled":t.disabled},attrs:{role:t.isInSemanticMenu&&"presentation"}},[e("button",t._b({staticClass:"action-button button-vue",class:{"action-button--active":t.isChecked,focusable:t.isFocusable},attrs:{"aria-label":t.ariaLabel,disabled:t.disabled,title:t.title,type:t.nativeType},on:{click:t.handleClick}},"button",t.buttonAttributes,!1),[t._t("icon",function(){return[e("span",{staticClass:"action-button__icon",class:[t.isIconUrl?"action-button__icon--url":t.icon],style:{backgroundImage:t.isIconUrl?`url(${t.icon})`:null},attrs:{"aria-hidden":"true"}})]}),e("span",{staticClass:"action-button__longtext-wrapper"},[t.name?e("strong",{staticClass:"action-button__name"},[t._v(" "+t._s(t.name)+" ")]):t._e(),t.isLongText?e("span",{staticClass:"action-button__longtext",domProps:{textContent:t._s(t.text)}}):e("span",{staticClass:"action-button__text"},[t._v(" "+t._s(t.text)+" ")]),t.description?e("span",{staticClass:"action-button__description",domProps:{textContent:t._s(t.description)}}):t._e()]),t.isMenu?e("NcIconSvgWrapper",{staticClass:"action-button__menu-icon",attrs:{directional:"",path:t.mdiChevronRight}}):t.isChecked?e("NcIconSvgWrapper",{staticClass:"action-button__pressed-icon",attrs:{path:t.mdiCheck}}):t.isChecked===!1?e("span",{staticClass:"action-button__pressed-icon material-design-icon"}):t._e(),t._e()],2)])},u=[],r=o(l,c,u,!1,null,"5b4c6c71");const b=r.exports;export{b as default}; +//# sourceMappingURL=NcActionButton-DK3gSVD8.chunk.mjs.map diff --git a/js/NcActionButton-Em4cBvPi.chunk.mjs.license b/js/NcActionButton-DK3gSVD8.chunk.mjs.license similarity index 100% rename from js/NcActionButton-Em4cBvPi.chunk.mjs.license rename to js/NcActionButton-DK3gSVD8.chunk.mjs.license diff --git a/js/NcActionButton-Em4cBvPi.chunk.mjs.map b/js/NcActionButton-DK3gSVD8.chunk.mjs.map similarity index 99% rename from js/NcActionButton-Em4cBvPi.chunk.mjs.map rename to js/NcActionButton-DK3gSVD8.chunk.mjs.map index 27ba30c78..030b5fed2 100644 --- a/js/NcActionButton-Em4cBvPi.chunk.mjs.map +++ b/js/NcActionButton-DK3gSVD8.chunk.mjs.map @@ -1 +1 @@ -{"version":3,"file":"NcActionButton-Em4cBvPi.chunk.mjs","sources":["../node_modules/@nextcloud/vue/dist/chunks/NcActionButton-1gSJfFUC.mjs"],"sourcesContent":["import '../assets/NcActionButton-CG4V9b5b.css';\nimport { m as mdiChevronRight, a as mdiCheck } from \"./mdi-DkJglNiS.mjs\";\nimport { N as NcIconSvgWrapper } from \"./NcIconSvgWrapper-Bui9PhAS.mjs\";\nimport { A as ActionTextMixin } from \"./actionText-BMig9Egt.mjs\";\nimport { n as normalizeComponent } from \"./_plugin-vue2_normalizer-DU4iP6Vu.mjs\";\nconst _sfc_main = {\n name: \"NcActionButton\",\n components: {\n NcIconSvgWrapper\n },\n mixins: [ActionTextMixin],\n inject: {\n isInSemanticMenu: {\n from: \"NcActions:isSemanticMenu\",\n default: false\n }\n },\n props: {\n /**\n * @deprecated To be removed in @nextcloud/vue 9. Migration guide: remove ariaHidden prop from NcAction* components.\n * @todo Add a check in @nextcloud/vue 9 that this prop is not provided,\n * otherwise root element will inherit incorrect aria-hidden.\n */\n ariaHidden: {\n type: Boolean,\n // eslint-disable-next-line vue/no-boolean-default\n default: null\n },\n /**\n * disabled state of the action button\n */\n disabled: {\n type: Boolean,\n default: false\n },\n /**\n * If this is a menu, a chevron icon will\n * be added at the end of the line\n */\n isMenu: {\n type: Boolean,\n default: false\n },\n /**\n * The button's behavior, by default the button acts like a normal button with optional toggle button behavior if `modelValue` is `true` or `false`.\n * But you can also set to checkbox button behavior with tri-state or radio button like behavior.\n * This extends the native HTML button type attribute.\n */\n type: {\n type: String,\n default: \"button\",\n validator: (behavior) => [\"button\", \"checkbox\", \"radio\", \"reset\", \"submit\"].includes(behavior)\n },\n /**\n * The buttons state if `type` is 'checkbox' or 'radio' (meaning if it is pressed / selected).\n * For checkbox and toggle button behavior - boolean value.\n * For radio button behavior - could be a boolean checked or a string with the value of the button.\n * Note: Unlike native radio buttons, NcActionButton are not grouped by name, so you need to connect them by bind correct modelValue.\n *\n * **This is not availabe for `type='submit'` or `type='reset'`**\n *\n * If using `type='checkbox'` a `model-value` of `true` means checked, `false` means unchecked and `null` means indeterminate (tri-state)\n * For `type='radio'` `null` is equal to `false`\n */\n modelValue: {\n type: [Boolean, String],\n default: null\n },\n /**\n * The value used for the `modelValue` when this component is used with radio behavior\n * Similar to the `value` attribute of ``\n */\n value: {\n type: String,\n default: null\n },\n /**\n * Small underlying text content of the entry\n */\n description: {\n type: String,\n default: \"\"\n }\n },\n setup() {\n return {\n mdiCheck,\n mdiChevronRight\n };\n },\n computed: {\n /**\n * determines if the action is focusable\n *\n * @return {boolean} is the action focusable ?\n */\n isFocusable() {\n return !this.disabled;\n },\n /**\n * The current \"checked\" or \"pressed\" state for the model behavior\n */\n isChecked() {\n if (this.type === \"radio\" && typeof this.modelValue !== \"boolean\") {\n return this.modelValue === this.value;\n }\n return this.modelValue;\n },\n /**\n * The native HTML type to set on the button\n */\n nativeType() {\n if (this.type === \"submit\" || this.type === \"reset\") {\n return this.type;\n }\n return \"button\";\n },\n /**\n * HTML attributes to bind to the