selectFile

Selects a file or files in an HTML5 input element or simulates dragging a file or files into the browser.

Syntax

.selectFile(file)
.selectFile(file, options)
.selectFile([file1, file2, ...])
.selectFile([file1, file2, ...], options)

Usage

Correct Usage

cy.get('input[type=file]').selectFile('file.json')
cy.get('input[type=file]').selectFile(['file.json', 'file2.json'])

cy.get('input[type=file]').selectFile({
  contents: Cypress.Buffer.from('file contents'),
  fileName: 'file.txt',
  mimeType: 'text/plain',
  lastModified: Date.now(),
})

cy.get('input[type=file]').selectFile('file.json', { action: 'drag-drop' })
cy.document().selectFile('file.json', { action: 'drag-drop' })

Incorrect Usage

// Errors, cannot be chained off 'cy'
cy.selectFile('file.json')

// Will attempt to find a file called 'file contents'
// on disk, probably not what you intended
cy.get('input[type=file]').selectFile('file contents')

Arguments

file (String, Array, Object or Cypress.Buffer)

Either a single file, or an array of files. A file can be:

  • A path to a file within the project root (the directory that contains the default Cypress configuration file). Eg: 'path/to/file.json'
  • @alias - An alias of any type, previously stored using .as(). Eg: '@alias'
  • A TypedArray containing binary data, such as Uint8Array.from('123'). Cypress.Buffer instances, such as those returned by cy.readFile('file.json', { encoding: null }) or created by Cypress.Buffer.from('foo') are TypedArray instances.
  • An object with a non-null contents property, specifying details about the file. Eg: {contents: '@alias', fileName: 'file.json'}

If an object is provided, it can have the following properties.

OptionDescription
contentsThe contents of the file. This can be a string shorthand as described above, a TypedArray instance containing binary data (such as a Cypress.Buffer instance) or a non-TypedArray object, which will be converted into a string with JSON.stringify() and utf8 encoded.
fileNameThe name of the file. If contents is a path on disk or an alias from cy.readFile() or cy.fixture(), this defaults to the actual filename. In any other case, this defaults to an empty string.
mimeTypeThe mimeType of the file. If omitted, it will be inferred from the file extension. If one cannot be inferred, it will default to an empty string.
lastModifiedThe file's last modified timestamp, in milliseconds elapsed since the UNIX epoch (eg. Date.prototype.getTime()). This defaults to Date.now().

options (Object)

Pass in an options object to change the default behavior of .selectFile().

OptionDefaultDescription
action'select'Switches modes. Valid values are select and drag-drop. See Actions below for more details.
animationDistanceThresholdanimationDistanceThresholdThe distance in pixels an element must exceed over time to be considered animating.
forcefalseForces the action, disables waiting for actionability.
logtrueDisplays the command in the Command log.
timeoutdefaultCommandTimeoutTime to wait for .selectFile() to resolve before timing out.
waitForAnimationswaitForAnimationsWhether to wait for elements to finish animating before executing the command.

Yields

  • .selectFile() yields the same subject it was given from the previous command.

Action

Depending on the action set in the options argument, .selectFile() can simulate two different user behaviors:

select (default)

By default, .selectFile() runs in 'select' mode, mimicking a user selecting one or more files on an HTML5 input element. In this mode, the subject must be a single input element with type="file", or a label element connected to an input (either with its for attribute or by containing the input).

drag-drop

Setting the action to drag-drop changes the behavior of the command to instead mimic a user dragging files from the operating system into the browser, and dropping them over the selected subject. In this mode, the subject can be any DOM element or the document as a whole.

Examples

From a file on disk

cy.get('input[type=file]').selectFile('path/to/file.json')
cy.get('input[type=file]').selectFile('path/to/file.png')

If given a path, .selectFile() will search for the file relative to the project root and attach the file exactly as it exists on disk. This is the preferred way to work with files on disk, avoiding many encoding-related pitfalls.

On a hidden input

cy.get('input[type=file]').selectFile('file.json', { force: true })

