Test comparison doesn't work as expected - angularjs

1) I have the very strange mistake in my protractor code. And I don't understand what may be reason of it.
it('should filtering by interval correctly', function () {
filter_field.click();
var filter_field_text = filter_field.element(by.css('input'));
var exist_value1 = element(by.xpath('//tr[#data-row-index="1"]/td[#data-column-index="5"]/div')).getText().then(function (value) {
var floatValue = parseFloat(value);
return (floatValue);
});
var exist_value2 = element(by.xpath('//tr[#data-row-index="1"]/td[#data-column-index="5"]/div')).getText().then(function (value) {
var floatValue = parseFloat(value);
return Math.round(floatValue) + 1;
});
filter_field_text.sendKeys(exist_value1);
filter_field_text.sendKeys('-');
filter_field_text.sendKeys(exist_value2);
browser.sleep(3000);
var filtered_values = element.all(by.xpath('//tr/td[#data-column-index="5"]/div'));
filtered_values.each(function (element, index) {
var current_value = element.getText().then(function (value) {
var floatValue = parseFloat(value);
return (floatValue);
});
expect(exist_value1 <= current_value).toBe(true);
});
if (true) console.log("Test done!");
});
I have wrong result: 'Expected false to be true'
Although, absolutely similar code working fine:
it('should filtering by one-sided < interval correctly', function () {
filter_field.click();
var filter_field_text = filter_field.element(by.css('input'));
var exist_value = element(by.xpath('//tr[#data-row-index="1"]/td[#data-column-index="5"]/div')).getText().then(function (value) {
var floatValue = parseFloat(value);
return (floatValue);
});
filter_field_text.sendKeys("<");
filter_field_text.sendKeys(exist_value);
browser.sleep(3000);
var filtered_values = element.all(by.xpath('//tr/td[#data-column-index="5"]/div'));
filtered_values.each(function (element, index) {
var current_value = element.getText().then(function (value) {
var floatValue = parseFloat(value);
return (floatValue);
});
expect(exist_value <= current_value).toBe(true);
});
if (true) console.log("Test done!");
});
2) Also I have a question about complex expectations. Can I do something like:
expect(exist_value1 >= current_value & exist_value2 <= current_value).toBe(true);
In my tests it isn't work.

Can you print all these values before the expect statement? The float value might be different if they are getting derived through some calculation. Use parseFloat(yourString).toFixed(2) to get the float value till 2 decimal places.

Today I found the answer for my question.
If somebody have the same problem: comparison should be in the function, because it is a js method.
Here is the right code:
it('should sorting by interval correctly', function () {
filter_field.click();
if (column_body.get(0).isPresent()) {
var exist_value1 = column_body.get(0).getText().then(function (value) {
var floatValue = parseFloat(value);
return (floatValue);
});
var exist_value2 = column_body.get(0).getText().then(function (value) {
var floatValue = parseFloat(value);
return Math.round(floatValue) + 1;
});
filter_field.sendKeys(exist_value1);
filter_field.sendKeys('-');
filter_field.sendKeys(exist_value2);
var filtered_values = element.all(by.xpath(column_body_xpath));
filtered_values.each(function (element) {
var current_value = element.getText().then(function (value) {
var floatValue = parseFloat(value);
expect((exist_value1 <= floatValue) && (exist_value2 >= floatValue)).toBeTruthy(); //INTO SCOPES!!!
});
});
}
else {
expect(true).toBe(false);
}
console.log("ps-grid-column-filter-range_spec_8");
});

Related

Angularsjs cannot find service function

