Files
apt-nl-map/static/Magic4/js/three.js-dev/test/unit/utils/qunit-utils.js
2024-12-04 10:21:04 +08:00

337 lines
8.0 KiB
JavaScript

//
// Custom QUnit assertions.
///* global QUnit */
import { SmartComparer } from './SmartComparer';
import { ObjectLoader } from '../../../src/loaders/ObjectLoader';
QUnit.assert.success = function ( message ) {
// Equivalent to assert( true, message );
this.pushResult( {
result: true,
actual: undefined,
expected: undefined,
message: message
} );
};
QUnit.assert.fail = function ( message ) {
// Equivalent to assert( false, message );
this.pushResult( {
result: false,
actual: undefined,
expected: undefined,
message: message
} );
};
QUnit.assert.numEqual = function ( actual, expected, message ) {
var diff = Math.abs( actual - expected );
message = message || ( actual + " should be equal to " + expected );
this.pushResult( {
result: diff < 0.1,
actual: actual,
expected: expected,
message: message
} );
};
QUnit.assert.equalKey = function ( obj, ref, key ) {
var actual = obj[ key ];
var expected = ref[ key ];
var message = actual + ' should be equal to ' + expected + ' for key "' + key + '"';
this.pushResult( {
result: actual == expected,
actual: actual,
expected: expected,
message: message
} );
};
QUnit.assert.smartEqual = function ( actual, expected, message ) {
var cmp = new SmartComparer();
var same = cmp.areEqual( actual, expected );
var msg = cmp.getDiagnostic() || message;
this.pushResult( {
result: same,
actual: actual,
expected: expected,
message: msg
} );
};
//
// GEOMETRY TEST HELPERS
//
function checkGeometryClone( geom ) {
// Clone
var copy = geom.clone();
QUnit.assert.notEqual( copy.uuid, geom.uuid, "clone uuid should differ from original" );
QUnit.assert.notEqual( copy.id, geom.id, "clone id should differ from original" );
var excludedProperties = [ 'parameters', 'widthSegments', 'heightSegments', 'depthSegments' ];
var differingProp = getDifferingProp( geom, copy, excludedProperties );
QUnit.assert.ok( differingProp === undefined, 'properties are equal' );
differingProp = getDifferingProp( copy, geom, excludedProperties );
QUnit.assert.ok( differingProp === undefined, 'properties are equal' );
// json round trip with clone
checkGeometryJsonRoundtrip( copy );
}
function getDifferingProp( geometryA, geometryB, excludedProperties ) {
excludedProperties = excludedProperties || [];
var geometryKeys = Object.keys( geometryA );
var cloneKeys = Object.keys( geometryB );
var differingProp = undefined;
for ( var i = 0, l = geometryKeys.length; i < l; i ++ ) {
var key = geometryKeys[ i ];
if ( excludedProperties.indexOf( key ) >= 0 ) continue;
if ( cloneKeys.indexOf( key ) < 0 ) {
differingProp = key;
break;
}
}
return differingProp;
}
// Compare json file with its source geometry.
function checkGeometryJsonWriting( geom, json ) {
QUnit.assert.equal( json.metadata.version, "4.5", "check metadata version" );
QUnit.assert.equalKey( geom, json, 'type' );
QUnit.assert.equalKey( geom, json, 'uuid' );
QUnit.assert.equal( json.id, undefined, "should not persist id" );
var params = geom.parameters;
if ( ! params ) {
return;
}
// All parameters from geometry should be persisted.
var keys = Object.keys( params );
for ( var i = 0, l = keys.length; i < l; i ++ ) {
QUnit.assert.equalKey( params, json, keys[ i ] );
}
// All parameters from json should be transfered to the geometry.
// json is flat. Ignore first level json properties that are not parameters.
var notParameters = [ "metadata", "uuid", "type" ];
var keys = Object.keys( json );
for ( var i = 0, l = keys.length; i < l; i ++ ) {
var key = keys[ i ];
if ( notParameters.indexOf( key ) === - 1 ) QUnit.assert.equalKey( params, json, key );
}
}
// Check parsing and reconstruction of json geometry
function checkGeometryJsonReading( json, geom ) {
var wrap = [ json ];
var loader = new ObjectLoader();
var output = loader.parseGeometries( wrap );
QUnit.assert.ok( output[ geom.uuid ], 'geometry matching source uuid not in output' );
// QUnit.assert.smartEqual( output[ geom.uuid ], geom, 'Reconstruct geometry from ObjectLoader' );
var differing = getDifferingProp( output[ geom.uuid ], geom, [ 'bones' ] );
if ( differing ) console.log( differing );
var excludedProperties = [ 'bones' ];
var differingProp = getDifferingProp( output[ geom.uuid ], geom, excludedProperties );
QUnit.assert.ok( differingProp === undefined, 'properties are equal' );
differingProp = getDifferingProp( geom, output[ geom.uuid ], excludedProperties );
QUnit.assert.ok( differingProp === undefined, 'properties are equal' );
}
// Verify geom -> json -> geom
function checkGeometryJsonRoundtrip( geom ) {
var json = geom.toJSON();
checkGeometryJsonWriting( geom, json );
checkGeometryJsonReading( json, geom );
}
// Look for undefined and NaN values in numerical fieds.
function checkFinite( geom ) {
var allVerticesAreFinite = true;
var vertices = geom.vertices || [];
for ( var i = 0, l = vertices.length; i < l; i ++ ) {
var v = geom.vertices[ i ];
if ( ! ( isFinite( v.x ) || isFinite( v.y ) || isFinite( v.z ) ) ) {
allVerticesAreFinite = false;
break;
}
}
// TODO Buffers, normal, etc.
QUnit.assert.ok( allVerticesAreFinite, "contains only finite coordinates" );
}
// Run common geometry tests.
function runStdGeometryTests( assert, geometries ) {
for ( var i = 0, l = geometries.length; i < l; i ++ ) {
var geom = geometries[ i ];
checkFinite( geom );
// Clone
checkGeometryClone( geom );
// json round trip
checkGeometryJsonRoundtrip( geom );
}
}
//
// LIGHT TEST HELPERS
//
// Run common light tests.
function runStdLightTests( assert, lights ) {
for ( var i = 0, l = lights.length; i < l; i ++ ) {
var light = lights[ i ];
// copy and clone
checkLightCopyClone( assert, light );
// THREE.Light doesn't get parsed by ObjectLoader as it's only
// used as an abstract base class - so we skip the JSON tests
if ( light.type !== "Light" ) {
// json round trip
checkLightJsonRoundtrip( assert, light );
}
}
}
function checkLightCopyClone( assert, light ) {
// copy
var newLight = new light.constructor( 0xc0ffee );
newLight.copy( light );
QUnit.assert.notEqual( newLight.uuid, light.uuid, "Copied light's UUID differs from original" );
QUnit.assert.notEqual( newLight.id, light.id, "Copied light's id differs from original" );
QUnit.assert.smartEqual( newLight, light, "Copied light is equal to original" );
// real copy?
newLight.color.setHex( 0xc0ffee );
QUnit.assert.notStrictEqual(
newLight.color.getHex(), light.color.getHex(), "Copied light is independent from original"
);
// Clone
var clone = light.clone(); // better get a new var
QUnit.assert.notEqual( clone.uuid, light.uuid, "Cloned light's UUID differs from original" );
QUnit.assert.notEqual( clone.id, light.id, "Clone light's id differs from original" );
QUnit.assert.smartEqual( clone, light, "Clone light is equal to original" );
// real clone?
clone.color.setHex( 0xc0ffee );
QUnit.assert.notStrictEqual(
clone.color.getHex(), light.color.getHex(), "Clone light is independent from original"
);
if ( light.type !== "Light" ) {
// json round trip with clone
checkLightJsonRoundtrip( assert, clone );
}
}
// Compare json file with its source Light.
function checkLightJsonWriting( assert, light, json ) {
assert.equal( json.metadata.version, "4.5", "check metadata version" );
var object = json.object;
assert.equalKey( light, object, 'type' );
assert.equalKey( light, object, 'uuid' );
assert.equal( object.id, undefined, "should not persist id" );
}
// Check parsing and reconstruction of json Light
function checkLightJsonReading( assert, json, light ) {
var loader = new ObjectLoader();
var outputLight = loader.parse( json );
assert.smartEqual( outputLight, light, 'Reconstruct Light from ObjectLoader' );
}
// Verify light -> json -> light
function checkLightJsonRoundtrip( assert, light ) {
var json = light.toJSON();
checkLightJsonWriting( assert, light, json );
checkLightJsonReading( assert, json, light );
}
export { runStdLightTests, runStdGeometryTests };