Protractor - Unable to access element due to fixed Top navigation bar - selenium-webdriver

I'm facing the following issue in protractor with jasmine
Click/mouse hover not working because of fixed top navigation bar in my application. I need to click/perform mouse hover on a web page.
Unfortunately that element is displaying behind that fixed navigation bar. So scroll till element present & click by x & y coordinates are not working.
My dependencies are :
protractor version 5.2.2
node 8.9.3
selenium standalone 3.13
chrome driver-2.40
chromebrowser v67
OS- Windows 10
Thanks in advance

Try using prototype executeScript
Just try clicking that element from the browser console using id,name or xpath.
For example :
var el = element(by.module('header'));
var tag = browser.executeScript('return arguments[0].click()', el).then(function() {
expect(something).toMatch(something);
});

Another way, along the same lines as what Bharath Kumar S and knowing JeffC's caveat that this approach is cheating, I had a similar issue where the App-Header kept getting in my way of clicking, and I knew I was willing to never need it (so, for instance, to find other ways to navigate or log out and not check for stuff that was on it). I, therefore, did the following, which solved the problem. Note if you refresh the screen, you have to call it again. Also note I am using a number of functions from https://github.com/hetznercloud/protractor-test-helper, which do what you would expect from their names.
var removeAppHeaderIfAny = async function() {
//this function hides the app header
//it is useful to avoid having covers there when Protractor worries that something else will get the click
let found = false;
try {
found = await waitToBeDisplayed(by.className("app-header"), 2000);
} catch (e) {
let s: string = "" + e;
if (s.search("TimeoutError") != 0) flowLog("presumably fine, cover already removed: " + e);
found = false;
}
if (!found) return;
if (found) {
let coverElement = await element(by.className("app-header"));
browser.executeScript(
"arguments[0].style.visibility='hidden';",
coverElement
);
await waitToBeNotDisplayed(by.className("app-header"), 10000);
}
return;
//note after this is called you will not see the item, so you cannot click it
};
As I look at the code, it strikes me one can probably remove the if (found) and associated brackets at the end. But I pasted in something I know has been working, so I am not messing with that.
As indicated up front, I knew I was willing to forego use of the app-header, and it is a bit crude.

Related

Taskpane Word Add-Ins (office-js) - The Search function return empty object {} in Word 365 online

I have created a Taskpane Word Add-Ins, written in React Typescript.
This sideload add-in is going to search a list of words in Word document and replace them by new words. All functionality works well in desktop MS Word and find all the words. When I upload manifest to Word 365 online, Taskpane loads and looks find but when I click on button to search, then nothing find. The result of search function is always empty object {}
Below you can see my code for searching part that will trigger when user click on search button. It is working on desktop version but is not working in Word 365 online
(async () => {
try {
let options = Word.SearchOptions.newObject(context);
options.matchCase = false;
options.matchWholeWord = true;
options.ignorePunct = true;
await Promise.all(
WordList.map(async (data: customWord) => {
// NOTE: In Word 365 online, searchResults is always {}
const searchResults = textSelected
? context.document.getSelection().search(data.word, options)
: context.document.body.search(data.word, options);
searchResults.load("items, text");
allSearchResults.push(searchResults);
})
);
} catch (error) {
console.error(error);
}
})();
Does anyone know why search result is empty in Word Online? Is it related to code Promise.all() when running via browser?
I figured it out where the issue comes from. This issue occurs when having matchWholeWord option in your search function or al least set it to True. By removing this option I was able to see the result in Word online eventhough the result I got wasn't as I expected which is make sense. I didn't try for other search options and don't know for others and these are only three of in my case. Below is my change to get result in Word online.
let options = Word.SearchOptions.newObject(context);
options.matchCase = false;
options.ignorePunct = true;
This is a SearchOption bug in Word online which is reported as an issue in office-js GitHub repo.
https://github.com/OfficeDev/office-js/issues/218
Microsoft common! Fix it! We need it!

Tampermonkey run script on specific tab

