I'm using Cypress.io to automate one file upload test case based on a react page. The input component(type=file) for file upload is created during runtime when the page is rendered.
Seems the button (by clicking the 'Choose file') opens a native file picker, which cypress Webdriver doesn't seem to support interacting with, so probably trigger an event to simulate file selection can be an option in this case. But the input(type=file) can't be located by Cypress because it is not a part of DOM, which means cy.get('input[type=file]') returns null.
Could you please give me some thoughts how to do it? this button opens a native file picker
I've tried with this -
const testfile = new File(['test data to upload'], 'upload.csv')
cy.get('input[type=file]').trigger('change', {
force: true,
data: testfile,
});
this brings no luck,because of CypressError: Timed out retrying: Expected to find element: 'input[type=file]', but never found it.
The source code of the page:
import React, { Component } from 'react'
interface Props {
text?: string
type?: string | undefined
fileID?: string
onFileSelected: (file: any) => void
}
interface State {
name: string
}
export default class FileUpload extends Component<Props, State> {
fileSelector = document.createElement('input')
state: State = {
name: '',
}
componentDidMount() {
this.fileSelector = this.buildFileSelector()
}
buildFileSelector = () => {
const { fileID, type } = this.props
this.fileSelector.setAttribute('type', 'file')
this.fileSelector.setAttribute('id', fileID || 'file')
this.fileSelector.setAttribute('multiple', 'multiple')
this.setAcceptType(type)
this.fileSelector.onchange = this.handleFileChange
return this.fileSelector
}
setAcceptType = (type: string | undefined) => {
if (type) {
type = type[0] === '.' ? type : type.replace(/^/, '.')
this.fileSelector.setAttribute('accept', type)
}
}
handleFileChange = (event: any) => {
const file = event.target.files[0]
if (file) {
this.setState({ name: file.name })
this.props.onFileSelected(file)
}
}
render() {
const { name } = this.state
return (
<div>
<button
onClick={(event: React.ChangeEvent<any>) => {
event.preventDefault()
this.fileSelector.click()
}}
style={{ marginRight: 10 }}
>
{this.props.text || 'Choose file'}
</button>
<label>{name || 'No file chosen'}</label>
</div>
)
}
}
I look forward to receiving suggestions how to automate this 'choose file' action in Cypress. Thanks in advance.