Skip to content

Commit

Permalink
Merge pull request #1471 from nextcloud/backport/1470/stable25
Browse files Browse the repository at this point in the history
  • Loading branch information
skjnldsv authored Nov 18, 2022
2 parents 9d6d19c + 7c30efa commit 155997e
Show file tree
Hide file tree
Showing 12 changed files with 78 additions and 53 deletions.
14 changes: 9 additions & 5 deletions cypress/e2e/mixins/audio.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*
*/

import { randHash } from '../../utils'
import { randHash } from '../../utils/index.js'
const randUser = randHash()

/**
Expand All @@ -29,7 +29,7 @@ const randUser = randHash()
* @param {string} fileName the audio to upload and test against
* @param {string} mimeType the audio mime type
*/
export default function(fileName = 'image1.jpg', mimeType = 'image/jpeg') {
export default function(fileName = 'audio.ogg', mimeType = 'audio/ogg') {
before(function() {
// Init user
cy.nextcloudCreateUser(randUser)
Expand All @@ -49,12 +49,16 @@ export default function(fileName = 'image1.jpg', mimeType = 'image/jpeg') {
.should('contain', fileName)
})

it('Open the viewer on file click', function() {
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}/${fileName}`).as('source')

// Open the file and check Viewer existence
cy.openFile(fileName)
cy.get('body > .viewer').should('be.visible')
})

it('Does not see a loading animation', function() {
// 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')
Expand Down
19 changes: 15 additions & 4 deletions cypress/e2e/mixins/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const randUser = randHash()
* @param {string} source the optional custom source to check against
*/
export default function(fileName = 'image1.jpg', mimeType = 'image/jpeg', source = null) {
let fileId
before(function() {
// Init user
cy.nextcloudCreateUser(randUser)
Expand All @@ -48,14 +49,24 @@ export default function(fileName = 'image1.jpg', mimeType = 'image/jpeg', source

cy.get(`.files-fileList tr[data-file="${fileName}"]`, { timeout: 10000 })
.should('contain', fileName)
.then(row => {
fileId = row[0].dataset.id
})
})

it('Open the viewer on file click', function() {
it('Open the viewer on file click and wait for loading to end', function() {
// Match image request
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')
})

it('Does not see a loading animation', function() {
// 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')
Expand All @@ -73,7 +84,7 @@ export default function(fileName = 'image1.jpg', mimeType = 'image/jpeg', source
cy.get('body > .viewer button.next').should('not.be.visible')
})

it('The image source is the preview url', function() {
it(`The image source is the ${source ? 'remote' : 'preview'} url`, function() {
cy.get('body > .viewer .modal-container img.viewer__file.viewer__file--active')
.should('have.attr', 'src')
.and('contain', source ?? '/index.php/core/preview')
Expand Down
28 changes: 23 additions & 5 deletions cypress/e2e/mixins/oddname.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ import { randHash } from '../../utils/'
/**
* Make a name aimed to break the viewer in case of escaping errors
*
* @param {String} realName
* @returns {String} a name for the file to be uploaded as
* @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`, '
'~⛰️ shot of a $[big} mountain`, '
+ "realy #1's "
+ '" #_+="%2520%27%22%60%25%21%23 was this called '
+ realName
Expand All @@ -50,7 +50,7 @@ Cypress.on('fail', (error, runnable) => {
throw error // throw error to have test still fail
})

export default function(file, type) {
export default function(file, type, sidebar = false) {
const placedName = naughtyFileName(file)

// We'll escape all the characters in the name to match it with css
Expand All @@ -62,7 +62,7 @@ export default function(file, type) {
const folderName
= 'Nextcloud "%27%22%60%25%21%23" >`⛰️<' + file + "><` e*'rocks!#?#%~"

describe(`Open ${file} in viewer with a naughty name`, function() {
describe(`Open ${file} in viewer with a naughty name ${sidebar ? 'with sidebar' : ''}`, function() {
before(function() {
// fail fast
if (failsLeft < 0) {
Expand Down Expand Up @@ -119,6 +119,24 @@ export default function(file, type) {
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.get('.action-button__icon.icon-menu-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__maintitle').should('contain', placedName)
// check we do not have a preview
cy.get('aside.app-sidebar .app-sidebar-header').should('have.class', 'app-sidebar-header--with-figure')
cy.get('aside.app-sidebar .app-sidebar-header').should('have.class', 'app-sidebar-header--compact')
cy.get('aside.app-sidebar .app-sidebar-header .app-sidebar-header__figure').should('have.attr', 'style').should('contain', 'core/filetypes')
})
}

it('Share the folder with a share link and access the share link', function() {
cy.createLinkShare(folderName).then((token) => {
cy.logout()
Expand Down
14 changes: 9 additions & 5 deletions cypress/e2e/mixins/video.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*
*/

import { randHash } from '../../utils'
import { randHash } from '../../utils/index.js'
const randUser = randHash()

/**
Expand All @@ -29,7 +29,7 @@ const randUser = randHash()
* @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') {
export default function(fileName = 'video1.mp4', mimeType = 'video/mp4') {
before(function() {
// Init user
cy.nextcloudCreateUser(randUser)
Expand All @@ -49,12 +49,16 @@ export default function(fileName = 'image1.jpg', mimeType = 'image/jpeg') {
.should('contain', fileName)
})

it('Open the viewer on file click', function() {
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}/${fileName}`).as('source')

// Open the file and check Viewer existence
cy.openFile(fileName)
cy.get('body > .viewer').should('be.visible')
})

it('Does not see a loading animation', function() {
// 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')
Expand Down
3 changes: 3 additions & 0 deletions cypress/e2e/oddname/oddname-sidebar.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import runTest from '../mixins/oddname.js'

runTest('image.png', 'image/png', true)
4 changes: 2 additions & 2 deletions js/viewer-main.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/viewer-main.js.map

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
"@types/dockerode": "^3.3.12",
"@vue/tsconfig": "^0.1.3",
"babel-loader-exclude-node-modules-except": "^1.2.1",
"cypress": "^10.10.0",
"cypress": "^10.11.0",
"cypress-visual-regression": "^1.7.0",
"dockerode": "^3.3.4",
"eslint-plugin-cypress": "^2.12.1",
Expand Down
5 changes: 3 additions & 2 deletions src/mixins/PreviewUrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import { encodePath } from '@nextcloud/paths'
import { generateUrl } from '@nextcloud/router'
import { getToken, isPublic } from '../utils/davUtils.js'
import { encodeFilePath, getDavPath } from '../utils/fileUtils.js'
import { getDavPath } from '../utils/fileUtils.js'

export default {
computed: {
Expand Down Expand Up @@ -73,7 +74,7 @@ export default {
if (hasPreview) {
// TODO: find a nicer standard way of doing this?
if (isPublic()) {
return generateUrl(`/apps/files_sharing/publicpreview/${getToken()}?file=${encodeFilePath(filename)}&${searchParams}`)
return generateUrl(`/apps/files_sharing/publicpreview/${getToken()}?file=${encodePath(filename)}&${searchParams}`)
}
return generateUrl(`/core/preview?${searchParams}`)
}
Expand Down
23 changes: 3 additions & 20 deletions src/utils/fileUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import { dirname } from '@nextcloud/paths'
import { dirname, encodePath } from '@nextcloud/paths'
import { generateUrl } from '@nextcloud/router'
import camelcase from 'camelcase'

import { getRootPath, getToken, getUserRoot, isPublic } from './davUtils.js'
import { isNumber } from './numberUtil.js'

/**
* Get an url encoded path
*
* @param {string} path the full path
* @return {string} url encoded file path
*/
const encodeFilePath = function(path) {
const pathSections = (path.startsWith('/') ? path : `/${path}`).split('/')
let relativePath = ''
pathSections.forEach((section) => {
if (section !== '') {
relativePath += '/' + encodeURIComponent(section)
}
})
return relativePath
}

/**
* Extract dir and name from file path
*
Expand Down Expand Up @@ -151,7 +134,7 @@ const getDavPath = function({ filename, basename, source = '' }) {
if (filename.startsWith(prefixUser)) {
filename = filename.slice(prefixUser.length)
}
return getRootPath() + encodeFilePath(filename)
return getRootPath() + encodePath(filename)
}

export { encodeFilePath, extractFilePaths, sortCompare, genFileInfo, getDavPath }
export { extractFilePaths, sortCompare, genFileInfo, getDavPath }
3 changes: 2 additions & 1 deletion src/views/Viewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,8 @@ export default {
return this.Sidebar && this.Sidebar.file
},
sidebarOpenFilePath() {
return this.currentFile?.davPath?.split(getUserRoot())[1]
const relativePath = this.currentFile?.davPath?.split(getUserRoot())[1]
return relativePath?.split('/')?.map(decodeURIComponent)?.join('/')
},
/**
Expand Down

0 comments on commit 155997e

Please sign in to comment.