In many cases in modern applications, the underlying file input is hidden from view, and activated by a user clicking on a button. In these cases, you will need to tell Cypress to ignore its actionability checks and select the file even though a user would not be able to directly activate the file input.

From a fixture

cy.fixture('file.json', { encoding: null }).as('myFixture')
cy.get('input[type=file]').selectFile('@myFixture')

Note the use of null encoding. By default, cy.fixture() and cy.readFile() attempt to interpret files read from disk, which would result in a JSON file being decoded and re-encoded as a utf-8 string - the contents would be preserved, but formatting would not be and the encoding might change. See cy.fixture or cy.readFile for more details on file encoding.

From an API response

cy.request('http://localhost:8888/users/827').its('body').as('responseBody')

cy.get('input[type=file]').selectFile('@responseBody')

Processing data inside the test

cy.readFile('users.json')
  .then((users) => {
    users[0].username = 'JohnCena'
  })
  .as('myFile')

cy.get('input[type=file]').selectFile('@myFile')

Selecting multiple files

cy.get('input[type=file]').selectFile([
  'file1.json',
  'file2.json',
  'file3.json',
])

Custom fileName, mimeType and lastModified

cy.get('input[type=file][multiple]')
  .selectFile([
    {
      contents: 'cypress/fixtures/example.json',
    },
    {
      contents: 'cypress/fixtures/example.json',
      fileName: 'file.png',
    },
    {
      contents: 'cypress/fixtures/example.json',
      fileName: 'file.png',
      mimeType: 'text/plain',
      lastModified: new Date('Feb 18 1989').valueOf(),
    },
  ])
  .then(($input) => {
    const files = $input[0].files

    // If nothing is specified, the fileName and MIME type will be inferred from the path on disk.:
    expect(files[0].name).to.eq('example.json')
    expect(files[0].type).to.eq('application/json')

    // If the fileName is given, the MIME type will be inferred based on that.
    expect(files[1].name).to.eq('file.png')
    expect(files[1].type).to.eq('image/png')

    // But an explicitly specified MIME type is always used.
    expect(files[2].name).to.eq('file.png')
    expect(files[2].type).to.eq('text/plain')

    // lastModified defaults to the current time, but can be overridden.
    expect(files[0].lastModified).to.be.closeTo(Date.now(), 1000)
    expect(files[1].lastModified).to.be.closeTo(Date.now(), 1000)
    expect(files[2].lastModified).to.eql(new Date('Feb 18 1989').valueOf())
  })

Dropping a file on the document

cy.document().selectFile('file.json', { action: 'drag-drop' })

Notes

Existence

Default file existence assertion

Whenever resolving a file path, .selectFile() asserts that the file exists and will fail if it does not exist. It will retry reading the file if it does not initially exist until the file exists or the command times out.

// will fail after the defaultCommandTimeout is reached
cy.get('input[type=file]').selectFile('does-not-exist.yaml')

Actionability

The element must first reach actionability

.selectFile() is an "action command" that follows all the rules of Actionability.

Rules

Requirements

  • .selectFile() requires being chained off a command that yields DOM element(s). With the input action (default), it further requires a single input element with type="file", or a label element attached to one.
  • If given a path, .selectFile() requires the file must exist.
  • If given an alias, .selectFile() requires that the subject of the alias must not be null or undefined.

Assertions

  • .selectFile() will automatically wait for the element to reach an actionable state.

Timeouts

  • .selectFile() can time out waiting for the element to reach an actionable state.
  • .selectFile() can time out waiting for a file to exist on disk or for an alias to resolve.

Command Log

Select file for input

cy.get('.file-input').selectFile(Cypress.Buffer.from('Hello world'))

The commands above will display in the Command Log as:

Command log for selectFile

When clicking on selectFile within the command log, the console outputs the following:

console.log for selectFile

History

VersionChanges
9.3.0.selectFile() command added
9.4.0Support for TypedArray and mimeType property added. Default fileName name is no longer lost when working with aliases.

Community Recognition

The .selectFile() command draws heavy inspiration from the now-deprecated Cypress File Upload plugin. It was made possible by @abramenal and contributors to the cypress-file-upload repository.

See also