Skip to content

Latest commit

 

History

History
80 lines (60 loc) · 3.55 KB

File metadata and controls

80 lines (60 loc) · 3.55 KB

file-upload-react

Tests React component that uploads a file. React source is in index.html, spec files in cypress/integration folder. To run tests

npm run cypress:open

Tests

  • The tests are trying to pass a synthetic test file to upload via an .trigger('change') event passing File reference using event property testFile. In the source code we try to grab this property before accessing the native file reference (which Cypress cannot set until we can fire the native file upload event)
// application code tries to grab the File reference from "testFile" property
// which is set by the end-to-end Cypress test
const file = e.nativeEvent.testFile || e.nativeEvent.target.files[0]

We can confirm that the file gets uploaded by stubbing either XHR request or intercepting the axios library method used by the application's code to actually perform the file upload. See the spec.js how to:

The most generic way to bypass all native event restrictions is to factor out accessing native change event to extract the file into the tiniest application method and stub it from the end-to-end test. Here is the relevant application code:

// browser will run "fileUpload" on change event
<input id="file1" type="file" onChange={this.fileUpload}/>
// inside our component's code
fileUpload (e) {
  const file = this.getFileToUpload(e)
  // upload returned file
},
getFileToUpload (e) {
  // either upload file directly from the event (from a test)
  // or from the DOM file input list
  return e.nativeEvent.testFile || e.nativeEvent.target.files[0]
}
// we set the initialized application instance on the "window" object
// to let test methods access "app.getFileToUpload"
let app = ReactDOM.render(
  <FileUploadApp/>,
  document.getElementById('app')
);
// if the application is being tested from Cypress
// pass the reference to the application instance
// via "window" object, so the tests can directly interact with the app
if (window.Cypress) {
  window.app = app
}

Notice how we factored out accessing the nativeEvent.target.files into its own JavaScript method getFileToUpload? This allows us to stub just that application method from the end-to-end test.

const testFile = new File(['data to upload'], 'upload.txt')
// directly stub the application method that returns the File object to upload
cy.window().its('app')
  .then((app) => {
    cy.stub(app, 'getFileToUpload').returns(testFile)
  })

The rest of the application's code runs "normally" without any stubbing.

Application stubbing

Check out a blog post that describes this technique in general "Shrink the Untestable Code With App Actions And Effects"

Attaches the CSV fixture using the cypress-file-upload. The attached file is parsed by the application using the papaparse library. The test then validates the parsed results.