My filterProducts function makes a call to findIntersection which is present but I get an error findIntersection is undefined.
angular.module('BrandService', [])
.service('BrandService', function ($filter, DataService) {
var productDb;
var products;
return {
filterProducts(brands, priceRange) {
var filteredProducts = [];
var brandProducts = [];
var priceProducts = [];
var productsArray = [];
var brandChecked = false;
var priceChecked = false;
angular.forEach(brands, function (brand) {
if (brand.checked) {
brandChecked = true;
angular.extend(brandProducts,
$filter('filter')(productDb, { 'brand': brand.name }));
}
if (brandChecked) {
productsArray.push(brandProducts);
console.log('brandProducts = ', brandProducts)
}
});
angular.forEach(priceRange, function (price) {
if (price.checked) {
priceChecked = true;
let filteredProductDb = productDb.filter((prod) => {
return (prod.price >= price.low && prod.price <= price.high);
});
angular.extend(priceProducts, filteredProductDb);
}
});
if (priceChecked) {
productsArray.push(priceProducts);
// console.log('priceProducts = ', priceProducts)
}
if (!brandChecked && !priceChecked) {
filteredProducts = products;
} else {
if (productsArray.length > 1) {
filteredProducts = findIntersection(productsArray);
} else {
filteredProducts = productsArray[0];
}
}
return filteredProducts;
},
findIntersection(productsArray) {
console.log('findIntersection called')
var filteredProducts = [];
var filteredSet = new Set();
for(var i=0; i < productsArray.length - 1; i++) {
var products1 = productsArray[i];
var products2 = productsArray[i+1];
angular.forEach(products1, function(product1) {
angular.forEach(products2, function(product2) {
if(product1._id == product2._id) {
filteredSet.add(product1);
}
});
});
}
filteredProducts = Array.from(filteredSet);
return filteredProducts;
}
}
})
My filterProducts function makes a call to findIntersection which is present but I get an error findIntersection is undefined.
My filterProducts function makes a call to findIntersection which is present but I get an error findIntersection is undefined.
You are returning a javascript object with properties. You are not defining global functions.
You need to store the service returned before :
var service = { findProducts: ... , findIntersection: ... };
return service;
And instead of calling findIntersection, call service.findIntersection.
You have to make a reference to local object.
Simply change this: filteredProducts = findIntersection(productsArray);
to this: filteredProducts = this.findIntersection(productsArray);

Cordova.writefile function doesn't run, but doesn't give an error

