Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/test/embind/imvu_test_adapter.js
4150 views
1
/* The embind test suite (embind.test.js) is configured to be runnable in two different testing engines:
2
- The Emscripten python test runner (open-source in emscripten repository) and
3
- The IMVU test runner (open-source via imvujs, available at https://github.com/imvu/imvujs)
4
5
Embind (and its tests) were originally developed in IMVU repository, which is the reason for two testing architectures.
6
This 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.
7
8
To run the Embind tests using the Emscripten test runner, invoke 'python test/runner.py other.test_embind' in the Emscripten root directory.
9
*/
10
11
/* global assert:true */
12
/* global Module, console, global, process */
13
14
//=== testing glue
15
16
function module(ignore, func) {
17
func({ Emscripten: Module });
18
}
19
20
/*global IMVU:true, TEST_MAX_OUTPUT_SIZE*/
21
//(function() {
22
// "use strict";
23
24
// { beforeTest: function,
25
// afterTest: function }
26
var superFixtures = [];
27
28
function registerSuperFixture(superFixture) {
29
superFixtures.push(superFixture);
30
}
31
32
// { fixture: Fixture instance,
33
// name: string,
34
// body: function() }
35
var allTests = [];
36
37
function test(name, fn) {
38
if (arguments.length !== 2) {
39
throw new TypeError("test requires 2 arguments");
40
}
41
42
if (undefined !== activeFixture && activeFixture.abstract) {
43
activeFixture.abstractTests.push({
44
name: name,
45
body: fn });
46
} else {
47
var fixtureName = (undefined !== activeFixture)? activeFixture.name + ': ' : '';
48
allTests.push({
49
name: fixtureName + name,
50
body: fn,
51
fixture: activeFixture });
52
}
53
}
54
55
function runTest(test, continuation) {
56
try {
57
var afterTests = [];
58
59
for (var i = 0; i < superFixtures.length; ++i) {
60
var superFixture = superFixtures[i];
61
62
var superScope = {};
63
superFixture.beforeTest.call(superScope);
64
afterTests.push(superFixture.afterTest.bind(superScope));
65
}
66
67
var testScope = test.fixture ?
68
Object.create(test.fixture.scope) :
69
{};
70
71
var runSetUp = function(fixtureObject) {
72
if (undefined === fixtureObject) {
73
return;
74
}
75
runSetUp(fixtureObject.parent);
76
fixtureObject.setUp.call(testScope);
77
afterTests.push(fixtureObject.tearDown.bind(testScope));
78
};
79
runSetUp(test.fixture);
80
81
test.body.call(testScope);
82
while (afterTests.length) {
83
afterTests.pop()();
84
}
85
return false;
86
} catch (e) {
87
console.error(e.stack);
88
console.error('error:', e);
89
return {stack: e.stack, e: e};
90
}
91
}
92
93
function run_all(reporter) {
94
for (var i = 0; i < allTests.length; ++i) {
95
var test = allTests[i];
96
reporter({
97
type: 'test-start',
98
name: test.name
99
});
100
101
var failed = runTest(test);
102
if (failed) {
103
reporter({
104
type: 'test-complete',
105
name: test.name,
106
verdict: 'FAIL',
107
stack: failed.stack,
108
e: failed.e
109
});
110
return false;
111
} else {
112
reporter({
113
type: 'test-complete',
114
name: test.name,
115
verdict: 'PASS'
116
});
117
}
118
}
119
120
reporter({
121
type: 'all-tests-complete'
122
});
123
124
allTests = [];
125
return true;
126
}
127
128
var activeFixture;
129
130
function Fixture(parent, name, definition, abstract_) {
131
if (!(definition instanceof Function)) {
132
throw new TypeError("fixture's 2nd argument must be a function");
133
}
134
135
this.name = name;
136
this.parent = parent;
137
this.abstract = abstract_;
138
if (this.abstract) {
139
// { name: string,
140
// body: function }
141
this.abstractTests = [];
142
}
143
144
if (this.parent !== undefined) {
145
this.parent.addAbstractTests(this);
146
}
147
148
this.scope = (this.parent === undefined ? {} : Object.create(this.parent.scope));
149
this.scope.setUp = function(setUp) {
150
this.setUp = setUp;
151
}.bind(this);
152
this.scope.tearDown = function(tearDown) {
153
this.tearDown = tearDown;
154
}.bind(this);
155
156
if (undefined !== activeFixture) {
157
throw new TypeError("Cannot define a fixture within another fixture");
158
}
159
160
activeFixture = this;
161
try {
162
definition.call(this.scope);
163
}
164
finally {
165
activeFixture = undefined;
166
}
167
}
168
Fixture.prototype.setUp = function defaultSetUp() {
169
};
170
Fixture.prototype.tearDown = function defaultTearDown() {
171
};
172
Fixture.prototype.addAbstractTests = function(concreteFixture) {
173
if (this.abstract) {
174
for (var i = 0; i < this.abstractTests.length; ++i) {
175
var test = this.abstractTests[i];
176
allTests.push({
177
name: concreteFixture.name + ': ' + test.name,
178
body: test.body,
179
fixture: concreteFixture});
180
}
181
}
182
if (this.parent) {
183
this.parent.addAbstractTests(concreteFixture);
184
}
185
};
186
187
Fixture.prototype.extend = function(fixtureName, definition) {
188
return new Fixture(this, fixtureName, definition, false);
189
};
190
191
function fixture(fixtureName, definition) {
192
return new Fixture(undefined, fixtureName, definition, false);
193
}
194
fixture.abstract = function(fixtureName, definition) {
195
return new Fixture(undefined, fixtureName, definition, true);
196
};
197
198
var AssertionError = Error;
199
200
function fail(exception, info) {
201
exception.info = info;
202
throw exception;
203
}
204
205
var formatTestValue = function(v) {
206
if (v === undefined) return 'undefined';
207
return v.toString();
208
/*
209
var s = IMVU.repr(v, TEST_MAX_OUTPUT_SIZE + 1);
210
if (s.length <= TEST_MAX_OUTPUT_SIZE) {
211
return s;
212
}
213
return s.substring(0, TEST_MAX_OUTPUT_SIZE) + '...';
214
*/
215
};
216
217
var assert = {};
218
219
////////////////////////////////////////////////////////////////////////////////
220
// GENERAL STATUS
221
222
assert.fail = function(info) {
223
info = info || "assert.fail()";
224
fail(new AssertionError(info));
225
};
226
227
////////////////////////////////////////////////////////////////////////////////
228
// BOOLEAN TESTS
229
230
assert['true'] = function(value) {
231
if (!value) {
232
fail(new AssertionError("expected truthy, actual " + formatTestValue(value)),
233
{Value: value});
234
}
235
};
236
237
assert['false'] = function(value) {
238
if (value) {
239
fail(new AssertionError("expected falsy, actual " + formatTestValue(value)),
240
{Value: value});
241
}
242
};
243
244
////////////////////////////////////////////////////////////////////////////////
245
// SCALAR COMPARISON
246
247
assert.equal = function(expected, actual) {
248
if (expected !== actual) {
249
fail(new AssertionError('expected: ' + formatTestValue(expected) + ', actual: ' + formatTestValue(actual)),
250
{Expected: expected, Actual: actual});
251
}
252
};
253
254
assert.notEqual = function(expected, actual) {
255
if (expected === actual) {
256
fail(new AssertionError('actual was equal to: ' + formatTestValue(expected)));
257
}
258
};
259
260
assert.greater = function(lhs, rhs) {
261
if (lhs <= rhs) {
262
fail(new AssertionError(formatTestValue(lhs) + ' not greater than ' + formatTestValue(rhs)));
263
}
264
};
265
266
assert.less = function(lhs, rhs) {
267
if (lhs >= rhs) {
268
fail(new AssertionError(formatTestValue(lhs) + ' not less than ' + formatTestValue(rhs)));
269
}
270
};
271
272
assert.greaterOrEqual = function(lhs, rhs) {
273
if (lhs < rhs) {
274
fail(new AssertionError(formatTestValue(lhs) + ' not greater than or equal to ' + formatTestValue(rhs)));
275
}
276
};
277
278
assert.lessOrEqual = function (lhs, rhs) {
279
if (lhs > rhs) {
280
fail(new AssertionError(formatTestValue(lhs) + ' not less than or equal to ' + formatTestValue(rhs)));
281
}
282
};
283
284
////////////////////////////////////////////////////////////////////////////////
285
// DEEP COMPARISON
286
287
assert.deepEqual = function(expected, actual) {
288
if (!_.isEqual(expected, actual)) {
289
fail(new AssertionError('expected: ' + formatTestValue(expected) + ', actual: ' + formatTestValue(actual)),
290
{Expected: expected, Actual: actual});
291
}
292
};
293
294
assert.notDeepEqual = function(expected, actual) {
295
if (_.isEqual(expected, actual)) {
296
fail(new AssertionError('expected: ' + formatTestValue(expected) + ' and actual: ' + formatTestValue(actual) + ' were equal'));
297
}
298
};
299
300
////////////////////////////////////////////////////////////////////////////////
301
// FLOATING POINT
302
303
assert.nearEqual = function( expected, actual, tolerance ) {
304
if( tolerance === undefined ) {
305
tolerance = 0.0;
306
}
307
if( expected instanceof Array && actual instanceof Array ) {
308
assert.equal(expected.length, actual.length);
309
for( var i=0; i<expected.length; ++i ) {
310
assert.nearEqual(expected[i], actual[i], tolerance);
311
}
312
return;
313
}
314
if( Math.abs(expected - actual) > tolerance ) {
315
fail( new AssertionError('expected: ' + formatTestValue(expected) + ', actual: ' + formatTestValue(actual) +
316
', tolerance: ' + formatTestValue(tolerance) + ', diff: ' + formatTestValue(actual-expected) ),
317
{ Expected:expected, Actual:actual, Tolerance:tolerance } );
318
}
319
};
320
321
////////////////////////////////////////////////////////////////////////////////
322
// STRING
323
324
assert.inString = function(expected, string){
325
if (-1 === string.indexOf(expected)){
326
fail(new AssertionError('expected: ' + formatTestValue(expected) + ' not in string: ' + formatTestValue(string)),
327
{Expected: expected, 'String': string});
328
}
329
};
330
331
assert.notInString = function(expected, string){
332
if (-1 !== string.indexOf(expected)){
333
fail(new AssertionError('unexpected: ' + formatTestValue(expected) + ' in string: ' + formatTestValue(string)),
334
{Expected: expected, 'String': string});
335
}
336
};
337
338
assert.matches = function(re, string) {
339
if (!re.test(string)) {
340
fail(new AssertionError('regexp ' + re + ' does not match: ' + string));
341
}
342
};
343
344
////////////////////////////////////////////////////////////////////////////////
345
// ARRAY
346
347
assert.inArray = function(expected, array) {
348
var found = false;
349
_.each(array, function(element){
350
if (_.isEqual(expected, element)){
351
found = true;
352
}
353
});
354
if (!found){
355
fail(new AssertionError('expected: ' + formatTestValue(expected) + ' not found in array: ' + formatTestValue(array)),
356
{Expected: expected, 'Array': array});
357
}
358
};
359
360
assert.notInArray = function(expected, array) {
361
var found = false;
362
_.each(array, function(element){
363
if (_.isEqual(expected, element)){
364
found = true;
365
}
366
});
367
if (found){
368
fail(new AssertionError('unexpected: ' + formatTestValue(expected) + ' found in array: ' + formatTestValue(array)),
369
{Expected: expected, 'Array': array});
370
}
371
};
372
373
////////////////////////////////////////////////////////////////////////////////
374
// OBJECTS
375
376
assert.hasKey = function (key, object) {
377
if (!(key in object)) {
378
fail(new AssertionError('Key ' + formatTestValue(key) + ' is not in object: ' + formatTestValue(object)));
379
}
380
};
381
382
assert.notHasKey = function (key, object) {
383
if (key in object) {
384
fail(new AssertionError('Unexpected key ' + formatTestValue(key) + ' is found in object: ' + formatTestValue(object)));
385
}
386
};
387
388
////////////////////////////////////////////////////////////////////////////////
389
// EXCEPTIONS
390
391
assert.throws = function(exception, fn) {
392
try {
393
fn();
394
} catch (e) {
395
if (e instanceof exception) {
396
return e;
397
}
398
fail(new AssertionError('Expected to throw "' + exception.name + '", actually threw: ' + formatTestValue(e) + ': ' + e.message),
399
{Expected: exception, Actual: e});
400
}
401
throw new AssertionError('did not throw');
402
};
403
404
////////////////////////////////////////////////////////////////////////////////
405
// TYPE
406
407
assert['instanceof'] = function(actual, type) {
408
if(!(actual instanceof type)) {
409
fail(new AssertionError(formatTestValue(actual) + ' not instance of ' + formatTestValue(type)),
410
{Type: type, Actual: actual});
411
}
412
};
413
414
////////////////////////////////////////////////////////////////////////////////
415
// DOM ASSERTIONS
416
417
// TODO: lift into separate file?
418
assert.dom = {
419
present: function (domElement) {
420
if (!$(domElement).length) {
421
fail(new AssertionError(decipherDomElement(domElement) + ' should be present'));
422
}
423
},
424
425
notPresent: function (selector) {
426
assert.equal(0, $(selector).length);
427
},
428
429
hasTag: function (tag, domElement) {
430
var elementTag = $(domElement)[0].tagName.toLowerCase();
431
if (elementTag !== tag.toLowerCase()) {
432
fail(new AssertionError(decipherDomElement(domElement) + ' expected to have tag name ' + formatTestValue(tag) + ', was ' + formatTestValue(elementTag) + ' instead'));
433
}
434
},
435
436
hasClass: function (className, domElement) {
437
if (!$(domElement).hasClass(className)) {
438
fail(new AssertionError(decipherDomElement(domElement) + ' expected to have class ' + formatTestValue(className) + ', has ' + formatTestValue($(domElement).attr('class')) + ' instead'));
439
}
440
},
441
442
notHasClass: function (className, domElement) {
443
assert.dom.present(domElement); // if domElement is empty, .hasClass will always return false
444
if ($(domElement).hasClass(className)) {
445
fail(new AssertionError(decipherDomElement(domElement) + ' expected NOT to have class ' + formatTestValue(className)));
446
}
447
},
448
449
hasAttribute: function (attributeName, selector) {
450
assert['true']($(selector).is('[' + attributeName + ']'));
451
},
452
453
notHasAttribute: function (attributeName, selector) {
454
assert.dom.present(selector);
455
assert['false']($(selector).is('[' + attributeName + ']'));
456
},
457
458
attr: function (value, attributeName, selector) {
459
assert.equal(value, $(selector).attr(attributeName));
460
},
461
462
attributeValues: function (values, selector) {
463
var $el = $(selector);
464
_(values).each(function (val, key) {
465
assert.equal(val, $el.attr(key));
466
});
467
},
468
469
text: function (expected, selector) {
470
assert.equal(expected, $(selector).text());
471
},
472
473
value: function (expected, selector) {
474
assert.equal(expected, $(selector).val());
475
},
476
477
count: function (elementCount, selector) {
478
assert.equal(elementCount, $(selector).length);
479
},
480
481
visible: function (domElement) {
482
if (!$(domElement).is(':visible')) {
483
fail(new AssertionError(decipherDomElement(domElement) + ' expected to be visible'));
484
}
485
},
486
487
notVisible: function (domElement) {
488
assert.dom.present(domElement);
489
if ($(domElement).is(':visible')) {
490
fail(new AssertionError(decipherDomElement(domElement) + ' expected to be NOT visible'));
491
}
492
},
493
494
disabled: function (domElement) {
495
if (!$(domElement).is(':disabled')) {
496
fail(new AssertionError(decipherDomElement(domElement) + ' expected to be disabled'));
497
}
498
},
499
500
enabled: function (domElement) {
501
if (!$(domElement).is(':enabled')) {
502
fail(new AssertionError(decipherDomElement(domElement) + ' expected to be enabled'));
503
}
504
},
505
506
focused: function (selector) {
507
var expected = $(selector)[0];
508
var actual = document.activeElement;
509
if (expected !== actual) {
510
throw new AssertionError(actual.outerHTML + ' has focus. expected: ' + expected.outerHTML);
511
}
512
},
513
514
notFocused: function (selector) {
515
var expected = $(selector)[0];
516
var actual = document.activeElement;
517
if (expected === actual) {
518
throw new AssertionError(expected.outerHTML + ' expected not to have focus.');
519
}
520
},
521
522
html: function (expected, selector) {
523
assert.equal(expected, $(selector).html());
524
},
525
526
css: function (expected, propertyName, selector) {
527
assert.equal(expected, $(selector).css(propertyName));
528
},
529
530
empty: function (selectorOrJQueryObject) {
531
var el = selectorOrJQueryObject;
532
assert.dom.present(el);
533
if (!$(el).is(':empty')) {
534
fail(new AssertionError(decipherDomElement(el) + ' expected to be empty'));
535
}
536
},
537
538
notEmpty: function (selectorOrJQueryObject) {
539
var el = selectorOrJQueryObject;
540
assert.dom.present(el);
541
if ($(el).is(':empty')) {
542
fail(new AssertionError(decipherDomElement(el) + ' expected NOT to be empty'));
543
}
544
}
545
};
546
547
function decipherDomElement(selectorOrJQueryObject) {
548
if (typeof selectorOrJQueryObject === 'string') {
549
return 'Selector ' + formatTestValue(selectorOrJQueryObject);
550
} else if (typeof selectorOrJQueryObject === 'object') {
551
return "'" + selectorOrJQueryObject[0] + "'";
552
}
553
}
554
555
(function() {
556
var g = 'undefined' === typeof window ? globalThis : window;
557
558
// synonyms
559
assert.equals = assert.equal;
560
assert.notEquals = assert.notEqual;
561
assert['null'] = assert.equal.bind(null, null);
562
assert.notNull = assert.notEqual.bind(null, null);
563
assert['undefined'] = assert.equal.bind(null, undefined);
564
assert.notUndefined = assert.notEqual.bind(null, undefined);
565
566
g.registerSuperFixture = registerSuperFixture;
567
g.test = test;
568
g.run_all = run_all;
569
g.fixture = fixture;
570
// g.repr = IMVU.repr;
571
g.AssertionError = AssertionError;
572
g.assert = assert;
573
g.test = test;
574
g.TEST_MAX_OUTPUT_SIZE = 1024;
575
576
g.setTimeout = function(fn, time) {
577
if (time === 1 || time === 0){
578
fn();
579
return 0;
580
}
581
throw new AssertionError("Don't call setTimeout in tests. Use fakes.");
582
};
583
584
g.setInterval = function() {
585
throw new AssertionError("Don't call setInterval in tests. Use fakes.");
586
};
587
588
Math.random = function() {
589
throw new AssertionError("Don't call Math.random in tests. Use fakes.");
590
};
591
592
g.requestAnimationFrame = function() {
593
throw new AssertionError("Don't call requestAnimationFrame in tests. Use fakes.");
594
};
595
})();
596
597
// Emscripten runner starts all tests from this function.
598
// IMVU runner uses a separate runner & reporting mechanism.
599
function run_all_tests() {
600
function report_to_stdout(msg) {
601
if (msg.type === "test-complete")
602
console.log(msg.name + ": " + msg.verdict);
603
}
604
run_all(report_to_stdout);
605
}
606
607
// Signal the embind test suite that it is being run from the Emscripten python test runner and not the
608
// IMVU test runner.
609
var INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER = 1;
610
611