// Keep a local reference to Date (GH-283)
Date = window.Date,
defined = {
- setTimeout: typeof window.setTimeout !== "undefined",
- sessionStorage: (function() {
- var x = "qunit-test-string";
- try {
- sessionStorage.setItem( x, x );
- sessionStorage.removeItem( x );
- return true;
- } catch( e ) {
- return false;
+ setTimeout: typeof window.setTimeout !== "undefined",
+ sessionStorage: (function() {
+ var x = "qunit-test-string";
+ try {
+ sessionStorage.setItem( x, x );
+ sessionStorage.removeItem( x );
+ return true;
+ } catch( e ) {
+ return false;
+ }
+ }())
+ },
+ /**
+ * Makes a clone of an object using only Array or Object as base,
+ * and copies over the own enumerable properties.
+ *
+ * @param {Object} obj
+ * @return {Object} New object with only the own properties (recursively).
+ */
+ objectValues = function( obj ) {
+ var key, val,
+ vals = QUnit.is( "array", obj ) ? [] : {};
+ for ( key in obj ) {
+ if ( hasOwn.call( obj, key ) ) {
+ val = obj[key];
+ vals[key] = val === Object(val) ? objectValues(val) : val;
+ }
}
- }())
-};
+ return vals;
+ };
function Test( settings ) {
extend( this, settings );
Test.prototype = {
init: function() {
var a, b, li,
- tests = id( "qunit-tests" );
+ tests = id( "qunit-tests" );
if ( tests ) {
b = document.createElement( "strong" );
},
/**
+ * @name propEqual
+ * @function
+ */
+ propEqual: function( actual, expected, message ) {
+ actual = objectValues(actual);
+ expected = objectValues(expected);
+ QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
+ },
+
+ /**
+ * @name notPropEqual
+ * @function
+ */
+ notPropEqual: function( actual, expected, message ) {
+ actual = objectValues(actual);
+ expected = objectValues(expected);
+ QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
+ },
+
+ /**
* @name deepEqual
* @function
*/
// Initialize the config, saving the execution queue
var banner, filter, i, label, len, main, ol, toolbar, userAgent, val, urlConfigCheckboxes, moduleFilter,
- numModules = 0,
- moduleFilterHtml = "",
+ numModules = 0,
+ moduleFilterHtml = "",
urlConfigHtml = "",
oldconfig = extend( {}, config );
moduleFilter.innerHTML = moduleFilterHtml;
addEvent( moduleFilter, "change", function() {
var selectBox = moduleFilter.getElementsByTagName("select")[0],
- selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);
+ selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);
window.location = QUnit.url( { module: ( selectedModule === "" ) ? undefined : selectedModule } );
});
});
module("assertions");
-test("raises",function() {
+
+test("propEqual", 5, function( assert ) {
+ var objectCreate = Object.create || function ( origin ) {
+ function O() {}
+ O.prototype = origin;
+ var r = new O();
+ return r;
+ };
+
+ function Foo( x, y, z ) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+ Foo.prototype.doA = function () {};
+ Foo.prototype.doB = function () {};
+ Foo.prototype.bar = 'prototype';
+
+ function Bar() {
+ }
+ Bar.prototype = objectCreate( Foo.prototype );
+ Bar.prototype.constructor = Bar;
+
+ assert.propEqual(
+ new Foo( 1, '2', [] ),
+ {
+ x: 1,
+ y: '2',
+ z: []
+ }
+ );
+
+ assert.notPropEqual(
+ new Foo( '1', 2, 3 ),
+ {
+ x: 1,
+ y: '2',
+ z: 3
+ },
+ 'Primitive values are strictly compared'
+ );
+
+ assert.notPropEqual(
+ new Foo( 1, '2', [] ),
+ {
+ x: 1,
+ y: '2',
+ z: {}
+ },
+ 'Array type is preserved'
+ );
+
+ assert.notPropEqual(
+ new Foo( 1, '2', {} ),
+ {
+ x: 1,
+ y: '2',
+ z: []
+ },
+ 'Empty array is not the same as empty object'
+ );
+
+ assert.propEqual(
+ new Foo( 1, '2', new Foo( [ 3 ], new Bar(), null ) ),
+ {
+ x: 1,
+ y: '2',
+ z: {
+ x: [ 3 ],
+ y: {},
+ z: null
+ }
+ },
+ 'Complex nesting of different types, inheritance and constructors'
+ );
+});
+
+test("raises", 8, function() {
function CustomError( message ) {
this.message = message;
}