CucumberJs skipping step definition - maybe callback last parameter in step definition? - angularjs

I just started working with cucumberJs, gulp and protractor for an angular app and noticed, luckily as all my steps were passing, that if you don't pass in and use that 'callback' parameter in the step definition, cucumberJs might NOT know when this step is completed and will skip other steps and mark them all as 'passed'
Below is an example from the cucumberJs doc: https://github.com/cucumber/cucumber-js
Example 1:
this.Given(/^I am on the Cucumber.js GitHub repository$/, function (callback) {
// Express the regexp above with the code you wish you had.
// `this` is set to a World instance.
// i.e. you may use this.browser to execute the step:
this.visit('https://github.com/cucumber/cucumber-js', callback);
//
The callback is passed to visit() so that when the job's finished, the
next step can
// be executed by Cucumber
.
});
Example 2:
this.When(/^I go to the README file$/, function (callback) {
// Express the regexp above with the code you wish you had.
Call callback() at the end
// of the step, or callback(null, 'pending') if the step is not yet implemented:
callback(null, 'pending');
});
Example 3:
this.Then(/^I should see "(.*)" as the page title$/, function (title, callback) {
// matching groups are passed as parameters to the step definition
var pageTitle = this.browser.text('title');
if (title === pageTitle) {
callback();
} else {
callback(new Error("Expected to be on page with title " + title));
}
});
};
I understand you have 2 choices here:
a. Either you return a promise and don't pass the call back OR
b. You pass in the callback parameter and call it whenever the step definition is complete so cucumberJs knows to return and go to next step or next scenario.
However, I tried both above and still running into a weird situation where the top two scenarios will work NORMALLY as you would expect, but the third and fourth scenario within that same feature file will be skipped and all passed.
Is there anything special to consider about features with more than 2 scenarios?
As long as I have <= 2 scenarios per feature files, everything works fine, but the moment I had a third scenario to that feature file, that third scenario is ignored and skipped.
Any ideas?

Without seeing your actual steps I can't say for sure but it sounds like an asynchronous issue or dare I say it, a syntax error in the scenario. Have you tried changing the order of the scenarios to see if that has an impact.

Related

Get method gets called n number of times when streaming MEAN stack

I have a MEAN stack, when the frontend calls for a url like /movies/KN3MJQR.mp4,
the get block in the routes.js looks like this
app.get('/movie/:url', function(req, res) {
try {
var url = req.url.split('/')[2]
res.sendfile(moviesFolder + url);
#i want to add my logic for incrementing view count here.
} catch (e) {
console.log(e);
}
});
I want to add logic to increment the view count of each of the movie whenever a request is raised for the .mp4 . I tried adding the increment view count logic at the place commented in the code as shown above only to find that the whole get method gets called n number of times as the streaming happens. How do I handle this logic?
Update : Code to check the same as answered by #rsp
if(req.get('Range')===('bytes=0-')){
console.log('first call');
}else{
console.log('further call');
}
The endpoint can be hit many times because res.sendfile() supports ranges and the client can do multiple downloads of partial data.
You can inspect the relevant header with req.get('Range') and see if it's the first or last part (depending on whether you want to count every started download or only the finished ones).
For more info on the header, see:
https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35

Removing created records in e2e tests after all tests have run

I have been looking around for suitable ways to 'clean up' created records after tests are run using Protractor.
As an example, I have a test suite that currently runs tests on create and update screens, but there is currently no delete feature, however there is a delete end point I can hit against the backend API.
So the approach I have taken is to record the id of the created record so that in an afterAll I can then issue a request to perform a delete operation on the record.
For example:
beforeAll(function() {
loginView.login();
page.customerNav.click();
page.customerAddBtn.click();
page.createCustomer();
});
afterAll(function() {
helper.buildRequestOptions('DELETE', 'customers/'+createdCustomerId).then(function(options){
request(options, function(err, response){
if(response.statusCode === 200) {
console.log('Successfully deleted customer ID: '+ createdCustomerId);
loginView.logout();
} else {
console.log('A problem occurred when attempting to delete customer ID: '+ createdCustomerId);
console.log('status code - ' + response.statusCode);
console.log(err);
}
});
});
});
//it statements below...
Whilst this works, I am unsure whether this is a good or bad approach, and if the latter, what are the alternatives.
I'm doing this in order to prevent a whole load of dummy test records being added over time. I know you could just clear down the database between test runs, e.g. through a script or similar on say a CI server, but it's not something I\we have looked into further. Plus this approach seems on the face of it simpler, but again I am unsure about the practicalities of such an approach directly inside the test spec files.
Can anyone out there provide further comments\solutions?
Thanks
Well, for what it's worth I basically use that exact same approach. We have an endpoint that can reset data for a specific user based on ID, and I hit that in a beforeAll() block as well to reset the data to an expected state before every run (I could have done it afterAll as well, but sometimes people mess with the test accounts so I do beforeAll). So I simply grab the users ID and send the http request.
I can't really speak to the practicality of it, as it was simply a task that I accomplished and it worked perfectly for me so I saw no need for an alternative. Just wanted to let you know you are not alone in that approach :)
I'm curious if other people have alternative solutions.
The more robust solution is to mock your server with $httpBackend so you don't have to do actual calls to your API.
You can then configure server responses from your e2e test specs.
here's a fake server example :
angular.module('myModule')
.config(function($provide,$logProvider) {
$logProvider.debugEnabled(true);
})
.run(function($httpBackend,$log) {
var request = new RegExp('\/api\/route\\?some_query_param=([^&]*)');
$httpBackend.whenGET(request).respond(function(method, url, data) {
$log.debug(url);
// see http://stackoverflow.com/questions/24542465/angularjs-how-uri-components-are-encoded/29728653#29728653
function decode_param(param) {
return decodeURIComponent(param.
replace('#', '%40').
replace(':', '%3A').
replace('$', '%24').
replace(',', '%2C').
replace(';', '%3B').
replace('+', '%20'));
}
var params = url.match(request);
var some_query_param = decodeURIComponent(params[1]);
return [200,
{
someResponse...
}, {}];
});
});
Then load this script in your test environnement and your done.

