Is there a way to unit-test unobstrusive jQuery scenarios - javascript

I would like to test if certain javascript (using jQuery or any other framework) applied to a certain html code would create certain behaviour on a page. For example:
If I have html (written in a test as a stub)
<div class="order">
<div class="id">15</div>
<div class="client">John</div>
</div>
And I have a js files included (written in a test also):
jquery.js
orders.js (the one I want to test)
And the main part of the test (syntax is imagined)
part 1:
'client'.is 'hidden'
part 2:
'order'.click
'client'.should_be visible
I want the test to pass only if orders.js has this code:
$(function(){
$('.client').hide();
$('.order').click(function(){
$(this).children('.client').show();
});
});
I guess, I can do such things with rspec features or cucumber, but is there any more specific frameworks for such tests? Any help would be appreciated.

There are at least two solutions.
First is jasmine-jquery HTML fixtures. Citation:
The Fixture module of jasmine-jquery allows you to load HTML content
to be used by your tests. The overall workflow is as follows:
In myfixture.html file:
<div id="my-fixture">some complex content here</div>
Inside your test:
loadFixtures('myfixture.html')
$('#my-fixture').myTestedPlugin()
expect($('#my-fixture')).to...
and
Also, a helper method for creating HTML elements for your tests is
provided:
sandbox([{attributeName: value[, attributeName: value, ...]}])
It creates an empty DIV element with a default id="sandbox". If a hash of
attributes is provided, they will be set for this DIV tag. If a hash
of attributes contains id attribute it will override the default
value. Custom attributes can also be set.
And also there is jasmine-fixtures library. Citation:
Let's say you want to write a Jasmine spec for some code that needs to
select elements from the DOM with jQuery:
$('#toddler .hidden.toy input[name="toyName"][value="cuddle bunny"]')
...
jasmine-fixture's affix method lets you do this instead:
beforeEach(function(){
affix('#toddler .hidden.toy input[name="toyName"][value="cuddle bunny"]')
});

Related

MathJax: Is it possible to highlight only specific elements and not the whole document?

