How can I set up the browser size before my protractor test runs? - angularjs

I have the following protractor test listed below. It runs fine. But I need to add some code that opens the browser to full screen since my test is sensitive to pixel location of gridster tiles. How can this be done?
describe('DragAndDrop Test', function () {
require('protractor');
require('jasmine-expect');
beforeAll(function () {
context = new Context();
context.get();
browser.waitForAngular();
browser.driver.manage().window().maximize();
});
it('should drag and drop Application Experience tile', function () {
//a = angular.element(document).find('h3')[1]
//target is where we are dragging the box to. Box is the Box
var target = { x: 300, y: 50 };
var box = element(by.cssContainingText('h3', 'Application Experience'));
var infoSpot = element(by.cssContainingText('h3', 'Application Experience'));
//scope is going to hold the scope variables that tell us where the box is located
//get the standardItems Scope
box.evaluate('dashboards').then(function(scope) {
//make sure the box we are using is initially set in column 0 and Row 0
expect(scope['1'].widgets[0].col).toEqual(0);
expect(scope['1'].widgets[0].row).toEqual(0);
});
//drag and drop the box somewhere else.
browser.actions().dragAndDrop(box, target).perform();
browser.waitForAngular();
browser.driver.sleep(5000);
//get the updated scope
box.evaluate('dashboards').then(function(scope) {
//test to see that the box was actually moved to column 1 and row 0
expect(scope['1'].widgets[0].col).toEqual(1);
expect(scope['1'].widgets[0].row).toEqual(0);
});
});
});
var Context = function () {
this.ignoreSynchronization = true;
//load the website
this.get = function () {
browser.get('http://127.0.0.1:57828/index.html#/dashboard');
};
};

I think the better practice is to do this in your config.
onPrepare: function() {
browser.manage().window().setSize(1600, 1000);
}
or
onPrepare: function() {
browser.manage().window().maximize();
}

You already have this line in your beforeAll function, which will maximize your browser before any test is run:
browser.driver.manage().window().maximize();
However, on some operating systems, Chrome browser won't maximize the window horizontally, only vertically. You have two options:
a) Set the width explicitly to some predefined value, e.g:
browser.driver.manage().window().setSize(1200, 768);
b) Get the screen resolution with a Javascript function and set the window size accordingly.
var width = GET_WIDTH;
var height = GET_HEIGHT;
browser.driver.manage().window().setSize(width, height);

Related

Share variable between two windows. Angularjs

From my angularjs application I open a new window:
$window.open($state.href('catalog-detalleTicketMapa', {
id: $localStorage.idRamdom
}), 'window', 'height=700,width=700');
And when I close that new window I want the parent window to know about that event, and I do the following
// controller auxiliary window
vm.onExit = function () {
$rootScope.$broadcast('ventanaCerrada');
};
$window.onbeforeunload = vm.onExit;
// controller main windows
$scope.$on('ventanaCerrada', function () {
$rootScope.ventanaAbierta = false;
});
If it enters the event $rootScope.$broadcast but not to the event scope.$on.
I have also tested with localStorage, but it is only updated in the auxiliary window, but the main one does not.
How can I share a variable between two open windows at the same time in my browser?
When you open a new window with $window.open, it won't share the scope with the calling window, so it's impossible (afaik) to broadcast anything between them with angular. But the calling window can access global variables in the opened window, so I'm using something like an observer to watch that variable.
I have the following code in a WindowService to open the new window (we only open a single window; if you need more, you need to adjust the code):
angular.module('myproject')
.service('WindowService', ['$window', '$interval', '$timeout',
function ($window, $interval, $timeout) {
var self = this;
this.myOpenWindow = null;
// opens a window and starts the wait-function
this.openWindow = function (url, callbackFn) {
// open the window
self.myOpenWindow = $window.open(url);
// Puts focus on the new window
if (window.focus) {
self.myOpenWindow.focus();
}
// check for response in opened window
self.waitForResponse(callbackFn);
};
this.waitStarted = false;
this.waitForResponse = function (callbackFn) {
if (!self.waitStarted && self.myOpenWindow) {
self.waitStarted = true;
var intervalPeriod = 1000; // check once every second
var waitHandler;
waitHandler = $interval(function (index) {
if (self.myOpenWindow.closed) {
// window was closed, commence cleaning operation
$interval.cancel(waitHandler);
waitHandler = $timeout(function () {
// re-initialize waitStarted so it can be used again
self.waitStarted = false;
// call callback-Function when the window is closed
if (callbackFn) {
callbackFn();
}
}, intervalPeriod);
} else {
// window is still open, check if the observed variable is set
if (self.myOpenWindow && self.myOpenWindow.response_message) {
var message = self.myOpenWindow.response_message;
// do what you want with the message
// ...
// afterwards close the window (or whatever)
if (self.myOpenWindow) {
self.myOpenWindow.close();
}
}
}
}, intervalPeriod);
}
};
}
]);
In the opened window you need to set that global variable somewhere, e.g. like this:
window['response_message'] = { 'result': 'Done' };
Normally you can't share storage data between two windows. If you really need that changes in data in one window reflect in another window then use socket or firebase to get real-time data.