I'm making an ionic application. I have a function called scope.win() that's supposed to fire when a quiz is finished, and then update the JSON file to add that quiz to the number of finished quizzes but it doesn't run properly.It doesn't give off any error. The function just stops running at a certain point and the app keeps going and nothing is happening.
This is the controller's file
angular.module('controllers', ['services'])
.controller('MainCtrl', function ($scope, $state, data) {
$scope.$on('$ionicView.enter', function () {
data.create();
});
$scope.chapter = data.chapterProgress();
})
.controller("BtnClick", function ($scope, lives, data, $cordovaFile, $ionicScrollDelegate) {
var live = 3;
var clickedOn = [];
var numQuestions;
$scope.part2Cred = false;
$scope.part3Cred = false;
$scope.part4Cred = false;
$scope.part5Cred = false;
$scope.part6Cred = false;
$scope.part7Cred = false;
$scope.part8Cred = false;
$scope.part9Cred = false;
$scope.part10Cred = false;
$scope.partQCred = false;
$scope.setNumQuestions = function(num){
numQuestions = num;
}
$scope.updatelives = function (){
//grabs the element that is called liv then updates it
var livesOnPage = document.getElementById('liv');
livesOnPage.innerHTML = live;
}
$scope.wrong = function (event){
var selec = document.getElementById(event.target.id);
if(clickedOn.includes(selec)){}
else{
selec.style.color = "grey";
clickedOn.push(selec);
live = live - 1;
if(live == 0){
$scope.gameover();
}
else{
$scope.updatelives();
}
}
}
$scope.right = function (event,chapter, section){
var selec = document.getElementById(event.target.id);
if(clickedOn.includes(selec)){}
else{
selec.style.color = "green";
clickedOn.push(selec);
numQuestions = numQuestions - 1;
if(numQuestions === 0){
$scope.win(chapter, section);
}
}
}
$scope.gameover = function(){
alert("game over please try again");
live = 3;
$ionicScrollDelegate.scrollTop();
$scope.partQCred = false;
$scope.part1Cred = !$scope.part1Cred;
for(i = 0; i< clickedOn.length;i++){
clickedOn[i].style.color = "rgb(68,68,68)";
}
}
$scope.win = function (chapter, section) {
alert("Well Done");
var data = data.chapterProgress(); // It is at this point that the //function stops running without giving off any error.
alert("Good Job");
var sectionsComplete = data[chapter].sectionsCompleted;
var totalsection = data[chapter].totalSections;
if (section === totalSection) {
window.location.href = "#/chapter1sections";
return;
}
if (section > sectionsComplete) {
data[chapter].sectionsCompleted += 1;
var url = "";
if (ionic.Platform.isAndroid()) {
url = "/android_asset/www/";
}
document.addEventListener('deviceready', function () {
$cordovaFile.writeFile(url + "js/", "chapters.json", data, true)
.then(function (success) {
// success
alert("Json file updated")
window.location.href = "#/chapter1sections";
}, function (error) {
// error
});
});
}
}
});
Here is the Services file. It seems to run fine but it is referenced a lot in the problematic sections of code in the controllers so I figured it was necessary to put it here.
angular.module('services', [])
.service('lives', function () {
var live = 3;
return {
getlives: function () {
return live;
},
setlives: function (value) {
live = value;
}
};
})
.service('data', function ($cordovaFile, $http) {
var url = "";
if (ionic.Platform.isAndroid()) {
url = "/android_asset/www/";
}
return {
//Run this function on startup to check if the chapters.json file exists, if not, then it will be created
create: function () {
var init = {
"one": {
"sectionsCompleted": 0,
"totalSections": 4
},
"two": {
"sectionsCompleted": 0,
"totalSections": 1
}
};
$cordovaFile.writeFile(url + "js/", "chapters.json", init, false)
.then(function (success) {
// success
}, function (error) {
// error
});
},
chapterProgress: function () {
return $http.get(url + "js/chapters.json").success(function (response) {
var json = JSON.parse(response);
return json;
}, function (error) {
alert(error);
});
}
}
});
Thank You so much for the help and time.

Protractor - astrolabe - Cannot set array value

I'm using Protractor with PageObject astrolabe as below
CampaignPage.js
module.exports = Page.create({
defaultCheckpoint: {
get: function () {
return {
giName: "auto",
giType: "auto",
}
}
},
getDefaultValue: {
value: function (campaignCode) {
var page = this;
var checkpoint = page.defaultCheckpoint;
/* #Tab General Info */
page.getTabByName(page.informationTabs.generalInfo);
page.giName.getAttribute("value").then(function (value) {
checkpoint.giName = value; //value 1
});
page.giType.findElement(this.by.selectedOption("field.value")).getText().then(function (value) {
checkpoint.giType = value; //value 2
});
return checkpoint;
} }});
CampaignTest.js
describe('Campaign Management - ', function () {
var loginPage = require('../pages/login.js');
var navigatorPage = require('../pages/navigator.js');
var campaignPage = require('../pages/campaign.js');
beforeEach(function () {
loginPage.loginAs();
navigatorPage.get("a", "b");
});
it('Default - AB_LF_FBX', function () {
var campaignCode = "AB_LF_FBX";
campaignPage.createCampaign(campaignCode); //AB_LF_FBX
var actualResult = campaignPage.getDefaultValue(campaignCode);
console.log("giName3:" + actualResult.giName);
console.log("giType3:" + actualResult.giType);
});
afterEach(function () {
});
});
When I run this test, the console printout
giName3: auto
giType3: auto,
instead of
giName3: value1
giType3: value2
Could you please correct where I do wrong ?
I've found out the solution
In page
getDefaultValue: {
value: function (campaignCode) {
var page = this;
var checkpoint = page.defaultCheckpoint;
/* #Tab General Info */
page.getTabByName(page.informationTabs.generalInfo);
page.giName.getAttribute("value").then(function (value) {
checkpoint.giName = value; //value 1
page.giType.findElement(this.by.selectedOption("field.value")).getText().then(function (value) {
checkpoint.giType = value; //value 2
return checkpoint;
});
});
}
}
In Test
campaignPage.getDefaultValue(campaignCode).then(function (actualResult) {
console.log("giName: " + actualResult.giName);
console.log("giType: " + actualResult.giType);
});
I've found out the solution
In page
getDefaultValue: {
value: function (campaignCode) {
var page = this;
var checkpoint = page.defaultCheckpoint;
/* #Tab General Info */
page.getTabByName(page.informationTabs.generalInfo);
page.giName.getAttribute("value").then(function (value) {
checkpoint.giName = value; //value 1
page.giType.findElement(this.by.selectedOption("field.value")).getText().then(function (value) {
checkpoint.giType = value; //value 2
return checkpoint;
});
});
}
}
In Test
campaignPage.getDefaultValue(campaignCode).then(function (actualResult) {
console.log("giName: " + actualResult.giName);
console.log("giType: " + actualResult.giType);
});

