12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907 |
- // Copyright 2006 The Closure Library Authors. All Rights Reserved.
- //
- // Licensed 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.
- /**
- * @fileoverview Unit tests for Closure's base.js.
- */
- goog.provide('goog.baseTest');
- goog.setTestOnly('goog.baseTest');
- goog.require('goog.Promise');
- // Used to test dynamic loading works, see testRequire*
- goog.require('goog.Timer');
- goog.require('goog.dom');
- goog.require('goog.dom.TagName');
- goog.require('goog.functions');
- goog.require('goog.object');
- goog.require('goog.test_module');
- goog.require('goog.testing.PropertyReplacer');
- goog.require('goog.testing.jsunit');
- goog.require('goog.testing.recordFunction');
- goog.require('goog.userAgent');
- var earlyTestModuleGet = goog.module.get('goog.test_module');
- /**
- * @param {?} name
- * @return {?}
- */
- function getFramedVars(name) {
- var w = window.frames[name];
- var doc = w.document;
- doc.open();
- doc.write(
- '<script>' +
- 'var a = [0, 1, 2];' +
- 'var o = {a: 0, b: 1};' +
- 'var n = 42;' +
- 'var b = true;' +
- 'var s = "string";' +
- 'var nv = null;' +
- 'var u = undefined;' +
- 'var fv = function(){};' +
- '</' +
- 'script>');
- doc.close();
- return {
- 'array': w.a,
- 'object': w.o,
- 'number': w.n,
- 'boolean': w.b,
- 'string': w.s,
- 'functionVar': w.fv,
- 'nullVar': w.nv,
- 'undefinedVar': w.u
- };
- }
- var framedVars = getFramedVars('f1');
- var framedVars2 = getFramedVars('f2');
- // remove iframe
- var iframeElement = document.getElementById('f2');
- iframeElement.parentNode.removeChild(iframeElement);
- var stubs = new goog.testing.PropertyReplacer();
- var originalGoogBind = goog.bind;
- function tearDown() {
- goog.setCssNameMapping(undefined);
- stubs.reset();
- goog.bind = originalGoogBind;
- }
- function testLibrary() {
- assertNotUndefined('\'goog\' not loaded', goog);
- }
- function testDefine() {
- goog.define('SOME_DEFINE', 123); // overridden by 456
- assertEquals(SOME_DEFINE, 456);
- goog.define('SOME_OTHER_DEFINE', 123); // not overridden
- assertEquals(SOME_OTHER_DEFINE, 123);
- // alias to avoid the being picked up by the deps scanner.
- var provide = goog.provide;
- provide('ns');
- goog.define('ns.SOME_DEFINE', 123); // overridden by 456
- assertEquals(SOME_DEFINE, 456);
- goog.define('ns.SOME_OTHER_DEFINE', 123); // not overridden
- assertEquals(SOME_OTHER_DEFINE, 123);
- }
- function testProvide() {
- // alias to avoid the being picked up by the deps scanner.
- var provide = goog.provide;
- provide('goog.test.name.space');
- assertNotUndefined('provide failed: goog.test', goog.test);
- assertNotUndefined('provide failed: goog.test.name', goog.test.name);
- assertNotUndefined(
- 'provide failed: goog.test.name.space', goog.test.name.space);
- // ensure that providing 'goog.test.name' doesn't throw an exception
- provide('goog.test');
- provide('goog.test.name');
- delete goog.test;
- }
- // "watch" is a native member of Object.prototype on Firefox
- // Ensure it can still be added as a namespace
- function testProvideWatch() {
- // alias to avoid the being picked up by the deps scanner.
- var provide = goog.provide;
- provide('goog.yoddle.watch');
- assertNotUndefined('provide failed: goog.yoddle.watch', goog.yoddle.watch);
- delete goog.yoddle;
- }
- // Namespaces should not conflict with elements added to the window based on
- // their id
- function testConflictingSymbolAndId() {
- // Create a div with a given id
- var divElement = document.createElement('div');
- divElement.id = 'clashingname';
- document.body.appendChild(divElement);
- // The object at window.clashingname is the element with that id
- assertEquals(window.clashingname, divElement);
- // Export a symbol to a sub-namespace of that id
- var symbolObject = {};
- goog.exportSymbol('clashingname.symbolname', symbolObject);
- // The symbol has been added...
- assertEquals(window.clashingname.symbolname, symbolObject);
- // ...and has not affected the original div
- assertEquals(window.clashingname, divElement);
- }
- function testProvideStrictness() {
- // alias to avoid the being picked up by the deps scanner.
- var provide = goog.provide;
- provide('goog.xy');
- assertProvideFails('goog.xy');
- provide('goog.xy.z');
- assertProvideFails('goog.xy');
- window['goog']['xyz'] = 'Bob';
- assertProvideFails('goog.xyz');
- delete goog.xy;
- delete goog.xyz;
- }
- /** @param {?} namespace */
- function assertProvideFails(namespace) {
- assertThrows(
- 'goog.provide(' + namespace + ') should have failed',
- goog.partial(goog.provide, namespace));
- }
- function testIsProvided() {
- // alias to avoid the being picked up by the deps scanner.
- var provide = goog.provide;
- provide('goog.explicit');
- assertTrue(goog.isProvided_('goog.explicit'));
- provide('goog.implicit.explicit');
- assertFalse(goog.isProvided_('goog.implicit'));
- assertTrue(goog.isProvided_('goog.implicit.explicit'));
- }
- function testGlobalize() {
- var a = {a: 1, b: 2, c: 3};
- var b = {};
- goog.globalize(a, b);
- assertNotUndefined('Globalize to arbitrary object', b.a);
- assertNotUndefined('Globalize to arbitrary object', b.b);
- assertNotUndefined('Globalize to arbitrary object', b.c);
- }
- function testExportSymbol() {
- var date = new Date();
- // alias to avoid the being picked up by the deps scanner.
- var provide = goog.provide;
- assertTrue(typeof nodots == 'undefined');
- goog.exportSymbol('nodots', date);
- assertEquals(date, nodots);
- nodots = undefined;
- assertTrue(typeof gotcher == 'undefined');
- goog.exportSymbol('gotcher.dots.right.Here', date);
- assertEquals(date, gotcher.dots.right.Here);
- gotcher = undefined;
- provide('an.existing.path');
- assertNotNull(an.existing.path);
- goog.exportSymbol('an.existing.path', date);
- assertEquals(date, an.existing.path);
- an = undefined;
- var foo = {foo: 'foo'};
- var bar = {bar: 'bar'};
- var baz = {baz: 'baz'};
- goog.exportSymbol('one.two.three.Four', foo);
- goog.exportSymbol('one.two.three.five', bar);
- goog.exportSymbol('one.two.six', baz);
- assertEquals(foo, one.two.three.Four);
- assertEquals(bar, one.two.three.five);
- assertEquals(baz, one.two.six);
- var win = {};
- var fooBar = {foo: 'foo', bar: 'bar'};
- goog.exportSymbol('one.two.four', fooBar, win);
- assertEquals(fooBar, win.one.two.four);
- assertTrue('four' in win.one.two);
- assertFalse('four' in one.two);
- one = undefined;
- }
- goog.exportSymbol('exceptionTest', function() {
- throw Error('ERROR');
- });
- function testExportSymbolExceptions() {
- var inner = function() {
- // If exceptionTest wasn't exported using execScript, IE8 will throw "Object
- // doesn't support this property or method" instead.
- exceptionTest();
- };
- var e = assertThrows('Exception wasn\'t thrown by exported function', inner);
- assertEquals('Unexpected error thrown', 'ERROR', e.message);
- }
- //=== tests for Require logic ===
- function testRequireClosure() {
- assertNotUndefined('goog.Timer should be available', goog.Timer);
- /** @suppress {missingRequire} */
- assertNotUndefined(
- 'goog.events.EventTarget should be available', goog.events.EventTarget);
- }
- function testRequireWithExternalDuplicate() {
- // alias to avoid the being picked up by the deps scanner.
- var provide = goog.provide;
- // Do a provide without going via goog.require. Then goog.require it
- // indirectly and ensure it doesn't cause a duplicate script.
- goog.addDependency('dup.js', ['dup.base'], []);
- goog.addDependency('dup-child.js', ['dup.base.child'], ['dup.base']);
- provide('dup.base');
- stubs.set(goog, 'isDocumentFinishedLoading_', false);
- stubs.set(goog.global, 'CLOSURE_IMPORT_SCRIPT', function(src) {
- if (src == goog.basePath + 'dup.js') {
- fail('Duplicate script written!');
- } else if (src == goog.basePath + 'dup-child.js') {
- // Allow expected script.
- return true;
- } else {
- // Avoid affecting other state.
- return false;
- }
- });
- // To differentiate this call from the real one.
- var require = goog.require;
- require('dup.base.child');
- }
- //=== tests for language enhancements ===
- function testTypeOf() {
- assertEquals('array', goog.typeOf([]));
- assertEquals('string', goog.typeOf('string'));
- assertEquals('number', goog.typeOf(123));
- assertEquals('null', goog.typeOf(null));
- assertEquals('undefined', goog.typeOf(undefined));
- assertEquals('object', goog.typeOf({}));
- assertEquals('function', goog.typeOf(function() {}));
- // Make sure that NodeList is not treated as an array... NodeLists should
- // be of type object but Safari incorrectly reports it as function so a not
- // equals test will have to suffice here.
- assertNotEquals('array', goog.typeOf(document.getElementsByName('*')));
- assertNotEquals('function', goog.typeOf(document.getElementsByName('*')));
- assertEquals('object', goog.typeOf(document.getElementsByName('*')));
- }
- function testTypeOfFramed() {
- assertEquals('array', goog.typeOf(framedVars.array));
- assertEquals('string', goog.typeOf(framedVars.string));
- assertEquals('number', goog.typeOf(framedVars.number));
- assertEquals('null', goog.typeOf(framedVars.nullVar));
- assertEquals('undefined', goog.typeOf(framedVars.undefinedVar));
- assertEquals('object', goog.typeOf(framedVars.object));
- assertEquals('function', goog.typeOf(framedVars.functionVar));
- // Opera throws when trying to do cross frame typeof on node lists.
- // IE behaves very strange when it comes to DOM nodes on disconnected frames.
- }
- function testTypeOfFramed2() {
- assertEquals('array', goog.typeOf(framedVars2.array));
- assertEquals('string', goog.typeOf(framedVars2.string));
- assertEquals('number', goog.typeOf(framedVars2.number));
- assertEquals('null', goog.typeOf(framedVars2.nullVar));
- assertEquals('undefined', goog.typeOf(framedVars2.undefinedVar));
- assertEquals('object', goog.typeOf(framedVars2.object));
- assertEquals('function', goog.typeOf(framedVars2.functionVar));
- // Opera throws when trying to do cross frame typeof on node lists.
- // IE behaves very strange when it comes to DOM nodes on disconnected frames.
- }
- function testIsDef() {
- var defined = 'foo';
- var nullVar = null;
- var notDefined;
- assertTrue('defined should be defined', goog.isDef(defined));
- assertTrue('null should be defined', goog.isDef(nullVar));
- assertFalse('undefined should not be defined', goog.isDef(notDefined));
- }
- function testIsDefAndNotNull() {
- assertTrue('string is defined and non-null', goog.isDefAndNotNull(''));
- assertTrue('object is defined and non-null', goog.isDefAndNotNull({}));
- assertTrue(
- 'function is defined and non-null',
- goog.isDefAndNotNull(goog.nullFunction));
- assertTrue('zero is defined and non-null', goog.isDefAndNotNull(0));
- assertFalse('null', goog.isDefAndNotNull(null));
- assertFalse('undefined', goog.isDefAndNotNull(undefined));
- }
- function testIsNull() {
- var notNull = 'foo';
- var nullVar = null;
- var notDefined;
- assertFalse('defined should not be null', goog.isNull(notNull));
- assertTrue('null should be null', goog.isNull(nullVar));
- assertFalse('undefined should not be null', goog.isNull(notDefined));
- }
- function testIsArray() {
- var array = [1, 2, 3];
- var arrayWithLengthSet = [1, 2, 3];
- arrayWithLengthSet.length = 2;
- var objWithArrayFunctions = {slice: function() {}, length: 0};
- var object = {a: 1, b: 2, c: 3};
- var nullVar = null;
- var notDefined;
- var elem = document.getElementById('elem');
- var text = document.getElementById('text').firstChild;
- var impostor = document.body.getElementsByTagName('BOGUS');
- impostor.push = Array.prototype.push;
- impostor.pop = Array.prototype.pop;
- impostor.slice = Array.prototype.slice;
- impostor.splice = Array.prototype.splice;
- assertTrue('array should be an array', goog.isArray(array));
- assertTrue(
- 'arrayWithLengthSet should be an array',
- goog.isArray(arrayWithLengthSet));
- assertFalse(
- 'object with array functions should not be an array unless ' +
- 'length is not enumerable',
- goog.isArray(objWithArrayFunctions));
- assertFalse('object should not be an array', goog.isArray(object));
- assertFalse('null should not be an array', goog.isArray(nullVar));
- assertFalse('undefined should not be an array', goog.isArray(notDefined));
- assertFalse('NodeList should not be an array', goog.isArray(elem.childNodes));
- assertFalse('TextNode should not be an array', goog.isArray(text));
- assertTrue(
- 'Array of nodes should be an array',
- goog.isArray([elem.firstChild, elem.lastChild]));
- assertFalse('An impostor should not be an array', goog.isArray(impostor));
- }
- function testTypeOfAcrossWindow() {
- if (goog.userAgent.IE && goog.userAgent.isVersionOrHigher('10') &&
- !goog.userAgent.isVersionOrHigher('11')) {
- // TODO(johnlenz): This test is flaky on IE10 (passing 90+% of the time).
- // When it flakes the values are undefined which appears to indicate the
- // script did not run in the opened window and not a failure of the logic
- // we are trying to test.
- return;
- }
- var w = window.open('', 'blank');
- if (w) {
- try {
- var d = w.document;
- d.open();
- d.write(
- '<script>function fun(){};' +
- 'var arr = [];' +
- 'var x = 42;' +
- 'var s = "";' +
- 'var b = true;' +
- 'var obj = {length: 0, splice: {}, call: {}};' +
- '</' +
- 'script>');
- d.close();
- assertEquals('function', goog.typeOf(w.fun));
- assertEquals('array', goog.typeOf(w.arr));
- assertEquals('number', goog.typeOf(w.x));
- assertEquals('string', goog.typeOf(w.s));
- assertEquals('boolean', goog.typeOf(w.b));
- assertEquals('object', goog.typeOf(w.obj));
- } finally {
- w.close();
- }
- }
- }
- function testIsArrayLike() {
- var array = [1, 2, 3];
- var objectWithNumericLength = {length: 2};
- var objectWithNonNumericLength = {length: 'a'};
- var object = {a: 1, b: 2};
- var nullVar = null;
- var notDefined;
- var elem = document.getElementById('elem');
- var text = document.getElementById('text').firstChild;
- assertTrue('array should be array-like', goog.isArrayLike(array));
- assertTrue(
- 'obj w/numeric length should be array-like',
- goog.isArrayLike(objectWithNumericLength));
- assertFalse(
- 'obj w/non-numeric length should not be array-like',
- goog.isArrayLike(objectWithNonNumericLength));
- assertFalse('object should not be array-like', goog.isArrayLike(object));
- assertFalse('null should not be array-like', goog.isArrayLike(nullVar));
- assertFalse(
- 'undefined should not be array-like', goog.isArrayLike(notDefined));
- assertTrue(
- 'NodeList should be array-like', goog.isArrayLike(elem.childNodes));
- // TODO(attila): Fix isArrayLike to return false for text nodes!
- // assertFalse('TextNode should not be array-like', goog.isArrayLike(text));
- assertTrue(
- 'Array of nodes should be array-like',
- goog.isArrayLike([elem.firstChild, elem.lastChild]));
- }
- /**
- * Use mock date in testIsDateLike() rather than a real goog.date.Date to
- * minimize dependencies in this unit test.
- */
- function MockGoogDate() {}
- /** @return {number} */
- MockGoogDate.prototype.getFullYear = function() {
- return 2007;
- };
- function testIsDateLike() {
- var jsDate = new Date();
- var googDate = new MockGoogDate();
- var string = 'foo';
- var number = 1;
- var nullVar = null;
- var notDefined;
- assertTrue('js Date should be date-like', goog.isDateLike(jsDate));
- assertTrue('goog Date should be date-like', goog.isDateLike(googDate));
- assertFalse('string should not be date-like', goog.isDateLike(string));
- assertFalse('number should not be date-like', goog.isDateLike(number));
- assertFalse('nullVar should not be date-like', goog.isDateLike(nullVar));
- assertFalse('undefined should not be date-like', goog.isDateLike(notDefined));
- }
- function testIsString() {
- var string = 'foo';
- var number = 2;
- var nullVar = null;
- var notDefined;
- assertTrue('string should be a string', goog.isString(string));
- assertFalse('number should not be a string', goog.isString(number));
- assertFalse('null should not be a string', goog.isString(nullVar));
- assertFalse('undefined should not be a string', goog.isString(notDefined));
- }
- function testIsBoolean() {
- var b = true;
- var s = 'true';
- var num = 1;
- var nullVar = null;
- var notDefined;
- assertTrue('boolean should be a boolean', goog.isBoolean(b));
- assertFalse('string should not be a boolean', goog.isBoolean(s));
- assertFalse('number should not be a boolean', goog.isBoolean(num));
- assertFalse('null should not be a boolean', goog.isBoolean(nullVar));
- assertFalse('undefined should not be a boolean', goog.isBoolean(notDefined));
- }
- function testIsNumber() {
- var number = 1;
- var string = '1';
- var nullVar = null;
- var notDefined;
- assertTrue('number should be a number', goog.isNumber(number));
- assertFalse('string should not be a number', goog.isNumber(string));
- assertFalse('null should not be a number', goog.isNumber(nullVar));
- assertFalse('undefined should not be a number', goog.isNumber(notDefined));
- }
- function testIsFunction() {
- var func = function() {
- return 1;
- };
- var object = {a: 1, b: 2};
- var nullVar = null;
- var notDefined;
- assertTrue('function should be a function', goog.isFunction(func));
- assertFalse('object should not be a function', goog.isFunction(object));
- assertFalse('null should not be a function', goog.isFunction(nullVar));
- assertFalse(
- 'undefined should not be a function', goog.isFunction(notDefined));
- }
- function testIsObject() {
- var object = {a: 1, b: 2};
- var string = 'b';
- var nullVar = null;
- var notDefined;
- var array = [0, 1, 2];
- var fun = function() {};
- assertTrue('object should be an object', goog.isObject(object));
- assertTrue('array should be an object', goog.isObject(array));
- assertTrue('function should be an object', goog.isObject(fun));
- assertFalse('string should not be an object', goog.isObject(string));
- assertFalse('null should not be an object', goog.isObject(nullVar));
- assertFalse('undefined should not be an object', goog.isObject(notDefined));
- }
- //=== tests for unique ID methods ===
- function testGetUid() {
- var a = {};
- var b = {};
- var c = {};
- var uid1 = goog.getUid(a);
- var uid2 = goog.getUid(b);
- var uid3 = goog.getUid(c);
- assertNotEquals('Unique IDs must be unique', uid1, uid2);
- assertNotEquals('Unique IDs must be unique', uid1, uid3);
- assertNotEquals('Unique IDs must be unique', uid2, uid3);
- }
- function testHasUid() {
- var a = {};
- assertFalse(goog.hasUid(a));
- assertFalse(goog.UID_PROPERTY_ in a);
- var uid = goog.getUid(a);
- assertTrue(goog.hasUid(a));
- assertEquals(uid, goog.getUid(a));
- }
- function testRemoveUidFromPlainObject() {
- var a = {};
- var uid = goog.getUid(a);
- goog.removeUid(a);
- assertNotEquals(
- 'An object\'s old and new unique IDs should be different', uid,
- goog.getUid(a));
- }
- function testRemoveUidFromObjectWithoutUid() {
- var a = {};
- // Removing a unique ID should not fail even if it did not exist
- goog.removeUid(a);
- }
- function testRemoveUidFromNode() {
- var node = goog.dom.createElement(goog.dom.TagName.DIV);
- var nodeUid = goog.getUid(node);
- goog.removeUid(node);
- assertNotEquals(
- 'A node\'s old and new unique IDs should be different', nodeUid,
- goog.getUid(node));
- }
- function testConstructorUid() {
- function BaseClass() {}
- function SubClass() {}
- goog.inherits(SubClass, BaseClass);
- var baseClassUid = goog.getUid(BaseClass);
- var subClassUid = goog.getUid(SubClass);
- assertTrue(
- 'Unique ID of BaseClass must be a number',
- typeof baseClassUid == 'number');
- assertTrue(
- 'Unique ID of SubClass must be a number', typeof subClassUid == 'number');
- assertNotEquals(
- 'Unique IDs of BaseClass and SubClass must differ', baseClassUid,
- subClassUid);
- assertNotEquals(
- 'Unique IDs of BaseClass and SubClass instances must differ',
- goog.getUid(new BaseClass), goog.getUid(new SubClass));
- assertEquals(
- 'Unique IDs of BaseClass.prototype and SubClass.prototype ' +
- 'should differ, but to keep the implementation simple, we do not ' +
- 'handle this edge case.',
- goog.getUid(BaseClass.prototype), goog.getUid(SubClass.prototype));
- }
- /**
- * Tests against Chrome bug where the re-created element will have the uid
- * property set but undefined. See bug 1252508.
- */
- function testUidNotUndefinedOnReusedElement() {
- var div = goog.dom.createElement(goog.dom.TagName.DIV);
- document.body.appendChild(div);
- div.innerHTML = '<form id="form"></form>';
- var span = goog.dom.getElementsByTagName(goog.dom.TagName.FORM, div)[0];
- goog.getUid(span);
- div.innerHTML = '<form id="form"></form>';
- var span2 = goog.dom.getElementsByTagName(goog.dom.TagName.FORM, div)[0];
- assertNotUndefined(goog.getUid(span2));
- }
- function testWindowUid() {
- var uid = goog.getUid(window);
- assertTrue('window unique id is a number', goog.isNumber(uid));
- assertEquals('returns the same id second time', uid, goog.getUid(window));
- goog.removeUid(window);
- assertNotEquals(
- 'generates new id after the old one is removed', goog.getUid(window));
- }
- //=== tests for clone method ===
- function testClonePrimitive() {
- assertEquals(
- 'cloning a primitive should return an equal primitive', 5,
- goog.cloneObject(5));
- }
- function testCloneObjectThatHasACloneMethod() {
- var original = {
- name: 'original',
- clone: function() {
- return {name: 'clone'};
- }
- };
- var clone = goog.cloneObject(original);
- assertEquals('original', original.name);
- assertEquals('clone', clone.name);
- }
- function testCloneFlatObject() {
- var original = {a: 1, b: 2, c: 3};
- var clone = goog.cloneObject(original);
- assertNotEquals(original, clone);
- assertEquals(1, clone.a);
- assertEquals(2, clone.b);
- assertEquals(3, clone.c);
- }
- function testCloneDeepObject() {
- var original = {a: 1, b: {c: 2, d: 3}, e: {f: {g: 4, h: 5}}};
- var clone = goog.cloneObject(original);
- assertNotEquals(original, clone);
- assertNotEquals(original.b, clone.b);
- assertNotEquals(original.e, clone.e);
- assertEquals(1, clone.a);
- assertEquals(2, clone.b.c);
- assertEquals(3, clone.b.d);
- assertEquals(4, clone.e.f.g);
- assertEquals(5, clone.e.f.h);
- }
- function testCloneFunctions() {
- var original = {
- f: function() {
- return 'hi';
- }
- };
- var clone = goog.cloneObject(original);
- assertNotEquals(original, clone);
- assertEquals('hi', clone.f());
- assertEquals(original.f, clone.f);
- }
- //=== tests for bind() and friends ===
- // Function.prototype.bind and Function.prototype.partial are purposefullly
- // not defined in open sourced Closure. These functions sniff for their
- // presence.
- var foo = 'global';
- var obj = {foo: 'obj'};
- /**
- * @param {?} arg1
- * @param {?} arg2
- * @return {?}
- */
- function getFoo(arg1, arg2) {
- return {foo: this.foo, arg1: arg1, arg2: arg2};
- }
- function testBindWithoutObj() {
- if (Function.prototype.bind) {
- assertEquals(foo, getFoo.bind()().foo);
- }
- }
- function testBindWithObj() {
- if (Function.prototype.bind) {
- assertEquals(obj.foo, getFoo.bind(obj)().foo);
- }
- }
- function testBindWithNullObj() {
- if (Function.prototype.bind) {
- assertEquals(foo, getFoo.bind()().foo);
- }
- }
- function testBindStaticArgs() {
- if (Function.prototype.bind) {
- var fooprime = getFoo.bind(obj, 'hot', 'dog');
- var res = fooprime();
- assertEquals(obj.foo, res.foo);
- assertEquals('hot', res.arg1);
- assertEquals('dog', res.arg2);
- }
- }
- function testBindDynArgs() {
- if (Function.prototype.bind) {
- var res = getFoo.bind(obj)('hot', 'dog');
- assertEquals(obj.foo, res.foo);
- assertEquals('hot', res.arg1);
- assertEquals('dog', res.arg2);
- }
- }
- function testBindCurriedArgs() {
- if (Function.prototype.bind) {
- var res = getFoo.bind(obj, 'hot')('dog');
- assertEquals(obj.foo, res.foo);
- assertEquals('hot', res.arg1);
- assertEquals('dog', res.arg2);
- }
- }
- function testBindDoubleBind() {
- var getFooP = goog.bind(getFoo, obj, 'hot');
- var getFooP2 = goog.bind(getFooP, null, 'dog');
- var res = getFooP2();
- assertEquals('res.arg1 should be \'hot\'', 'hot', res.arg1);
- assertEquals('res.arg2 should be \'dog\'', 'dog', res.arg2);
- }
- function testBindWithCall() {
- var obj = {};
- var obj2 = {};
- var f = function() {
- assertEquals('this should be bound to obj', obj, this);
- };
- var b = goog.bind(f, obj);
- b.call(null);
- b.call(obj2);
- }
- function testBindJs() {
- assertEquals(1, goog.bindJs_(add, {
- valueOf: function() {
- return 1;
- }
- })());
- assertEquals(3, goog.bindJs_(add, null, 1, 2)());
- }
- function testBindNative() {
- if (Function.prototype.bind &&
- Function.prototype.bind.toString().indexOf('native code') != -1) {
- assertEquals(1, goog.bindNative_(add, {
- valueOf: function() {
- return 1;
- }
- })());
- assertEquals(3, goog.bindNative_(add, null, 1, 2)());
- assertThrows(function() {
- goog.bindNative_(null, null);
- });
- }
- }
- function testBindDefault() {
- assertEquals(1, goog.bind(add, {
- valueOf: function() {
- return 1;
- }
- })());
- assertEquals(3, goog.bind(add, null, 1, 2)());
- }
- /**
- * @param {...?} var_args
- * @return {?}
- */
- function add(var_args) {
- var sum = Number(this) || 0;
- for (var i = 0; i < arguments.length; i++) {
- sum += arguments[i];
- }
- return sum;
- }
- function testPartial() {
- var f = function(x, y) {
- return x + y;
- };
- var g = goog.partial(f, 1);
- assertEquals(3, g(2));
- var h = goog.partial(f, 1, 2);
- assertEquals(3, h());
- var i = goog.partial(f);
- assertEquals(3, i(1, 2));
- }
- function testPartialUsesGlobal() {
- var f = function(x, y) {
- assertEquals(goog.global, this);
- return x + y;
- };
- var g = goog.partial(f, 1);
- var h = goog.partial(g, 2);
- assertEquals(3, h());
- }
- function testPartialWithCall() {
- var obj = {};
- var f = function(x, y) {
- assertEquals(obj, this);
- return x + y;
- };
- var g = goog.partial(f, 1);
- var h = goog.partial(g, 2);
- assertEquals(3, h.call(obj));
- }
- function testPartialAndBind() {
- // This ensures that this "survives" through a partial.
- var p = goog.partial(getFoo, 'hot');
- var b = goog.bind(p, obj, 'dog');
- var res = b();
- assertEquals(obj.foo, res.foo);
- assertEquals('hot', res.arg1);
- assertEquals('dog', res.arg2);
- }
- function testBindAndPartial() {
- // This ensures that this "survives" through a partial.
- var b = goog.bind(getFoo, obj, 'hot');
- var p = goog.partial(b, 'dog');
- var res = p();
- assertEquals(obj.foo, res.foo);
- assertEquals('hot', res.arg1);
- assertEquals('dog', res.arg2);
- }
- function testPartialMultipleCalls() {
- var f = goog.testing.recordFunction();
- var a = goog.partial(f, 'foo');
- var b = goog.partial(a, 'bar');
- a();
- a();
- b();
- b();
- assertEquals(4, f.getCallCount());
- var calls = f.getCalls();
- assertArrayEquals(['foo'], calls[0].getArguments());
- assertArrayEquals(['foo'], calls[1].getArguments());
- assertArrayEquals(['foo', 'bar'], calls[2].getArguments());
- assertArrayEquals(['foo', 'bar'], calls[3].getArguments());
- }
- function testGlobalEval() {
- goog.globalEval('var foofoofoo = 125;');
- assertEquals('Var should be globally assigned', 125, goog.global.foofoofoo);
- var foofoofoo = 128;
- assertEquals('Global should not have changed', 125, goog.global.foofoofoo);
- // NOTE(user): foofoofoo would normally be available in the function scope,
- // via the scope chain, but the JsUnit framework seems to do something weird
- // which makes it not work.
- }
- function testGlobalEvalWithHtml() {
- // Make sure we don't trip on HTML markup in the code
- goog.global.evalTestResult = 'failed';
- goog.global.evalTest = function(arg) {
- goog.global.evalTestResult = arg;
- };
- goog.globalEval('evalTest("<test>")');
- assertEquals(
- 'Should be able to evaluate strings with HTML in', '<test>',
- goog.global.evalTestResult);
- }
- //=== tests for inherits ===
- function testInherits() {
- function Foo() {}
- function Bar() {}
- goog.inherits(Bar, Foo);
- var bar = new Bar();
- assert('object should be instance of constructor', bar instanceof Bar);
- assert('object should be instance of base constructor', bar instanceof Foo);
- }
- function testInherits_constructor() {
- function Foo() {}
- function Bar() {}
- goog.inherits(Bar, Foo);
- var bar = new Bar();
- assertEquals(
- 'constructor property should match constructor function', Bar,
- bar.constructor);
- assertEquals(
- 'Superclass constructor should match constructor function', Foo,
- Bar.superClass_.constructor);
- }
- //=== tests for makeSingleton ===
- function testMakeSingleton() {
- function Foo() {}
- goog.addSingletonGetter(Foo);
- assertNotNull('Should add get instance function', Foo.getInstance);
- var x = Foo.getInstance();
- assertNotNull('Should successfully create an object', x);
- var y = Foo.getInstance();
- assertEquals('Should return the same object', x, y);
- delete Foo.instance_;
- var z = Foo.getInstance();
- assertNotNull('Should work after clearing for testing', z);
- assertNotEquals(
- 'Should return a different object after clearing for testing', x, z);
- }
- //=== tests for now ===
- function testNow() {
- var toleranceMilliseconds = 20; // 10 ms was not enough for IE7.
- var now1 = new Date().getTime();
- var now2 = goog.now();
- assertTrue(Math.abs(now1 - now2) < toleranceMilliseconds);
- }
- //=== test non-html context ===
- function testInHtmlDocument() {
- var savedGoogGlobal = goog.global;
- try {
- goog.global = {};
- assertFalse(goog.inHtmlDocument_());
- goog.global.document = {};
- assertFalse(goog.inHtmlDocument_());
- goog.global.document.write = function() {};
- assertTrue(goog.inHtmlDocument_());
- } finally {
- // Restore context to respect other tests.
- goog.global = savedGoogGlobal;
- }
- }
- function testLoadInNonHtmlNotThrows() {
- var savedGoogGlobal = goog.global;
- try {
- goog.global = {};
- goog.global.document = {};
- assertFalse(goog.inHtmlDocument_());
- // The goog code which is executed at load.
- goog.findBasePath_();
- goog.writeScriptTag_(goog.basePath + 'deps.js');
- } finally {
- // Restore context to respect other tests.
- goog.global = savedGoogGlobal;
- }
- }
- function testLoadBaseWithQueryParamOk() {
- var savedGoogGlobal = goog.global;
- try {
- goog.global = {};
- goog.global.document = {
- write: goog.nullFunction,
- getElementsByTagName:
- goog.functions.constant([{src: '/path/to/base.js?zx=5'}])
- };
- assertTrue(goog.inHtmlDocument_());
- goog.findBasePath_();
- assertEquals('/path/to/', goog.basePath);
- } finally {
- // Restore context to respect other tests.
- goog.global = savedGoogGlobal;
- }
- }
- function testLoadBaseFromGlobalVariableOk() {
- var savedGoogGlobal = goog.global;
- try {
- goog.global = {};
- goog.global.document = {
- write: goog.nullFunction,
- getElementsByTagName:
- goog.functions.constant([{src: '/path/to/base.js?zx=5'}])
- };
- goog.global.CLOSURE_BASE_PATH = '/from/constant/';
- goog.findBasePath_();
- assertEquals(goog.global.CLOSURE_BASE_PATH, goog.basePath);
- } finally {
- // Restore context to respect other tests.
- goog.global = savedGoogGlobal;
- }
- }
- function testLoadBaseFromGlobalVariableDOMClobbered() {
- var savedGoogGlobal = goog.global;
- try {
- goog.global = {};
- goog.global.document = {
- write: goog.nullFunction,
- getElementsByTagName:
- goog.functions.constant([{src: '/path/to/base.js?zx=5'}])
- };
- // Make goog.global.CLOSURE_BASE_PATH an object with a toString, like
- // it would be if it were a DOM clobbered HTMLElement.
- goog.global.CLOSURE_BASE_PATH = {};
- goog.global.CLOSURE_BASE_PATH.toString = function() {
- return '/from/constant/';
- };
- goog.findBasePath_();
- assertEquals('/path/to/', goog.basePath);
- } finally {
- // Restore context to respect other tests.
- goog.global = savedGoogGlobal;
- }
- }
- function testLoadBaseFromCurrentScriptIgnoringOthers() {
- var savedGoogGlobal = goog.global;
- try {
- goog.global = {};
- goog.global.document = {
- write: goog.nullFunction,
- currentScript: {src: '/currentScript/base.js?zx=5'},
- getElementsByTagName:
- goog.functions.constant([{src: '/path/to/base.js?zx=5'}])
- };
- goog.findBasePath_();
- assertEquals('/currentScript/', goog.basePath);
- } finally {
- // Restore context to respect other tests.
- goog.global = savedGoogGlobal;
- }
- }
- //=== tests for getmsg ===
- function testGetMsgWithDollarSigns() {
- var msg = goog.getMsg('{$amount} per minute', {amount: '$0.15'});
- assertEquals('$0.15 per minute', msg);
- msg = goog.getMsg('{$amount} per minute', {amount: '$0.$1$5'});
- assertEquals('$0.$1$5 per minute', msg);
- msg = goog.getMsg('This is a {$rate} sale!', {rate: '$$$$$$$$$$10'});
- assertEquals('This is a $$$$$$$$$$10 sale!', msg);
- msg = goog.getMsg(
- '{$name}! Hamburgers: {$hCost}, Hotdogs: {$dCost}.',
- {name: 'Burger Bob', hCost: '$0.50', dCost: '$100'});
- assertEquals('Burger Bob! Hamburgers: $0.50, Hotdogs: $100.', msg);
- }
- function testGetMsgWithPlaceholders() {
- var msg = goog.getMsg('{$a} has {$b}', {a: '{$b}', b: 1});
- assertEquals('{$b} has 1', msg);
- msg = goog.getMsg('{$a}{$b}', {b: ''});
- assertEquals('{$a}', msg);
- }
- //=== miscellaneous tests ===
- function testGetObjectByName() {
- var m = {
- 'undefined': undefined,
- 'null': null,
- emptyString: '',
- 'false': false,
- 'true': true,
- zero: 0,
- one: 1,
- two: {three: 3, four: {five: 5}},
- 'six|seven': '6|7',
- 'eight.nine': 8.9
- };
- goog.global.m = m;
- assertNull(goog.getObjectByName('m.undefined'));
- assertNull(goog.getObjectByName('m.null'));
- assertEquals(goog.getObjectByName('m.emptyString'), '');
- assertEquals(goog.getObjectByName('m.false'), false);
- assertEquals(goog.getObjectByName('m.true'), true);
- assertEquals(goog.getObjectByName('m.zero'), 0);
- assertEquals(goog.getObjectByName('m.one'), 1);
- assertEquals(goog.getObjectByName('m.two.three'), 3);
- assertEquals(goog.getObjectByName('m.two.four.five'), 5);
- assertEquals(goog.getObjectByName('m.six|seven'), '6|7');
- assertNull(goog.getObjectByName('m.eight.nine'));
- assertNull(goog.getObjectByName('m.notThere'));
- assertEquals(goog.getObjectByName('one', m), 1);
- assertEquals(goog.getObjectByName('two.three', m), 3);
- assertEquals(goog.getObjectByName('two.four.five', m), 5);
- assertEquals(goog.getObjectByName('six|seven', m), '6|7');
- assertNull(goog.getObjectByName('eight.nine', m));
- assertNull(goog.getObjectByName('notThere', m));
- }
- function testGetCssName() {
- assertEquals('classname', goog.getCssName('classname'));
- assertEquals('random-classname', goog.getCssName('random-classname'));
- assertEquals('control-modifier', goog.getCssName('control', 'modifier'));
- goog.setCssNameMapping({'goog': 'a', 'disabled': 'b'}, 'BY_PART');
- var g = goog.getCssName('goog');
- assertEquals('a', g);
- assertEquals('a-b', goog.getCssName(g, 'disabled'));
- assertEquals('a-b', goog.getCssName('goog-disabled'));
- assertEquals('a-button', goog.getCssName('goog-button'));
- goog.setCssNameMapping({'goog-button': 'a', 'active': 'b'}, 'BY_WHOLE');
- g = goog.getCssName('goog-button');
- assertEquals('a', g);
- assertEquals('a-b', goog.getCssName(g, 'active'));
- assertEquals('goog-disabled', goog.getCssName('goog-disabled'));
- e = assertThrows(function() {
- goog.getCssName('.name');
- });
- assertEquals(
- 'className passed in goog.getCssName must not start with ".".' +
- ' You passed: .name',
- e.message);
- assertNull(goog.getCssName(null));
- }
- function testGetCssName_nameMapFn() {
- assertEquals('classname', goog.getCssName('classname'));
- goog.global.CLOSURE_CSS_NAME_MAP_FN = function(classname) {
- return classname + '!';
- };
- assertEquals('classname!', goog.getCssName('classname'));
- }
- function testAddDependency() {
- stubs.set(goog, 'writeScriptTag_', goog.nullFunction);
- goog.addDependency('foo.js', ['testDep.foo'], ['testDep.bar']);
- // alias to avoid the being picked up by the deps scanner.
- var provide = goog.provide;
- provide('testDep.bar');
- // To differentiate this call from the real one.
- var require = goog.require;
- // this used to throw an exception
- require('testDep.foo');
- assertTrue(goog.isObject(testDep.bar));
- // Unset provided namespace so the test can be re-run.
- testDep = undefined;
- }
- function testAddDependencyModule() {
- var load = goog.testing.recordFunction();
- stubs.set(goog, 'writeScriptTag_', load);
- goog.addDependency('mod.js', ['testDep.mod'], [], true);
- goog.addDependency('empty.js', ['testDep.empty'], [], {});
- goog.addDependency('mod-goog.js', ['testDep.goog'], [], {'module': 'goog'});
- // To differentiate this call from the real one.
- var require = goog.require;
- var assertModuleLoad = function(module, args) {
- assertEquals(2, args.length);
- assertEquals('', args[0]);
- assertRegExp(
- '^goog\\.retrieveAndExec_\\(".*/' + module + '", true, false\\);$',
- args[1]);
- };
- require('testDep.mod');
- assertEquals(1, load.getCallCount());
- assertModuleLoad('mod.js', load.getCalls()[0].getArguments());
- require('testDep.empty');
- assertEquals(2, load.getCallCount());
- assertEquals(2, load.getCalls()[1].getArguments().length);
- assertRegExp('^.*/empty.js$', load.getCalls()[1].getArguments()[0]);
- assertUndefined(load.getCalls()[1].getArguments()[1]);
- require('testDep.goog');
- assertEquals(3, load.getCallCount());
- assertModuleLoad('mod-goog.js', load.getCalls()[2].getArguments());
- // Unset provided namespace so the test can be re-run.
- testDep = undefined;
- }
- function testAddDependencyEs6() {
- var script = null;
- var requireTranspilation = false;
- stubs.set(goog, 'needsTranspile_', function() {
- return requireTranspilation;
- });
- stubs.set(goog, 'writeScriptTag_', function(src, scriptText) {
- if (script != null) {
- throw new Error('Multiple scripts written');
- }
- script = scriptText;
- });
- goog.addDependency(
- 'fancy.js', ['testDep.fancy'], [],
- {'lang': 'es6-impl', 'module': 'goog'});
- goog.addDependency('super.js', ['testDep.superFancy'], [], {'lang': 'es6'});
- // To differentiate this call from the real one.
- var require = goog.require;
- requireTranspilation = false;
- require('testDep.fancy');
- assertRegExp(
- /^goog\.retrieveAndExec_\(".*\/fancy\.js", true, false\);$/, script);
- script = null;
- requireTranspilation = true;
- require('testDep.superFancy');
- assertRegExp(
- /^goog\.retrieveAndExec_\(".*\/super\.js", false, true\);$/, script);
- // Unset provided namespace so the test can be re-run.
- testDep = undefined;
- }
- function testBaseMethod() {
- function A() {}
- A.prototype.foo = function(x, y) {
- return x + y;
- };
- function B() {}
- goog.inherits(B, A);
- B.prototype.foo = function(x, y) {
- return 2 + goog.base(this, 'foo', x, y);
- };
- function C() {}
- goog.inherits(C, B);
- C.prototype.foo = function(x, y) {
- return 4 + goog.base(this, 'foo', x, y);
- };
- var d = new C();
- d.foo = function(x, y) {
- return 8 + goog.base(this, 'foo', x, y);
- };
- assertEquals(15, d.foo(1, 0));
- assertEquals(16, d.foo(1, 1));
- assertEquals(16, d.foo(2, 0));
- assertEquals(7, (new C()).foo(1, 0));
- assertEquals(3, (new B()).foo(1, 0));
- assertThrows(function() {
- goog.base(d, 'foo', 1, 0);
- });
- delete B.prototype.foo;
- assertEquals(13, d.foo(1, 0));
- delete C.prototype.foo;
- assertEquals(9, d.foo(1, 0));
- }
- function testBaseMethodAndBaseCtor() {
- // This will fail on FF4.0 if the following bug is not fixed:
- // https://bugzilla.mozilla.org/show_bug.cgi?id=586482
- function A(x, y) {
- this.foo(x, y);
- }
- A.prototype.foo = function(x, y) {
- this.bar = x + y;
- };
- function B(x, y) {
- goog.base(this, x, y);
- }
- goog.inherits(B, A);
- B.prototype.foo = function(x, y) {
- goog.base(this, 'foo', x, y);
- this.bar = this.bar * 2;
- };
- assertEquals(14, new B(3, 4).bar);
- }
- function testBaseClass() {
- function A(x, y) {
- this.foo = x + y;
- }
- function B(x, y) {
- goog.base(this, x, y);
- this.foo += 2;
- }
- goog.inherits(B, A);
- function C(x, y) {
- goog.base(this, x, y);
- this.foo += 4;
- }
- goog.inherits(C, B);
- function D(x, y) {
- goog.base(this, x, y);
- this.foo += 8;
- }
- goog.inherits(D, C);
- assertEquals(15, (new D(1, 0)).foo);
- assertEquals(16, (new D(1, 1)).foo);
- assertEquals(16, (new D(2, 0)).foo);
- assertEquals(7, (new C(1, 0)).foo);
- assertEquals(3, (new B(1, 0)).foo);
- }
- function testClassBaseOnMethod() {
- function A() {}
- A.prototype.foo = function(x, y) {
- return x + y;
- };
- function B() {}
- goog.inherits(B, A);
- B.prototype.foo = function(x, y) {
- return 2 + B.base(this, 'foo', x, y);
- };
- function C() {}
- goog.inherits(C, B);
- C.prototype.foo = function(x, y) {
- return 4 + C.base(this, 'foo', x, y);
- };
- var d = new C();
- assertEquals(7, d.foo(1, 0));
- assertEquals(8, d.foo(1, 1));
- assertEquals(8, d.foo(2, 0));
- assertEquals(3, (new B()).foo(1, 0));
- delete B.prototype.foo;
- assertEquals(5, d.foo(1, 0));
- delete C.prototype.foo;
- assertEquals(1, d.foo(1, 0));
- }
- function testClassBaseOnConstructor() {
- function A(x, y) {
- this.foo = x + y;
- }
- function B(x, y) {
- B.base(this, 'constructor', x, y);
- this.foo += 2;
- }
- goog.inherits(B, A);
- function C(x, y) {
- C.base(this, 'constructor', x, y);
- this.foo += 4;
- }
- goog.inherits(C, B);
- function D(x, y) {
- D.base(this, 'constructor', x, y);
- this.foo += 8;
- }
- goog.inherits(D, C);
- assertEquals(15, (new D(1, 0)).foo);
- assertEquals(16, (new D(1, 1)).foo);
- assertEquals(16, (new D(2, 0)).foo);
- assertEquals(7, (new C(1, 0)).foo);
- assertEquals(3, (new B(1, 0)).foo);
- }
- function testClassBaseOnMethodAndBaseCtor() {
- function A(x, y) {
- this.foo(x, y);
- }
- A.prototype.foo = function(x, y) {
- this.bar = x + y;
- };
- function B(x, y) {
- B.base(this, 'constructor', x, y);
- }
- goog.inherits(B, A);
- B.prototype.foo = function(x, y) {
- B.base(this, 'foo', x, y);
- this.bar = this.bar * 2;
- };
- assertEquals(14, new B(3, 4).bar);
- }
- function testGoogRequireCheck() {
- // alias to avoid the being picked up by the deps scanner.
- var provide = goog.provide;
- stubs.set(goog, 'ENABLE_DEBUG_LOADER', true);
- stubs.set(goog, 'useStrictRequires', true);
- stubs.set(goog, 'implicitNamespaces_', {});
- // Aliased so that build tools do not mistake this for an actual call.
- var require = goog.require;
- assertThrows('Requiring non-required namespace should fail', function() {
- require('far.outnotprovided');
- });
- assertUndefined(goog.global.far);
- assertEvaluatesToFalse(goog.getObjectByName('far.out'));
- assertObjectEquals({}, goog.implicitNamespaces_);
- assertFalse(goog.isProvided_('far.out'));
- provide('far.out');
- assertNotUndefined(far.out);
- assertEvaluatesToTrue(goog.getObjectByName('far.out'));
- assertObjectEquals({'far': true}, goog.implicitNamespaces_);
- assertTrue(goog.isProvided_('far.out'));
- goog.global.far.out = 42;
- assertEquals(42, goog.getObjectByName('far.out'));
- assertTrue(goog.isProvided_('far.out'));
- // Empty string should be allowed.
- goog.global.far.out = '';
- assertEquals('', goog.getObjectByName('far.out'));
- assertTrue(goog.isProvided_('far.out'));
- // Null or undefined are not allowed.
- goog.global.far.out = null;
- assertNull(goog.getObjectByName('far.out'));
- assertFalse(goog.isProvided_('far.out'));
- goog.global.far.out = undefined;
- assertNull(goog.getObjectByName('far.out'));
- assertFalse(goog.isProvided_('far.out'));
- stubs.reset();
- delete far;
- }
- /**
- * @return {?}
- */
- function diables_testCspSafeGoogRequire() {
- if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('10')) {
- return;
- }
- stubs.set(goog, 'ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING', true);
- // Aliased so that build tools do not mistake this for an actual call.
- var require = goog.require;
- require('goog.Uri');
- // Set a timeout to allow the user agent to finish parsing this script block,
- // thus allowing the appended script (via goog.require) to execute.
- var ASYNC_TIMEOUT_MS = 1000;
- var resolver = goog.Promise.withResolver();
- window.setTimeout(function() {
- assertNotUndefined(goog.Uri);
- resolver.resolve();
- stubs.reset();
- }, ASYNC_TIMEOUT_MS);
- return resolver.promise;
- }
- function testLateRequireProtection() {
- if (!document.readyState) return;
- var e = assertThrows(function() {
- // To differentiate this call from the real one.
- var require = goog.require;
- require('goog.ui.Component');
- });
- assertContains('after document load', e.message);
- }
- function testDefineClass() {
- var Base = goog.defineClass(null, {
- constructor: function(foo) {
- this.foo = foo;
- },
- statics: {x: 42},
- frobnicate: function() {
- return this.foo + this.foo;
- }
- });
- var Derived = goog.defineClass(Base, {
- constructor: function() {
- Derived.base(this, 'constructor', 'bar');
- },
- frozzle: function(foo) {
- this.foo = foo;
- }
- });
- assertEquals(42, Base.x);
- var der = new Derived();
- assertEquals('barbar', der.frobnicate());
- der.frozzle('qux');
- assertEquals('quxqux', der.frobnicate());
- }
- function testDefineClass_interface() {
- /** @interface */
- var Interface =
- goog.defineClass(null, {statics: {foo: 'bar'}, qux: function() {}});
- assertEquals('bar', Interface.foo);
- assertThrows(function() {
- new Interface();
- });
- }
- function testDefineClass_seals() {
- if (!(Object.seal instanceof Function)) return; // IE<9 doesn't have seal
- var A = goog.defineClass(null, {constructor: function() {}});
- var a = new A();
- try {
- a.foo = 'bar';
- } catch (expectedInStrictModeOnly) { /* ignored */
- }
- assertEquals(undefined, a.foo);
- }
- function testDefineClass_unsealable() {
- var LegacyBase = function() {};
- LegacyBase.prototype.foo = null;
- LegacyBase.prototype.setFoo = function(foo) {
- this.foo = foo;
- };
- goog.tagUnsealableClass(LegacyBase);
- var Derived = goog.defineClass(LegacyBase, {constructor: function() {}});
- var der = new Derived();
- der.setFoo('bar');
- assertEquals('bar', der.foo);
- }
- function testDefineClass_constructorIsNotWrappedWhenSealingIsDisabled() {
- var org = goog.defineClass;
- var ctr = null;
- var replacement = function(superClass, def) {
- ctr = def.constructor;
- return org(superClass, def);
- };
- // copy all the properties
- goog.object.extend(replacement, org);
- replacement.SEAL_CLASS_INSTANCES = false;
- stubs.replace(goog, 'defineClass', replacement);
- var MyClass = goog.defineClass(null, {constructor: function() {}});
- assertEquals('The constructor should not be wrapped.', ctr, MyClass);
- }
- function testDefineClass_unsealableConstructorIsWrapped() {
- var LegacyBase = function() {};
- LegacyBase.prototype.foo = null;
- LegacyBase.prototype.setFoo = function(foo) {
- this.foo = foo;
- };
- goog.tagUnsealableClass(LegacyBase);
- var org = goog.defineClass;
- var ctr = null;
- var replacement = function(superClass, def) {
- ctr = def.constructor;
- return org(superClass, def);
- };
- // copy all the properties
- goog.object.extend(replacement, org);
- stubs.replace(goog, 'defineClass', replacement);
- var Derived = goog.defineClass(LegacyBase, {constructor: function() {}});
- assertNotEquals('The constructor should be wrapped.', ctr, Derived);
- }
- // Validate the behavior of goog.module when used from traditional files.
- function testGoogModuleGet() {
- // assert that goog.module doesn't modify the global namespace
- assertUndefined(
- 'module failed to protect global namespace: ' +
- 'goog.test_module_dep',
- goog.test_module_dep);
- // assert that goog.module with goog.module.declareLegacyNamespace is present.
- assertNotUndefined(
- 'module failed to declare global namespace: ' +
- 'goog.test_module',
- goog.test_module);
- // assert that a require'd goog.module is available immediately after the
- // goog.require call.
- assertNotUndefined(
- 'module failed to protect global namespace: ' +
- 'goog.test_module_dep',
- earlyTestModuleGet);
- // assert that an non-existent module request doesn't throw and returns null.
- assertEquals(null, goog.module.get('unrequired.module.id'));
- // Validate the module exports
- var testModuleExports = goog.module.get('goog.test_module');
- assertTrue(goog.isFunction(testModuleExports));
- // Test that any escaping of </script> in test files is correct. Escape the
- // / in </script> here so that any such code does not affect it here.
- assertEquals('<\/script>', testModuleExports.CLOSING_SCRIPT_TAG);
- // Validate that the module exports object has not changed
- assertEquals(earlyTestModuleGet, testModuleExports);
- }
- // Validate the behavior of goog.module when used from traditional files.
- function testGoogLoadModuleByUrl() {
- if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('10')) {
- // IE before 10 don't report an error.
- return;
- }
- stubs.set(goog, 'loadFileSync_', function(src) {
- return 'closure load file sync: ' + src;
- });
- // "goog.loadModuleByUrl" is not a general purpose code loader, it can
- // not be used to late load code.
- var err =
- assertThrows('loadModuleFromUrl should not hide failures', function() {
- goog.loadModuleFromUrl('bogus url');
- });
- assertContains('Cannot write "bogus url" after document load', err.message);
- }
- function testModuleExportSealed() {
- if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9')) {
- // IE before 9 don't support sealing objects
- return;
- }
- goog.loadModule('goog.module("a.b.supplied"); exports.foo = {};');
- var exports0 = goog.module.get('a.b.supplied');
- assertTrue(Object.isSealed(exports0));
- goog.loadModule('goog.module("a.b.object"); exports = {};');
- var exports1 = goog.module.get('a.b.object');
- assertTrue(Object.isSealed(exports1));
- goog.loadModule('goog.module("a.b.fn"); exports = function() {};');
- var exports2 = goog.module.get('a.b.fn');
- assertFalse(Object.isSealed(exports2));
- }
- function testWorkaroundSafari10EvalBug0() {
- // Validate the safari module loading workaround isn't triggered for
- // browsers we know it isn't needed.
- if (goog.userAgent.SAFARI) {
- return;
- }
- assertFalse(goog.useSafari10Workaround());
- }
- function testWorkaroundSafari10EvalBug1() {
- assertEquals(
- '(function(){' + // no \n
- 'goog.module(\'foo\');\n' +
- '\n;})();\n',
- goog.workaroundSafari10EvalBug(
- 'goog.module(\'foo\');\n'));
- }
- function testWorkaroundSafari10EvalBug2() {
- assertEquals(
- '(function(){' + // no \n
- 'goog.module(\'foo\');\n' +
- 'alert("//# sourceMappingURL a.b.c.map")\n' +
- 'alert("//# sourceURL a.b.c.js")\n' +
- '\n;})();\n',
- goog.workaroundSafari10EvalBug(
- 'goog.module(\'foo\');\n' +
- 'alert("//# sourceMappingURL a.b.c.map")\n' +
- 'alert("//# sourceURL a.b.c.js")\n'));
- }
- function testGoogLoadModuleInSafari10() {
- try {
- eval('let es6 = 1');
- } catch (e) {
- // If ES6 block scope syntax isn't supported, don't run the rest of the
- // test.
- return;
- }
- goog.loadModule(
- 'goog.module("a.safari.test");' +
- 'let x = true;' +
- 'function fn() { return x }' +
- 'exports.fn = fn;');
- var exports = goog.module.get('a.safari.test');
- // Safari 10 will throw an exception if the module being loaded is eval'd
- // without a containing function.
- assertNotThrows(exports.fn);
- }
- function testLoadFileSync() {
- var fileContents = goog.loadFileSync_('deps.js');
- assertTrue(
- 'goog.loadFileSync_ returns string', typeof fileContents === 'string');
- assertTrue('goog.loadFileSync_ string length > 0', fileContents.length > 0);
- stubs.set(goog.global, 'CLOSURE_LOAD_FILE_SYNC', function(src) {
- return 'closure load file sync: ' + src;
- });
- assertEquals(
- 'goog.CLOSURE_LOAD_FILE_SYNC override', goog.loadFileSync_('test url'),
- 'closure load file sync: test url');
- }
- function testNormalizePath1() {
- assertEquals('foo/path.js', goog.normalizePath_('./foo/./path.js'));
- assertEquals('foo/path.js', goog.normalizePath_('bar/../foo/path.js'));
- assertEquals('bar/path.js', goog.normalizePath_('bar/foo/../path.js'));
- assertEquals('path.js', goog.normalizePath_('bar/foo/../../path.js'));
- assertEquals('../foo/path.js', goog.normalizePath_('../foo/path.js'));
- assertEquals('../../foo/path.js', goog.normalizePath_('../../foo/path.js'));
- assertEquals('../path.js', goog.normalizePath_('../foo/../path.js'));
- assertEquals('../../path.js', goog.normalizePath_('../foo/../../path.js'));
- assertEquals('/../foo/path.js', goog.normalizePath_('/../foo/path.js'));
- assertEquals('/path.js', goog.normalizePath_('/foo/../path.js'));
- assertEquals('/foo/path.js', goog.normalizePath_('/./foo/path.js'));
- assertEquals('//../foo/path.js', goog.normalizePath_('//../foo/path.js'));
- assertEquals('//path.js', goog.normalizePath_('//foo/../path.js'));
- assertEquals('//foo/path.js', goog.normalizePath_('//./foo/path.js'));
- assertEquals('http://../x/y.js', goog.normalizePath_('http://../x/y.js'));
- assertEquals('http://path.js', goog.normalizePath_('http://foo/../path.js'));
- assertEquals('http://x/path.js', goog.normalizePath_('http://./x/path.js'));
- }
- function testGoogModuleNames() {
- // avoid usage checks
- var module = goog.module;
- function assertInvalidId(id) {
- var err = assertThrows(function() {
- module(id);
- });
- assertEquals('Invalid module identifier', err.message);
- }
- function assertValidId(id) {
- // This is a cheesy check, but we validate that we don't get an invalid
- // namespace warning, but instead get a module isn't loaded correctly
- // error.
- var err = assertThrows(function() {
- module(id);
- });
- assertTrue(err.message.indexOf('has been loaded incorrectly') != -1);
- }
- assertInvalidId('/somepath/module.js');
- assertInvalidId('./module.js');
- assertInvalidId('1');
- assertValidId('a');
- assertValidId('a.b');
- assertValidId('a.b.c');
- assertValidId('aB.Cd.eF');
- assertValidId('a1.0E.Fg');
- assertValidId('_');
- assertValidId('$');
- assertValidId('_$');
- assertValidId('$_');
- }
|