How we solved the issue of file download & upload in WDIO

Bony Mondal
Capillary Technologies
3 min readApr 18, 2023

Introduction:

As a DevTools developer, we recently built a framework on WDIO ( webdriverIO) with TypeScript language. When it came to adoption, users were facing issues with file upload/download. So we set out to find a solution. In this article, I’ll share how we solved this problem.

Problem Identification:

The first step was identifying the issues:
1. In the case of file download, the prompt which comes when we click on the UI button to download a file didn’t have any access to the web driver session. This meant that we can’t handle it using any of the element operations.
2. For file upload, there is no prompt on the UI where we can upload the file.
We researched more on these issues and found the below solutions

Solution:

File download :

To fix the issue, we used thecdp command, it is a custom command added to the browser scope that allows you to call directly commands to the protocol.

browser.cdp(<domain>, <command>, <arguments>)

The cdp the command can be used to call the Page.setDownloadBehavior command of Devtools Protocol to set the behaviour when downloading a file. Make sure the downloadPath is an absolute path and the browser.cdp() call is made before the file is downloaded.

await browser.cdp('Page', 'setDownloadBehavior', {
behavior: 'allow',
downloadPath: '/home/root/webdriverio-project/',
});

Next, you need to install a dependency @wdio/devtools-service. With this service, you can enhance the wdio browser object to leverage that access and call Chrome DevTools commands within your tests to e.g. intercept requests, throttle network capabilities or take CSS/JS coverage.

The easiest way is to keep @wdio/devtools-service as a devDependency in your package.json, via:

npm install @wdio/devtools-service --save-dev

Configuration

In order to use the service you just need to add the service to your service list in your wdio.conf.js and tsconfig.json, like:

// wdio.conf.js
export const config = {
// ...
services: ['devtools'],
// ...
};
// tsconfig.json
{
"compilerOptions": {
"moduleResolution": "node",
"esModuleInterop": true,
"allowSyntheticDefaultImports":true,
"resolveJsonModule": true,
"types": [
"node",
"webdriverio/async",
// ...
"@wdio/devtools-service"
// ...
],
"typeRoots": [
"node_modules/@types"
],
"target": "es2019"
}
}

and also need to set capabilities in the wdio.conf.js file :

// wdio.conf.js
{
browserName: 'chrome',
acceptInsecureCerts: true,
'goog:chromeOptions': {
args: ['--no-sandbox', '--disable-dev-shm-usage', '--disable-popup-blocking', '--head', '--window-size=1920,1080'],
prefs: {
'download.prompt_for_download':false,
'download.directory_upgrade':true,
'safebrowsing_for_trusted_sources_enabled': false,
'safebrowsing.enabled': false
}
}
},

for setting path of download folder we can keep the dependency “downloads-folder” in our package.json file :

"downloads-folder": "^3.0.3"

File upload :

To fix this issue, we have found on the UI we don’t have any upload field instead of this we have a file upload button e.g.

so we implemented the setValue command in WDIO to set the value of the file path to the input element:

/**
* it is recommended to always use the absolute path of the file as it ensures
* that it can be found by the browser.
*/
const path = require('path');
const filePath = path.join(__dirname, 'path/to/your/file');
fileUpload.setValue(filePath);

Conclusion:

Using WebdriverIO for testing has been a game-changer. Its extensive documentation, built-in features, and ecosystem of plugins have made it easy to write and maintain robust tests. By using the Page Object Model (POM) design pattern, we were able to organize our tests and make them more maintainable. Overall, we highly recommend WebdriverIO to anyone looking for a powerful and easy-to-use UI testing framework.

--

--