overte-JulianGro/scripts/developer/tests/unit_tests/moduleUnitTests.js
2017-03-07 16:36:10 -05:00

317 lines
14 KiB
JavaScript

/* eslint-env jasmine */
var isNode = instrument_testrunner();
var NETWORK_describe = xdescribe,
INTERFACE_describe = !isNode ? describe : xdescribe,
NODE_describe = isNode ? describe : xdescribe;
print("DESCRIBING");
describe('require', function() {
describe('resolve', function() {
it('should resolve relative filenames', function() {
var expected = Script.resolvePath('./moduleTests/example.json');
expect(require.resolve('./moduleTests/example.json')).toEqual(expected);
});
});
describe('JSON', function() {
it('should import .json modules', function() {
var example = require('./moduleTests/example.json');
expect(example.name).toEqual('Example JSON Module');
});
INTERFACE_describe('inteface', function() {
NETWORK_describe('network', function() {
//xit('should import #content-type=application/json modules', function() {
// var results = require('https://jsonip.com#content-type=application/json');
// expect(results.ip).toMatch(/^[.0-9]+$/);
//});
it('should import content-type: application/json modules', function() {
var scope = { 'content-type': 'application/json' };
var results = require.call(scope, 'https://jsonip.com');
expect(results.ip).toMatch(/^[.0-9]+$/);
});
});
});
});
INTERFACE_describe('system', function() {
it('require(id)', function() {
expect(require('vec3')).toEqual(jasmine.any(Function));
});
it('require(id).function', function() {
expect(require('vec3')().isValid).toEqual(jasmine.any(Function));
});
});
describe('exceptions', function() {
it('should reject blank "" module identifiers', function() {
expect(function() {
require.resolve('');
}).toThrowError(/Cannot find/);
});
it('should reject excessive identifier sizes', function() {
expect(function() {
require.resolve(new Array(8193).toString());
}).toThrowError(/Cannot find/);
});
it('should reject implicitly-relative filenames', function() {
expect(function() {
var mod = require.resolve('example.js');
}).toThrowError(/Cannot find/);
});
it('should reject non-existent filenames', function() {
expect(function() {
var mod = require.resolve('./404error.js');
}).toThrowError(/Cannot find/);
});
it('should reject identifiers resolving to a directory', function() {
expect(function() {
var mod = require.resolve('.');
//console.warn('resolved(.)', mod);
}).toThrowError(/Cannot find/);
expect(function() {
var mod = require.resolve('..');
//console.warn('resolved(..)', mod);
}).toThrowError(/Cannot find/);
expect(function() {
var mod = require.resolve('../');
//console.warn('resolved(../)', mod);
}).toThrowError(/Cannot find/);
});
if (typeof MODE !== 'undefined' && MODE !== 'node') {
it('should reject non-system, extensionless identifiers', function() {
expect(function() {
require.resolve('./example');
}).toThrowError(/Cannot find/);
});
}
});
describe('cache', function() {
it('should cache modules by resolved module id', function() {
var value = new Date;
var example = require('./moduleTests/example.json');
example['.test'] = value;
var example2 = require('../../tests/unit_tests/moduleTests/example.json');
expect(example2).toBe(example);
expect(example2['.test']).toBe(example['.test']);
});
it('should reload cached modules set to null', function() {
var value = new Date;
var example = require('./moduleTests/example.json');
example['.test'] = value;
require.cache[require.resolve('../../tests/unit_tests/moduleTests/example.json')] = null;
var example2 = require('../../tests/unit_tests/moduleTests/example.json');
expect(example2).not.toBe(example);
expect(example2['.test']).not.toBe(example['.test']);
});
it('should reload when module property is deleted', function() {
var value = new Date;
var example = require('./moduleTests/example.json');
example['.test'] = value;
delete require.cache[require.resolve('../../tests/unit_tests/moduleTests/example.json')];
var example2 = require('../../tests/unit_tests/moduleTests/example.json');
expect(example2).not.toBe(example);
expect(example2['.test']).not.toBe(example['.test']);
});
});
describe('cyclic dependencies', function() {
describe('should allow lazy-ref cyclic module resolution', function() {
const MODULE_PATH = './moduleTests/cycles/main.js';
var main;
beforeEach(function() {
try { this._print = print; } catch(e) {}
// for this test print is no-op'd so it doesn't disrupt the reporter output
//console = typeof console === 'object' ? console : { log: function() {} };
print = function() {};
Script.resetModuleCache();
});
afterEach(function() {
print = this._print;
});
it('main requirable', function() {
main = require(MODULE_PATH);
expect(main).toEqual(jasmine.any(Object));
});
it('main with both a and b', function() {
expect(main.a['b.done?']).toBe(true);
expect(main.b['a.done?']).toBe(false);
});
it('a.done?', function() {
expect(main['a.done?']).toBe(true);
});
it('b.done?', function() {
expect(main['b.done?']).toBe(true);
});
});
});
describe('JS', function() {
it('should throw catchable local file errors', function() {
expect(function() {
require('file:///dev/null/non-existent-file.js');
}).toThrowError(/path not found|Cannot find.*non-existent-file/);
});
it('should throw catchable invalid id errors', function() {
expect(function() {
require(new Array(4096 * 2).toString());
}).toThrowError(/invalid.*size|Cannot find.*,{30}/);
});
it('should throw catchable unresolved id errors', function() {
expect(function() {
require('foobar:/baz.js');
}).toThrowError(/could not resolve|Cannot find.*foobar:/);
});
NETWORK_describe('network', function() {
// note: with retries these tests can take up to 60 seconds each to timeout
var timeout = 75 * 1000;
it('should throw catchable host errors', function() {
expect(function() {
var mod = require('http://non.existent.highfidelity.io/moduleUnitTest.js');
print("mod", Object.keys(mod));
}).toThrowError(/error retrieving script .ServerUnavailable.|Cannot find.*non.existent/);
}, timeout);
it('should throw catchable network timeouts', function() {
expect(function() {
require('http://ping.highfidelity.io:1024');
}).toThrowError(/error retrieving script .Timeout.|Cannot find.*ping.highfidelity/);
}, timeout);
});
});
INTERFACE_describe('entity', function() {
var sampleScripts = [
'entityConstructorAPIException.js',
'entityConstructorModule.js',
'entityConstructorNested2.js',
'entityConstructorNested.js',
'entityConstructorRequireException.js',
'entityPreloadAPIError.js',
'entityPreloadRequire.js',
].filter(Boolean).map(function(id) { return Script.require.resolve('./moduleTests/entity/'+id); });
var uuids = [];
for(var i=0; i < sampleScripts.length; i++) {
(function(i) {
var script = sampleScripts[ i % sampleScripts.length ];
var shortname = '['+i+'] ' + script.split('/').pop();
var position = MyAvatar.position;
position.y -= i/2;
it(shortname, function(done) {
var uuid = Entities.addEntity({
text: shortname,
description: Script.resolvePath('').split('/').pop(),
type: 'Text',
position: position,
rotation: MyAvatar.orientation,
script: script,
scriptTimestamp: +new Date,
lifetime: 20,
lineHeight: 1/8,
dimensions: { x: 2, y: .5, z: .01 },
backgroundColor: { red: 0, green: 0, blue: 0 },
color: { red: 0xff, green: 0xff, blue: 0xff },
}, !Entities.serversExist() || !Entities.canRezTmp());
uuids.push(uuid);
var ii = Script.setInterval(function() {
Entities.queryPropertyMetadata(uuid, "script", function(err, result) {
if (err) {
throw new Error(err);
}
if (result.success) {
clearInterval(ii);
if (/Exception/.test(script))
expect(result.status).toMatch(/^error_(loading|running)_script$/);
else
expect(result.status).toEqual("running");
done();
} else {
print('!result.success', JSON.stringify(result));
}
});
}, 100);
Script.setTimeout(function() {
Script.clearInterval(ii);
}, 4900);
}, 5000 /* timeout */);
})(i);
}
Script.scriptEnding.connect(function() {
uuids.forEach(function(uuid) { Entities.deleteEntity(uuid); });
});
});
});
function run() {}
function instrument_testrunner() {
var isNode = typeof process === 'object' && process.title === 'node';
if (isNode) {
// for consistency this still uses the same local jasmine.js library
var jasmineRequire = require('../../libraries/jasmine/jasmine.js');
var jasmine = jasmineRequire.core(jasmineRequire);
var env = jasmine.getEnv();
var jasmineInterface = jasmineRequire.interface(jasmine, env);
for (var p in jasmineInterface)
global[p] = jasmineInterface[p];
env.addReporter(new (require('jasmine-console-reporter')));
// testing mocks
Script = {
resetModuleCache: function() {
module.require.cache = {};
},
setTimeout: setTimeout,
clearTimeout: clearTimeout,
resolvePath: function(id) {
// this attempts to accurately emulate how Script.resolvePath works
var trace = {}; Error.captureStackTrace(trace);
var base = trace.stack.split('\n')[2].replace(/^.*[(]|[)].*$/g,'').replace(/:[0-9]+:[0-9]+.*$/,'');
if (!id)
return base;
var rel = base.replace(/[^\/]+$/, id);
console.info('rel', rel);
return require.resolve(rel);
},
require: function(mod) {
return require(Script.require.resolve(mod));
}
};
Script.require.cache = require.cache;
Script.require.resolve = function(mod) {
if (mod === '.' || /^\.\.($|\/)/.test(mod))
throw new Error("Cannot find module '"+mod+"' (is dir)");
var path = require.resolve(mod);
//console.info('node-require-reoslved', mod, path);
try {
if (require('fs').lstatSync(path).isDirectory()) {
throw new Error("Cannot find module '"+path+"' (is directory)");
}
//console.info('!path', path);
} catch(e) { console.info(e) }
return path;
};
print = console.info.bind(console, '[print]');
} else {
global = this;
// Interface Test mode
Script.require('../../../system/libraries/utils.js');
this.jasmineRequire = Script.require('../../libraries/jasmine/jasmine.js');
Script.require('../../libraries/jasmine/hifi-boot.js')
require = Script.require;
// polyfill console
console = {
log: print,
info: print.bind(this, '[info]'),
warn: print.bind(this, '[warn]'),
error: print.bind(this, '[error]'),
debug: print.bind(this, '[debug]'),
};
}
run = function() { global.jasmine.getEnv().execute(); };
return isNode;
}
run();