Let's say you have a web application that calls browser FileSystem API to read a file. How do you write an end-to-end test for this app?
The application above shows the system file selection which lets the user pick a local file. Its contents is then pasted into the output text area.
1 | document.getElementById('read-file').addEventListener('click', async () => { |
🎁 You can find the application and the tests in the repo bahmutov/cypress-browser-file-system-example.
Whenever you need to deal with the standard browser APIs in Cypress, take advantage of its unique architecture - you can access each browser object from the test, and then spy or stub its methods. I have shown examples in other blog posts Spy On DOM Methods And Properties, Stubbing The Non-configurable, Stub navigator API in end-to-end tests, Stub window.open, and a few others. In our case, we want to stub the window.showOpenFilePicker
method. Let's do it.
1 | it('shows file contents', () => { |
In general, you need to stub a method before the application calls it. I like stubbing things early to ensure the application sees the stubbed method from the moment it loads. Using cy.visit onBeforeLoad
callback is a good place to set up the stubs.
What should the stub return? It should resolve (which means async result) with a "file handle" object. That object should have a method that resolves with some text. So I will use three different stubs.
1 | cy.visit('/', { |
Nice, but if we want to see the calls in the Command Log and assert they have happened, let's give each stub an alias.
1 | it('shows file contents', () => { |
Beautiful - the test runs.
What happens if the user cancels selecting the file? Hmm, our application does not handle it at all!
We need to handle the errors in our application, at least let's put try / catch
around the code
1 | try { |
Let's test it. Our stub will reject with an error, and we will check if the alert
method is called with excepted message.
1 | it('shows alert when the user cancels', () => { |
The test runs and confirms our application now behaves correctly.
Nice.