Skip to content

Commit

Permalink
feat(UploadPicker): Use @nextcloud/files filename validation by def…
Browse files Browse the repository at this point in the history
…ault

This allows to make use of Nextcloud 30 server capabilities.

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
  • Loading branch information
susnux committed Aug 6, 2024
1 parent f269d36 commit 40213fd
Show file tree
Hide file tree
Showing 7 changed files with 749 additions and 219 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
// eslint-disable-next-line import/no-unresolved,n/no-missing-import
import { Folder, Permission, addNewFileMenuEntry, type Entry } from '@nextcloud/files'
import { generateRemoteUrl } from '@nextcloud/router'
import { UploadPicker, getUploader } from '../../lib/index.ts'
import { basename } from 'path'
import { UploadPicker, getUploader } from '../../../lib/index.ts'

let state: string | undefined
before(() => {
Expand Down Expand Up @@ -114,155 +113,6 @@ describe('UploadPicker valid uploads', () => {
})
})

describe('UploadPicker invalid uploads', { testIsolation: true }, () => {

// Cypress shares the module state between tests, we need to reset it
// ref: https://github.com/cypress-io/cypress/issues/25441
beforeEach(() => {
getUploader(false, true)
})

afterEach(() => resetDocument())

it('Fails a file if forbidden character', () => {
// Make sure we reset the destination
// so other tests do not interfere
const propsData = {
destination: new Folder({
id: 56,
owner: 'user',
source: generateRemoteUrl('dav/files/user'),
permissions: Permission.ALL,
root: '/files/user',
}),
forbiddenCharacters: ['$', '#', '~', '&'],
}

// Mount picker
cy.mount(UploadPicker, { propsData }).as('uploadPicker')

// Label is displayed before upload
cy.get('[data-cy-upload-picker]').shouldHaveTrimmedText('New')

// Check and init aliases
cy.get('[data-cy-upload-picker] [data-cy-upload-picker-input]').as('input').should('exist')
cy.get('[data-cy-upload-picker] .upload-picker__progress').as('progress').should('exist')

// Intercept single upload
cy.intercept('PUT', '/remote.php/dav/files/*/*', (req) => {
req.reply({
statusCode: 201,
delay: 2000,
})
}).as('upload')

// Upload 2 files
cy.get('@input').attachFile({
// Fake file of 5 MB
fileContent: new Blob([new ArrayBuffer(2 * 1024 * 1024)]),
fileName: 'invalid-image$.jpg',
mimeType: 'image/jpeg',
encoding: 'utf8',
lastModified: new Date().getTime(),
})

cy.get('@input').attachFile({
// Fake file of 5 MB
fileContent: new Blob([new ArrayBuffer(2 * 1024 * 1024)]),
fileName: 'valid-image.jpg',
mimeType: 'image/jpeg',
encoding: 'utf8',
lastModified: new Date().getTime(),
})

cy.get('[data-cy-upload-picker] .upload-picker__progress')
.as('progress')
.should('not.be.visible')

cy.wait('@upload')
// Should not have been called more than once as the first file is invalid
cy.get('@upload.all').should('have.length', 1)
cy.contains('[role="dialog"]', 'Invalid file name')
.should('be.visible')
})

it('Can rename invalid files', () => {
// Make sure we reset the destination
// so other tests do not interfere
const propsData = {
destination: new Folder({
id: 56,
owner: 'user',
source: generateRemoteUrl('dav/files/user'),
permissions: Permission.ALL,
root: '/files/user',
}),
forbiddenCharacters: ['$', '#', '~', '&'],
}

// Mount picker
cy.mount(UploadPicker, { propsData }).as('uploadPicker')

cy.wait(4000)

// Label is displayed before upload
cy.get('[data-cy-upload-picker]').contains('New').should('be.visible')

// Check and init aliases
cy.get('[data-cy-upload-picker] [data-cy-upload-picker-input]').as('input').should('exist')
cy.get('[data-cy-upload-picker] .upload-picker__progress').as('progress').should('exist')

// Intercept single upload
cy.intercept('PUT', '/remote.php/dav/files/*/*', (req) => {
req.reply({
statusCode: 201,
delay: 2000,
})
}).as('upload')

// Upload 2 files
cy.get('@input').attachFile({
// Fake file of 5 MB
fileContent: new Blob([new ArrayBuffer(2 * 1024 * 1024)]),
fileName: 'invalid-image$.jpg',
mimeType: 'image/jpeg',
encoding: 'utf8',
lastModified: new Date().getTime(),
})

cy.get('@input').attachFile({
// Fake file of 5 MB
fileContent: new Blob([new ArrayBuffer(2 * 1024 * 1024)]),
fileName: 'valid-image.jpg',
mimeType: 'image/jpeg',
encoding: 'utf8',
lastModified: new Date().getTime(),
})

cy.get('[data-cy-upload-picker] .upload-picker__progress')
.as('progress')
.should('not.be.visible')

cy.contains('[role="dialog"]', 'Invalid file name')
.should('be.visible')
.contains('button', 'Rename')
.click()

cy.wait('@upload')
// Should have been called two times with an valid name now
cy.get('@upload.all').should('have.length', 2).then((array): void => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const requests = (array as unknown as any[]).map(({ request }) => basename(request.url))
// The valid one is included
expect(requests).to.contain('valid-image.jpg')
// The invalid is NOT included
expect(requests).to.not.contain('invalid-image$.jpg')
// The invalid was made valid
expect(requests).to.contain('invalid-image-.jpg')
})
})
})

describe('NewFileMenu handling', () => {
const propsData = {
destination: new Folder({
Expand Down
Loading

0 comments on commit 40213fd

Please sign in to comment.