UNPKG

@gerhobbelt/mathjax-third-party-extensions

Version:

A list of MathJax extensions provided by third-party contributors

949 lines (757 loc) 49.8 kB
require('jasmine-only'); describe('amdclean specs', function() { var amdclean = require('../../src/amdclean'), requirejs = require('requirejs'), _ = require('lodash'), fs = require('fs'), defaultOptions = { // We don't need the IIFE wrapper by default, since it makes the tests more verbose 'wrap': { 'start': '', 'end': '' }, // Makes sure the code output is on one line (easier to test) 'escodegen': { 'format': { 'compact': true } } } describe('define() method conversions', function() { describe('functions', function() { it('should convert function return values to immediately invoked function declarations', function() { var AMDcode = "define('example', [], function() {});", cleanedCode = amdclean.clean(AMDcode, defaultOptions); standardJavaScript = "var example;example=undefined;"; expect(cleanedCode).toBe(standardJavaScript); }); it('should preserve single line comments when converting function return values to immediately invoked function declarations', function() { var AMDcode = "define('example', [], function() { // Answer\n var test = true; return test; });", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var example;example=function (){// Answer\nvar test=true;return test;}();"; expect(cleanedCode).toBe(standardJavaScript); }); it('should preserve multi-line comments when converting function return values to immediately invoked function declarations', function() { var AMDcode = "define('example', [], function() { /* Answer */\nvar test = true; return test; });", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var example;example=function (){/* Answer */\nvar test=true;return test;}();"; expect(cleanedCode).toBe(standardJavaScript); }); it('should pass a file path instead of the code directly', function() { var options = _.merge(_.cloneDeep(defaultOptions), { 'filePath': __dirname + '/../filePathTest.js' }), cleanedCode = amdclean.clean(options), standardJavaScript = "var example;example=undefined;"; expect(cleanedCode).toBe(standardJavaScript); }); it('should correctly set callback parameters to the callback function', function() { var AMDcode = "define('example', ['example1', 'example2'], function(one, two) {var test = true;});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var example;example=function (one,two){var test=true;}(example1,example2);"; expect(cleanedCode).toBe(standardJavaScript); }); it('should not hoist and remove callback and IIFE parameters that are only used once', function() { var AMDcode = "define('example1', function() { var count = 0;return 'firstModule'; });define('example2', function() { var count = 0;return 'secondModule'; });define('example', ['example1', 'example2'], function(yo, yoyo) {var test = true;});define('blah', ['example2'], function(yoooo, comon) { return false; });", options = _.merge(_.cloneDeep(defaultOptions), { 'aggressiveOptimizations': true }); cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var example1,example2,example,blah;example1=function (){var count=0;return'firstModule';}();example2=function (){var count=0;return'secondModule';}();example=function (yo,yoyo){var test=true;}(example1,example2);blah=function (yoooo,comon){return false;}(example2);"; expect(cleanedCode).toBe(standardJavaScript); }); it('should hoist and remove callback and IIFE parameters that are used more than once', function() { var AMDcode = "define('example1', function() { var count = 0;return 'firstModule'; });define('example2', function() { var count = 0;return 'secondModule'; });define('example', ['example1', 'example2'], function(yo, yoyo) {var test = true;});define('blah', ['example1', 'example2'], function(yo, yoooo, comon) { var test; return false; });", options = _.merge(_.cloneDeep(defaultOptions), { 'aggressiveOptimizations': true }); cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var example1,example2,example,blah,yo;example1=yo=function (){var count=0;return'firstModule';}();example2=function (){var count=0;return'secondModule';}();example=function (yoyo){var test=true;}(example2);blah=function (yoooo,comon){var test;return false;}(example2);"; expect(cleanedCode).toBe(standardJavaScript); }); it('should correctly normalize relative file paths', function() { var AMDcode = "define('./modules/example', ['example1', 'example2'], function(one, two) {var test = true;});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var modules_example;modules_example=function (one,two){var test=true;}(example1,example2);"; expect(cleanedCode).toBe(standardJavaScript); }); it('should correctly normalize relative file paths dependencies', function() { var AMDcode = "define('./modules/example', ['./example1', './example2', '../example3'], function(one, two, three) {var test = true;});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var modules_example;modules_example=function (one,two,three){var test=true;}(modules_example1,modules_example2,example3);"; expect(cleanedCode).toBe(standardJavaScript); }); it('should correctly normalize multi-level relative file paths dependencies', function() { var AMDcode = "define('./foo/prototype/subModule/myModule', ['example1','example2', '/anotherModule/example3', '../../example4','../anotherModule/example5'], function(one, two, three, four, five) { var test = true;});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var foo_prototype_subModule_myModule;foo_prototype_subModule_myModule=function (one,two,three,four,five){var test=true;}(example1,example2,anotherModule_example3,foo_example4,foo_prototype_anotherModule_example5);"; expect(cleanedCode).toBe(standardJavaScript); }); it('should correctly normalize multi-level relative file paths', function() { var AMDcode = "define('./foo/prototype/commonMethodName.js', ['example1', 'example2'], function(one, two) { var test = true;});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var foo_prototype_commonMethodNamejs;foo_prototype_commonMethodNamejs=function (one,two){var test=true;}(example1,example2);"; expect(cleanedCode).toBe(standardJavaScript); }); it('should correctly prefix reserved keywords with an underscore', function() { var AMDcode = "define('foo', ['./function'], function(fn){ fn.bar(); });", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var foo;foo=function (fn){fn.bar();}(_function);"; expect(cleanedCode).toBe(standardJavaScript); }); it('should allow underscores and dollar signs as module names', function() { var AMDcode = "define('fo.o', ['./function'], function(fn){ fn.bar(); });", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var foo;foo=function (fn){fn.bar();}(_function);"; expect(cleanedCode).toBe(standardJavaScript); }); it('should not convert defines with an /*amdclean*/ comment before it', function() { var AMDcode = "/*amdclean*/define('./modules/example', ['example1', 'example2'], function(one, two) {});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "/*amdclean*/\ndefine('./modules/example',['example1','example2'],function(one,two){});"; expect(cleanedCode).toBe(standardJavaScript); }); it('should not convert defines with a custom commentCleanName comment before it', function() { var AMDcode = "/*donotremove*/define('./modules/example', ['example1', 'example2'], function(one, two) {});", options = _.merge(_.cloneDeep(defaultOptions), { 'commentCleanName': 'donotremove' }); cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "/*donotremove*/\ndefine('./modules/example',['example1','example2'],function(one,two){});"; expect(cleanedCode).toBe(standardJavaScript); }); it('should not convert defines that are added to the ignoreModules options array', function() { var AMDcode = "define('exampleModule', ['example1', 'example2'], function(one, two) {});", options = _.merge(_.cloneDeep(defaultOptions), { 'ignoreModules': ['exampleModule'] }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "define('exampleModule',['example1','example2'],function(one,two){});"; expect(cleanedCode).toBe(standardJavaScript); }); it('should remove defines that are added to the removeModules options array', function() { var AMDcode = "define('exampleModule', ['example1', 'example2'], function(one, two) {});define('exampleModule2', function() {})", options = _.merge(_.cloneDeep(defaultOptions), { 'removeModules': ['exampleModule'] }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var exampleModule,exampleModule2;exampleModule2=undefined;"; expect(cleanedCode).toBe(standardJavaScript); }); it('should support global modules', function() { var AMDcode = "define('foo', ['require', 'exports', './bar'], function(require, exports){exports.bar = require('./bar');});", options = _.merge(_.cloneDeep(defaultOptions), { 'globalModules': ['foo'] }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var foo={};foo=function (exports){exports.bar=bar;return exports;}(foo);window.foo=foo;"; expect(cleanedCode).toBe(standardJavaScript); }); it('should support converting shimmed modules that export a global object', function() { var AMDcode = "define('backbone', ['underscore', 'jquery'], (function (global) { return function () { var ret, fn; return ret || global.Backbone; }; }(this)));", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var backbone;backbone=window.Backbone;"; expect(cleanedCode).toBe(standardJavaScript); }); it('should support setting the module return value via the shimOverrides option', function() { var AMDcode = "define('backbone', ['underscore', 'jquery'], (function (global) { return {}; }(this)));", options = _.merge(_.cloneDeep(defaultOptions), { 'shimOverrides': { 'backbone': 'window.Backbone' } }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var backbone;backbone=window.Backbone;"; expect(cleanedCode).toBe(standardJavaScript); }); it('should support specifying shimOverrides with module identifier', function() { var AMDcode = "define('bower_components/backbone/backbone', ['underscore', 'jquery'], (function (global) { return {}; }(this)));", options = _.merge(_.cloneDeep(defaultOptions), { 'shimOverrides': { 'bower_components/backbone/backbone': 'window.Backbone' } }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var bower_components_backbone_backbone;bower_components_backbone_backbone=window.Backbone;"; expect(cleanedCode).toBe(standardJavaScript); }); it('should correctly rewrite shimmed functions', function() { var AMDcode = "define('browserglobal', (function (global) { return function () { var ret, fn; return ret || global.BrowserGlobal; }; }(this)));", options = _.merge(_.cloneDeep(defaultOptions), { 'shimOverrides': { 'browserglobal': 'BrowserGlobal' } }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var browserglobal;browserglobal=BrowserGlobal;"; expect(cleanedCode).toBe(standardJavaScript); }); it('should support converting define() methods with identifiers', function() { var AMDcode = "define('esprima', ['exports'], factory);", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var esprima={};esprima=function (){return typeof factory==='function'?factory():factory;}();"; expect(cleanedCode).toBe(standardJavaScript); }); it('should not remove comments from the source code', function() { var AMDcode = "//Test comment\n define('example', [], function() {});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "//Test comment\nvar example;example=undefined;"; expect(cleanedCode).toBe(standardJavaScript); }); it('should not remove comments from the source code (special case)', function() { var fs = require('fs'), AMDcode = fs.readFileSync(__dirname + '/../comments.js').toString(), cleanedCode = amdclean.clean(AMDcode, {wrap: false, removeUseStricts: false}), standardJavaScript = fs.readFileSync(__dirname + '/../comments-output.js').toString(); expect(cleanedCode).toBe(standardJavaScript); }); it('should not automatically convert conditional AMD checks that are using the appropriate commentCleanName', function() { var AMDcode = "//amdclean\n if(typeof define === 'function') {}", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "//amdclean\nif(typeof define==='function'){}"; expect(cleanedCode).toBe(standardJavaScript); }); it('should not automatically convert conditional AMD checks, and the associated named AMD module, if the transformAMDChecks option is set to false', function() { var AMDcode = "if(typeof define === 'function') { define('example', [], function() {}); }", options = _.merge(_.cloneDeep(defaultOptions), { 'transformAMDChecks': false }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "if(typeof define==='function'){define('example',[],function(){});}"; expect(cleanedCode).toBe(standardJavaScript); }); it('should not automatically convert conditional AMD checks, and the associated anonymous AMD module, if the transformAMDChecks option is set to false', function() { var AMDcode = "if(typeof define === 'function') { define([], function() {}); }", options = _.merge(_.cloneDeep(defaultOptions), { 'transformAMDChecks': false }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "if(typeof define==='function'){define([],function(){});}"; expect(cleanedCode).toBe(standardJavaScript); }); it('should create an anonymous AMD module, if the transformAMDChecks option is set to false and the createAnonymousAMDModule option is set to true', function() { var AMDcode = "if(typeof define === 'function') { define('test', [], function() {}); }", options = _.merge(_.cloneDeep(defaultOptions), { 'transformAMDChecks': false, 'createAnonymousAMDModule': true }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "if(typeof define==='function'){define([],function(){});}"; expect(cleanedCode).toBe(standardJavaScript); }); it('should handle loader plugins', function(){ var fs = require('fs'), AMDcode = fs.readFileSync(__dirname + '/../loaderPlugin.js').toString(), cleanedCode = amdclean.clean(AMDcode, {wrap: false}), standardJavaScript = fs.readFileSync(__dirname + '/../loaderPlugin-output.js').toString().replace(/\r\n/g, "\n"); expect(cleanedCode).toBe(standardJavaScript); }); describe('optimized defines', function() { it('should optimize basic define() methods that return a function expression', function() { var AMDcode = "define('example', function () { return function ( thing ) {return !isNaN( parseFloat( thing ) ) && isFinite( thing );};});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var example;example=function(thing){return!isNaN(parseFloat(thing))&&isFinite(thing);};"; expect(cleanedCode).toBe(standardJavaScript); }); it('should optimize basic define() methods that have an empty factory function', function() { var AMDcode = "define('example', function () {});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var example;example=undefined;"; expect(cleanedCode).toBe(standardJavaScript); }); it('should support the start and end wrap options', function() { var AMDcode = "define('example', function () {});", options = _.merge(_.cloneDeep(defaultOptions), { 'wrap': { 'start': ';(function() {', 'end': '}());' } }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = ";(function() {var example;example=undefined;}());"; expect(cleanedCode).toBe(standardJavaScript); }); it('should optimize more complex define() methods that return a function expression', function() { var AMDcode = "define('example', function () { return function ( thing ) { var anotherThing = true; return !isNaN( parseFloat( thing ) ) && isFinite( thing );};});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var example;example=function(thing){var anotherThing=true;return!isNaN(parseFloat(thing))&&isFinite(thing);};"; expect(cleanedCode).toBe(standardJavaScript); }); it('should optimize more complex define() methods that have a "use strict" statement and return a function expression', function() { var AMDcode = "define('example', function () { 'use strict'; return function ( thing ) { return !isNaN( parseFloat( thing ) ) && isFinite( thing );};});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var example;example=function(thing){return!isNaN(parseFloat(thing))&&isFinite(thing);};"; expect(cleanedCode).toBe(standardJavaScript); }); it('should not optimize more complex define() methods that have a "use strict" statement and return a function expression, but have also set the removeUseStricts option to false', function() { var AMDcode = "define('example', function () { 'use strict'; return function ( thing ) { return !isNaN( parseFloat( thing ) ) && isFinite( thing );};});", options = _.merge(_.cloneDeep(defaultOptions), { 'removeUseStricts': false }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var example;example=function (){'use strict';return function(thing){return!isNaN(parseFloat(thing))&&isFinite(thing);};}();"; expect(cleanedCode).toBe(standardJavaScript); }); it('should remove "use strict" statement when removeUseStricts option is set to true (which is default)', function() { var AMDcode = "define('example', function () { 'use strict'; function example() {};example.prototype.test = 1;return example;});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var example;example=function (){function example(){}example.prototype.test=1;return example;}();"; expect(cleanedCode).toBe(standardJavaScript); }); it('should keep "use strict" statement when removeUseStricts option is set to false', function() { var AMDcode = "define('example', function () { 'use strict'; function example() {};example.prototype.test = 1;return example;});", options = _.merge(_.cloneDeep(defaultOptions), { 'removeUseStricts': false }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var example;example=function (){'use strict';function example(){}example.prototype.test=1;return example;}();"; expect(cleanedCode).toBe(standardJavaScript); }); it('should not optimize define() methods that have logic outside of the return statement', function() { var AMDcode = "define('example', [], function () { var test = true; return function ( thing ) { var anotherThing = true; return !isNaN( parseFloat( thing ) ) && isFinite( thing );};});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var example;example=function (){var test=true;return function(thing){var anotherThing=true;return!isNaN(parseFloat(thing))&&isFinite(thing);};}();"; expect(cleanedCode).toBe(standardJavaScript); }); it('should optimize basic define() methods that return a literal value', function() { var AMDcode = "define('example', [], function() { return 'Convert AMD code to standard JavaScript';});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var example;example='Convert AMD code to standard JavaScript';"; expect(cleanedCode).toBe(standardJavaScript); }); it('should not optimize basic define() methods that return a literal value and contain more than one code block', function() { var AMDcode = "define('example', [], function() { var example = true; return 'Convert AMD code to standard JavaScript';});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var example;example=function (){var example=true;return'Convert AMD code to standard JavaScript';}();"; expect(cleanedCode).toBe(standardJavaScript); }); it('should optimize basic define() methods that return a literal value that have one or more dependencies', function() { var AMDcode = "define('example', ['someDependency'], function() { return 'Convert AMD code to standard JavaScript';});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var example;example='Convert AMD code to standard JavaScript';"; expect(cleanedCode).toBe(standardJavaScript); }); it('should optimize basic define() methods that return a nested object expression', function() { var AMDcode = "define('example', [], function() {return { 'example': 'Convert AMD code to standard JavaScript' };});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var example;example={'example':'Convert AMD code to standard JavaScript'};"; expect(cleanedCode).toBe(standardJavaScript); }); it('should optimize basic define() methods that return a new expression', function() { var AMDcode = "define('example', [], function() { return new String('test');});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var example;example=new String('test');"; expect(cleanedCode).toBe(standardJavaScript); }); it('should not optimize basic define() methods that return an identifier', function() { var AMDcode = "define('jquery', [], function() {return jQuery;});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var jquery;jquery=function (){return jQuery;}();"; expect(cleanedCode).toBe(standardJavaScript); }); it('should correctly transform each module name when using the prefixTransform option', function() { var AMDcode = "var example = require('util/anotherModule');", options = _.merge(_.cloneDeep(defaultOptions), { 'prefixTransform': function(moduleName, moduleId) { return moduleName.substring(moduleName.lastIndexOf('_') + 1, moduleName.length); }, 'wrap': { start: '', end: '' } }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var example=anotherModule;"; expect(cleanedCode).toBe(standardJavaScript); }); it('should correctly transform each module variable declaration name when using the IIFEVariableNameTransform option', function() { var AMDcode = "define('A', ['B', 'C'], function(B, C){return 2; }); ", options = _.merge(_.cloneDeep(defaultOptions), { 'IIFEVariableNameTransform': function(moduleName, moduleId) { return "MyModules['" + moduleName +"']=" + moduleName; } }), cleanedCode = amdclean.clean(AMDcode, options); expect(cleanedCode.indexOf("MyModules['A']=A=function")!== -1).toBe(true); }); it('should remove original function parameters if their arguments are not declared in the callback', function() { var AMDcode = "define('A',['B','C','D'],function(B){return 1;});", options = _.merge(_.cloneDeep(defaultOptions), {}), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var A;A=function (B){return 1;}(B);"; expect(cleanedCode).toBe(standardJavaScript); }); it('should not remove original function parameters if their arguments are not declared in the callback', function() { var AMDcode = "define('A',['B','C','D'],function(B){return arguments[0];});", options = _.merge(_.cloneDeep(defaultOptions), {}), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var A;A=function (B,C,D){return arguments[0];}(B,C,D);"; expect(cleanedCode).toBe(standardJavaScript); }); it('should remove original function parameters if "arguments" is used but only in an inner function', function() { var AMDcode = "define('A',['B','C','D'],function(B){return function(){return arguments[0];}});", options = _.merge(_.cloneDeep(defaultOptions), {}), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var A;A=function (B){return function(){return arguments[0];};}(B);"; expect(cleanedCode).toBe(standardJavaScript); }); describe('aggressiveOptimizations option', function() { it('should correctly remove callback and IIFE parameters that directly match stored module names', function() { var AMDcode = "define('example1', function() {});define('example2', function() {});define('example', ['example1', 'example2'], function(example1, example2) {var test = true;});", options = _.merge(_.cloneDeep(defaultOptions), { 'aggressiveOptimizations': true }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var example1,example2,example;example1=undefined;example2=undefined;example=function (){var test=true;}();"; expect(cleanedCode).toBe(standardJavaScript); }); it('should correctly preserve callback and IIFE parameters that do not directly match stored module names', function() { var AMDcode = "define('example1', function() {});define('example2', function() {});define('example', ['example1', 'example2'], function(example3, example2) {var test = true;});", options = _.merge(_.cloneDeep(defaultOptions), { 'aggressiveOptimizations': true }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var example1,example2,example;example1=undefined;example2=undefined;example=function (example3){var test=true;}(example1);"; expect(cleanedCode).toBe(standardJavaScript); }); it('should correctly preserve callback and IIFE parameters that do not directly match stored module names 2', function() { var AMDcode = "define('example1', function() {});define('example2', function() {});define('example', ['example1', 'example2'], function() {var test = true;});", options = _.merge(_.cloneDeep(defaultOptions), { 'aggressiveOptimizations': true }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var example1,example2,example;example1=undefined;example2=undefined;example=function (){var test=true;}();"; expect(cleanedCode).toBe(standardJavaScript); }); it('should handle extra parameters', function() { var AMDcode = "define('example1', function() {});define('example2', ['example1'], function(example1, test) {var test = true;});", options = _.merge(_.cloneDeep(defaultOptions), { 'aggressiveOptimizations': true }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var example1,example2;example1=undefined;example2=function (test){var test=true;}();"; expect(cleanedCode).toBe(standardJavaScript); }); }); }); }); describe('objects', function() { it('should convert object return values to variable declarations', function() { var AMDcode = "define('example', { exampleProp: 'This is an example' });", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var example;example={exampleProp:'This is an example'};"; expect(cleanedCode).toBe(standardJavaScript); }); }); describe('CommonJS Support', function() { it('should convert CommonJS require() calls', function() { var AMDcode = "var example = require('anotherModule');", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var example=anotherModule;"; expect(cleanedCode).toBe(standardJavaScript); }); it('should convert CommonJS require() calls with file paths', function() { var AMDcode = "var example = require('./anotherModule');", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var example=anotherModule;"; expect(cleanedCode).toBe(standardJavaScript); }); it('should convert CommonJS require() calls with advanced file paths', function() { var AMDcode = "var example = require('./../anotherModule');", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var example=anotherModule;"; expect(cleanedCode).toBe(standardJavaScript); }); it('should convert CommonJS require() calls with single properties', function() { var AMDcode = "var example = require('./anotherModule').prop;", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var example=anotherModule.prop;"; expect(cleanedCode).toBe(standardJavaScript); }); it('should convert CommonJS require() calls with method calls', function() { var AMDcode = "var example = require('./anotherModule').prop();", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var example=anotherModule.prop();"; expect(cleanedCode).toBe(standardJavaScript); }); it('should support the simplified CJS wrapper', function() { var AMDcode = "define('foo', ['require', 'exports', './bar'], function(require, exports, bar){exports.bar = require('./bar');});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var foo={};foo=function (exports,bar){exports.bar=bar;return exports;}(foo,bar);"; expect(cleanedCode).toBe(standardJavaScript); }); it('should support the plain simplified CJS wrapper', function() { var AMDcode = "define('foo',['require','exports','module','bar'],function(require, exports){exports.bar = require('bar');});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var foo={};foo=function (exports){exports.bar=bar;return exports;}(foo);"; expect(cleanedCode).toBe(standardJavaScript); }); it('should support the plain simplified CJS wrapper and not bomb when a variable is not initialized', function() { var AMDcode = "define('has',['require','exports','module'],function( require, exports, module ){exports.all = function( subject, properties ){if(subject === undefined || typeof subject != 'object'){return false;}var i = 0,len = properties.length,prop; //<--- error thrown because this isn't initialized\nfor(; i < len; i++){prop = properties[i];if(!(prop in subject)){return false;}}return true;};});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var has={};has=function (exports){exports.all=function(subject,properties){if(subject===undefined||typeof subject!='object'){return false;}var i=0,len=properties.length,prop;//<--- error thrown because this isn't initialized\nfor(;i<len;i++){prop=properties[i];if(!(prop in subject)){return false;}}return true;};return exports;}(has);"; expect(cleanedCode).toBe(standardJavaScript); }); it('should support relative dependency paths for require expressions', function() { var AMDcode = "define('app/utils/test', [], function(){return function(){console.log('hello world!');}});define('app/utils/test2',[], function(){exports.test = require('./test');});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var app_utils_test,app_utils_test2;app_utils_test=function(){console.log('hello world!');};app_utils_test2=function (){exports.test=app_utils_test;}();"; expect(cleanedCode).toBe(standardJavaScript); }); it('should convert CommonJS require() calls and use the character prefix', function() { var AMDcode = "var example = require('bb_customs');", options = _.merge(_.cloneDeep(defaultOptions), { 'prefixMode': 'camelCase' }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var example=bbCustoms;"; expect(cleanedCode).toBe(standardJavaScript); }); it('should convert CommonJS require() calls and use the character prefix', function() { var AMDcode = "var example = require('util/anotherModule');", options = _.merge(_.cloneDeep(defaultOptions), { 'prefixMode': 'camelCase' }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var example=utilAnotherModule;"; expect(cleanedCode).toBe(standardJavaScript); }); it('should support the Require.js optimizer cjsTranslate option that converts CommonJS modules to AMD modules', function(done) { var cleanedCode, standardJavaScript = "var commonjs3={},commonjs2={},commonjs4={},commonjs1={};commonjs3=function (exports){exports.exampleFunc=function(){var test=true;return test;};return exports;}(commonjs3);commonjs2=function (exports){exports={'exampleBool':true,'exampleFunc':commonjs3.exampleFunc};return exports;}(commonjs2);commonjs4=function (exports){exports.test='this is a test';return exports;}(commonjs4);commonjs1=function (exports,__commonjs2__,_commonjs4_){var commonjs2=__commonjs2__;var _commonjs2_='blah';var commonjs4=_commonjs4_;commonjs2.exampleFunc();return exports;}(commonjs1,commonjs2,commonjs4);"; requirejs.optimize({ 'baseUrl': './test/', 'include': ['commonjs1'], 'out': './test/commonjsoutput.js', 'cjsTranslate': true, 'optimize': 'none', 'onModuleBundleComplete': function(data) { var outputFile = data.path, options = _.merge(_.cloneDeep(defaultOptions), { 'filePath': outputFile }), cleanedCode = amdclean.clean(options); fs.writeFileSync(outputFile, cleanedCode); expect(cleanedCode).toBe(standardJavaScript); done(); } }); }); }); }); describe('require() method conversions', function() { describe('functions', function() { it('should convert function return values to locally scoped IIFEs', function() { var AMDcode = "require([], function() { var example = true; });", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "(function(){var example=true;}());"; expect(cleanedCode).toBe(standardJavaScript); }); it('should preserve single line comments when converting require methods', function() { var AMDcode = "require([], function() { // test comment\n var example = true; });", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "(function(){// test comment\nvar example=true;}());"; expect(cleanedCode).toBe(standardJavaScript); }); it('should pass the correct parameters to the locally scoped IIFEs', function() { var AMDcode = "require(['anotherModule'], function(anotherModule) { var example = true; });", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "(function(anotherModule){var example=true;}(anotherModule));"; expect(cleanedCode).toBe(standardJavaScript); }); it('should correctly normalize relative file paths', function() { var AMDcode = "require(['./modules/anotherModule'], function(anotherModule) { var example = true; });", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "(function(anotherModule){var example=true;}(modules_anotherModule));"; expect(cleanedCode).toBe(standardJavaScript); }); it('should not convert requires with an /*amdclean*/ comment before it', function() { var AMDcode = "/*amdclean*/require(['./modules/anotherModule'], function(anotherModule) { var example = true; });", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "/*amdclean*/\nrequire(['./modules/anotherModule'],function(anotherModule){var example=true;});"; expect(cleanedCode).toBe(standardJavaScript); }); it('should remove require() calls with no callback functions', function() { var AMDcode = "require(['anotherModule']);", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = ""; expect(cleanedCode).toBe(standardJavaScript); }); it('should remove require() calls with an empty callback function', function() { var AMDcode = "require(['testModule'], function() {});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = ""; expect(cleanedCode).toBe(standardJavaScript); }); it('should not remove require() calls with a non-empty callback function', function() { var AMDcode = "require(['testModule'], function() {var test=true;});", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "(function(){var test=true;}());"; expect(cleanedCode).toBe(standardJavaScript); }); it('should remove all require() calls when the removeAllRequires option is set to true', function() { var AMDcode = "require(['testModule'], function() {var test=true;});", options = _.merge(_.cloneDeep(defaultOptions), { 'removeAllRequires': true }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = ""; expect(cleanedCode).toBe(standardJavaScript); }); it('should not bomb on extra parameters being passed to the require() method', function() { var AMDcode = "require(['blah'], function(blahParam) { var two = 1 + 1; }, undefined, true);", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "(function(blahParam){var two=1+1;}(blah));"; expect(cleanedCode).toBe(standardJavaScript); }); it('should correctly convert libraries with simple conditional AMD checks', function() { var AMDcode = "(function (root, factory) {" + "'use strict';" + "if (typeof define === 'function') {" + "define('esprima', ['exports'], factory);" + "} else if (typeof exports !== 'undefined') {" + "factory(exports);" + "} else {" + "factory((root.esprima = {}));" + "}" + "}(this, function (exports) {" + "var test = true;" + "}));", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var esprima;(function(root,factory){'use strict';if(true){esprima=function (exports){return typeof factory==='function'?factory(exports):factory;}({});}else if(typeof exports!=='undefined'){factory(exports);}else{factory(root.esprima={});}}(this,function(exports){exports=exports||{};var test=true;return exports;}));"; expect(cleanedCode).toBe(standardJavaScript); }); it('should correctly convert libraries that use factory function parameters', function() { var AMDcode = "(function (factory) {" + "if (typeof exports === 'object') {" + "module.exports = factory(require('backbone'), require('underscore'));" + "} else if (typeof define === 'function' && define.amd) {" + "define('backbonevalidation', ['backbone', 'underscore'], factory);" + "}" + "}(function (Backbone, _) {" + "//= backbone-validation.js\n" + "return Backbone.Validation;" + "}));", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var backbonevalidation;(function(factory){if(typeof exports==='object'){module.exports=factory(backbone,underscore);}else if(true){backbonevalidation=function (backbone,underscore){return typeof factory==='function'?factory(backbone,underscore):factory;}(backbone,underscore);}}(function(Backbone,_){//= backbone-validation.js\nreturn Backbone.Validation;}));"; expect(cleanedCode).toBe(standardJavaScript); }); it('should correctly convert libraries that return define methods', function() { var AMDcode = "(function(window, factory) {" + "if (typeof define === 'function' && define.amd) {" + "return define('backbonelayoutmanager', ['backbone', 'underscore', 'jquery'], function() {" + "return factory.apply(window, arguments);" + "});" + "}" + "}());", cleanedCode = amdclean.clean(AMDcode, defaultOptions); standardJavaScript = "(function(window,factory){if(true){backbonelayoutmanager=function (backbone,underscore,jquery){return factory.apply(window,arguments);}(backbone,underscore,jquery);}}());"; expect(cleanedCode).toBe(standardJavaScript); }); it('should correctly convert libraries that do define.amd checks in their AMD conditional', function() { var AMDcode = " if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {" + "root._ = _;" + "define(function() {" + "return _;" + "});" + "}", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "if(true){root._=_;define(function(){return _;});}"; expect(cleanedCode).toBe(standardJavaScript); }); it('should correctly convert libraries that include an exports parameter', function() { var AMDcode = "(function(window, factory) {" + "if (typeof define === 'function' && define.amd) {" + "define('backbonerelational', ['exports', 'backbone', 'underscore'], factory)" + "}" + "}());", cleanedCode = amdclean.clean(AMDcode, defaultOptions); standardJavaScript = "var backbonerelational;(function(window,factory){if(true){backbonerelational=function (exports,backbone,underscore){return typeof factory==='function'?factory(exports,backbone,underscore):factory;}({},backbone,underscore);}}());"; expect(cleanedCode).toBe(standardJavaScript); }); it('should correctly convert libraries that include require, exports, and module parameters', function() { var AMDcode = "(function(window, factory) {" + "var moment;" + "if (typeof define === 'function' && define.amd) {" + "return define('moment', ['require', 'exports', 'module'], function(require, exports, module) {" + "return moment" + "});" + "}" + "}());", cleanedCode = amdclean.clean(AMDcode, defaultOptions); standardJavaScript = "(function(window,factory){var moment;if(true){moment=function (require,exports,module){return moment;}({},{},{});}}());"; expect(cleanedCode).toBe(standardJavaScript); }); it('should correctly convert libraries with simple reversed conditional AMD checks', function() { var AMDcode = "(function (root, factory) {" + "'use strict';" + "if ('function' === typeof define) {" + "define('esprima', ['exports'], factory);" + "} else if (typeof exports !== 'undefined') {" + "factory(exports);" + "} else {" + "factory((root.esprima = {}));" + "}" + "}(this, function (exports) {" + "var test = true;" + "}));", cleanedCode = amdclean.clean(AMDcode, defaultOptions), standardJavaScript = "var esprima;(function(root,factory){'use strict';if(true){esprima=function (exports){return typeof factory==='function'?factory(exports):factory;}({});}else if(typeof exports!=='undefined'){factory(exports);}else{factory(root.esprima={});}}(this,function(exports){exports=exports||{};var test=true;return exports;}));"; expect(cleanedCode).toBe(standardJavaScript); }); }); }); describe('Require.js Compatibility', function() { it('should support the Require.js config option with the simplified CJS format', function() { var AMDcode = 'if (typeof define === "function" && define.amd) {' + 'define("moment", function (require, exports, module) {' + 'return moment;' + '});' + '}', options = _.merge(_.cloneDeep(defaultOptions), { 'config': { 'moment': { 'noGlobal': true } } }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var moment,module={'moment':{'config':function(){return{'noGlobal':true};}}};if(true){moment=function (require,exports,module){return moment;}({},{},module['moment']);}"; expect(cleanedCode).toBe(standardJavaScript); }); it('should support the Require.js config option when the special module ID, "module", is passed', function() { var AMDcode = 'if (typeof define === "function" && define.amd) {' + 'define("moment", ["module"], function (module) {' + 'return moment;' + '});' + '}', options = _.merge(_.cloneDeep(defaultOptions), { 'config': { 'moment': { 'noGlobal': true } } }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var moment,module={'moment':{'config':function(){return{'noGlobal':true};}}};if(true){moment=function (module){return moment;}(module['moment']);}"; expect(cleanedCode).toBe(standardJavaScript); }); it('should support the Require.js config option when the special module ID, "module", is passed with more than one argument', function() { var AMDcode = 'if (typeof define === "function" && define.amd) {' + 'define("moment", ["test", "module"], function (test, module) {' + 'return moment;' + '});' + '}', options = _.merge(_.cloneDeep(defaultOptions), { 'config': { 'moment': { 'noGlobal': true } } }), cleanedCode = amdclean.clean(AMDcode, options), standardJavaScript = "var moment,module={'moment':{'config':function(){return{'noGlobal':true};}}};if(true){moment=function (test,module){return moment;}(test,module['moment']);}"; expect(cleanedCode).toBe(standardJavaScript); }); }); });