Feel Physics
Feel Physics

Reputation: 2783

Async function depends on a external module in Protractor test

I want to

  1. save the image file which is in remote web server, and
  2. upload it to another server

in Protractor Test.

// depend on a external module
var fs = require('fs');

// save remote file(url) to local(dest)
var download = function (url, dest) {

    // let this function be async
    browser.executeAsyncScript(function (url, dest, done) {

        var file = fs.createWriteStream(dest);
        var request = http.get(url, function (response) {
            response.pipe(file);
            file.on('finish', function () {
                file.close(done);
            });
        });
    }, url, dest);
};

describe('', function () {
    it('', function () {
        browser.get('http://...');

        download('http://.../foo.jpg', 'foo.jpg'); /*** DOESN'T WORK! ***/

        var absolutePath = path.resolve(__dirname, 'foo.jpg');
        $('input[type=file]').sendKeys(absolutePath);
        $('#uploadButton').click();
        ...

but this doesn't work:

   Stacktrace:
     UnknownError: javascript error: fs is not defined

When I put var fs = require('fs'); in download function, the error message is below:

   Stacktrace:
     UnknownError: javascript error: require is not defined

Upvotes: 1

Views: 1025

Answers (1)

Andres D
Andres D

Reputation: 8900

When you call executeAsyncScript the function that you pass is serialized an executed inside the browser. The function will not run in the context of your protractor test, but on the browser.

You need to create a promise that resolves when you are done downloading the file.

// depend on a external module
var fs = require('fs');

describe('', function () {

  // save remote file(url) to local(dest)
  var download = function (url, dest) {
      // Create a promise that will be resolved after download.
      var d = protractor.promise.defer();

      var file = fs.createWriteStream(dest);
      var request = http.get(url, function (response) {
          response.pipe(file);
          file.on('finish', function () {
              file.close();
              // The file has been read, resolve the promise
              d. fulfill();
          });
      });

      // Return the promise
      d.promise;
  };

  it('', function () {
      browser.get('http://...');

      // Get the file and wait for the promise to resolve to move on
      download('http://.../foo.jpg', 'foo.jpg').then(function() {
          // Make sure you specify a path where you can write and read the file.
          var absolutePath = path.resolve(__dirname, 'foo.jpg');
          $('input[type=file]').sendKeys(absolutePath);
          $('#uploadButton').click();
          ...
      });

Let me know if it works

Here is the documentation: https://code.google.com/p/selenium/wiki/WebDriverJs#Deferred_Objects

Upvotes: 4

Related Questions