The challenge is to download an excel file and check its content in headless browsers (Chrome). Thanks to my coworker, we finally can accomplish this task. Although this is an example for Excel file, you can use it for another type of files.

I am using WebdriverIO and Mocha for our regression test, and the package that I used to download files is download-file. It’s pretty simple.

Step 1: Write your asynchronous test:

const page = require('./page.js'); describe('Assert file download function:', () => {

before( () => {

browser.url('/');

});



it('Download an Excel file', async () => {

await page.downloadExcelFile();

await page.assertExcelFile();

});

});

Step 2: Write your download and assert functions

Before downloading, you need to install this package:

npm install download-file

Then write your download function. This will help to download your excel file and put it on tempDownload folder.

// page.js downloadExcelFile() {

// Get excel url

let excelUrl = $(this.excelBtn).getAttribute('href');



let options = {

directory: './tempDownload',

filename: 'file-name.xlsx'

} return new Promise(async (reject) => {

download(excelUrl, options, err => {

reject(err);

});

});

}

Them write your testing function. Just to let you know that I’m using xlsx package to read the content of an excel file.

// page.js async assertExcelFile() {

const filePath = path.join('your-download-dir', 'file-name.xlsx'); browser.call(() => {

return waitForFileExists(filePath, 10000);

}); let workbook = XLSX.readFile(filePath);

let firstSheetName = workbook.SheetNames[0];

let workSheet = workbook.Sheets[firstSheetName];

// Do what ever you want here. Remember to read the document // Remove temporary download folder

rmdir('your-download-dir');

}

You may wonder where the waitForFileExists and rmdir come from. Well they are extra functions that help to check whether the file exists before testing and make sure that the download folder will be deleted after the test.

// wait_for_file_exists.js const fs = require('fs')

const path = require('path')

module.exports = function waitForFileExists(filePath, timeout) {

return new Promise(function (resolve, reject) {

let timer = setTimeout(function () {

watcher.close();

reject(new Error('File did not exists and was not created during the timeout.'));

}, timeout);



fs.access(filePath, fs.constants.R_OK, function (err) {

if (!err) {

clearTimeout(timer);

watcher.close();

resolve();

}

}); // pulled from https://stackoverflow.com/a/47764403 module.exports = function waitForFileExists(filePath, timeout) {return new Promise(function (resolve, reject) {let timer = setTimeout(function () {watcher.close();reject(new Error('File did not exists and was not created during the timeout.'));}, timeout);fs.access(filePath, fs.constants.R_OK, function (err) {if (!err) {clearTimeout(timer);watcher.close();resolve();}); let dir = path.dirname(filePath);

let basename = path.basename(filePath);

let watcher = fs.watch(dir, function (eventType, filename) {

if (eventType === 'rename' && filename === basename) {

clearTimeout(timer);

watcher.close();

resolve();

}

});

});

}

For remove folder function:

// rmdir.js const path = require('path')

const fs = require('fs')

module.exports = function rmdir(dir) {

let list = fs.readdirSync(dir);

for(let i = 0; i < list.length; i++) {

let filename = path.join(dir, list[i]);

let stat = fs.statSync(filename); // Pulled from https://gist.github.com/tkihira/2367067 module.exports = function rmdir(dir) {let list = fs.readdirSync(dir);for(let i = 0; i < list.length; i++) {let filename = path.join(dir, list[i]);let stat = fs.statSync(filename); if(filename == "." || filename == "..") {

// pass these files

} else if(stat.isDirectory()) {

// rmdir recursively

rmdir(filename);

} else {

// rm fiilename

fs.unlinkSync(filename);

}

}

fs.rmdirSync(dir);

}

From now, you can download any files in Chrome headless. I haven’t tried with other drivers yet.

Hope this help ;)