blob: ace76169c93ca9c5c4207f4fe7a6bd9816b2aacb [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
describe('require + define', function () {
const { require, define } = cordova;
function clearModules () {
Object.keys(define.moduleMap).forEach(m => define.remove(m));
}
// Restore our actual modules (cordova etc.) after all tests have finished
const originalModules = {};
beforeAll(() => Object.assign(originalModules, define.moduleMap));
afterAll(() => {
clearModules();
Object.assign(define.moduleMap, originalModules);
});
// Begin each test on a clean slate
beforeEach(clearModules);
it('exists off of cordova', function () {
expect(require).toBeDefined();
expect(define).toBeDefined();
});
describe('when defining', function () {
it('Test#001 : can define and remove module', function () {
define('a', jasmine.createSpy());
expect(define.moduleMap.a).toBeDefined();
define.remove('a');
expect(define.moduleMap.a).toBeUndefined();
});
it("Test#002 : can remove a module that doesn't exist", function () {
expect(() => {
define.remove("can't touch this");
}).not.toThrow();
});
it('Test#003 : throws an error if the module already exists', function () {
define('cordova', function () {});
expect(function () {
define('cordova', function () {});
}).toThrow('module cordova already defined');
});
it("Test#004 : doesn't call the factory method when defining", function () {
var factory = jasmine.createSpy();
define('ff', factory);
expect(factory).not.toHaveBeenCalled();
});
});
describe('when requiring', function () {
it("Test#005 : throws an exception when module doesn't exist", function () {
expect(function () {
require('your mom');
}).toThrow('module your mom not found');
});
it('Test#006 : throws an exception when modules depend on each other', function () {
define('ModuleA', function (require, exports, module) {
require('ModuleB');
});
define('ModuleB', function (require, exports, module) {
require('ModuleA');
});
expect(function () {
require('ModuleA');
}).toThrow('Cycle in require graph: ModuleA->ModuleB->ModuleA');
});
it('Test#007 : throws an exception when a cycle of requires occurs', function () {
define('ModuleA', function (require, exports, module) {
require('ModuleB');
});
define('ModuleB', function (require, exports, module) {
require('ModuleC');
});
define('ModuleC', function (require, exports, module) {
require('ModuleA');
});
expect(function () {
require('ModuleA');
}).toThrow('Cycle in require graph: ModuleA->ModuleB->ModuleC->ModuleA');
});
it('Test#008 : calls the factory method when requiring', function () {
var factory = jasmine.createSpy();
define('dino', factory);
require('dino');
expect(factory).toHaveBeenCalledTimes(1);
const [req, exports, module] = factory.calls.argsFor(0);
expect(req).toEqual(jasmine.any(Function));
expect(module).toEqual({ id: 'dino', exports: {} });
expect(exports).toBe(module.exports);
});
it('Test#009 : returns the exports object', function () {
define('a', function (require, exports, module) {
exports.stuff = 'asdf';
});
expect(require('a').stuff).toBe('asdf');
});
it('Test#010 : can use both the exports and module.exports object', function () {
define('a', function (require, exports, module) {
exports.a = 'a';
module.exports.b = 'b';
});
expect(require('a')).toEqual({ a: 'a', b: 'b' });
});
it('Test#011 : returns what is assigned to module.exports', function () {
const Foo = {};
define('a', function (require, exports, module) {
module.exports = Foo;
});
expect(require('a')).toBe(Foo);
});
it('Test#012 : supports a unique, namespace-based flavor of relative require paths', function () {
define('plugin.ios.foo', function (require, exports, module) {
module.exports = require('./bar') * 2;
});
define('plugin.ios.bar', function (require, exports, module) {
module.exports = 2;
});
expect(require('plugin.ios.foo')).toEqual(4);
});
// Adapted version of CommonJS test `determinism`
it('Test#013 : does not fall back to relative modules when absolutes are not available', () => {
define('submodule.a', function (require, exports, module) {
expect(() => {
require('a');
}).toThrow('module a not found');
});
require('submodule.a');
});
// Adapted version of CommonJS test `absolute`
it('Test#014 : correctly handles non-trivial dependecy graphs', () => {
define('submodule/a', function (require, exports, module) {
exports.foo = () => require('b');
});
define('b', function (require, exports, module) {
exports.foo = () => {};
});
const a = require('submodule/a');
const b = require('b');
expect(a.foo().foo).toBe(b.foo);
});
// Adapted version of CommonJS test `transitive`
it('Test#015 : correctly handles transitive dependecies', () => {
define('a', function (require, exports, module) {
exports.foo = require('b').foo;
});
define('b', function (require, exports, module) {
exports.foo = require('c').foo;
});
define('c', function (require, exports, module) {
exports.foo = () => 1;
});
expect(require('a').foo()).toBe(1);
});
// Adapted version of CommonJS test `method`
it('Test#016 : does not bind members of `exports` implicitly', () => {
define('a', function (require, exports, module) {
module.exports = {
foo () { return this; },
set (x) { this.x = x; },
get () { return this.x; },
getClosed () { return module.exports.x; }
};
});
const a = require('a');
const { foo, getClosed } = a;
expect(a.foo()).toBe(a);
expect(foo()).toBe((function () { return this; })());
a.set(10);
expect(a.get()).toBe(10);
expect(getClosed()).toBe(10);
});
// Adapted version of CommonJS test `nested`
it('Test#017 : allows any strings as module names', () => {
define('a/b/c/d', function (require, exports, module) {
exports.foo = () => 1;
});
define('ラーメン', function (require, exports, module) {
exports.foo = () => 2;
});
expect(require('a/b/c/d').foo()).toBe(1);
expect(require('ラーメン').foo()).toBe(2);
});
// Adapted version of CommonJS test `hasOwnProperty`
it('Test#018 : allows properties of Object.prototype as module names', () => {
expect(() => {
define('hasOwnProperty', jasmine.createSpy());
}).not.toThrow();
expect(() => {
define('toString', jasmine.createSpy());
}).not.toThrow();
});
});
});