Angularjs paging limit data load

I always manage pagination with angular
retrieve all the data from the server
and cache it client side (simply put it in a service)
now I have to cope with quite lot of data
ie 10000/100000.
I'm wondering if can get into trouble
using the same method.
Imo passing parameter to server like
page search it's very annoying for a good
user experience.
UPDATE (for the point in the comment)
So a possible way to go
could be get from the server
like 1000 items at once if the user go too close
to the offset (ie it's on the 800 items)
retrieve the next 1000 items from the server
merge cache and so on
it's quite strange not even ng-grid manage pagination
sending parameters to the server
UPDATE
I ended up like:
(function(window, angular, undefined) {
'use strict';
angular.module('my.modal.stream',[])
.provider('Stream', function() {
var apiBaseUrl = null;
this.setBaseUrl = function(url) {
apiBaseUrl = url;
};
this.$get = function($http,$q) {
return {
get: function(id) {
if(apiBaseUrl===null){
throw new Error('You should set a base api url');
}
if(typeof id !== 'number'){
throw new Error('Only integer is allowed');
}
if(id < 1){
throw new Error('Only integer greater than 1 is allowed');
}
var url = apiBaseUrl + '/' + id;
var deferred = $q.defer();
$http.get(url)
.success(function (response) {
deferred.resolve(response);
})
.error(function(data, status, headers, config) {
deferred.reject([]);
});
return deferred.promise;
}
};
};
});
})(window, angular);
(function(window, angular, undefined) {
'use strict';
angular.module('my.mod.pagination',['my.mod.stream'])
.factory('Paginator', function(Stream) {
return function(pageSize) {
var cache =[];
var staticCache =[];
var hasNext = false;
var currentOffset= 0;
var numOfItemsXpage = pageSize;
var numOfItems = 0;
var totPages = 0;
var currentPage = 1;
var end = 0;
var start = 0;
var chunk = 0;
var currentChunk = 1;
var offSetLimit = 0;
var load = function() {
Stream.get(currentChunk).then(function(response){
staticCache = _.union(staticCache,response.data);
cache = _.union(cache,response.data);
chunk = response.chunk;
loadFromCache();
});
};
var loadFromCache= function() {
numOfItems = cache.length;
offSetLimit = (currentPage*numOfItemsXpage)+numOfItemsXpage;
if(offSetLimit > numOfItems){
currentChunk++;
load();
}
hasNext = numOfItems > numOfItemsXpage;
totPages = Math.ceil(numOfItems/numOfItemsXpage);
paginator.items = cache.slice(currentOffset, numOfItemsXpage*currentPage);
start = totPages + 1;
end = totPages+1;
hasNext = numOfItems > (currentPage * numOfItemsXpage);
};
var paginator = {
items : [],
notFilterLabel: '',
hasNext: function() {
return hasNext;
},
hasPrevious: function() {
return currentOffset !== 0;
},
hasFirst: function() {
return currentPage !== 1;
},
hasLast: function() {
return totPages > 2 && currentPage!==totPages;
},
next: function() {
if (this.hasNext()) {
currentPage++;
currentOffset += numOfItemsXpage;
loadFromCache();
}
},
previous: function() {
if(this.hasPrevious()) {
currentPage--;
currentOffset -= numOfItemsXpage;
loadFromCache();
}
},
toPageId:function(num){
currentPage=num;
currentOffset= (num-1) * numOfItemsXpage;
loadFromCache();
},
first:function(){
this.toPageId(1);
},
last:function(){
this.toPageId(totPages);
},
getNumOfItems : function(){
return numOfItems;
},
getCurrentPage: function() {
return currentPage;
},
getEnd: function() {
return end;
},
getStart: function() {
return start;
},
getTotPages: function() {
return totPages;
},
getNumOfItemsXpage:function(){
return numOfItemsXpage;
},
search:function(str){
if(str===this.notFilterLabel){
if(angular.equals(staticCache, cache)){
return;
}
cache = staticCache;
}
else{
cache = staticCache;
cache = _.filter(cache, function(item){ return item.type == str; });
}
currentPage = 1;
currentOffset= 0;
loadFromCache();
}
};
load();
return paginator;
}
});
})(window, angular);
server side with laravel (All the items are cached)
public function tag($page)
{
$service = new ApiTagService(new ApiTagModel());
$items = $service->all();
$numOfItems = count($items);
if($numOfItems > 0){
$length = self::CHUNK;
if($length > $numOfItems){
$length = $numOfItems;
}
$numOfPages = ceil($numOfItems/$length);
if($page > $numOfPages){
$page = $numOfPages;
}
$offSet = ($page - 1) * $length;
$chunk = array_slice($items, $offSet, $length);
return Response::json(array(
'status'=>200,
'pages'=>$numOfPages,
'chunk'=>$length,
'data'=> $chunk
),200);
}
return Response::json(array(
'status'=>200,
'data'=> array()
),200);
}
The only trouble by now is managing filter
I've no idea how to treat filtering :(

Getting the response from an angular function

I have the following scope function in my controller
$scope.getStaff = function (request, response) {
var a = [];
if ($scope.staff !== null) {
// all terms must be contained
a = $scope.staff;
var terms = request.term.toLowerCase().split(' ');
for (var i = 0; i < terms.length; i++) {
var t = terms[i];
if (t) {
a = $.grep(a, function (item, index) {
var v = item.label.toLowerCase();
return v.indexOf(t) !== -1;
});
}
}
}
response(a.length > 0 ? a : null);
};
I'm attempting to test it using jasmine like this:
describe('getStaff', function() {
it('...', function() {
$scope.staff = [
{ label: "test1" },
{ label: "test2" }
];
var req = { term: "a b c" };
expect(req.term.toLowerCase()).toBe('a b c');
var res = function(a) {
return a;
}
var result = $scope.getStaff(req, res).response;
expect(result).toBe(null);
});
});
I'm ultimately trying to see what "a" is in the getStaff function. How can I get that value in my jasmine test?
My answer is really an opinion. Unless you are willing to expose your 'a' in the scope of the controller, then my answer would be "you don't care" your jasmine test should only be testing the answer of response(a.length > 0 ? a : null); returned.
My gut tells me you may want to consider creating a helper function for this code
$.grep(a, function (item, index) {
var v = item.label.toLowerCase();
return v.indexOf(t) !== -1;
});
and unit testing that separate from your getStaff function.

Resources