Path: blob/main/test/embind/imvu_test_adapter.js
4150 views
/* The embind test suite (embind.test.js) is configured to be runnable in two different testing engines:1- The Emscripten python test runner (open-source in emscripten repository) and2- The IMVU test runner (open-source via imvujs, available at https://github.com/imvu/imvujs)34Embind (and its tests) were originally developed in IMVU repository, which is the reason for two testing architectures.5This adapter file is used when the embind tests are run as part of the Emscripten test runner, to provide the necessary glue code to adapt the tests to Emscripten runner.67To run the Embind tests using the Emscripten test runner, invoke 'python test/runner.py other.test_embind' in the Emscripten root directory.8*/910/* global assert:true */11/* global Module, console, global, process */1213//=== testing glue1415function module(ignore, func) {16func({ Emscripten: Module });17}1819/*global IMVU:true, TEST_MAX_OUTPUT_SIZE*/20//(function() {21// "use strict";2223// { beforeTest: function,24// afterTest: function }25var superFixtures = [];2627function registerSuperFixture(superFixture) {28superFixtures.push(superFixture);29}3031// { fixture: Fixture instance,32// name: string,33// body: function() }34var allTests = [];3536function test(name, fn) {37if (arguments.length !== 2) {38throw new TypeError("test requires 2 arguments");39}4041if (undefined !== activeFixture && activeFixture.abstract) {42activeFixture.abstractTests.push({43name: name,44body: fn });45} else {46var fixtureName = (undefined !== activeFixture)? activeFixture.name + ': ' : '';47allTests.push({48name: fixtureName + name,49body: fn,50fixture: activeFixture });51}52}5354function runTest(test, continuation) {55try {56var afterTests = [];5758for (var i = 0; i < superFixtures.length; ++i) {59var superFixture = superFixtures[i];6061var superScope = {};62superFixture.beforeTest.call(superScope);63afterTests.push(superFixture.afterTest.bind(superScope));64}6566var testScope = test.fixture ?67Object.create(test.fixture.scope) :68{};6970var runSetUp = function(fixtureObject) {71if (undefined === fixtureObject) {72return;73}74runSetUp(fixtureObject.parent);75fixtureObject.setUp.call(testScope);76afterTests.push(fixtureObject.tearDown.bind(testScope));77};78runSetUp(test.fixture);7980test.body.call(testScope);81while (afterTests.length) {82afterTests.pop()();83}84return false;85} catch (e) {86console.error(e.stack);87console.error('error:', e);88return {stack: e.stack, e: e};89}90}9192function run_all(reporter) {93for (var i = 0; i < allTests.length; ++i) {94var test = allTests[i];95reporter({96type: 'test-start',97name: test.name98});99100var failed = runTest(test);101if (failed) {102reporter({103type: 'test-complete',104name: test.name,105verdict: 'FAIL',106stack: failed.stack,107e: failed.e108});109return false;110} else {111reporter({112type: 'test-complete',113name: test.name,114verdict: 'PASS'115});116}117}118119reporter({120type: 'all-tests-complete'121});122123allTests = [];124return true;125}126127var activeFixture;128129function Fixture(parent, name, definition, abstract_) {130if (!(definition instanceof Function)) {131throw new TypeError("fixture's 2nd argument must be a function");132}133134this.name = name;135this.parent = parent;136this.abstract = abstract_;137if (this.abstract) {138// { name: string,139// body: function }140this.abstractTests = [];141}142143if (this.parent !== undefined) {144this.parent.addAbstractTests(this);145}146147this.scope = (this.parent === undefined ? {} : Object.create(this.parent.scope));148this.scope.setUp = function(setUp) {149this.setUp = setUp;150}.bind(this);151this.scope.tearDown = function(tearDown) {152this.tearDown = tearDown;153}.bind(this);154155if (undefined !== activeFixture) {156throw new TypeError("Cannot define a fixture within another fixture");157}158159activeFixture = this;160try {161definition.call(this.scope);162}163finally {164activeFixture = undefined;165}166}167Fixture.prototype.setUp = function defaultSetUp() {168};169Fixture.prototype.tearDown = function defaultTearDown() {170};171Fixture.prototype.addAbstractTests = function(concreteFixture) {172if (this.abstract) {173for (var i = 0; i < this.abstractTests.length; ++i) {174var test = this.abstractTests[i];175allTests.push({176name: concreteFixture.name + ': ' + test.name,177body: test.body,178fixture: concreteFixture});179}180}181if (this.parent) {182this.parent.addAbstractTests(concreteFixture);183}184};185186Fixture.prototype.extend = function(fixtureName, definition) {187return new Fixture(this, fixtureName, definition, false);188};189190function fixture(fixtureName, definition) {191return new Fixture(undefined, fixtureName, definition, false);192}193fixture.abstract = function(fixtureName, definition) {194return new Fixture(undefined, fixtureName, definition, true);195};196197var AssertionError = Error;198199function fail(exception, info) {200exception.info = info;201throw exception;202}203204var formatTestValue = function(v) {205if (v === undefined) return 'undefined';206return v.toString();207/*208var s = IMVU.repr(v, TEST_MAX_OUTPUT_SIZE + 1);209if (s.length <= TEST_MAX_OUTPUT_SIZE) {210return s;211}212return s.substring(0, TEST_MAX_OUTPUT_SIZE) + '...';213*/214};215216var assert = {};217218////////////////////////////////////////////////////////////////////////////////219// GENERAL STATUS220221assert.fail = function(info) {222info = info || "assert.fail()";223fail(new AssertionError(info));224};225226////////////////////////////////////////////////////////////////////////////////227// BOOLEAN TESTS228229assert['true'] = function(value) {230if (!value) {231fail(new AssertionError("expected truthy, actual " + formatTestValue(value)),232{Value: value});233}234};235236assert['false'] = function(value) {237if (value) {238fail(new AssertionError("expected falsy, actual " + formatTestValue(value)),239{Value: value});240}241};242243////////////////////////////////////////////////////////////////////////////////244// SCALAR COMPARISON245246assert.equal = function(expected, actual) {247if (expected !== actual) {248fail(new AssertionError('expected: ' + formatTestValue(expected) + ', actual: ' + formatTestValue(actual)),249{Expected: expected, Actual: actual});250}251};252253assert.notEqual = function(expected, actual) {254if (expected === actual) {255fail(new AssertionError('actual was equal to: ' + formatTestValue(expected)));256}257};258259assert.greater = function(lhs, rhs) {260if (lhs <= rhs) {261fail(new AssertionError(formatTestValue(lhs) + ' not greater than ' + formatTestValue(rhs)));262}263};264265assert.less = function(lhs, rhs) {266if (lhs >= rhs) {267fail(new AssertionError(formatTestValue(lhs) + ' not less than ' + formatTestValue(rhs)));268}269};270271assert.greaterOrEqual = function(lhs, rhs) {272if (lhs < rhs) {273fail(new AssertionError(formatTestValue(lhs) + ' not greater than or equal to ' + formatTestValue(rhs)));274}275};276277assert.lessOrEqual = function (lhs, rhs) {278if (lhs > rhs) {279fail(new AssertionError(formatTestValue(lhs) + ' not less than or equal to ' + formatTestValue(rhs)));280}281};282283////////////////////////////////////////////////////////////////////////////////284// DEEP COMPARISON285286assert.deepEqual = function(expected, actual) {287if (!_.isEqual(expected, actual)) {288fail(new AssertionError('expected: ' + formatTestValue(expected) + ', actual: ' + formatTestValue(actual)),289{Expected: expected, Actual: actual});290}291};292293assert.notDeepEqual = function(expected, actual) {294if (_.isEqual(expected, actual)) {295fail(new AssertionError('expected: ' + formatTestValue(expected) + ' and actual: ' + formatTestValue(actual) + ' were equal'));296}297};298299////////////////////////////////////////////////////////////////////////////////300// FLOATING POINT301302assert.nearEqual = function( expected, actual, tolerance ) {303if( tolerance === undefined ) {304tolerance = 0.0;305}306if( expected instanceof Array && actual instanceof Array ) {307assert.equal(expected.length, actual.length);308for( var i=0; i<expected.length; ++i ) {309assert.nearEqual(expected[i], actual[i], tolerance);310}311return;312}313if( Math.abs(expected - actual) > tolerance ) {314fail( new AssertionError('expected: ' + formatTestValue(expected) + ', actual: ' + formatTestValue(actual) +315', tolerance: ' + formatTestValue(tolerance) + ', diff: ' + formatTestValue(actual-expected) ),316{ Expected:expected, Actual:actual, Tolerance:tolerance } );317}318};319320////////////////////////////////////////////////////////////////////////////////321// STRING322323assert.inString = function(expected, string){324if (-1 === string.indexOf(expected)){325fail(new AssertionError('expected: ' + formatTestValue(expected) + ' not in string: ' + formatTestValue(string)),326{Expected: expected, 'String': string});327}328};329330assert.notInString = function(expected, string){331if (-1 !== string.indexOf(expected)){332fail(new AssertionError('unexpected: ' + formatTestValue(expected) + ' in string: ' + formatTestValue(string)),333{Expected: expected, 'String': string});334}335};336337assert.matches = function(re, string) {338if (!re.test(string)) {339fail(new AssertionError('regexp ' + re + ' does not match: ' + string));340}341};342343////////////////////////////////////////////////////////////////////////////////344// ARRAY345346assert.inArray = function(expected, array) {347var found = false;348_.each(array, function(element){349if (_.isEqual(expected, element)){350found = true;351}352});353if (!found){354fail(new AssertionError('expected: ' + formatTestValue(expected) + ' not found in array: ' + formatTestValue(array)),355{Expected: expected, 'Array': array});356}357};358359assert.notInArray = function(expected, array) {360var found = false;361_.each(array, function(element){362if (_.isEqual(expected, element)){363found = true;364}365});366if (found){367fail(new AssertionError('unexpected: ' + formatTestValue(expected) + ' found in array: ' + formatTestValue(array)),368{Expected: expected, 'Array': array});369}370};371372////////////////////////////////////////////////////////////////////////////////373// OBJECTS374375assert.hasKey = function (key, object) {376if (!(key in object)) {377fail(new AssertionError('Key ' + formatTestValue(key) + ' is not in object: ' + formatTestValue(object)));378}379};380381assert.notHasKey = function (key, object) {382if (key in object) {383fail(new AssertionError('Unexpected key ' + formatTestValue(key) + ' is found in object: ' + formatTestValue(object)));384}385};386387////////////////////////////////////////////////////////////////////////////////388// EXCEPTIONS389390assert.throws = function(exception, fn) {391try {392fn();393} catch (e) {394if (e instanceof exception) {395return e;396}397fail(new AssertionError('Expected to throw "' + exception.name + '", actually threw: ' + formatTestValue(e) + ': ' + e.message),398{Expected: exception, Actual: e});399}400throw new AssertionError('did not throw');401};402403////////////////////////////////////////////////////////////////////////////////404// TYPE405406assert['instanceof'] = function(actual, type) {407if(!(actual instanceof type)) {408fail(new AssertionError(formatTestValue(actual) + ' not instance of ' + formatTestValue(type)),409{Type: type, Actual: actual});410}411};412413////////////////////////////////////////////////////////////////////////////////414// DOM ASSERTIONS415416// TODO: lift into separate file?417assert.dom = {418present: function (domElement) {419if (!$(domElement).length) {420fail(new AssertionError(decipherDomElement(domElement) + ' should be present'));421}422},423424notPresent: function (selector) {425assert.equal(0, $(selector).length);426},427428hasTag: function (tag, domElement) {429var elementTag = $(domElement)[0].tagName.toLowerCase();430if (elementTag !== tag.toLowerCase()) {431fail(new AssertionError(decipherDomElement(domElement) + ' expected to have tag name ' + formatTestValue(tag) + ', was ' + formatTestValue(elementTag) + ' instead'));432}433},434435hasClass: function (className, domElement) {436if (!$(domElement).hasClass(className)) {437fail(new AssertionError(decipherDomElement(domElement) + ' expected to have class ' + formatTestValue(className) + ', has ' + formatTestValue($(domElement).attr('class')) + ' instead'));438}439},440441notHasClass: function (className, domElement) {442assert.dom.present(domElement); // if domElement is empty, .hasClass will always return false443if ($(domElement).hasClass(className)) {444fail(new AssertionError(decipherDomElement(domElement) + ' expected NOT to have class ' + formatTestValue(className)));445}446},447448hasAttribute: function (attributeName, selector) {449assert['true']($(selector).is('[' + attributeName + ']'));450},451452notHasAttribute: function (attributeName, selector) {453assert.dom.present(selector);454assert['false']($(selector).is('[' + attributeName + ']'));455},456457attr: function (value, attributeName, selector) {458assert.equal(value, $(selector).attr(attributeName));459},460461attributeValues: function (values, selector) {462var $el = $(selector);463_(values).each(function (val, key) {464assert.equal(val, $el.attr(key));465});466},467468text: function (expected, selector) {469assert.equal(expected, $(selector).text());470},471472value: function (expected, selector) {473assert.equal(expected, $(selector).val());474},475476count: function (elementCount, selector) {477assert.equal(elementCount, $(selector).length);478},479480visible: function (domElement) {481if (!$(domElement).is(':visible')) {482fail(new AssertionError(decipherDomElement(domElement) + ' expected to be visible'));483}484},485486notVisible: function (domElement) {487assert.dom.present(domElement);488if ($(domElement).is(':visible')) {489fail(new AssertionError(decipherDomElement(domElement) + ' expected to be NOT visible'));490}491},492493disabled: function (domElement) {494if (!$(domElement).is(':disabled')) {495fail(new AssertionError(decipherDomElement(domElement) + ' expected to be disabled'));496}497},498499enabled: function (domElement) {500if (!$(domElement).is(':enabled')) {501fail(new AssertionError(decipherDomElement(domElement) + ' expected to be enabled'));502}503},504505focused: function (selector) {506var expected = $(selector)[0];507var actual = document.activeElement;508if (expected !== actual) {509throw new AssertionError(actual.outerHTML + ' has focus. expected: ' + expected.outerHTML);510}511},512513notFocused: function (selector) {514var expected = $(selector)[0];515var actual = document.activeElement;516if (expected === actual) {517throw new AssertionError(expected.outerHTML + ' expected not to have focus.');518}519},520521html: function (expected, selector) {522assert.equal(expected, $(selector).html());523},524525css: function (expected, propertyName, selector) {526assert.equal(expected, $(selector).css(propertyName));527},528529empty: function (selectorOrJQueryObject) {530var el = selectorOrJQueryObject;531assert.dom.present(el);532if (!$(el).is(':empty')) {533fail(new AssertionError(decipherDomElement(el) + ' expected to be empty'));534}535},536537notEmpty: function (selectorOrJQueryObject) {538var el = selectorOrJQueryObject;539assert.dom.present(el);540if ($(el).is(':empty')) {541fail(new AssertionError(decipherDomElement(el) + ' expected NOT to be empty'));542}543}544};545546function decipherDomElement(selectorOrJQueryObject) {547if (typeof selectorOrJQueryObject === 'string') {548return 'Selector ' + formatTestValue(selectorOrJQueryObject);549} else if (typeof selectorOrJQueryObject === 'object') {550return "'" + selectorOrJQueryObject[0] + "'";551}552}553554(function() {555var g = 'undefined' === typeof window ? globalThis : window;556557// synonyms558assert.equals = assert.equal;559assert.notEquals = assert.notEqual;560assert['null'] = assert.equal.bind(null, null);561assert.notNull = assert.notEqual.bind(null, null);562assert['undefined'] = assert.equal.bind(null, undefined);563assert.notUndefined = assert.notEqual.bind(null, undefined);564565g.registerSuperFixture = registerSuperFixture;566g.test = test;567g.run_all = run_all;568g.fixture = fixture;569// g.repr = IMVU.repr;570g.AssertionError = AssertionError;571g.assert = assert;572g.test = test;573g.TEST_MAX_OUTPUT_SIZE = 1024;574575g.setTimeout = function(fn, time) {576if (time === 1 || time === 0){577fn();578return 0;579}580throw new AssertionError("Don't call setTimeout in tests. Use fakes.");581};582583g.setInterval = function() {584throw new AssertionError("Don't call setInterval in tests. Use fakes.");585};586587Math.random = function() {588throw new AssertionError("Don't call Math.random in tests. Use fakes.");589};590591g.requestAnimationFrame = function() {592throw new AssertionError("Don't call requestAnimationFrame in tests. Use fakes.");593};594})();595596// Emscripten runner starts all tests from this function.597// IMVU runner uses a separate runner & reporting mechanism.598function run_all_tests() {599function report_to_stdout(msg) {600if (msg.type === "test-complete")601console.log(msg.name + ": " + msg.verdict);602}603run_all(report_to_stdout);604}605606// Signal the embind test suite that it is being run from the Emscripten python test runner and not the607// IMVU test runner.608var INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER = 1;609610611