Mock built-in objects with NightmareJS - javascript

I am trying use NightmareJS to load a page, click a button, then take a screenshot to test. The click handler on the button requests the geolocation. This is part of what I'm testing for. I want the page to appear a certain way if the user grants the geolocation permission, and another way if they decline.
The problem is that Nightmare doesn't expose a method for me to intercept the permission prompt to accept or decline it. After some research I learned that Electron just hardcodes this permission to 'granted' so there may not even be a way to set it to declined.
What I'd like to do is replace Electron's navigator.geolocation object with a mock that responds to the geolocation request in a certain way.
new Nightmare().goto('https://example.com')
.evaluate(function () {
navigator.geolocation = {
getCurrentPosition(cb) {
cb({coords: latitude: 42, longitude: -42});
}
}
})
.click('#locateMe')
.screenshot()
.end()
.then(diffScreenshot)
However when I try this it seems like the navigator.geolocation object doesn't change. Is there some other way to accomplish this goal?

I think this is possible (or should be) in both projects, you might try changing:
navigator.geolocation
To
window.navigator.geolocation
This is because most evaluate calls are run in a clean context, or so I think. If this doesn't work then Navalia might be able to do it as it's fairly "bare-metal" so-to-speak.
Best of luck!

Related

How can I access appInsights.context from javascript code

I want to display the UserId on the website, so users can communicate it to us whenever they encounter a problem. However, in code, appInsights.context is undefined. How can I access this?
window.appInsights = appInsights;
appInsights.trackPageView();
console.log(appInsights.context);
is logged as undefined. However, I can access it in the developer console when I run the application. It seems like the context is being removed/not added yet.
I believe this is because the appInsights context is not necessarily created right away?
you may need to do this work "asynchronously" by adding events to the ai queue:
appInsights.queue.push(function () {
console.log(appInsights.context);
});

Is there a 'GPS status changed' event for html5 geolocation?

I'm developing a web app for mobile and using html5's geolocation api.
When the page is loaded I start a watch position:
function enableWatchPosition() {
if (navigator.geolocation) {
watchPositionId = navigator.geolocation.watchPosition(locateByBrowser, handleErrorGettingLocation, {
timeout : 30000,
enableHighAccuracy : true,
maximumAge : 1000
});
}
}
If a user doesn't have his GPS on, handleErrorGettingLocation is triggered and I show him an error message, asking him to turn GPS on.
My Question is:
Suppose the user then turns his GPS on - how can I detect that (so I could retry and call enableWatchPosition() again)? Is there some sort of js event I can listen to?
Thanks!
There is no such event that’s exposed in a way you could see from your Web-application code. Certainly there is no such event defined in the standard Geolocation API spec. And I don’t believe there are any non-standard events that any browsers expose for it. So I don’t think you’re going to be able to automatically re-trigger a call to your enableWatchPosition() function.
I’m sure that’s not the answer you were hoping for, but it is the answer. :-(

How to use pure JavaScript to determine whether Facebook/Twitter is blocked?

Some countries like China is blocking Facebook/Twitter. How to use JavaScript to check whether a website is not accessible?
update:
I am adding a "Share to Facebook" button on a web page. 50% of the visitors are from China and 50% are from outside of China.
For those China visitors, they would never see that Facebook button because it's blocked. I want to use $.hide() or $.empty() to remove the related HTML if I detected that Facebook is blocked. How can I do that?
You can check if loading the facebook SDK is blocked in china (//connect.facebook.net/en_UK/all.js)
If this is the case then you could do something like this:
$.getScript('//connect.facebook.net/en_UK/all.js')
.success(function(){
// do something if facebook is available
});
You need to take care because you need to define a timeout if you want to make a callback for the fail case. I need to check the correct settings later, but currently i don't have time to.
EDIT
Based on the comment of funkybro it would be better to do a JSONP request. Loading the API would inject a butch of code you probably don't need.
So just request e.g.:
$.getJSON('https://graph.facebook.com/feed?callback=?')
.success(function(){
// do something if facebook is available
});
The request will include a failure code because you don't provide at graph node, but knowing that you get an error message from facebook means that it is reachable for the client.
Use jQuery.get like this:
$.get("http://facebook.com").fail(function() {
$(...).hide()
}).done(function() {
$(...).show()
})
Note that this is a cross-site request that will fail for security reasons unless you disable that browser feature.
If that's not possible for you, I suggest you use GeoIP or similar technologies to determine the users origin.

Javascript GeoLocation Caching

I'm using the following to successfully capture user's location (mobile browser):
<script>
if ( navigator.geolocation ) {
navigator.geolocation.getCurrentPosition(handlePosition);
}
function handlePosition(pos) {
//this passes lat/long to additional code
}
</script>
This works, but often times the browser will seemingly cache the location data. The page that calls this geolocation code shows information relative to the user's location, so what happens is the user can move (change location), the page is reloaded, but the previous location data is used (showing incorrect data). Sometimes the page will have to be refreshed once or even twice for the page to use new location data.
Does anyone know of any means to force the code to get and use "up to date" location data each time script is executed?
FWIW, I'm experiencing problem in iOS Safari (6.1). Have not been able to test in Android yet.
Thanks for reading and for any help.
Edit: As Oleksiy has written in his answer, the Geolocation API now supports this. You can add {maximumAge: 0} as the third option parameter of getCurrentPosition. There is also a timeout and a high accuracy option available in the PositionOptions as noted in the specification.
Your navigator call would change to the following:
navigator.geolocation.getCurrentPosition(
handlePosition,
(error)=>{},
{maximumAge:0}
);
No can't be done. You don't have any control over the browser geolocation other than the code in your example. The html5 geo location api is very, very limited and that is a pain. I also had a question whether I could ask it if permission for the domain had already been granted and the answer was also no.
The problem is that the api is implemented in the browser itself and that are just no endpoints for these kind of functions.
What you could do is make an array in js to store previous locations and before you update your view test against that array to see if you got a stale location.
You do have this ability now.
getCurrentPosition takes three parameters: success, failure and options
Try this:
<script>
if ( navigator.geolocation ) {
navigator.geolocation.getCurrentPosition(handlePosition, (error)=>{}, {maximumAge:0});
}
function handlePosition(pos) {
//this passes lat/long to additional code
}
</script>

How does one handle a Facebook Connect timeout

I don't see any way to respond to a timeout issue if Facebook is down or not responding when I use FB.init. There's no option here: http://wiki.developers.facebook.com/index.php/JS_API_M_FB.Bootstrap.Init_2
Would be nice if there were some way to respond to errors like you can with normal xmlhttprequests. Is there such a thing with Facebook Connect?
As far as I know, you cannot gracefully handle timeouts with FB.init.
That's why I never use FB.init directly. Instead, I always call FB_RequireFeatures. This wraps the FB.init call so that I can deal with errors and degrade gracefully. What I do is write my own function that checks whether Facebook Connect initialized correctly and then does something appropriate if it did not.
For example:
FB_RequireFeatures(["Connect"], function() {
FB.init("API_KEY", "xd_receiver.htm");
myPostConnectFunction();
});
function myPostConnectFunction() {
// Check for success of FBconnect, and deal with errors accordingly.
};
If that seems hacky, well... it is. :-)

Categories

Resources