Drag and Drop with Protractor in AngularJS

I appreciate there's quite a bit of stuff already been said about automating drag and drop as part of E2E testing. However after many, many hours of fiddling around, I cannot get any of the methods described to work...that is using Functions, coordinates etc etc. Oddly enough, console.log maintains the tests have passed, but the screenshots clearly show nothing has happened.
Screenshots shows a portion of the application
The user selects a paper and drags onto the image. As the drag 'starts' the grey overlay on the image clears and the paper is rendered on the room.
The code snippet shows one of the more simple ideas I've tried and I would be very pleased to receive any help going!
const JS_HTML5_DND = 'function e(e,t,n,i){var r=a.createEvent("DragEvent");r.initMouseEvent(t,!0,!0,o,0,0,0,c,g,!1,!1,!1,!1,0,null),Object.defineProperty(r,"dataTransfer",{get:function(){return d}}),e.dispatchEvent(r),o.setTimeout(i,n)}var t=arguments[0],n=arguments[1],i=arguments[2]||0,r=arguments[3]||0;if(!t.draggable)throw new Error("Source element is not draggable.");var a=t.ownerDocument,o=a.defaultView,l=t.getBoundingClientRect(),u=n?n.getBoundingClientRect():l,c=l.left+(l.width>>1),g=l.top+(l.height>>1),s=u.left+(u.width>>1)+i,f=u.top+(u.height>>1)+r,d=Object.create(Object.prototype,{_items:{value:{}},effectAllowed:{value:"all",writable:!0},dropEffect:{value:"move",writable:!0},files:{get:function(){return this._items.Files}},types:{get:function(){return Object.keys(this._items)}},setData:{value:function(e,t){this._items[e]=t}},getData:{value:function(e){return this._items[e]}},clearData:{value:function(e){delete this._items[e]}},setDragImage:{value:function(e){}}});if(n=a.elementFromPoint(s,f),!n)throw new Error("The target element is not interactable and need to be scrolled into the view.");u=n.getBoundingClientRect(),e(t,"dragstart",101,function(){var i=n.getBoundingClientRect();c=i.left+s-u.left,g=i.top+f-u.top,e(n,"dragenter",1,function(){e(n,"dragover",101,function(){n=a.elementFromPoint(c,g),e(n,"drop",1,function(){e(t,"dragend",1,callback)})})})})';
describe('Drag and Drop Test', function() {
it('should drag', function () {
var e1 = element(by.xpath('html/body/webapp-app/div/div/webapp-johnlewis-visualiser/div/div[2]/div/digitalbridge-shortlist/div/div/ul/li[1]/a/img'));
var e2 = element(by.css('.db-project-designer'));
element(by.xpath('html/body/webapp-app/div/div/webapp-johnlewis-visualiser/div/div[2]/div/digitalbridge-shortlist/div/div/ul/li[1]/a/img')).click();
//element(by.xpath('html/body/webapp-app/div/div/webapp-johnlewis-visualiser/div/div[1]/div/div/digitalbridge-project/div/digitalbridge-project-designer/canvas')).click();
browser.driver.actions().dragAndDrop(e1.getWebElement(),e2.getWebElement()).perform();
browser.sleep(2000);
});
});
The constant is showing an error 'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz). (W104) - I do have ES6 installed in Node_Modules.
I inserted the click line to see if pre-selecting the item made any difference...it didn't!
Thank you
David
Try this library https://github.com/SunGard-Labs/sg-protractor-tools
The library also includes functions that simplify common tasks like
Scrolling to an element
Drag and drop
Waiting for DOM elements to become visible or hidden
module.exports = function simulateDragAndDrop(sourceNode, destinationNode) {
const EVENT_TYPES = {
DRAG_END: 'dragend',
DRAG_START: 'dragstart',
DROP: 'drop'
};
function createCustomEvent(type) {
const event = new CustomEvent('CustomEvent');
event.initCustomEvent(type, true, true, null);
event.dataTransfer = {
data: {
},
setData: function(type, val) {
this.data[type] = val;
},
getData: function(type) {
return this.data[type];
}
};
return event;
}
function dispatchEvent(node, type, event) {
if (node.dispatchEvent) {
return node.dispatchEvent(event);
}
if (node.fireEvent) {
return node.fireEvent('on' + type, event);
}
}
const event = createCustomEvent(EVENT_TYPES.DRAG_START);
dispatchEvent(sourceNode, EVENT_TYPES.DRAG_START, event);
const dropEvent = createCustomEvent(EVENT_TYPES.DROP);
dropEvent.dataTransfer = event.dataTransfer;
dispatchEvent(destinationNode, EVENT_TYPES.DROP, dropEvent);
const dragEndEvent = createCustomEvent(EVENT_TYPES.DRAG_END);
dragEndEvent.dataTransfer = event.dataTransfer;
dispatchEvent(sourceNode, EVENT_TYPES.DRAG_END, dragEndEvent);
}
You can call it from you code like this
browser.executeScript(dragAndDrop, element, targetArea);

how can I click the spinner on a Kendo NumericTextBox in a protractor test

