To run the existing tests or create new ones, you'll need an HTTP server with PHP (for contribution to w3c, server behavior is limited to PHP), node.js/npm, and grunt.
Tests must be run from an HTTP Server with PHP installed. You can use one of the following server/PHP bundles to setup a local testing environment.
In order to build the tests, you'll also need node.js and npm. Install instructions are available from the node.js wiki.
npm now ships with node.js, so you shouldn't have to do anything special to install it. You can check for its presence by running:
npm -v
If command not found, install with:
curl http://npmjs.org/install.sh | sh
npm install grunt -g
Fork this repository and clone your fork:
git clone git://github.com/username/rng.io.git
Enter the repo and add the upstream as a remote:
cd rng.io && git remote add upstream git://github.com/facebook/rng.io.git
Install development dependencies:
npm install
Start your local web server with the web root pointed at the rng.io repository root.
Open http://localhost/dev/test.html
in your browser to preview and run the tests.
(You may need to include a specific port number eg. http://localhost:8888/dev/test.html
)
For organizational purposes, Pull Requests must correspond to an issue. Pull Requests should made from branches and branches should be named by issue number. To get started writing a new test, first make sure there is an issue covering the API which you intend to test. If no issue exists, feel free to file one.
Create a new branch, named with the issue number of the feature, spec or API you intend to test:
git checkout -b [[issue-number]]
...or...
git checkout -b [[issue-number]]-[[description]]
Use the new
test tool to generate a new working directory for your tests. The test name must be lowercased, with dashes in place of spaces.
For example, to create a new set of tests for an api called "Neato API", run the following:
./new neato-api
If new
does not run, try adding execution permission:
chmod +x new
This will create a new directory at:
/tests/neato-api/
.
├── config.yml # required
├── fixture.html # optional
├── iframe.html # optional
└── test.js # required
See CSS2.1 Selectors Tests for an example of test directory file structure.
Configuration settings and meta data for this group of tests.
---
r: 0
spec: "url"
sources: ["url", "url"]
title: ""
contributor: ""
- r: The ring number for this feature
- spec: URL of this feature/spec, if one exists
- sources: An array of URLs for existing resources that this test derives from
- title: Displayed name of feature/spec
- contributor: The name of the copyright holder.
HTML markup used by the test, defaults to:
<iframe id="neato-api" src="/tests/neato-api/iframe.html"></iframe>
If a fixture is not required, please delete this file from your directory.
DOM "Sandbox" for HTML markup used by the test, defaults to:
<!doctype html>
<html>
<head>
</head>
<body>
<script>
// Run tests, postMessage results
top.postMessage( "Hi!", "*" );
</script>
</body>
</html>
If an embedded fixture is not required, please delete this file from your directory.
This file is where all of the test blocks and assertions are written, defaults to:
test("<%= title %>", function() {
// Prerequisite Assertions
assert( truthy, "Spec supported" );
// assert tests whether a value is Boolean true or truthy
});
asyncTest("<%= title %> Practical Application", function( async ) {
// asyncTest callback receives "async" object as first argument
// Assertion
assert( truthy, "This thing is true" );
// assert tests whether a value is Boolean true or truthy
// async object
// @instance
// @type Object
// step
// @method
// @memberOf async
// @param callback function, wraps async assertions.
async.step(function() {
// Assertion
assert( true, "This thing is true" );
// done
// @method
// @memberOf async
// @param indicate async test is complete.
async.done();
});
});
Represents a "unit" of functionality that will be tested. testFunctionExpression
wraps test code and assertions.
Use asyncTest
anytime the unit being tested would benefit from (or depends on) the use of events, timeouts and/or callbacks. (eg. a message
event awaiting a postMessage
from an iframe). In simple terms, asyncTest
makes the test runner "wait" until the unit is done testing. (see asyncTest
example below)
Use the async.step(functionExpression)
to wrap assertions
When the asyncTest
is complete, include a call to async.done()
to signal that the unit is finished and the runner may continue.
There is only one assertion method which serves to simplify test writing and maintainability. Furthermore, this maximizes readability and comprehensibility.
assert( actual, description );
actual
is any value; this value will be evaluated for "truthyness"*description
description of what is being asserted.
* In addition to Boolean true
, "non empty string" and 1 are evaluated as "truthy". Use !
negation to test "falsy" values: "", 0, null, undefined, NaN
Take a look at /tests/postmessage/test.js
for a good example of how test.js files are used:
test("postMessage", function() {
var postMessage = window.postMessage;
assert( !!postMessage, "postMessage supported" );
});
test("onmessage", function() {
assert( "onmessage" in window, "onmessage supported" );
});
asyncTest("postMessage/onmessage In Practice", function( async ) {
window.onmessage = function( event ) {
async.step(function() {
assert( true, "onmessage event fired" );
assert( event.data === "This is Ground Control", "message content matched expected" );
async.done();
});
};
window.postMessage( "This is Ground Control", "*" );
});
The rng.io includes a helper library called H
. H
provides a simple set of utility methods designed to make it easier to author browser API tests.
Derive and assert the existence of an API that may or may not be prefixed and prefix testing is optional. This function exists to simplify the testing of new host object APIs that may exist in prefixed form.
The following prefixes are tested:
"", "webkit", "Webkit", "WebKit", "moz", "Moz", "ms", MS", "O", "o" (the first is no prefix)
H.API( object, api [, withPrefixes ])
Example:
test("Vibration", function() {
var vibrate = H.API( navigator, "vibrate", true );
// This actually tested for:
// vibrate, webkitVibrate, WebkitVibrate, WebKitVibrate, mozVibrate, MozVibrate,
// msVibrate, MSVibrate, oVibrate, OVibrate
assert( vibrate, "vibrate supported" );
});
The H.check
object provides methods to check elements for prefixed style and or DOM properties. Most of the logic was derived from or inspired by the excellent work done by the Modernizr team
Test that an element's style contains a specific property, Prefixes can be tested by optionally.
The following prefixes are tested:
"", "Webkit", "WebKit", "Moz", "ms", "MS", "O" (the first is no prefix)
H.check.cssProp( elem, prop [, withPrefixes ])
Example:
test("CSS Text Stroke", function() {
var elem = document.createElement("div");
assert( H.check.cssProp( elem, "textStroke", true ), "textStroke supported" );
// This actually tested for:
// textStroke, WebkitTextStroke, WebKitTextStroke, MozTextStroke,
// msTextStroke, MSTextStroke, OTextStroke
// ...
});
Test that an element contains a specific property, Prefixes can be tested by optionally.
H.check.domProp( elem, prop [, withPrefixes ])
The H.API
is a shortcut to H.check.domProp
The H.prefixes
object contains the table of prefixes used in all of the prefix-aware tests.
Array; contains all of the CSS prefixes
[ "-webkit-", "-moz-", "-o-", "-ms-" ]
Array; contains all of the CSS "Object Model" mode prefixes (see: H.prefixes.css
)
Returns prefix expanded CSS Rule.
H.prefixes.expand( rule )
Example:
> H.prefixes.expand( "text-shadow" );
"text-shadow;-webkit-text-shadow;-moz-text-shadow;-o-text-shadow;-ms-text-shadow;"
All contributors must agree to and sign the Facebook CLA prior to submitting Pull Requests. Ringmark cannot accept Pull Requests until this document is signed and submitted.
Tests must be able to compile to a W3C flat file test runner, this can be confirmed by running:
grunt generate
In order to maintain a consistent level of readability and maintainability, all contributions should pass lint (use grunt
)
- 2 Space, Soft Tabs
- Double Quotes
Once you're satisfied with your tests:
- Commit new tests to your local branch,
- Push the branch to your fork,
- Make a pull request from your fork on github.
To generate static files for donation to the Coremob WG and W3C, use the following commands:
grunt generate
To generate one or more specific tests, use the following:
grunt generate:*:test1:test2:test3
eg.
grunt generate:*:appcache:webworkers
(This would generate static files from the appcache and webworkers tests.)
Contributions are restricted to code in the /tests/
directory. Any changes to code outside of this directory will be disregarded and may block your Pull Request.
Copyright (c) 2012 Facebook
All of the tests in the Coremob test suites are intended to be released under both the W3C Test Suite license and the 3-clause BSD license.
Contributors must grant permission to distribute their contribution under these two licenses, and this requires completing the W3C's license grant form.