Writing tests is super easy and follows this pattern:
S.open("//myapp/myapp.html") //click something
S('#myButton').click()
//type something
S('#myInput').type("hello") //Wait until it is visible
S('#myMenu').visible()
//wait until something exists
S('#myArea').exists() S('#myMenu').visible(function(){
//check that offset is right
equals(S('#myMenu').offset().left, 500,
"menu is in the right spot");
}) FuncUnit supports three types of commands: asynchronous actions and waits, and synchronous getters.
Actions are used to simulate user behavior such as clicking, typing, moving the mouse.
Waits are used to pause the test script until a condition has been met.
Getters are used to get information about elements in the page
Typically, a test looks like a series of action and wait commands followed by qUnit test of the result of a getter command. Getter commands are almost always in a action or wait callback.
Actions simulate user behavior. FuncUnit provides the following actions:
open - opens a page.click - clicks an element (mousedown, mouseup, click).dblclick - two clicks followed by a dblclick.rightClick - a right mousedown, mouseup, and contextmenu.type - types characters into an element.move - mousemove, mouseover, and mouseouts from one element to another.drag - a drag motion from one element to another.scroll - scrolls an element.Actions run asynchronously, meaning they do not complete all their events immediately.
However, each action is queued so that you can write actions (and waits) linearly.
The following might simulate typing and resizing a "resizable" textarea plugin:
S.open('resizableTextarea.html');
S('textarea').click().type("Hello World");
S('.resizer').drag("+20 +20");
Getters are used to test the conditions of the page. Most getter commands correspond to a jQuery method of the same name. The following getters are provided:
| Dimensions | Attributes | Position | Selector | Style | |
|---|---|---|---|---|---|
| width | height | attr | position | size | css |
| innerWidth | innerHeight | hasClass | offset | exists | visible |
| outerWidth | outerHeight | val | scrollLeft | missing | invisible |
| text | scrollTop | ||||
| html | |||||
Since getters run synchronously, it's important that they happen after the action or wait command completes. This is why getters are typically found in an action or wait command's callback:
The following performs a drag, then checks that the textarea is 20 pixels taller after the drag.
S.open('resizableTextarea.html');
var txtarea = S('textarea'), //save textarea reference
startingWidth = txtarea.width(), // save references to width and height
startingHeight = txtarea.height();
S('.resizer').drag("+20 +20", function(){
equals(txtarea.width(),
startingWidth,
"width stays the same");
equals(txtarea.height(),
startingHeight+20,
"height got bigger");
});
Waits are used to wait for a specific condition to be met before continuing to the next wait or action command. Like actions, waits execute asynchronously. They can be given a callback that runs after their wait condition is met.
Every getter commands can become a wait command when given a check value or function.
For example, the following waits until the width of an element is 200 pixels and tests its offset.
var sm = S("#sliderMenu");
sm.width( 200, function(){
var offset = sm.offset();
equals( offset.left, 200)
equals( offset.top, 200)
})
You can also provide a test function that when true, continues to the next action or wait command. The following is equivalent to the previous example:
var sm = S("#sliderMenu");
sm.width(
function( width ) {
return width == 200;
},
function(){
var offset = sm.offset();
equals( offset.left, 200)
equals( offset.top, 200)
}
)
By default, wait commands will wait a 10s timeout period. If the condition isn't true after that time, the test will fail. You can provide your own timeout for each wait condition as the parameter after the wait condition. For example, the following will check if "#trigger" contains "I was triggered" for 5 seconds before failing the test.
("#trigger").text("I was triggered", 5000)
In addition to all the jQuery-like wait functions, FuncUnit provides S.wait, which waits a timeout before continuing.
This function should be used with CAUTION. You should almost never need it, because its presence means brittle tests that depend on unreliable
timing conditions. Much better than a time based wait is a wait that depends on a page condition (like a menu element appearing).