How can I make a POST request from a Protractor test?

18,021

Solution 1

I found a way to do it, with the help of Andres D. The gist of it is to run a script in the browser via browser.executeAsyncScript and inject the $http service in there. The $http service is then told to make a POST request. Here's example CoffeeScript of how it's done:

browser.get('http://your-angular-app.com')
browser.executeAsyncScript((callback) ->
  $http = angular.injector(["ng"]).get("$http")
  $http(
    url: "http://yourservice.com"
    method: "post"
    data: yourData
    dataType: "json"
  )
  .success(->
    callback([true])
  ).error((data, status) ->
    callback([false, data, status])
  )
)
.then((data) ->
  [success, response] = data
  if success
    console.log("Browser async finished without errors")
  else
    console.log("Browser async finished with errors", response)
)

Solution 2

You can just use another library to run the POST request if you just want to populate your database.

For example, you can use superagent in your beforeEach like so:

var request = require( "superagent" );

describe( "Something", function() {

  beforeEach( function( done ) {
    request
      .post( "http://localhost/api/foo" )
      .send( {data : "something"} )
      .end( done );
  } );

} );

Solution 3

It is possible to run some async setup code in your onPrepare function of your protractor config. You need to explicitly tell protractor to wait for your request to finish. This can be done with flow.await() which plays nice with promises.

onPrepare: function() {

  flow = protractor.promise.controlFlow()

  flow.await(setup_data({data: 'test'})).then( function(result) {
    console.log(result);
  })

}

** As of protractor 1.1.0 on prepare can return a promise, so the use of flow to explictly wait for the promise to resolve is unnecessary.

See: https://github.com/angular/protractor/blob/master/CHANGELOG.md

Solution 4

Another way of doing POST request from protractor is using "http"

const http = require('http');

   const data = yourData; 
   const options = {
        port: portnumber,
        hostname: hostname,  // without http
        path: '/api/path/',
        method: 'POST',
        headers: {
            "content-type": "application/json"                
        }
    };

    const request = http.request(options, function (result) {
        var body = '';

        result.on("data", function (chunk) {
            body = body + chunk;
        });

        result.on("end", function () {
          console.log(body);
        });
    });

    request.write(JSON.stringify(data));
    request.end(); 
Share:
18,021

Related videos on Youtube

aknuds1
Author by

aknuds1

Pragmatic Go/Rust/JavaScript ++ software engineer Homepage GitLab LinkedIn profile

Updated on September 15, 2022

Comments

  • aknuds1
    aknuds1 over 1 year

    I would like to make a POST request (with JSON payload) to a database server prior to running a Protractor test, in order to inject test data. How can I do this, if at all possible?

  • aknuds1
    aknuds1 about 10 years
    Not familiar with onPrepare, but would this be run once for the whole suite? I would really need per-test setup/teardown methods.
  • rjferguson21
    rjferguson21 about 10 years
    Yes, it is run once, before any tests are run. It doesn't sound like onPrepare would do what you want.
  • Ricbermo
    Ricbermo almost 10 years
    where does this angular at 3rd line come from?. I got undefined angular.
  • aknuds1
    aknuds1 almost 10 years
    @Ricbermo I don't have the code in front of me, but it's part of Angular's global API. IIRC that function is executed within the context of the loaded page (e.g., http://your-angular-app.com), which must have loaded Angular.
  • Riley Lark
    Riley Lark almost 10 years
    flow.await seems to work in an it or beforeEach function also; I don't think there's a restriction to onPrepare.
  • afternoon
    afternoon over 9 years
    Forgive me if I'm missing something, but doesn't await expect a promise? Protractor allows you to return a promise from an onPrepare function, so you could just do return setup_data({data: 'test'});.
  • rjferguson21
    rjferguson21 over 9 years
    This was written prior to Protractor 1.1.0, before onPrepare allowed you to return a promise. It could indeed be simplified.