I'm on learning Tempermonkey and it's userscripts. And I have some questions.
I want to run one script for all firefox opened containers but this script must have different settings according the container's tab it ran on. Like some data and different conditions in some functions.
I tried to use GM_getTab for that but it sends me an empty object for some reasons.
// #grant GM_getTab
GM_getTab(function (e) {
console.log(e); // 'e is empty in console and in debug window either'
});
So basically how to use this function for my task?
P.S. Firefox: Portable 93.0 (64-bit)
Omg why always like this, just asked the question and found the solution in next 10 minutes :D
So the solution is:
(async () => {
const tabObj = await GM.getTab();
// You first have to define ID for all tabs you need, then just comment this part
tabObj.id = Math.random();
GM_saveTab(tabObj); // update the object
// get all stored objects
const tabsDatabase = await GM.getTabs();
const dbL = Object.keys(tabsDatabase).length;
console.log('Script-owned tab:', tabObj); // Current tab
console.log('Script-owned tabs count:', tabsDatabase); // All opened tabs
})();

Implementing google custom search in angularjs

I am trying to implement google custom search in an angular js website.
When I click on the search button it does not display me anything, but the url is updated to the url.
I have followed the steps mentioned in the documentation by google.
I am not sure what I am doing wrong?
My search bar is located on the home page as -
<gcse:searchbox-only enableAutoComplete="true" resultsUrl="#/searchresult" lr="lang_en" queryParameterName="search"></gcse:searchbox-only>
my search result has -
<gcse:searchresults-only lr="lang_en"></gcse:searchresults-only>
Any input is much appreciated.
Thanks,
You may have more than one problem happening at the same time...
1. Query Parameter mismatch
Your searchresults-only does not match the queryParameterName specified on gcse:searchbox-only.
Index.html
<gcse:searchresults-only queryParameterName="search"></gcse:searchresults-only>
Search.html
<gcse:searchresults-only queryParameterName="search"></gcse:searchresults-only>
2. Angular.js is blocking the flow of Google CSE
Under normal circumstances, Google Search Element will trigger an HTTP GET with the search parameter. However, since you are dealing with a one-page application, you may not see the query parameter. If that suspicion is true when you target resultsUrl="#/searchresult", then you have two options:
Force a HTTP GET on resultsUrl="http://YOURWEBSITE/searchresult". You may have to match routes, or something along those lines in order to catch the REST request (Ember.js is really easy to do so, but I haven't done in Angular.js yet.)
Use JQuery alongside Angular.js to get the input from the user on Index.html and manually trigger a search on search.html. How would you do it? For the index.html you would do something like below and for the results you would implement something like I answered in another post.
Index.html
<div>GSC SEARCH BUTTON HOOK: <strong><div id="search_button_hook">NOT ACTIVATED.</div></strong></div>
<div>GSC SEARCH TEXT: <strong><div id="search_text_hook"></div></strong></div>
<gcse:search ></gcse:search>
Index.js
//Hook a callback into the rendered Google Search. From my understanding, this is possible because the outermost rendered div has id of "___gcse_0".
window.__gcse = {
callback: googleCSELoaded
};
//When it renders, their initial customized function cseLoaded() is triggered which adds more hooks. I added comments to what each one does:
function googleCSELoaded() {
$(".gsc-search-button").click(function() {
$("#search_button_hook").text('HOOK ACTIVATED');
});
$("#gsc-i-id1").keydown(function(e) {
if (e.which == 13) {
$("#enter_keyboard_hook").text('HOOK ACTIVATED');
}
else{
$("#search_text_hook").text($("#gsc-i-id1").val());
}
});
}
(function() {
var cx = '001386805071419863133:cb1vfab8b4y';
var gcse = document.createElement('script');
gcse.type = 'text/javascript';
gcse.async = true;
gcse.src = 'https://cse.google.com/cse.js?cx=' + cx;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(gcse, s);
})();
I have a live version of the index.html code, but I don't make promises that will be permanently live since it is hosted in my NDSU FTP.

Angular in chrome auto-firing ng-click

I think I'm losing my mind
I'm working on a medium-large angular app. I came in and rebooted this morning and now angular seems to be executing every ng-click function when the state loads (I'm using $stateProvider). Was definitely not happening yesterday.
Doesn't happen in canary, or ie, or FF.. Just vanilla chrome (I'm on 43.0.2357.124 m)
If I step out of one of the ng-click calls it dumps me into angular.js:10555
functionCall: function(fn, contextGetter) {
var argsFn = [];
if (this.peekToken().text !== ')') {
do {
argsFn.push(this.expression());
} while (this.expect(','));
}
this.consume(')');
var parser = this;
return function(scope, locals) {
var args = [];
var context = contextGetter ? contextGetter(scope, locals) : scope;
for (var i = 0; i < argsFn.length; i++) {
args.push(argsFn[i](scope, locals));
}
var fnPtr = fn(scope, locals, context) || noop;
ensureSafeObject(context, parser.text);
ensureSafeObject(fnPtr, parser.text);
// IE stupidity! (IE doesn't have apply for some native functions)
//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvRIGHT HEREvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
var v = fnPtr.apply
? fnPtr.apply(context, args)
: fnPtr(args[0], args[1], args[2], args[3], args[4]);
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^RIGHT HERE^^^^^^^^^^^^^^^^^^^^^^^^^^^^
return ensureSafeObject(v, parser.text);
};
}
(Since the problem is in chrome it's hitting fnPtr.apply(context, args) which is running my ng-clicks)
Once it's loaded all the way, everything works as expected. It's as though when it links my ng-clicks it's executing them!
It's 'running' the ng-clicks in every scope. Both in the 'master controller' down to directives in whichever state I've loaded (it makes datepickers go absolutely nuts)
Going back and forth between scopes doesn't re-fire the ng-clicks that weren't cleaned up (nav bar buttons for instance). But any new elements that load are susceptible.
I undid changes far back enough that I'm sure anything weird I did should be gone.
I'm going to poke around another few hours then try to re-create in a minimal example, but I'm hoping it's a chrome-update (although none of my other angular apps are having this problem :/ )
My impression is the functionCall method above should be running, and returning a function that'll get called when I actually click, but it's executing it as well as 'linking' it for later executing.
Update #1 - I stuck a console.log in the above function to spit out what it was trying to parse out
ok, in canary (and I assume FF and IE): only non-click-y angular-y things get run through the above functionCall function (like
<button title="{{'Edit '+myCoolName.replace('_', ')}}"... </button>
buut, in chrome: the above AND ng-clicks are getting run through that function.
Loaded: btTypeName.replace('', ' ')
Loaded: ((!newModel.author) ? "Create New " : ("Edit "+newModel.author+"'s ")) + btTypeName.replace('', ' ')
Loaded: btTypeName.replace('', ' ')
Loaded: ((!newModel.author) ? "Create New " : ("Edit "+newModel.author+"'s ")) + btTypeName.replace('', ' ')
Loaded: openReports(); <---- this shouldn't be here :o
Sweet lord I figured it out.
AngularJS Batarang released a new update and it killed everything. Removed it and everything's good as new (good as old?) anyways...
Looks like version: 0.8.0 released yesterday (6/18/15) is responsible.
I filed an issue in github, https://github.com/angular/angularjs-batarang/issues/227

WMS GetFeatureInfo; multiple layers, different sources

I'm developing a web application using GeoExt, OpenLayers and having my own GeoServer to serve various maps. Still, I want to let the user add other WMS's if needed, to be able to play around with all desired layers.
Thus, my problem with the GetFeatureInfo request. Right now I have a toolbar button attached to geoext's map panel,
new GeoExt.Action({
iconCls: "feature",
map: map,
toggleGroup: "tools",
tooltip: "Feature",
control: featureControl
})
its control attribute being
var featureControl = new OpenLayers.Control.WMSGetFeatureInfo({
queryVisible: true,
drillDown: true,
infoFormat:"application/vnd.ogc.gml"
});
I've also defined an event listener to do what I really want once I receive the responses, but that is not relevant here. My problem is the following:
Considering the user clicks on a point where there are 2+ visible layers and at least one of them is from a different source, OpenLayers will have to do one AJAX request per different source and, from OpenLayers own documentation,
Triggered when a GetFeatureInfo response is received. The event
object has a text property with the body of the response (String), a
features property with an array of the parsed features, an xy property
with the position of the mouse click or hover event that triggered the
request, and a request property with the request itself. If drillDown
is set to true and multiple requests were issued to collect feature
info from all layers, text and request will only contain the response
body and request object of the last request.
so, yeah, it will obviously wont work like that right away. Having a look at the debugger I can clearly see that, giving two layers from different sources, it actually DOES the request, it's just that it doesn't wait for the first's response and jumps for the next one (obviously, being asynchronous). I've thought about doing the requests one-by-one, meaning doing the first one as stated above and once it's finished and the response saved, go for the next one. But I'm still getting used to the data structure GeoExt uses.
Is there any API (be it GeoExt or OpenLayers) option/method I'm missing? Any nice workarounds?
Thanks for reading :-)
PS: I'm sorry if I've not been clear enough, english is not my mother tongue. Let me know if something stated above was not clear enough :)
i Hope this help to someone else, I realized that: you're rigth this control make the request in asynchronous mode, but this is ok, no problem with that, the real problem is when the control handle the request and trigger the event "getfeatureinfo" so, i modified 2 methods for this control and it works!, so to do this i declare the control first, and then in the savage mode i modified the methods here is de code:
getInfo = new OpenLayers.Control.WMSGetFeatureInfo({ drillDown:true , queryVisible: true , maxFeatures:100 });
//then i declare a variable that help me to handle more than 1 request.....
getInfo.responses = [];
getInfo.handleResponse=function(xy, request) { var doc = request.responseXML;
if(!doc || !doc.documentElement) { doc = request.responseText; }
var features = this.format.read(doc);
if (this.drillDown === false) {
this.triggerGetFeatureInfo(request, xy, features);
} else {
this._requestCount++;
this._features = (this._features || []).concat(features);
if( this._numRequests > 1){
//if the num of RQ, (I mean more than 1 resource ), i put the Request in array, this is for maybe in a future i could be need other properties or methods from RQ, i dont know.
this.responses.push(request);}
else{
this.responses = request;}
if (this._requestCount === this._numRequests) {
//here i change the code....
//this.triggerGetFeatureInfo(request, xy, this._features.concat());
this.triggerGetFeatureInfo(this.responses, xy, this._features.concat());
delete this._features;
delete this._requestCount;
delete this._numRequests;
// I Adding this when the all info is done 4 reboot
this.responses=[];
}
}
}
getInfo.triggerGetFeatureInfo= function( request , xy , features) {
//finally i added this code for get all request.responseText's
if( isArray( request ) ){
text_rq = '';
for(i in request ){
text_rq += request[i].responseText;
}
}
else{
text_rq = request.responseText;
}
this.events.triggerEvent("getfeatureinfo", {
//text: request.responseText,
text : text_rq,
features: features,
request: request,
xy: xy
});
// Reset the cursor.
OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");}
Thanks, you bring me a way for discover my problem and here is the way i solved, i hope this can help to somebody else.
saheka's answer was almost perfect! Congratulations and thank you, I had the same problem, and with it I finally managed to solve it.
What I would change in your code:
isArray() does not work, change it like this: if(request instanceof Array) {...} at the first line of getInfo.triggerGetFeatureInfo()
to show the results in a popup this is the way:
My code:
getInfo.addPopup = function(map, text, xy) {
if(map.popups.length > 0) {
map.removePopup(map.popups[0]);
}
var popup = new OpenLayers.Popup.FramedCloud(
"anything",
map.getLonLatFromPixel(xy),
null,
text,
null,
true
);
map.addPopup(popup);
}
and in the getInfo.triggerGetFeatureInfo() function, after the last line, append:
this.addPopup(map, text_rq, xy);
A GetFeatureInfo request is send as a JavaScript Ajax call to the external server. So, the requests are likely blocked for security reasons. You'll have to send the requests to the external servers by a proxy on your own domain.
Then, configure this proxy in openlayers by setting OpenLayers.ProxyHost to the proper path. For example:
OpenLayers.ProxyHost = "/proxy_script";
See http://trac.osgeo.org/openlayers/wiki/FrequentlyAskedQuestions#ProxyHost for more background information.

Resources