casperjs evaluate function not working - casperjs

I am working on casperjs. I write following program to get output:
var casper = require('casper').create();
var cookie;
casper.start('http://wordpress.org/');
casper.then(function() {
this.evaluate(function() {
cookie=document.cookie;
})
})
casper.then(function() {
console.log("Page cookie");
console.log(cookie);
})
casper.run(function() {
this.echo('Done.').exit();
})
Output for above is:
Page cookie
undefined
Done.
why it give me undefined? Help me into this.

Concept behind evaluate is, you will pass your code to browser's console and execute your code there. If you define any variable inside evaluate method that variable will be local to that method. That scope is local. When you are dealing with Casper you should consider the scope of the variable.
So when you try to print out "cookie" in the main function it will say it is undefined.Which is expected.
note that you cant use echo (),console.log () inside evaluate method.
cookie = this.evaluate(function() {
var cookieLocal=document.cookie;
return cookieLocal;
})
Here "cookieLocal" is a local variable.
This will return value to Gloabal variable "cookie". So when you try to print the value in the main function it will work as expected. I hope this will make you to consider scope when declaring variable. You can directly return do the return . No Need of using local variable.
cookie = this.evaluate(function() {
return document.cookie;
})
Another important thing i recommend when you using an evaluate method. try to use Try catch method while developing the code. It wont be needed in production as per you requirement. We cannot print anything inside console. so use try catch for debugging purpose.
casper.then(function() {
cookie = this.evaluate(function() {
try {
return document.cookie;
} catch (e) {
return e;
}
})
this.echo (JSON.stringify ('cookie :'+cookie));
})
Note that this.echo () should be outside evaluate method.
Hope this will be an helpful one.

remove var cookie
cookie = casper.evaluate(function() {
return document.cookie;
})
casper.then(function() {
console.log("Page cookie");
console.log(cookie);
})
The above code works fine for me.

Related

.then is not a function Angularjs factory

