qunit-utils.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. //
  2. // Custom QUnit assertions.
  3. //
  4. QUnit.assert.success = function( message ) {
  5. // Equivalent to assert( true, message );
  6. this.pushResult( {
  7. result: true,
  8. actual: undefined,
  9. expected: undefined,
  10. message: message
  11. } );
  12. };
  13. QUnit.assert.fail = function( message ) {
  14. // Equivalent to assert( false, message );
  15. this.pushResult( {
  16. result: false,
  17. actual: undefined,
  18. expected: undefined,
  19. message: message
  20. } );
  21. };
  22. QUnit.assert.numEqual = function( actual, expected, message ) {
  23. var diff = Math.abs(actual - expected);
  24. message = message || ( actual + " should be equal to " + expected );
  25. this.pushResult( {
  26. result: diff < 0.1,
  27. actual: actual,
  28. expected: expected,
  29. message: message
  30. } );
  31. };
  32. QUnit.assert.equalKey = function( obj, ref, key ) {
  33. var actual = obj[key];
  34. var expected = ref[key];
  35. var message = actual + ' should be equal to ' + expected + ' for key "' + key + '"';
  36. this.pushResult( {
  37. result: actual == expected,
  38. actual: actual,
  39. expected: expected,
  40. message: message
  41. } );
  42. };
  43. QUnit.assert.smartEqual = function( actual, expected, message ) {
  44. var cmp = new SmartComparer();
  45. var same = cmp.areEqual(actual, expected);
  46. var msg = cmp.getDiagnostic() || message;
  47. this.pushResult( {
  48. result: same,
  49. actual: actual,
  50. expected: expected,
  51. message: msg
  52. } );
  53. };
  54. //
  55. // GEOMETRY TEST HELPERS
  56. //
  57. function checkGeometryClone( geom ) {
  58. // Clone
  59. var copy = geom.clone();
  60. QUnit.assert.notEqual( copy.uuid, geom.uuid, "clone uuid should differ from original" );
  61. QUnit.assert.notEqual( copy.id, geom.id, "clone id should differ from original" );
  62. var excludedProperties = [ 'parameters', 'widthSegments', 'heightSegments', 'depthSegments' ];
  63. var differingProp = getDifferingProp( geom, copy, excludedProperties );
  64. QUnit.assert.ok( differingProp === undefined, 'properties are equal' );
  65. differingProp = getDifferingProp( copy, geom, excludedProperties );
  66. QUnit.assert.ok( differingProp === undefined, 'properties are equal' );
  67. // json round trip with clone
  68. checkGeometryJsonRoundtrip( copy );
  69. }
  70. function getDifferingProp( geometryA, geometryB, excludedProperties) {
  71. excludedProperties = excludedProperties || [];
  72. var geometryKeys = Object.keys( geometryA );
  73. var cloneKeys = Object.keys( geometryB );
  74. var differingProp = undefined;
  75. for ( var i = 0, l = geometryKeys.length; i < l; i++ ) {
  76. var key = geometryKeys[ i ];
  77. if ( excludedProperties.indexOf(key) >= 0 ) {
  78. continue;
  79. }
  80. if ( cloneKeys.indexOf( key ) < 0 ) {
  81. differingProp = key;
  82. break;
  83. }
  84. }
  85. return differingProp;
  86. }
  87. // Compare json file with its source geometry.
  88. function checkGeometryJsonWriting( geom, json ) {
  89. QUnit.assert.equal( json.metadata.version, "4.5", "check metadata version" );
  90. QUnit.assert.equalKey( geom, json, 'type' );
  91. QUnit.assert.equalKey( geom, json, 'uuid' );
  92. QUnit.assert.equal( json.id, undefined, "should not persist id" );
  93. var params = geom.parameters;
  94. if ( !params ) {
  95. return;
  96. }
  97. // All parameters from geometry should be persisted.
  98. var keys = Object.keys( params );
  99. for ( var i = 0, l = keys.length; i < l; i++ ) {
  100. QUnit.assert.equalKey( params, json, keys[ i ] );
  101. }
  102. // All parameters from json should be transfered to the geometry.
  103. // json is flat. Ignore first level json properties that are not parameters.
  104. var notParameters = [ "metadata", "uuid", "type" ];
  105. var keys = Object.keys( json );
  106. for ( var i = 0, l = keys.length; i < l; i++ ) {
  107. var key = keys[ i ];
  108. if ( notParameters.indexOf( key) === -1 ) QUnit.assert.equalKey( params, json, key );
  109. }
  110. }
  111. // Check parsing and reconstruction of json geometry
  112. function checkGeometryJsonReading( json, geom ) {
  113. var wrap = [ json ];
  114. var loader = new THREE.ObjectLoader();
  115. var output = loader.parseGeometries( wrap );
  116. QUnit.assert.ok( output[ geom.uuid ], 'geometry matching source uuid not in output' );
  117. // QUnit.assert.smartEqual( output[ geom.uuid ], geom, 'Reconstruct geometry from ObjectLoader' );
  118. var differing = getDifferingProp(output[ geom.uuid ], geom, ['bones']);
  119. if (differing) {
  120. console.log(differing);
  121. }
  122. var excludedProperties = [ 'bones' ];
  123. var differingProp = getDifferingProp( output[ geom.uuid ], geom, excludedProperties );
  124. QUnit.assert.ok( differingProp === undefined, 'properties are equal' );
  125. differingProp = getDifferingProp( geom, output[ geom.uuid ], excludedProperties );
  126. QUnit.assert.ok( differingProp === undefined, 'properties are equal' );
  127. }
  128. // Verify geom -> json -> geom
  129. function checkGeometryJsonRoundtrip( geom ) {
  130. var json = geom.toJSON();
  131. checkGeometryJsonWriting( geom, json );
  132. checkGeometryJsonReading( json, geom );
  133. }
  134. // Look for undefined and NaN values in numerical fieds.
  135. function checkFinite( geom ) {
  136. var allVerticesAreFinite = true;
  137. var vertices = geom.vertices || [];
  138. for ( var i = 0, l = vertices.length; i < l; i++ ) {
  139. var v = geom.vertices[ i ];
  140. if ( !( isFinite( v.x ) || isFinite( v.y ) || isFinite( v.z ) ) ) {
  141. allVerticesAreFinite = false;
  142. break;
  143. }
  144. }
  145. // TODO Buffers, normal, etc.
  146. QUnit.assert.ok( allVerticesAreFinite, "contains only finite coordinates" );
  147. }
  148. // Run common geometry tests.
  149. function runStdGeometryTests( assert, geometries ) {
  150. for ( var i = 0, l = geometries.length; i < l; i++ ) {
  151. var geom = geometries[ i ];
  152. checkFinite( geom );
  153. // Clone
  154. checkGeometryClone( geom );
  155. // json round trip
  156. checkGeometryJsonRoundtrip( geom );
  157. }
  158. }
  159. //
  160. // LIGHT TEST HELPERS
  161. //
  162. // Run common light tests.
  163. function runStdLightTests( lights ) {
  164. for ( var i = 0, l = lights.length; i < l; i ++ ) {
  165. var light = lights[ i ];
  166. // copy and clone
  167. checkLightCopyClone( light );
  168. // THREE.Light doesn't get parsed by ObjectLoader as it's only
  169. // used as an abstract base class - so we skip the JSON tests
  170. if ( light.type !== "Light" ) {
  171. // json round trip
  172. checkLightJsonRoundtrip( light );
  173. }
  174. }
  175. }
  176. function checkLightCopyClone( light ) {
  177. // copy
  178. var newLight = new light.constructor( 0xc0ffee );
  179. newLight.copy( light );
  180. QUnit.assert.notEqual( newLight.uuid, light.uuid, "Copied light's UUID differs from original" );
  181. QUnit.assert.notEqual( newLight.id, light.id, "Copied light's id differs from original" );
  182. QUnit.assert.smartEqual( newLight, light, "Copied light is equal to original" );
  183. // real copy?
  184. newLight.color.setHex( 0xc0ffee );
  185. QUnit.assert.notStrictEqual(
  186. newLight.color.getHex(), light.color.getHex(), "Copied light is independent from original"
  187. );
  188. // Clone
  189. var clone = light.clone(); // better get a new var
  190. QUnit.assert.notEqual( clone.uuid, light.uuid, "Cloned light's UUID differs from original" );
  191. QUnit.assert.notEqual( clone.id, light.id, "Clone light's id differs from original" );
  192. QUnit.assert.smartEqual( clone, light, "Clone light is equal to original" );
  193. // real clone?
  194. clone.color.setHex( 0xc0ffee );
  195. QUnit.assert.notStrictEqual(
  196. clone.color.getHex(), light.color.getHex(), "Clone light is independent from original"
  197. );
  198. if ( light.type !== "Light" ) {
  199. // json round trip with clone
  200. checkLightJsonRoundtrip( clone );
  201. }
  202. }
  203. // Compare json file with its source Light.
  204. function checkLightJsonWriting( light, json ) {
  205. QUnit.assert.equal( json.metadata.version, "4.5", "check metadata version" );
  206. var object = json.object;
  207. QUnit.assert.equalKey( light, object, 'type' );
  208. QUnit.assert.equalKey( light, object, 'uuid' );
  209. QUnit.assert.equal( object.id, undefined, "should not persist id" );
  210. }
  211. // Check parsing and reconstruction of json Light
  212. function checkLightJsonReading( json, light ) {
  213. var loader = new THREE.ObjectLoader();
  214. var outputLight = loader.parse( json );
  215. QUnit.assert.smartEqual( outputLight, light, 'Reconstruct Light from ObjectLoader' );
  216. }
  217. // Verify light -> json -> light
  218. function checkLightJsonRoundtrip( light ) {
  219. var json = light.toJSON();
  220. checkLightJsonWriting( light, json );
  221. checkLightJsonReading( json, light );
  222. }