Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation - REST API GET & POST commands #1541

Closed
thim81 opened this issue Aug 4, 2017 · 15 comments
Closed

Documentation - REST API GET & POST commands #1541

thim81 opened this issue Aug 4, 2017 · 15 comments
Labels

Comments

@thim81
Copy link

thim81 commented Aug 4, 2017

After having a lot of struggle to hook in API REST calls in a test scenario, I wanted to share my code.

Based on several discussions on StackOverflow and GitHub (#444), I landed on this result:

1) Install a HTTP client

npm install request --save

PS: I know that there are better HTTP clients but this one works for now

2) Add custom commands

in the commands folder, add the following files:

  • ./commands/apiGet.js
  • ./commands/apiPost.js

PS: I know that there are better manners to implement the Request methods using Promises, but for now it works.

The apiGet.js content:

var util = require('util');
var events = require('events');

function apiGet () {}
util.inherits(apiGet, events.EventEmitter);

apiGet.prototype.command = function(apiUrl, success) {
  var request = require("request");

  request.get(apiUrl, function (error, response) {
    if (error) {
      console.log(error);
      return;
    }

    success(response);
    this.emit('complete');
  }.bind(this));
};

module.exports = apiGet;

The apiPost.js content:

var util = require('util');
var events = require('events');

function apiPost () {}
util.inherits(apiPost, events.EventEmitter);

apiPost.prototype.command = function (apiUrl, postBody, postHeaders, postAuth, success) {
    var request = require("request");

    var options = {
        uri: apiUrl,
        method: "POST",
        json: postBody
    };

    if (postHeaders !== undefined) {
        options.headers = postHeaders;
    }
    if (postAuth !== undefined) {
        options.auth = postAuth;
    }

    request(options, function (error, response) {
        if (error) {
            console.log(error);
            return;
        }

        success(response);
        this.emit('complete');
    }.bind(this));
};

module.exports = apiPost;

3) Update nightwatch.json

add the following to your nightwatch config

` "custom_commands_path": "./commands",

Test GET sample

module.exports = {
  "Retrieve API (GET)": function (client) {
        var apiUrl = 'https://dog.ceo/api/breeds/list/all';
    client.apiGet(apiUrl, function (response) {
      console.log(response.body);
      var data = JSON.parse(response.body);
      console.log(data.status);

      client.assert.equal(response.statusCode, 200, "200 OK");

      client.end();
    });

  }

};

Test POST sample

module.exports = {
  "Retrieve API (POST)": function (client) {
        var apiUrl = 'https://your-api-endpoint/;
 var postData = {'lorem':'ipsum'};
    client.apiPost(apiUrl, postData, function (response) {
      console.log(response.body);
      var data = JSON.parse(response.body);
      console.log(data.status);

      client.assert.equal(response.statusCode, 200, "200 OK");

      client.end();
    });

  }

};
@m1r342b2r
Copy link

Thanks a lot for your post! I appreciate this collaboration.
Only must be correct two things on the code of Post Example: the close quote to the end in the variable apiUrl and client.apiPost(... on cclient.apiPost(...
Thanks for all again!

@enuggetry
Copy link

I can't seem to get this working at all.
I don't get any errors running the test.
It just never seems to reach the callback.
What am i doing wrong??

This is my test:

var nightwatch = require('nightwatch');

var nightwatchTest = 'default';
var nightwatchConf = require('../../nightwatch.conf.js');
var nw_conf = Object.assign(nightwatchConf.test_settings[nightwatchTest]);
var client = nightwatch.initClient(nw_conf);
var browser = client.api();

describe('ServiceController', function() {
    it('it should get login state', function (done) {
        browser.apiGet('http://localhost/loginstate', function (response) {

            console.log('*** we never get here ***);

            var data = JSON.parse(response.body);
            console.log('>>>>>>>>>>>> status',data.status);
            client.assert.equal(response.statusCode, 200, "200 OK");
        });
        done();
    });
});

@saileshbotcha
Copy link

saileshbotcha commented Nov 3, 2017

Hi, I have a Query : I want to get the href value of a link and get HttpResponse status code for that, how can it be done ?? Instead of clicking on each link and asserting the page i want to get the http response code of each link href value..suggest me if any other solution for this

@jesse-custer
Copy link

Hello !
it works and that's great !

In my use I would like to know how to add a header with an Authorization and a Content-Type on your "Test POST sample" ? would it be possible to help me on that ?

thank you very much for your help :)

@thim81
Copy link
Author

thim81 commented Nov 9, 2017

@enuggetry

Have you put the commands in the right folder?

./commands/apiGet.js
./commands/apiPost.js

And make sure that in nightwatch.json the following path is added

` "custom_commands_path": "./commands",

In case you have a different custom_commands_path, you should put the files in there.

@thim81
Copy link
Author

thim81 commented Nov 9, 2017

@saileshbotcha

I have not tested this, but it could point you in the right direction:

Rough idea:

"Retrieve Link status (GET)": function (client) {
    var apiUrl = '';
    client.getAttribute('.blabla-link', 'href', function (link) {
        apiUrl = link.value;
    });
    
    client.apiGet(apiUrl, function (response) {
        console.log(response.body);
        var data = JSON.parse(response.body);
        console.log(data.status);

        client.assert.equal(response.statusCode, 200, "200 OK");

        client.end();
    });

}

@thim81
Copy link
Author

