How can I make a POST request from a Protractor test?
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();
Related videos on Youtube
aknuds1
Pragmatic Go/Rust/JavaScript ++ software engineer Homepage GitLab LinkedIn profile
Updated on September 15, 2022Comments
-
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?
-
Andres D about 10 years
-
-
aknuds1 about 10 yearsNot familiar with onPrepare, but would this be run once for the whole suite? I would really need per-test setup/teardown methods.
-
rjferguson21 about 10 yearsYes, it is run once, before any tests are run. It doesn't sound like onPrepare would do what you want.
-
Ricbermo almost 10 yearswhere does this angular at 3rd line come from?. I got undefined angular.
-
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 almost 10 yearsflow.await seems to work in an
it
orbeforeEach
function also; I don't think there's a restriction toonPrepare
. -
afternoon over 9 yearsForgive me if I'm missing something, but doesn't
await
expect a promise? Protractor allows you to return a promise from anonPrepare
function, so you could just doreturn setup_data({data: 'test'});
. -
rjferguson21 over 9 yearsThis was written prior to Protractor 1.1.0, before onPrepare allowed you to return a promise. It could indeed be simplified.