I am writing a blog with markdown-functionality, the lib I use is called showdown.js. But this markdown-lib doesn't support formula-rendering. So that's why I wonder, if it is possible, to let MathJax only render a given DOM-Element?
I know, that there is a lib, called showdown-katex, but considering that I use Spring Boot for my server, I am not able to include javascript-libs, installed with npm.
Use the elements option in the startup section of your MathJax configuration (documentation:
<script>
MathJax = {
startup: {
elements: ['#id', '.class']
}
};
</script>
where id is replaced by the ID of an element to typeset, or class is replaced by a class that selects the elements to typeset. You can use any CSS selectors, this is just an example.

Dojo: defining Select-like widget with Options declaratively

The goal is to write custom widget similar to Select with options. Options should be able to be specified declarative. Example:
<div data-dojo-type="MySelect">
<span class="my-select-option" data-dojo-type="MySelectOption>Foo</span>
<span class="my-select-option" data-dojo-type="MySelectOption>Bar</span>
</div>
The problem is that all <span>s get overwritten and removed. What is the way to handle them correctly inside MySelect's JavaScript file?
You can use data-dojo-props together with dojo/parser to decoratively configure your custom widget.
Here a quick example for a possible markup, please note:
Use data-dojo-type to specify your custom "class" for your widget.
Use data-dojo-props to pass to the constructor any sort of configuration information upon instantiation.
data-dojo-props is a HTML5 data attributes and works with the latest version of Dojo.
Markup in your HTML:
<div id="instanceId" data-dojo-type="nameSpace/class" data-dojo-props="data: 'some data'"></div>
This reading is a good start:
https://dojotoolkit.org/documentation/tutorials/1.10/declarative/
For more information about parsing:
https://dojotoolkit.org/reference-guide/1.10/dojo/parser.html

Minimal jQuery template

I am creating a UI, in which user can add / delete items (of similar layout).
It starts with one item and you can click 'add' to add more. The UI consists of several different types of items.
What I am doing currently is populating a single item item 1 ( of each type ) and on add event, I clone the item 1, replace the changes done by user in item 1 and append the clone to the container.
In simple words, instead of dynamically creating html with jQuery, I am cloning html of a div. But in this approach , I had to change a lot of things to keep to give the new item to initial state.
So, I want to avoid the replacing the edits done by user, so I was thinking something like below,
<script type="text/template" id="item_type1">
<div>
<div>Box</div>
</div>
</script>
<script type="text/template" id="item_type2">
<div>
<div>Box2</div>
</div>
</script>
And on add event, I want to do something like $('#item_type1').html() and $('#item_type2') to create new items.
I know there are sophisticated libraries like handlebar and mustache and underscore has its own way of implementing templates.
But I am not using any of these already and thus do not want to included them just to copy content. I dont want anything special. I am not passing variables. I am just cloning some markup to use again and again.
Is this way to insert html in script tags , going to work in all browsers ? and is it a good way ?
EDIT:
Its for the wp plugin and I assume js is turned on , else the plugin wont work anyways.
What about:
Your HTML should be, for example:
<script type="text/template" id="item_type1">
<div>
<h1>Box1</h1>
<p>
</p>
</div>
</script>
And your code would be:
var templateHtml = $('#item_type1').html();
var $item = $(templateHtml);
$('body').append($item);
$item.on('click', function() {});
This is an easy way that will work on all browsers.
Step 1: Create an HTML file with your template inside of it
Step 2: Using jQuery's load() method, call your HTML template into a div element in the main HTML file:
$("#main-div").load("yourtemplate.html")
Step 3: Be amazed
Is this a good idea? It depends:
If it's a self contained application on a known environment with a determined supported browser and with equally determined settings (like if JavaScript is on or not) then yea, sure. Why not?
If it's open to the public in every single browser possible with many different configurations, then no, it's a horrible idea. If your user doesn't have JavaScript enabled, then your content doesn't show up. Also, if one of your scripts break in production, then you are again left with no content. You can learn this lesson from when Gawker made this same mistake

The effective way to call javascript initializing form?

One often have form with some dynamic parts, that needs to be initialized onload. E.g. datepickers, enhanced selects, section toggling, hiding/showing conditional elements etc.
Example:
<form>
<input type="text" name="date">
<select name="selection"></select>
</form>
and I want to init datepicker on the date element and Select2 on the selection element.
Where to put the form initialization?
My thoughts:
Init throught global selector:
$(function() {
$('input[name=date]').datepicker();
$('select[name=selection]').select2();
})`.
But I have one js file for the whole web, so this would led to crawling the whole DOM on each page load, even if the element is not present on current page.
Some kind of conditional selector. E.g. give <body> and id and add to my global js file something like this: $(function() { $('input[name=date]', 'body#foo').datepicker(); })
Encapsulate the init for each form into a function (or class method), and call the function from HTML:
<script type="text/javascript">
$(document).ready(initMyForm());
</script>
But I'm guessing, isn't there any better way? What would you suggest, especially for bigger projects with many different forms requiring different javascript initialization?
If for your current project you are running one JS file, or even for medium-size projects where a 'generic' form setup function is appropriate, using a function as you described would be appropriate.
See example below, with the function wrapped as a small jQuery plugin, so you can call this on specific selectors as required, to avoid running through the whole DOM.
;(function($){
$.extend({
initMyForm : function(){
$(this).find('input[name=date]').datepicker();
$(this).find('select[name=selection]').select2();
}
});
})(jQuery);
So you can use this like:
$(document).ready(function(){
$(body).find(form).initMyForm();
});
$("#my-form").initMyForm();
$(".page-content .form").initMyForm();

Dojo Parameters for Tabs

I'm having trouble with the Dojo documentation (as usual).
On their TabContainer API, they list the second argument as an object called "params", but they never say what you can actually put in this params object. Can I specify the width? The height? Do I specify the id's of the divs I want to be the tabs inside the container?
There's also no specification of what attributes I would put in HTML if I wanted to specify the tab containers to be parsed by the Dojo parser. I found the following example that lets you put the title, selected and closable options. Is there anything else?
<div id="tabA1" dojoType="dijit.layout.ContentPane" title="First Tab" selected="true" closable="true">
First Tab
</div>
<div id="tabA2" dojoType="dijit.layout.ContentPane" title="Second Tab" closable="true">
Second Tab
</div>
<div id="tabA3" dojoType="dijit.layout.ContentPane" title="Third Tab" closable="true">
Third Tab
</div>
</div>
I am not an expert in Dojo widgets, but this is what I know:
All Dojo widget constructors have signature:
var widget = new Widget(params, node);
The best way to discover params is to look at the source code — don't get scared, they would be documented variables at the beginning of a relevant class.
The relevant file is usually simple to find using the name of the widget because they are named by their path.
The best way to look up this stuff is to use a Dojo checkout with your favorite text editor. But the nightly checkout works too (if you follow the trunk). Or the Trac source browser.
Don't underestimate the power of looking at tests and demos.
Example: dijit.layout.TabContainer ⇒ dijit/layout/TabContainer.js. If the file is missing look into directories of the hierarchy for _base.js, or some similarly sounding files — the latter can bundle related classes together. But in most cases (like with TabContainer) you'll find it immediately. Let's go and look.
There are two public documented parameters in the top of the class:
tabPosition — String. Defines where tabs go relative to tab content. "top", "bottom", "left-h", "right-h". Default: "top".
tabStrip — bool. Defines whether the tablist gets an extra class for layouting. Default: false.
_controllerWidget — just ignore it, no public parameters start with the underscore — it is a common JavaScript convention to designate protected members.
But it is not all. TabContainer is based on dijit.layout.StackContainer (just look at the dojo.declare() header). We can use StackContainer's public parameters as well:
doLayout — Boolean. If true, change the size of my currently displayed child to match my size. Default: true.
persist — Boolean. Remembers the selected child across sessions. Default: false.
As you can see the code and parametrs are nicely documented, yet not always reflected in the API tool. Now we can create the tab container with confidence.
But let's see it in action first. All Dijit tests are always in dijit/tests. Any dijit.layout.* widget will be tested in dijit/tests/layout. The relevant test file would be named something like test_TabContainer.html, and in fact I see 5 files for that:
test_TabContainer.html.
test_TabContainer_noLayout.html.
test_TabContainer_prog.html.
test_TabContainer_remote.html.
test_TabContainerTitlePane.html.
For example, let's recreate the first TabContainer of test_TabContainer.html:
var tc = new dijit.layout.TabContainer(
{persist: true, tabStrip: true}, "mainTabContainer");
Or we can do it like in the test inline:
<div id="mainTabContainer" dojoType="dijit.layout.TabContainer"
persist="true" tabStrip="true" style="width: 100%; height: 20em;">
...
</div>
Coming back to your original question: now you can see that width and height are specified simply as styles, no special attributes, nothing fancy, just some intuitive CSS. So if you want to do it programmatically, just set them on a node before creating a new instance of TabContainer.
Yeah, I wish the API doc got all these small details too, but the whole setup is intuitive, and relevant parts are documented right in the file. We did go to the source code, but we didn't try to decipher the source code, just read human-readable comments on the top of the class.

Categories

Resources