Protractor hanging on IsPresent() -- Or any other Action

I am working on trying to get some end to end tests implemented for an AngularJS site, and I am having a bit of an issue getting past a call to the IsPresent() method on the ElementFinder returned by a call to the element method.
Sadly I am governed by rules from my employer preventing me from posting ANY of our code on StackOverflow, but essentially this is what I am doing...
describe('Some feature', function () {
it('Some Scenario', function () {
browser.get(browser.baseUrl + '/#/somePage');
var ee = element(by.css('.test-comment'));
expect(ee.isPresent()).toBeTruthy();
});
});
If I comment out the call to the expect() method, then the test executes and passes without issue. If I leave it in, I get :
Failed: Timed out waiting for Protractor to synchronize with the page
after 20 seconds. Please see
https://github.com/angular/protractor/blob/master/docs/fa q.md. The
following tasks were pending:
- $timeout: function (){n=null}
This doesn't make any sense to me - the IsPresent() method returns a promise, which is resolved by the expect method, or at least that is what I would expect to happen.
Any clues?
Try the browser.isElementPresent() instead:
expect(browser.isElementPresent(ee)).toBeTruthy();
If you are curious about the differences, please see:
In protractor, browser.isElementPresent vs element.isPresent vs element.isElementPresent
Also, you may introduce the "presence of" explicit wait before making the expectation:
var EC = protractor.ExpectedConditions;
var ee = element(by.css('.test-comment'));
browser.wait(EC.presenceOf(ee), 5000);
expect(ee.isPresent()).toBeTruthy();
.isDisplayed() might be of help to you as well.
See What is the difference between the isPresent and isDisplayed methods for more info.

AngularJS testing $httpBackend.whenGET().respond() not working with number as parameter

This test:
it("getFooCount success", function () {
httpBackend.whenGET('/api/getFooCount').respond(1);
fooService.getFooCount();
httpBackend.flush();
expect(fooService.FooCount).toBe(1);
});
fails: "Expected null to be 1"
(fooService.fooCount is null before the api get method is called).
Yet this test passes:
it("getFooCount success", function () {
httpBackend.whenGET('/api/getFooCount').respond("1");
fooService.getFooCount();
httpBackend.flush();
expect(fooService.fooCount).toBe("1");
});
It seems to be able to pass the test with anything (an object, string, array, etc) EXCEPT a number in the .respond().
The api I am calling just returns an integer, any advice as to how I can get this to work, and/or why it is failing?
Have a look at the API for respond, because the first argument is actually the status code.
Try instead respond(200, 1).
Angularjs seems to smart its way around when you provide a non statist object as first parameter

How to exit a testcase in protractor if element contains value

I've been writing a suite of tests in Protractor, and am almost finished. I'm having difficulty figuring out how to do something fairly common though. I want to be able to check if a textbox contains a value, and if so, exit the testcase with a failure. (If the textbox contains a value, I know there's no chance the test case can pass anyway)
I'm currently trying something like this:
tasksPage.generalInformationDateOfBirthTextbox.getAttribute('value').then(function(attr){
//attr contains the correct value in the textbox here but how do I return it to parent scope so I can exit the test case?
console.log("attr length is " + attr.length);
expect(attr.length).toBe(0);
},function(err){
console.log("An error was caught while evaluating Date of Birth text value: " + err);
});
The expect statement fails as I'd expect it to, but the testcase keeps going, which seems to be the intended behavior of expect. So I tried returning a true/false from within the 'then' block, but I can't seem to figure out how to return that value to the parent scope to make a determination on. In other words, if I change the above to:
var trueFalse = tasksPage.generalInformationDateOfBirthTextbox.getAttribute('value').then(function(attr){
if(attr === ""){
return true;
}else{
return false;
}
},function(err){
console.log("An error was caught while evaluating Date of Birth text value: " + err);
});
//This is the 'it' block's scope
if(trueFalse == true){
return;
}
I know my inexperience with promises is probably to blame for this trouble. Basically, I just want a way of saying, 'if such and such textbox contains text, stop the test case with a failure'.
Thanks,
This is not a protractor issue, it is a testing framework issue (jasmine, mocha etc).
Though, there was an issue on protractor's issue tracker:
--fail-fast CLI option
which was closed with a reference to an opened issue in jasmine issue tracker:
Feature Request - fail-fast option
While this is not implemented, there is a workaround (originally mentioned here):
jasmine-bail-fast package
After installing the module with npm, when you want your test to fail and exit, add:
jasmine.getEnv().bailFast();
(don't forget to load the dependency require('jasmine-bail-fast');)
Also see:
Does jasmine-node offer any type of "fail fast" option?
The issue with the code above is that you are trying to compare a 'Promise' and a 'value'.
trueFalse.then(function(value)
{
if(value)
....
});
OR compare it via an expect statement. Something like expect(trueFalse).toBe(false);

Resources