thim81 commented Nov 9, 2017

@jesse-custer

Then you could something like this.

REMARK: not fully tested

module.exports = {
"Retrieve API (POST)": function (client) {
var apiUrl = 'https://your-api-endpoint/';
var postData = {'lorem': 'ipsum'};
var postHeaders = {'Content-Type': 'application/json'};
var postAuth = {'user': 'loginname', 'password': 'loginpassword'};

    client.apiPost(apiUrl, postData,postHeaders,postAuth, function (response) {
        console.log(response.body);
        var data = JSON.parse(response.body);
        console.log(data.status);

        client.assert.equal(response.statusCode, 200, "200 OK");

        client.end();
    });

}

};

@jesse-custer
Copy link

indeed ! it works thank you very much !

@thim81
Copy link
Author

thim81 commented Nov 9, 2017

@jesse-custer

I have updated the POST command code above to support this case.

I know it's not perfect but feel free to improve it.

@hayds
Copy link

hayds commented Dec 12, 2017

Thanks this helped me heaps!

I chose to refactor my apiGet function to be more in line with the current format of the examples provided for custom commands.

I am not sure how accurate/safe it is but it's working fine for me, but any feedback is welcomed.

var util = require('util');
var events = require('events');
var request = require('request');
function apiGet () {
  events.EventEmitter.call(this);
}
util.inherits(apiGet, events.EventEmitter);

apiGet.prototype.command = function(options, callback) {
  var self = this;
  this.api.perform(function() {
    setTimeout(function() {
      defaultOptions = {
        method: 'GET',
        json : true,
      };
      options = Object.assign(defaultOptions, options);

      request(options, function(error, response){
        if (error) {
          console.error(error);
          return;
        }
        if (callback) {
          callback(response);
        }
      });
      self.emit('complete');
    }, 10);
  });
  return this;
};

module.exports = apiGet;

The call in a test

var url = 'http://yourapi.com/api/lookup?query=whatever'
var data;
browser.apiGet({
  uri: url,
  auth: {
    'user': 'username',
    'password': 'password123',
  },
}, function(response) {
  data = response.body;
});

@saileshbotcha
Copy link

@thim81

Thanks for your response , I have tried like this but I get below error when i run my Code
Error: options.uri is a required argument

My Requirement is to check Http Response status for all the links present on a web Page instead of clicking and checking each link separately.
Below is my apiGet.js under Commands:

 var util = require('util');
 var events = require('events');

 function apiGet () {}
 util.inherits(apiGet, events.EventEmitter);

 apiGet.prototype.command = function(apiUrl, success) {
       var request = require("request");

       request.get(apiUrl, function (error, response) {
    if (error) {
        console.log(error);
        return;
    }

       success(response);
       this.emit('complete');
    }.bind(this));
};

 module.exports = apiGet;

Below is Test code , I took an example of facebook url here

   "HrefStatus": function (client) {
        var apiUrl = '';
       client.maximizeWindow()
           .url('https://www.facebook.com/');
        client.elements('css selector', ' a', function (result) {
             for (var a = 0; a < result.value.length; a++) {
                 client.elementIdAttribute(result.value[a].ELEMENT, 'href', function (link) {
                    console.log('tags :' + link.value);
                    apiUrl = link.value;
              });

               client.apiGet(apiUrl, function (response) {
                   console.log(response.body);
                   var data = JSON.parse(response.body);
                   console.log(data.status);

                  client.assert.equal(response.statusCode, 200, "200 OK");

               });
           }
       });
   }

@stale
Copy link

stale bot commented Nov 14, 2018

This issue has been automatically marked as stale because it has not had any recent activity.
If possible, please retry using the latest Nightwatch version and update the issue with any relevant details. If no further activity occurs, it will be closed. Thank you for your contribution.

@stale stale bot added the stale label Nov 14, 2018
@stale stale bot closed this as completed Nov 21, 2018
@sumanthhegde04
Copy link

Hi All,

When I am using Success function in apipost.js in commands file, Why I am getting Success is not valid function. Please need the help how to overcome this issue.

Thanks,

@Adrian-Tamas
Copy link

Hi All,

When I am using Success function in apipost.js in commands file, Why I am getting Success is not valid function. Please need the help how to overcome this issue.

Thanks,

when doing the request you need to specify all the params not just the ones in the example:
If your command is defined as:
command(apiUrl, postBody, postHeaders=null, postAuth=null, success)

then the call is like this if you don't have headers or oath:
client.apiPost(url, payload, null, null, function (response) { ... })

@prajwalhp7
Copy link

I can't seem to get this working at all. I don't get any errors running the test. It just never seems to reach the callback. What am i doing wrong??

This is my test:

var nightwatch = require('nightwatch');

var nightwatchTest = 'default';
var nightwatchConf = require('../../nightwatch.conf.js');
var nw_conf = Object.assign(nightwatchConf.test_settings[nightwatchTest]);
var client = nightwatch.initClient(nw_conf);
var browser = client.api();

describe('ServiceController', function() {
    it('it should get login state', function (done) {
        browser.apiGet('http://localhost/loginstate', function (response) {

            console.log('*** we never get here ***);

            var data = JSON.parse(response.body);
            console.log('>>>>>>>>>>>> status',data.status);
            client.assert.equal(response.statusCode, 200, "200 OK");
        });
        done();
    });
});

Hey, Did you get it worked?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

9 participants