I'm using zombiejs + mocha to write some tests for a library that manipulates the DOM, it uses JavaScript native functions like document.createElement(), my problem is, when I run the tests I get an exception saying that 'document is not defined'.
Is it a problem with zombiejs, or with jsDOM? and how can I fix it?
here is an example of my code:
HTML:
<!DOCTYPE html>
<html>
<head>
<script src="mocha.js"></script>
<script src="expect.js"></script>
<title>XS UI Tests</title>
<script type="text/javascript" charset="utf-8" src="../lib/mylibrary.js"></script>
<script>
mocha.setup('bdd');
</script>
</head>
<body>
<div id="table"></div>
<div id="controls"></div>
<div id="form"></div>
<div id="mocha"></div>
<script src="tests.js"></script>
</body>
</html>
in tests.js:
var expect = require( 'expect.js' )
, Zombie = require( 'zombie' )
, browser = new Zombie( { debug: true } )
;
describe( 'XS UI Tests:', function() {
before( function( done ) {
browser.visit( 'http://localhost:8080/test/ui.html', done );
} );
it( 'expect ui.html to be loaded', function() {
expect( browser.success ).to.be( true );
} );
describe( 'Table Tests:', function() {
it( 'expect div#table ( table container ) to exist', function() {
expect( browser.query( "#table" ) ).to.be.ok();
} );
} );
} );
Thank you for your help
The document object is contained within the zombie browser. If your code doesn't find document, it is likely you are not running it within the zombie sandbox context.
Are you loading your library via zombie.visit('/page/with/library') or are you requiring it directly and trying to use it within the test?
It is best to test complete webpages rather than libraries. You should create a test page that has a few buttons/links on it which test different functions of the library, and pressButton or visit those with zombie.
Related
My component is loading fine but the styles are not loading, nor are the events firing. I am following the documentation and no errors are being thrown but it seems I might be missing something fundamental here?
View template rendered with res.marko:
import Explanation from "./components/explanation.marko";
<!DOCTYPE html>
<html lang="en">
<head>
...
</head>
<body>
...
<include(Explanation, input.explanation) />
...
</body>
</html>
explanation.marko file:
class {
onExplanationClick() {
console.log("Explanation clicked");
}
}
style {
.explanation-paragraph {
color: red;
}
}
<div id="explanation" on-click('onExplanationClick')>
<for (paragraph in input.content)>
<p class="explanation-paragraph">${paragraph}</p>
</for>
</div>
Server side:
app.get("/explanation/:id", async function(req, res) {
var explanation = await findExplanation(req.params.id);
var template = require("../../views/explanation/explanation.marko");
res.marko(template, { explanation, user: req.user });
});
Also using marko/node-require and marko/express.
You will need to integrate a module bundler/asset pipeline. In the sample marko-express app we are using Lasso (an asset pipeline + JavaScript module bundler).
There's also another sample app that integrates Webpack: https://github.com/marko-js-samples/marko-webpack
The Marko team supports both Lasso and Webpack, but we recommend Lasso because it is simpler and requires minimal configuration.
Please take a look at the marko-express app and feel free to ask questions in our Gitter chat room if you get stuck: https://gitter.im/marko-js/marko
I am trying to embed "HelloWorld" module into existing HTML page.
I found that module is rendered asynchronously (i don't get rendered element
immediately after calling "embed").
I want to use Elm in an existing project and rewrite some parts of JavaScript
in Elm. But asynchronous rendering makes things difficult.
Is there a way to render it synchronously?
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="app.js" type="text/javascript"></script>
</head>
<body>
<script type="text/javascript">
var appContainer = document.createElement('div');
Elm.HelloWorld.embed(appContainer);
console.log('Html: ' + appContainer.innerHTML); // Will print an empty string
setTimeout(function() {
console.log('Html: ' + appContainer.innerHTML); // Will print "Hello, World!"
}, 0);
</script>
</body>
</html>
HelloWorld.elm
module HelloWorld exposing (main)
import Html exposing (text)
main =
text "Hello, World!"
UPD: Removed redundant code.
Nowadays, Elm doesn't expose this kind of hook.
You have basically two different approaches, one based on events and the other based on timing (the setTimeout() method you are already using).
The event-driven approach involves the MutationObserver Api.
Creating a new MutationObserver, you can observe the HTML Node onto which you run the Elm module: this way, you have a hook on the DOM update.
A naive check would be checking against the children's list of the appContainer:
<body>
<div id="myDiv"></div>
<script type="text/javascript">
var appContainer = document.getElementById('myDiv');
var mo = new MutationObserver(function(mutationRecords, instance) {
for (var i = 0; i < mutationRecords.length; i += 1) {
if (mutationRecords[i].addedNodes.length > 0) {
// a trivial check
console.log('Html: ' + appContainer.innerHTML);
// stop observing, if not needed anymore
mo.disconnect();
}
}
});
mo.observe(appContainer, { childList: true });
Elm.HelloWorld.embed(appContainer);
</script>
</body>
Note that the above code is assuming that your HelloWorld module is adding children to the appContainer, so you should modify it conveniently:
module HelloWorld exposing (main)
import Html exposing (p, text)
main =
p [] [ text "Hello, World!" ]
I have a problem with the AccountKit JavaScript SDK ,
When i integrate it with my website it works fine with Firefox but in Chrome it works fine first, but when i try to use it again it gives me this error:
'AccountKit SDK was not initialized. Call AccountKit.init first.'
Any idea?
The idea is to add the initialization immediately after the sdk loads. Seems like when there is much data/code to load before the initialization, it sometimes hangs.
ie
<script src="https://sdk.accountkit.com/en_US/sdk.js"></script>
<script type="text/javascript">
AccountKit_OnInteractive = function(){
AccountKit.init(
{
appId:youID,
state:"{{csrf}}",
version:"v1.1"
}
);
console.log("{{csrf}}")
};
</script>
NOT
<script src="https://sdk.accountkit.com/en_US/sdk.js"></script>
// some code
<script type="text/javascript">
AccountKit_OnInteractive = function(){
AccountKit.init(
{
appId:youID,
state:"{{csrf}}",
version:"v1.1"
}
);
console.log("{{csrf}}")
};
</script>
I have same issue and I solve it. Just call your AccountKit.init your main file(index.html) where your app hold all scripts. From me it looks like this:
index.html
<script src="https://sdk.accountkit.com/en_US/sdk.js"></script>
<script type="text/javascript">
AccountKit_OnInteractive = function(){
AccountKit.init(
{
appId:youID,
state:"{{csrf}}",
version:"v1.1"
}
);
console.log("{{csrf}}")
};
</script>
Can you add in the code that you're using?
https://developers.facebook.com/docs/accountkit/web
You do need to call AccountKit.init as part of the setup.
Sencha Touch application has requires:[] option to specify the list of controllers and models and stores etc that are loaded that we need for the application to work but is there a way to execute something that we need even before the loading of the dependencies. FOr e.g. I need the Browsers Language even before the loading of all dependencies. So is it possible to do?
Keep in mind: Sencha Touch is nothing but JavaScript.
You can add some script in your index.html in front of the script tag that loads the sencha microloader.
<!DOCTYPE HTML>
<html manifest="" lang="en-US">
<head>
<meta charset="UTF-8">
<title>FNL</title>
<style type="text/css">
<!-- sencha stuff -->
</style>
<script id="myScript" type="text/javascript" src="myScript.js"></script>
<!-- The line below must be kept intact for Sencha Command to build your application -->
<script id="microloader" type="text/javascript" src=".sencha/app/microloader/development.js"></script>
</head>
<body>
<div id="appLoadingIndicator">
<div></div>
<div></div>
<div></div>
</div>
</body>
</html>
I added some lines to the ST Microloader:
this.css = processAssets(manifest.css, 'css');
// Load language strings
var xhr = new XMLHttpRequest();
xhr.open('GET', 'api/Settings', false);
xhr.send(null);
var settings = eval("(" + xhr.responseText + ")");
Lang = settings.Translations[0];
Options = settings.Options[0];
// End Load Language Strings
this.js = processAssets(manifest.js, 'js');
In ExtJS i accomplished this by loading a Dependency class first
Ext.require([
'MyApp.Dependencies',
..
]);
so the Dependecies class is loaded before all controllers which looks like this
Dependencies.js:
Ext.define('MyApp.Dependencies', {
singleton: true,
init: function() {
// load translation data
}
});
MyApp.Dependecies.init();
and for completition my init function looks something like this:
inti: function(){
function loadScriptSync(url) {
var xhrObj = new XMLHttpRequest();
// open and send a synchronous request
xhrObj.open('GET', url, false);
xhrObj.send('');
// add the returned content to a newly created script tag
var se = document.createElement('script');
se.type = "text/javascript";
se.text = xhrObj.responseText;
document.getElementsByTagName('head')[0].appendChild(se);
}
var language = this.getLanguage();
loadScriptSync("resources/locale/locale." + language + ".js");
}
I see many references to this error on the web, but they are not helping me. I guess i am new enough to this that i need a specific answer for my problem.
I am attaching the first portion of code on a page that i am running. the last line i show is the line that is creating the error stating in the title. Please let me know if you have any suggestions.
Thank you!
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>CDI Web Portal</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<script src="js\dojo\dojo.js" type="text/javascript"></script>
<script type="text/javascript" src="http://www.google.com/jsapi?key=ABQIAAAA5a4NhilcmrdMQ5e3o22QWRQWrGbhbxAguaJ-a4SLWYiya7Z2NRTDfQBdxmHdf5ydkZYLZTiz1tDXfg"></script>
<script type="text/javascript" src="ge-poly-fit-hack.js"></script>
<script type="text/javascript" src="kmldomwalk.js"></script>
<style type="text/css">
#import "js/dijit/themes/tundra/tundra.css";
#import "js/dojo/resources/dojo.css";
</style>
<style type="text/css">#import "index.css";</style>
<script type="text/javascript"> dojo.ready(function() { dojo.byId("greeting").innerHTML += ", from " + dojo.version; }); </script>
<script type="text/javascript">
// <![CDATA[
djConfig = { parseOnLoad: true };
// google.load("dojo", "1.6.1");
google.load("maps", "2");
google.load("earth", "1");
var g_ge;
var g_earthDisabled = false;
var g_kmlObject;
google.setOnLoadCallback(function() {
dojo.require('dijit.layout.BorderContainer');
dojo.require('dijit.layout.SplitContainer');
dojo.require('dijit.layout.ContentPane');
dojo.require('dijit.Tree');
//dojo.require('CheckboxTree');
dojo.require('dijit.form.CheckBox');
dojo.require('dijit.form.Button');
dojo.require('dijit.form.TextBox');
dojo.require('dojo.data.ItemFileWriteStore');
dojo.require('dojo.parser');
dojo.require('dojo.cookie');
dojo.require('dojo.fx');
dojo.addOnLoad(function() {
// load checkboxtree
var scpt = document.createElement('script');
scpt.src = "dijit.CheckboxTree.js";
document.body.appendChild(scpt);
{ dijit.byId('load-button').setDisabled(true) };
// build earth
google.earth.createInstance(
'map3d',
function(ge) {
g_ge = ge;
g_ge.getWindow().setVisibility(true);
g_ge.getNavigationControl().setVisibility(ge.VISIBILITY_AUTO);
g_ge.getLayerRoot().enableLayerById(g_ge.LAYER_BORDERS, true);
g_ge.getLayerRoot().enableLayerById(g_ge.LAYER_BUILDINGS, true);
dijit.byId('load-button').setDisabled(false);
checkAutoload();
},
function() {
g_earthDisabled = true;
dijit.byId('load-button').setDisabled(true);
From your comment, you used declarative syntax to create the dijit, i.e. <button id="load-button" dojoType="dijit.form.Button" onclick="loadKml();">. If the declarative syntax is used, the dijit is actually created after the page is loaded. So you should put the code to use the dijit in the Dojo's load callback, i.e. inside of dojo.addOnLoad callback.
But your code is bad formatted and mingled with Google Maps load callback, it's not easy to inspect the code. My suggestion would be to wrap the dijit.byId('load-button').setDisabled(true); with dojo.addOnLoad, like below:
dojo.addOnLoad(function() {
dijit.byId('load-button').setDisabled(true);
});
It means that you've got a dojo object rather than a dijit object -- or possibly no object named load-button at all, since it's not clear from this where load-button is being created. Make sure there is an object with id="load-button" that was created with dijit.