Does anyone know how I can programmatically select an element in a protractor test that has the attribute unselectable="on"?
I need to write a protractor test that checks whether my ng-model is being incremented correctly but I can't select the arrow to click because of this attribute.
So this doesn't work in my test:
var arrow = element(by.css('k-icon k-i-arrow-n')); // this should select the up, increment arrow
arrow.click(); // this doesn't work because nothing has been selected.
Your CSS selector would not match the element, use dots for class names:
element(by.css('.k-icon.k-i-arrow-n')).click();
You may also locate the arrow up by title:
element(by.css('span[title="Increase value"]')).click();
Working demo test (using this Kendo UI demo page):
describe("Kendo UI numeric field", function () {
beforeEach(function () {
browser.ignoreSynchronization = true;
browser.get("http://demos.telerik.com/kendo-ui/numerictextbox/index");
});
it("should increase numeric currency value", function () {
var container = element.all(by.css(".k-numerictextbox")).first();
var input = container.element(by.id("currency"));
var arrowUp = container.element(by.css('span[title="Increase value"]'));
var times = 5;
input.getAttribute("value").then(function (oldValue) {
for (var i=0; i < times; i++) {
arrowUp.click();
}
expect(input.getAttribute("value")).toEqual((parseInt(oldValue) + times).toString());
});
});
});

$ionicScrollDelegate locks the view on the scrolled value

When I'm getting the list of results in my cordova app, i want to roll it to the specified element with this function:
$scope.roll = function () {
//var rankScroll = $ionicScrollDelegate.$getByHandle('rank');
var meElement = document.getElementById('scroll');
if (!meElement) {
$ionicScrollDelegate.scrollTo(0, 0);
return;
}
var top = meElement.getBoundingClientRect().top - 50;
$ionicScrollDelegate.scrollTo(0, top);
console.log(top);
console.log($ionicScrollDelegate.getScrollView());
}
It works nicely, but I can't scroll to any other place in the list. I want to unlock scrolling in this solution or find better one. It should scroll on page loaded, not on click.
All the best
That function lock your scroll because of the $scope's binding.
If you only want that function to be invoked when the view is loaded, you should call it once at the the time the view is loaded.
You can do that by this way in your controller:
var roll = function () {
//var rankScroll = $ionicScrollDelegate.$getByHandle('rank');
var meElement = document.getElementById('scroll');
if (!meElement) {
$ionicScrollDelegate.scrollTo(0, 0);
return;
}
var top = meElement.getBoundingClientRect().top - 50;
$ionicScrollDelegate.scrollTo(0, top);
console.log(top);
console.log($ionicScrollDelegate.getScrollView());
}
$scope.$on("$ionicView.loaded", function (scopes, states) {
roll();
});
You can check more $ionicView events in this ion-view Document

Drupal.attachBehaviours with jQuery infinitescroll and jQuery masonry

I am a little desperate here. I have been reading everything I was able to find on Drupal.behaviours but obviously its still not enough. I try running a masonry grid with the infinitescroll plugin to attach the new images to the masonry. This works fine so far. The next thing I wanted to implement to my website is a hover effect (which shows information on the images) and later fancybox to show the images in a huger size.
(function ($) {
Drupal.behaviors.views_fluidgrid = {
attach: function (context) {
$('.views-fluidgrid-wrapper:not(.views-fluidgrid-processed)', context).addClass('views-fluidgrid-processed').each(function () {
// hide items while loading
var $this = $(this).css({opacity: 0}),
id = $(this).attr('id'),
settings = Drupal.settings.viewsFluidGrid[id];
$this.imagesLoaded(function() {
// show items after .imagesLoaded()
$this.animate({opacity: 1});
$this.masonry({
//the masonry settings
});
});
//implement the function of jquery.infinitescroll.min.js
$this.infinitescroll({
//the infinitescroll settings
},
//show new items and attach behaviours in callback
function(newElems) {
var newItems = $(newElems).css({opacity: 0});
$(newItems).imagesLoaded(function() {
$(newItems).animate({opacity: 1});
$this.masonry('appended', newItems);
Drupal.attachBehaviours(newItems);
});
});
});
}
};
})(jQuery);
Now I read that I need to Reattach the Drupal.behaviours if I want the hover event to also take place on the newly added content.
(function ($) {
Drupal.behaviors.imgOverlay = {
attach: function (context) {
var timeout;
$('.img_gallery').hover(function() {
$this = $(this);
timeout = setTimeout(change_opacity, 500);
}, reset_opacity);
function change_opacity() {
//set opacity to show the desired elements
}
function reset_opacity() {
clearTimeout(timeout);
//reset opacity to 0 on desired elements
}
}
};
})(jQuery)
Where do I now write the Drupal.attachBehaviours() to make it work actually? Or is there some other error I just dont see atm? I hope I wrote the question so that its understandable and maybe it also helps somebody else, since I experienced that there is no real "official" running Version of this combination in drupal 7.
Ok, the solution is actually pretty simple. When writing it correctly than it also runs. its of course not Drupal.attachBehaviours() but Drupal.attachBehaviors() . So this combination now works and I am finally relieved :).

Resources