I just started learning Jasmine test cases for angularjs. I am unable to test below code.Kindly help
$scope.getConstants = function(lovName) {
ConstantService.getConstants(lovName).then(function(d) {
switch (lovName) {
case 'WORKFLOW':
$scope.workflowTypes = d;
$scope.loadCounterpartyTmp();
break;
--------Other Cases
}
My ConstantService is defined as
App.factory('ConstantService', [ '$http', '$q', function($http, $q) {
return {
getConstants : function(lovName) {
return $http.post('/sdwt/data/getConstants/', lovName).then(function(response) {
return response.data;
}, function(errResponse) {
return $q.reject(errResponse);
});
}
I want to test getConstants function.I need to create a mock of ConstantService and pass the data to it.
I have written below test case but the test case is not working.Please let me know how to test the above code
describe('getConstantsForMurexEntity', function() {
it('testing getConstantsForMurexEntity function', function() {
var d=[];
d.push(
{id:1,value:'ABC'},
{id:2,value:'DEF'},
{id:3,value:'IJK'},
{id:4,value:'XYZ'},
);
//defined controller
spyOn(ConstantService, 'getConstants').and.returnValue(d);
$scope.getConstants('WORKFLOW');
expect($scope.workflowTypes).toBe(d);
The above test case is not working as it is saying "ConstantService.getConstants(...).then is not a function".
Your ConstantService.getConstants() function returns a promise, which your actual code is using, with the .then() call. This means means that when you spy on it, you also need to return a promise, which you are not doing. Because you are not returning a promise, when your actual call tries to call .then(), it is undefined, which is the reason for the error message.
Also, you aren't using Array.push correctly.
Your test should probably look something like the following (note, this is untested):
describe('getConstantsForMurexEntity', function() {
it('should set workflowTypes to the resolved value when lovName is "WORKFLOW"', inject(function($q) {
var deferred = $q.defer();
spyOn(ConstantService, 'getConstants').and.returnValue(deferred.promise);
var d = [
{id:1,value:'ABC'},
{id:2,value:'DEF'},
{id:3,value:'IJK'},
{id:4,value:'XYZ'},
];
$scope.getConstants('WORKFLOW');
deferred.resolve(d);
$scope.$apply();
expect($scope.workflowTypes).toBe(d);
}));
});

How to use Magiczoom Callbacks

The magiczoom documentation describes callbacks that will execute at given times, but it's unclear how to use or assign those callbacks.
For example, how would I print a console message onZoomReady?
The closest I've found is a MagicZoom.defaults.onready property, but it's unclear how to set it via javascript (my attempts aren't working as expected).
The callbacks are configured via mzOptions, for example:
var mzOptions = {
onZoomReady: function() { … } }
;
Or:
var mzOptions = {};
mzOptions.onZoomReady = function() { … };
You can do something like this:
MagicZoom.registerCallback('onUpdate',
function() {
console.log('onUpdated', arguments[0], arguments[1], arguments[2]);
});
That will log stuff in the console like this:
onUpdated (id-of-mz-wraper) (html of old element) (html of new element)
Other options that you can use are as per the documentation:
MagicZoom.registerCallback('onZoomReady', function() {
console.log('onReady', arguments[0]);
});
MagicZoom.registerCallback('onZoomIn', function() {
console.log('onZoomIn', arguments[0]);
});
MagicZoom.registerCallback('onZoomOut', function() {
console.log('onZoomOut', arguments[0]);
});

Async call in beforeAll

Here are 2 samples of the same test. The only difference is that first one uses a promise in beforeAll block to assign a value to the variable while the second one assigns the value directly.
I raised a similar question Running spec after promise has been resolved with one of the comments pointing to this issue https://github.com/jasmine/jasmine/issues/412 which says that this is not supported in Jasmine. Has somebody figured out any workaround?
This fails with TypeError: Cannot read property 'forEach' of undefined
describe('Async car test', function () {
var cars;
beforeAll(function (done) {
// getCars() is a promise which resolves to ['audi', 'bmw']
getCars().then(function (data) {
cars = data;
console.log(cars) // ['audi', 'bmw']
done();
});
});
cars.forEach(function (car) {
it('car ' + car, function () {
expect(car).toBe(car);
});
});
});
This works fine
describe('Car test', function () {
var cars = ['audi', 'bmw'];
cars.forEach(function (car) {
it('car ' + car, function () {
expect(car).toBe(car);
});
});
});
Posting it as an answer, because I can't see things properly in comments.
I'm actually generating tests in my spec as well, and I'm using https://www.npmjs.com/package/jasmine-data-provider , I think you probably cannot generate it directly from resolved promise. And wrapping in another it doesn't work for you. This should work:
var using = require('jasmine-data-provider');
using(cars.forEach, function (car) {
it(car + ' should be' + car, function () {
expect(car).toBe(car);
});
});
This is not an issue with jasmine, it is an issue with your code.
beforeAll does not block subsequent code below the statement. it blocks code that is defined in it('should ...', (done)=>{...});
it('should have cars', (done) => {
cars.forEach(function (car) {
expect(car).toBe(car);
});
});
Since Jasmine does not support adding tests at runtime, the trick is to request the asynchronous data before starting Jasmine, and then using the retrieved data during runtime instead. This can be achieved with a singleton and programmatically starting Jasmine.
See here for a working example.
// car-collection.js
class CarCollection {
static load() {
return this.request()
then((data) => this.cars = data);
}
static request() {
// in practice this function would do something cooler
return Promise.resolve(['audi', 'bmw']);
}
}
modules.export = CarCollection;
Since CarCollection has methods that are static they will be shared across imports and this.cars will persist.
// launcher.js
const Jasmine = require('jasmine');
const CarCollection = require('./car-collection');
CarCollection.load()
.then(() => {
console.log(`car count is ${CarCollection.cars.length}`); // prints: car count is 2
const jasmine = new Jasmine();
jasmine.loadConfigFile(...); // path to jasmine.json
jasmine.execute();
});
An important step here is configure jasmine to know where to look for the test files. Either by loading a config or passing specifics into the execute function.
// car.spec.js
const CarCollection = require('./car-collection');
describe('test', function () {
CarCollection.cars.forEach((car) => {
it('test' + car, () => {
expect(car).toBe(car);
});
});
});
Now run node ./launcher.js and the tests should run.

Angular: update scope with async AJAX data from a factory

What's the recommended way to do this?
1.
factory.updater = function(varObjToBeUpdated){
$http.post('/url', {})
.success(function(data){
for (data_field in data)
varObjToBeUpdated[data_field] = data[data_field];
});
}
...
myFactory.updater($scope.varObjToBeUpdated);
Or 2.,
myFactory.updater().success(function(data, ..){
$scope.varObjToBeUpdated = data;
});
...
factory.updater = function(){
return $http.post('/url', {});
}
Is it ok to to pass a reference scope variable to a factory? I always thought factories as delivering data.
And what's wrong with the second method (if it's less acceptable)?
I prefer the second approach, as this allows you to just inject the service when you need it across multiple controllers. Use .then to continue the promise pattern:
myFactory.updater().then(function(data, ..){
$scope.varObjToBeUpdated = data;
});
app.factory('myFactor', function($http) {
return {
updater: function() {
return $http({'/url',}).then(function(result) {
return result.data;
});
}
}
});

How to make Dajax callback into scoped object

I cant seem to find a way to make django-dajaxice have its callback inside same scoped object from which made the initial call.
MyViewport = Ext.extend(MyViewportUi, {
initComponent: function() {
MyViewport.superclass.initComponent.call(this);
},
LoadRecordsCallback: function(data){
if(data!='DAJAXICE_EXCEPTION')
{ alert(data); }
else
{ alert('DAJAXICE_EXCEPTION'); }
},
LoadRecords: function(){
Dajaxice.Console.GetUserRecords(this.LoadRecordsCallback);
}
});
var blah = new MyViewport();
blah.LoadRecords();
I'm on django, and like the calling syntax to django-dajaxice. I'm using Extjs 3.2 and tried passing a Ext.createCallback but Dajax's returning eval seems to only want a string for the callback.
BozoJoe, this should work.
MyViewport = Ext.extend(MyViewportUi, {
initComponent: function() {
MyViewport.superclass.initComponent.call(this);
},
LoadRecordsCallback: function(data){
if(data!='DAJAXICE_EXCEPTION')
{ alert(data); }
else
{ alert('DAJAXICE_EXCEPTION'); }
},
LoadRecords: function(){
Dajaxice.Console.GetUserRecords('blah.LoadRecordsCallback');
}
});
var blah = new MyViewport();
blah.LoadRecords();
I'm not familiar with django at all, but I think I understand the problem.
It seems that the API mandates that you pass a string which will be eval'd as a function call, so you must pass the name of the function, rather than the function itself.
This in turn means that it must be a name that is meaningful at the window scope - either a function defined outside of an Ext class (e.g. "myGlobalFunction"), or a member function of an Ext class that is accessible as a variable (e.g. "window.blah.LoadRecordsCallback")

Resources