I'm using the needle npm package to check the Status Code of a page under test in my Nightwatchjs test script.
My code is;
var needle = require('needle');
module.exports = {
'#tags':['bug'],
'Page status code = 200': function (browser) {
browser.perform(function() {
needle.get(browser.globals.mcnMemberSiteUrl, function (error, response) {
if (!error && response.statusCode == 200) {
console.log('page status code = ', response.statusCode);
}
});
});
},
What I'd now like to do is carry on with testing on this page.
For example, assert that an element is present on the page.
Is it possible to do this, or would I have to reload the page, by using the conventional;
browser.url(browser.globals.mcnMemberSiteUrl)
and then assert the element in the usual way (browser.assert.elementPresent....)?
If so, this seems a bit of an anomaly as in theory I'd be checking the Status Code of the 'needle' loaded page, and the reloaded page my not have a 200 page status code (appreciate unlikely).
Any help would be appreciated.
Related
How to make through an interval requests before tests?
I tried 2 ways to retry requests but either was failing;
I need to upload a file, waiting till one got imported successfully
On the first step i upload a file to my server in cypress
before( ()=> {
//my custom POST command
cy.form_request(url, data)
.then(({id}) => {
Then i wait for id of the uploaded file
check_It_Till_Success_It(id);
})
})
Then the received id i pass into a new request to verified its status on the server and need to repeat the request till the file processing is finished.
At the solution below it says
CypressError: cy.wait() only accepts aliases for routes.
The alias: 'check_it_request' did not match a route.
function check_It_Till_Success_It(id) {
function checkRequest() {
cy.request("GET", "http://localhost:28080/admin/api/catalog/import/status/" + id)
.then(({status}) => {
if (status === "FINISHED" || status === "FAILED") {
clearInterval(check_It);
} else {
console.log('retry one more time');
}
}).as('check_it_request');
cy.wait("#check_it_request");
}
checkRequest();
const check_It = setInterval(checkRequest, 1000);
}
or here is another my solution through a recursive requesting:
function check_It_Till_Success_It(id) {
return (
cy.request("GET", BASE_URL + "/admin/api/catalog/import/status/" + id)
.then(({status}) => {
if (status === "FINISHED" || status === "FAILED") {
console.log('success');
} else {
console.log('retry one more time');
setTimeout(() => check_It_Till_Success_It(id), 1000)
}
})
)
}
but it throws an error:
Uncaught CypressError: Cypress detected that you returned a promise from a command while also invoking one or more cy commands in that promise.
What am i doing wrong?
I found my mystake because of the use of native JS tools as setTimeout, setInterval.
Cypress doesnt allow to use them and replaces with controllable methods: cy.clock and cy.tick
So i took the recursion implementation and replaced with the methods above and my code became:
function check_It_Till_Success_It(id) {
cy.request("GET", BASE_URL + "/admin/api/catalog/import/status/" + id)
.then(resp => {
const status = resp.body.status;
if (status === "FINISHED" || status === "FAILED") {
console.log('success');
} else {
console.log('retry one more time');
cy.clock();
cy.tick(1000);
check_It_Till_Success_It(id)
}
})
}
Offtopic note: I'm new with Cypress and as i understood it replaces the most of the js native features so it's needed to look the docs much closer (BINGO!) or look at issue section because some JS specific feature just crash Cypress without any notification or catched error, for example: FormData object crashed Cypress'es request method.
Ok, so I'm looking to test the https response code of a URL using Nightwatch.js.
I've install the npm 'request' package, and successfully tested the response of the URL under test using the following code;
var request = require('request');
request('http://www.google.com', function (error, response, body) {
if (response.statusCode != 200)
console.log("error!!!")
});
My problem is 'converting' this working (request) code into a standard nightwatch.js setup, so that if the response code is not a 200 then the test will fail?
At the moment my nightwatch.js scripts begin with, for example;
module.exports = {
'test response code': function (browser) {
browser
and I would like to keep it in a similar format.
Any help would be greatly appreciated.
You can use the perform() method from nightwatch: http://nightwatchjs.org/api/perform.html
In the perform block you can write every code you want, you can also youse every assertion library. A simple example, based on yours, could look like this:
var request = require('request');
var assert = require('assert')
module.exports = {
'test response code': function (browser) {
browser.perform(done => {
request('http://www.google.com', function (error, response, body) {
assert.ok(response.statusCode == 200)
done()
})
})
}
}
I am running this test and it seems that when the test get's to the function portion of my describe block, it skips the whole thing and gives a false positive for passing.
// required libraries
var webdriverio = require('webdriverio');
var describe = require('describe');
var after = require('after');
console.log("Lets begin");
describe('Title Test for google site', function() {
console.log("MARTY!!");
// set timeout to 10 seconds
this.timeout(10000);
var driver = {};
console.log("before we start");
// hook to run before tests
before( function (done) {
// load the driver for browser
console.log("before browser");
driver = webdriverio.remote({ desiredCapabilities: {browserName: 'firefox'} });
driver.init(done);
});
it('should load correct page and title', function () {
// load page, then call function()
return driver
.console.log("before site")
.url('http://www.ggogle.com')
// get title, then pass title to function()
.getTitle().then( function (title) {
// verify title
(title).should.be.equal("google");
// uncomment for console debug
// console.log('Current Page Title: ' + title);
});
});
});
// a "hook" to run after all tests in this block
after(function(done) {
driver.end(done);
});
console.log ("Fin");
This is the output I get
Lets begin
Fin
[Finished in 0.4s]
As you can see it skips everything else.
This is wrong and should be removed:
var describe = require('describe');
var after = require('after');
Mocha's describe and after are added to the global space of your test files by Mocha. You do not need to import them. Look at all the examples on the Mocha site, you won't find anywhere where they tell you to import describe and its siblings.
To get Mocha to add describe and its siblings, you need to be running your test through mocha. Running node directly on a test file won't work. And for mocha to be findable it has to be in your PATH. If you installed it locally, it is (most likely) not in your PATH so you have to give the full path ./node_modules/.bin/mocha.
This time I want to use res.render to display html as success of DB update. I did it several times, but this time it doesn't work. It's not render html file, just displayed on chrome's console.
I think it caused because of async problem or duplicated response. I tried to many ways but I couldn't solve it, so pointers appreciated.
The code is related when the user paid service, increase user's level.
Get Access Token => Validate => res.render
app.post('/payment/validate', function(req, res, next){
// Get access token
request.post({
url : 'https://payment-company/get/token'
}, function(err, response, body) {
if(!err & response.statusCode == 200) {
var result = JSON.parse(body);
var accessToken = result.response.access_token;
// Validate payment (compare paid and would be paid)
request.get({
headers : { 'Authorization' : accessToken }
url : 'https://payment-company/find/paymentid'
}, function (err, response, body) {
if (!err && response.statusCode == 200){
var result = JSON.parse(body);
if (result.response.amount == req.body.price){
Members.findOne({id : req.user.id}, function(err, member){
// If no problem, update user level
member.level = 2;
member.save(function(err, result){
if (err) return next();
res.render('payment.view.result.ejs',
{
title : 'Success !',
description : 'level up.'
});
});
});
}
} else {
...
}
});
}
})
});
sorry to verbose code I tried to shorten code, No problem until res.render, res.render will work but it's not display page instead it just send html code to chrome's console.
Looks like there's a bit of a misunderstanding of how these requests work. What I think you intend:
Browser makes a GET request, server responds with an HTML document, the browser renders it
User takes an action
Browser makes a POST request, server responds with an HTML document, the browser renders it
What you've started coded on the frontend is an alternate method:
You make a POST request via AJAX, server responds with some JSON, you modify the current document with JavaScript to let the user know
Now I ran into a problem with managing ajax requests on nodeJS server. Currently I have this system it works, but it's ugly and not that efficient.
router.post('/get', function(req, res) {
var request = req.body.request;
if (request == null) {
res.json({success: 'false', error: 'Response returned null'});
return;
}
if (request == "render_page") {
var page = req.body.page;
if (page == null) {
res.json({success: 'false', error: 'Page returned null'});
return;
}
res.render(page);
} else if (request == "render_article") {
var temp = {
articles: [
{title: 'ABC', text: 'This is a test article'},
{title: 'XYZ', text: 'Just another random article'}
]
};
res.render('template/article-format', temp);
} else {
res.json({success: 'false', error: "Unknown request " + request});
}
Is there a better way to do this and even maybe make it dynamic? Also the server likes to crash if something goes wrong so there's that.
You seem to be fighting with the concepts of GET and POST. GET requests are supposed to be used for fetching things (like pages). Yet, you have specified a POST request, then named it /get, and then put the context in the request body.
If you simply leveraged some parameters in your GET requests, then you don't need to send a post with body (which I'm assuming you are using a POST request because you thought you needed to be able to send the request context data, in this case the page name).
So, you have a bunch of get requests that are being called as post requests. Really what you want is something like this:
router.get('/page/:page', function(req, res) {
var page = req.params.page;
// Logic here
});
And for handling the "null" page, you just route them to the /page url automatically (since if there is no parameter, it is just the /page url).
For further reading, I'd look over:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
http://expressjs.com/4x/api.html#req