qunit-utils.js 8.0 KB

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