I've got a very simple geolocation test script (live test; code below) - this works fine in Chrome, but not Firefox (35) where it consistently fires the geoError() function (regardless of the value of timeout). Chrome alerts the latitude almost instantly. Other sites requiring geolocation (e.g. traintimes.org.uk) do work reliably in Firefox. What else do I need to do make Firefox play nicely?!
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>
<script type="text/javascript">
$(document).ready(function(){ $("#rungl").click(function() {
navigator.geolocation.getCurrentPosition(
geoSuccess,
geoError,
{ maximumAge: 1, timeout: 5000 }
);
});
});
function geoSuccess(p) { alert(p.coords.latitude); }
function geoError() { alert("oh no :( "); }
</script>
test
</body>
</html>
Related
Suppose we have a webpage with embedded JavaScript as in index.html as follows:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8" />
<title>Cypress - Testing the Tester</title>
<script>/*<![CDATA[*/
function foo() {
return "bar";
}
function outputMessage(message) {
document.querySelector("output").innerHTML += message + "<br />";
}
window.addEventListener("pageshow", function(){
outputMessage(foo());
});
/*]]>*/</script>
</head>
<body>
<h1>Cypress - Testing the Tester</h1>
<output></output>
</body>
</html>
On page show (e.g. load) this inserts the string "bar" inside <output></output>.
If my_cypress_spec.js is:
describe('The Home Page Tests', () => {
it('Test HTML embedded JavaScript function', () => {
// Assumes, e.g. "baseUrl": "http://127.0.0.1:5500" set in cypress.json
cy.visit('index.html');
expect(foo()).to.equal("bar");
});
});
then in the Cypress test runner I get a "ReferenceError ... foo is not defined". That is, it appears Cypress doesn't recognize the foo() function.
Is there a way for Cypress to directly unit test the foo() function? That is, without relying on ES6/ES2015 export/imports (where the above is refactored to put foo() in its own JavaScript file where it is exported and my_cypress_spec.js imports this)?
Attempting #Fody's suggestion my my_cypress_spec.js becomes:
describe('The Home Page Tests', () => {
it('Test HTML embedded JavaScript function', () => {
// Assumes, e.g. "baseUrl": "http://127.0.0.1:5500" set in cypress.json
cy.visit('index.html');
cy.window().then(win => {
expect(win.foo()).to.eq('bar');
});
});
});
and I get the error "TypeError ... win.foo is not a function".
I'm not sure how well this will apply if you are using a more complex app, e.g created with Angular or React. Those frameworks have specialized test harnesses for unit testing.
For the vanilla JS example you gave, it's quite easy since foo() gets attached to the window of the AUT.
cy.window().then(win => {
expect(win.foo()).to.eq('bar')
})
Fody's answer works. So, in full my_cypress_spec.js can become something like:
describe('The Home Page Tests', () => {
it('Test HTML embedded JavaScript function', () => {
// Assumes, e.g. "baseUrl": "http://127.0.0.1:5500" set in cypress.json
cy.visit('index.html');
cy.window().then(win => {
expect(win.foo()).to.eq('bar');
});
});
});
However, the reason I was getting a "TypeError ... win.foo is not a function" was because in my index.html on my machine (not as originally posted above) I had an opening <script type="module">. Changing that back to <script> made the test pass.
So for completeness I'll tag this as The Answer while noting the insights come from #Fody and #jonrsharpe.
I try to select a specific script on the adobe air download site
https://get.adobe.com/de/air/download/?installer=Adobe_AIR_30.0_for_Win32&stype=7645&standalone=1 (look out download should start)
Problem is the script I'm trying to get has no attributes and is between some other scripts.
<script type="text/javascript" src="https://wwwimages2.adobe.com/uber/js/pdc_s_code.js"></script>
<script src="//assets.adobedtm.com/659ec8ada5450db95675e43beaaae92399591a11/satelliteLib-7123a14bc11ffd1ad43be190a593a8932494dcb0.js"></script>
<script>
setTimeout("location.href = 'https://airdownload.adobe.com/air/win/download/30.0/AdobeAIRInstaller.exe';", 2000);
$(function() {
$("#whats_new_panels").bxSlider({
controls: false,
auto: true,
pause: 15000
});
});
setTimeout(function(){
$("#download_messaging").hide();
$("#next_button").show();
}, 10000);
</script>
<script type="text/javascript" src="https://wwwimages2.adobe.com/downloadcenter/js/live/polarbear.js"></script>
I'm able to get the first and fourth one with
/html/body/script[1] and
/html/body/script[2]
but I don't know how to get the one I actually need.
Try to use
//script[not(#*)]
to select script node with no attributes
Does reactjs works fine with IE8? I am using React v0.11.1.
Following code is NOT working in IE8. Works fine on all the other browsers
SCRIPT438: Object doesn't support property or method 'isArray'
File: react.js, Line: 17372, Column: 37
SCRIPT5009: 'React' is undefined
File: myreact.js, Line: 3, Column: 1
SCRIPT438: Object doesn't support property or method 'map'
File: JSXTransformer.js, Line: 12637, Column: 3
/** #jsx React.DOM */
var MyComponent = React.createClass({displayName: 'MyComponent',
getDefaultProps:function(){
return{
text:"",
numbers:0
}
},
getInitialState:function(){
return {txt:"initial", id:0}
},
updateText: function(event){
this.setState({text:event.target.value})
},
propTypes:{
text:React.PropTypes.string,
numbers: React.PropTypes.number.isRequired
},
render:function(){
return (
React.DOM.div(null,
Widget({text: this.state.text, update: this.updateText}),
Widget({text: this.state.text, update: this.updateText})
)
)
}
});
var Widget = React.createClass({displayName: 'Widget', render:function(){
return(
React.DOM.div(null,
React.DOM.input({type: "text", onChange: this.props.update}),
React.DOM.div(null, this.props.text)
)
)
}
});
React.renderComponent(
MyComponent({text: "HI there", numbers: 34}),
document.getElementById("content")
);
You need to use the following shims/pollyfills as noted in the react docs. es5-shim will resolve the specific isArray bug you are seeing.
I've managed to launch my React app in IE8 using the following code:App.js:
require('core-js'); //Important!
var React = require('react');
var ReactDOM = require('react-dom');
var Application = React.createClass({ ... });
ReactDOM.render(React.createElement(Application,null), document.getElementById("app-container"));
index.html:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.7/es5-shim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.7/es5-sham.min.js"></script>
<script type="text/javascript" src="bundle.js" defer></script>
</head>
<body>
<div id="app-container"></div>
</body>
</html>
Comments: bundle.js will be loaded after es5-shim/es5-sham because of defer html attribute
Our application uses an $http interceptor to add tokens to $http requests as a form of security, the token that the interceptor adds are updated every 5 or so minutes. We now want to use ng-grid.
However, the $http interceptor makes is so that ng-grid will not load the template it uses for the header row, which causes the header row to not render.
Here is the issue in action: http://plnkr.co/edit/krvBF2e4bHauQmHoa05T?p=preview
If you check the console it shows the following error:
GET http://run.plnkr.co/l0BZkZ2qCLnzBRKa/ng1389719736618headerRowTemplate.html?securityToken=123456 404 (Not Found)
The reason why this happens is because ng-grid stores the template for the header row in the $templateCache, and then uses an ng-include to later retrieve it.
ng-include uses a $http.get request, with $templateCache as the cache, to get the template.
The $http.get request is intercepted by the interceptor which adds the security token to the url before it has a chance to query $templateCache for the template using the url.
$templateCache is expecting ng1389719736618headerRowTemplate.html but instead gets ng1389719736618headerRowTemplate.html?securityToken=123456
The result is that the $templateCache can't find the template, which then results in $http.get hitting the server and getting the 404 error.
The other issue is that if we ever wanted to use $templateCache to store templates and later retrieve it with ng-include or $http.get, $templateCache would not being able to find the template because the url would get modified.
How can I get ng-grid to display the header row with the $http interceptor adding security tokens to the end of the urls?
here is the code
Html:
<!DOCTYPE html>
<html ng-app="myApp">
<head lang="en">
<meta charset="utf-8">
<title>Custom Plunker</title>
<link rel="stylesheet" type="text/css" href="http://angular-ui.github.com/ng-grid/css/ng-grid.css" />
<link rel="stylesheet" type="text/css" href="style.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.4/angular.min.js"></script>
<script type="text/javascript" src="http://angular-ui.github.com/ng-grid/lib/ng-grid.debug.js"></script>
<script type="text/javascript" src="main.js"></script>
</head>
<body ng-controller="MyCtrl">
<div class="gridStyle" ng-grid="gridOptions"></div>
</body>
</html>
javascript:
var app = angular.module('myApp', ['ngGrid']);
app.controller('MyCtrl', function($scope) {
$scope.myData = [{name: "Moroni", age: 50},
{name: "Tiancum", age: 43},
{name: "Jacob", age: 27},
{name: "Nephi", age: 29},
{name: "Enos", age: 34}];
$scope.gridOptions = { data: 'myData' };
});
app.config(function($provide, $httpProvider) {
$provide.factory('tokenAuthInterceptor', function($q){
return {
// optional method
'request': function(config) {
// do something on success
config.url = config.url + "?securityToken=123456";
return config || $q.when(config);
}
};
});
$httpProvider.interceptors.push('tokenAuthInterceptor');
});
Update
The solution that was finally decided upon was to use an angular decorator and decorate $templateCache, the plunker was updated to reflect this.
$provide.decorator('$templateCache', function($delegate) {
var get = $delegate.get;
function formatKey(key)
{
// code for formatting keys
}
$delegate.get = function(key) {
var entry = get(key);
if (entry)
{
return entry;
}
else
{
return get(formatKey(key));
}
};
return $delegate;
});
We ran into this same issue and implemented a quick check in our interceptor to check if the item was already in the templateCache.
if ($templateCache.get(config.url)){
return config;
}
I got the idea from the cachebuster project.
Using soundManager2, I made a simple anchor with onclick="mySound.play()", but there is a big gap (almost half a second) before the sound is actually heard! This is, even though I pre-loaded the sound. How can I get a better response-time?
Here is the source code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" >
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="author" content="Shawn Inder" />
<title>jeuReno</title>
<style type="text/css">
<!--
-->
</style>
<!-- include SM2 library -->
<script type="text/javascript" src="soundManager/script/soundmanager2.js"></script>
<!-- configure it for your use -->
<script type="text/javascript">
soundManager.url = 'soundManager/swf/'; // directory where SM2 .SWFs live
// Note that SoundManager will determine and append the appropriate .SWF file to the URL,
// eg. /path/to/sm2-flash-movies/soundmanager2.swf automatically.
// Beta-ish HTML5 audio support (force-enabled for iPad), flash-free sound for Safari + Chrome. Enable if you want to try it!
// soundManager.useHTML5Audio = true;
// do this to skip flash block handling for now. See the flashblock demo when you want to start getting fancy.
soundManager.useFlashBlock = false;
// disable debug mode after development/testing..
// soundManager.debugMode = false;
// Option 1: Simple onload() + createSound() method
/*soundManager.onload = function() {
// SM2 has loaded - now you can create and play sounds!
soundManager.createSound('helloWorld','sounds/crash.mp3');
soundManager.play('helloWorld');
};*/
// Option 2 (better): More flexible onload() + createSound() method
/*soundManager.onload = function() {
var mySound = soundManager.createSound({
id: 'aSound',
url: 'sounds/kick.mp3'
// onload: [ event handler function object ],
// other options here..
});
mySound.play();
}*/
// Option 3 (best): onready() + createSound() / ontimeout() methods for success/failure:
/*soundManager.onready(function() {
// SM2 has loaded - now you can create and play sounds!
var mySound = soundManager.createSound({
id: 'aSound',
url: 'sounds/snare.mp3'
// onload: [ event handler function object ],
// other options here..
});
mySound.play();
});*/
soundManager.useHighPerformance = true;
soundManager.ontimeout(function() {
// (Optional) Hrmm, SM2 could not start. Show an error, etc.?
alert("wtf");
});
</script>
<script type="text/javascript">
/*var snare = soundManager.createSound({
id: 'snare',
url: 'sounds/snare.mp3'
});
var kick = soundManager.createSound({
id: 'kick',
url: 'sounds/kick.mp3'
});
var crash = soundManager.createSound({
id: 'crash',
url: 'sounds/crash.mp3'
});
var highHat = soundManager.createSound({
id: 'highHat',
url: 'sounds/highHat.mp3'
});*/
soundManager.onready(function() {
// SM2 has loaded - now you can create and play sounds!
mySound = soundManager.createSound({
id: 'aSound',
url: 'sounds/snare.mp3'
// onload: [ event handler function object ],
// other options here..
});
mySound.load();
// mySound.play();
});
</script>
</head>
<body>
click
</body>
</html>
I don't see where the song gets preloaded. You want to set autoLoad to true in the default or createSound section (the defaults should be inherited by createSound).
In the default section it would be soundManager.autoLoad = true;
Or in the createSound method autoLoad:true, id: 'aSound', url: 'sounds/kick.mp3'