1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622 |
- var Test = {};var isCommonJS = typeof window == "undefined" && typeof exports == "object";
- /**
- * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
- *
- * @namespace
- */
- var jasmine = {};
- if (isCommonJS) exports.jasmine = jasmine;
- /**
- * @private
- */
- jasmine.unimplementedMethod_ = function() {
- throw new Error("unimplemented method");
- };
- /**
- * Use <code>jasmine.undefined</code> instead of <code>undefined</code>, since <code>undefined</code> is just
- * a plain old variable and may be redefined by somebody else.
- *
- * @private
- */
- jasmine.undefined = jasmine.___undefined___;
- /**
- * Show diagnostic messages in the console if set to true
- *
- */
- jasmine.VERBOSE = false;
- /**
- * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed.
- *
- */
- jasmine.DEFAULT_UPDATE_INTERVAL = 250;
- /**
- * Maximum levels of nesting that will be included when an object is pretty-printed
- */
- jasmine.MAX_PRETTY_PRINT_DEPTH = 40;
- /**
- * Default timeout interval in milliseconds for waitsFor() blocks.
- */
- jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
- /**
- * By default exceptions thrown in the context of a test are caught by jasmine so that it can run the remaining tests in the suite.
- * Set to false to let the exception bubble up in the browser.
- *
- */
- jasmine.CATCH_EXCEPTIONS = true;
- jasmine.getGlobal = function() {
- function getGlobal() {
- return this;
- }
- return getGlobal();
- };
- /**
- * Allows for bound functions to be compared. Internal use only.
- *
- * @ignore
- * @private
- * @param base {Object} bound 'this' for the function
- * @param name {Function} function to find
- */
- jasmine.bindOriginal_ = function(base, name) {
- var original = base[name];
- if (original.apply) {
- return function() {
- return original.apply(base, arguments);
- };
- } else {
- // IE support
- return jasmine.getGlobal()[name];
- }
- };
- jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout');
- jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout');
- jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval');
- jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval');
- jasmine.MessageResult = function(values) {
- this.type = 'log';
- this.values = values;
- this.trace = new Error(); // todo: test better
- };
- jasmine.MessageResult.prototype.toString = function() {
- var text = "";
- for (var i = 0; i < this.values.length; i++) {
- if (i > 0) text += " ";
- if (jasmine.isString_(this.values[i])) {
- text += this.values[i];
- } else {
- text += jasmine.pp(this.values[i]);
- }
- }
- return text;
- };
- jasmine.ExpectationResult = function(params) {
- this.type = 'expect';
- this.matcherName = params.matcherName;
- this.passed_ = params.passed;
- this.expected = params.expected;
- this.actual = params.actual;
- this.message = this.passed_ ? 'Passed.' : params.message;
- var trace = (params.trace || new Error(this.message));
- this.trace = this.passed_ ? '' : trace;
- };
- jasmine.ExpectationResult.prototype.toString = function () {
- return this.message;
- };
- jasmine.ExpectationResult.prototype.passed = function () {
- return this.passed_;
- };
- /**
- * Getter for the Jasmine environment. Ensures one gets created
- */
- jasmine.getEnv = function() {
- var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
- return env;
- };
- /**
- * @ignore
- * @private
- * @param value
- * @returns {Boolean}
- */
- jasmine.isArray_ = function(value) {
- return jasmine.isA_("Array", value);
- };
- /**
- * @ignore
- * @private
- * @param value
- * @returns {Boolean}
- */
- jasmine.isString_ = function(value) {
- return jasmine.isA_("String", value);
- };
- /**
- * @ignore
- * @private
- * @param value
- * @returns {Boolean}
- */
- jasmine.isNumber_ = function(value) {
- return jasmine.isA_("Number", value);
- };
- /**
- * @ignore
- * @private
- * @param {String} typeName
- * @param value
- * @returns {Boolean}
- */
- jasmine.isA_ = function(typeName, value) {
- return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
- };
- /**
- * Pretty printer for expecations. Takes any object and turns it into a human-readable string.
- *
- * @param value {Object} an object to be outputted
- * @returns {String}
- */
- jasmine.pp = function(value) {
- var stringPrettyPrinter = new jasmine.StringPrettyPrinter();
- stringPrettyPrinter.format(value);
- return stringPrettyPrinter.string;
- };
- /**
- * Returns true if the object is a DOM Node.
- *
- * @param {Object} obj object to check
- * @returns {Boolean}
- */
- jasmine.isDomNode = function(obj) {
- return obj.nodeType > 0;
- };
- /**
- * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter.
- *
- * @example
- * // don't care about which function is passed in, as long as it's a function
- * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function));
- *
- * @param {Class} clazz
- * @returns matchable object of the type clazz
- */
- jasmine.any = function(clazz) {
- return new jasmine.Matchers.Any(clazz);
- };
- /**
- * Returns a matchable subset of a JSON object. For use in expectations when you don't care about all of the
- * attributes on the object.
- *
- * @example
- * // don't care about any other attributes than foo.
- * expect(mySpy).toHaveBeenCalledWith(jasmine.objectContaining({foo: "bar"});
- *
- * @param sample {Object} sample
- * @returns matchable object for the sample
- */
- jasmine.objectContaining = function (sample) {
- return new jasmine.Matchers.ObjectContaining(sample);
- };
- /**
- * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.
- *
- * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine
- * expectation syntax. Spies can be checked if they were called or not and what the calling params were.
- *
- * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs).
- *
- * Spies are torn down at the end of every spec.
- *
- * Note: Do <b>not</b> call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj.
- *
- * @example
- * // a stub
- * var myStub = jasmine.createSpy('myStub'); // can be used anywhere
- *
- * // spy example
- * var foo = {
- * not: function(bool) { return !bool; }
- * }
- *
- * // actual foo.not will not be called, execution stops
- * spyOn(foo, 'not');
- // foo.not spied upon, execution will continue to implementation
- * spyOn(foo, 'not').andCallThrough();
- *
- * // fake example
- * var foo = {
- * not: function(bool) { return !bool; }
- * }
- *
- * // foo.not(val) will return val
- * spyOn(foo, 'not').andCallFake(function(value) {return value;});
- *
- * // mock example
- * foo.not(7 == 7);
- * expect(foo.not).toHaveBeenCalled();
- * expect(foo.not).toHaveBeenCalledWith(true);
- *
- * @constructor
- * @see spyOn, jasmine.createSpy, jasmine.createSpyObj
- * @param {String} name
- */
- jasmine.Spy = function(name) {
- /**
- * The name of the spy, if provided.
- */
- this.identity = name || 'unknown';
- /**
- * Is this Object a spy?
- */
- this.isSpy = true;
- /**
- * The actual function this spy stubs.
- */
- this.plan = function() {
- };
- /**
- * Tracking of the most recent call to the spy.
- * @example
- * var mySpy = jasmine.createSpy('foo');
- * mySpy(1, 2);
- * mySpy.mostRecentCall.args = [1, 2];
- */
- this.mostRecentCall = {};
- /**
- * Holds arguments for each call to the spy, indexed by call count
- * @example
- * var mySpy = jasmine.createSpy('foo');
- * mySpy(1, 2);
- * mySpy(7, 8);
- * mySpy.mostRecentCall.args = [7, 8];
- * mySpy.argsForCall[0] = [1, 2];
- * mySpy.argsForCall[1] = [7, 8];
- */
- this.argsForCall = [];
- this.calls = [];
- };
- /**
- * Tells a spy to call through to the actual implemenatation.
- *
- * @example
- * var foo = {
- * bar: function() { // do some stuff }
- * }
- *
- * // defining a spy on an existing property: foo.bar
- * spyOn(foo, 'bar').andCallThrough();
- */
- jasmine.Spy.prototype.andCallThrough = function() {
- this.plan = this.originalValue;
- return this;
- };
- /**
- * For setting the return value of a spy.
- *
- * @example
- * // defining a spy from scratch: foo() returns 'baz'
- * var foo = jasmine.createSpy('spy on foo').andReturn('baz');
- *
- * // defining a spy on an existing property: foo.bar() returns 'baz'
- * spyOn(foo, 'bar').andReturn('baz');
- *
- * @param {Object} value
- */
- jasmine.Spy.prototype.andReturn = function(value) {
- this.plan = function() {
- return value;
- };
- return this;
- };
- /**
- * For throwing an exception when a spy is called.
- *
- * @example
- * // defining a spy from scratch: foo() throws an exception w/ message 'ouch'
- * var foo = jasmine.createSpy('spy on foo').andThrow('baz');
- *
- * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch'
- * spyOn(foo, 'bar').andThrow('baz');
- *
- * @param {String} exceptionMsg
- */
- jasmine.Spy.prototype.andThrow = function(exceptionMsg) {
- this.plan = function() {
- throw exceptionMsg;
- };
- return this;
- };
- /**
- * Calls an alternate implementation when a spy is called.
- *
- * @example
- * var baz = function() {
- * // do some stuff, return something
- * }
- * // defining a spy from scratch: foo() calls the function baz
- * var foo = jasmine.createSpy('spy on foo').andCall(baz);
- *
- * // defining a spy on an existing property: foo.bar() calls an anonymnous function
- * spyOn(foo, 'bar').andCall(function() { return 'baz';} );
- *
- * @param {Function} fakeFunc
- */
- jasmine.Spy.prototype.andCallFake = function(fakeFunc) {
- this.plan = fakeFunc;
- return this;
- };
- /**
- * Resets all of a spy's the tracking variables so that it can be used again.
- *
- * @example
- * spyOn(foo, 'bar');
- *
- * foo.bar();
- *
- * expect(foo.bar.callCount).toEqual(1);
- *
- * foo.bar.reset();
- *
- * expect(foo.bar.callCount).toEqual(0);
- */
- jasmine.Spy.prototype.reset = function() {
- this.wasCalled = false;
- this.callCount = 0;
- this.argsForCall = [];
- this.calls = [];
- this.mostRecentCall = {};
- };
- jasmine.createSpy = function(name) {
- var spyObj = function() {
- spyObj.wasCalled = true;
- spyObj.callCount++;
- var args = jasmine.util.argsToArray(arguments);
- spyObj.mostRecentCall.object = this;
- spyObj.mostRecentCall.args = args;
- spyObj.argsForCall.push(args);
- spyObj.calls.push({object: this, args: args});
- return spyObj.plan.apply(this, arguments);
- };
- var spy = new jasmine.Spy(name);
- for (var prop in spy) {
- spyObj[prop] = spy[prop];
- }
- spyObj.reset();
- return spyObj;
- };
- /**
- * Determines whether an object is a spy.
- *
- * @param {jasmine.Spy|Object} putativeSpy
- * @returns {Boolean}
- */
- jasmine.isSpy = function(putativeSpy) {
- return putativeSpy && putativeSpy.isSpy;
- };
- /**
- * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something
- * large in one call.
- *
- * @param {String} baseName name of spy class
- * @param {Array} methodNames array of names of methods to make spies
- */
- jasmine.createSpyObj = function(baseName, methodNames) {
- if (!jasmine.isArray_(methodNames) || methodNames.length === 0) {
- throw new Error('createSpyObj requires a non-empty array of method names to create spies for');
- }
- var obj = {};
- for (var i = 0; i < methodNames.length; i++) {
- obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]);
- }
- return obj;
- };
- /**
- * All parameters are pretty-printed and concatenated together, then written to the current spec's output.
- *
- * Be careful not to leave calls to <code>jasmine.log</code> in production code.
- */
- jasmine.log = function() {
- var spec = jasmine.getEnv().currentSpec;
- spec.log.apply(spec, arguments);
- };
- /**
- * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy.
- *
- * @example
- * // spy example
- * var foo = {
- * not: function(bool) { return !bool; }
- * }
- * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops
- *
- * @see jasmine.createSpy
- * @param obj
- * @param methodName
- * @return {jasmine.Spy} a Jasmine spy that can be chained with all spy methods
- */
- var spyOn = function(obj, methodName) {
- return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
- };
- if (isCommonJS) exports.spyOn = spyOn;
- /**
- * Creates a Jasmine spec that will be added to the current suite.
- *
- * // TODO: pending tests
- *
- * @example
- * it('should be true', function() {
- * expect(true).toEqual(true);
- * });
- *
- * @param {String} desc description of this specification
- * @param {Function} func defines the preconditions and expectations of the spec
- */
- var it = function(desc, func) {
- return jasmine.getEnv().it(desc, func);
- };
- if (isCommonJS) exports.it = it;
- /**
- * Creates a <em>disabled</em> Jasmine spec.
- *
- * A convenience method that allows existing specs to be disabled temporarily during development.
- *
- * @param {String} desc description of this specification
- * @param {Function} func defines the preconditions and expectations of the spec
- */
- var xit = function(desc, func) {
- return jasmine.getEnv().xit(desc, func);
- };
- if (isCommonJS) exports.xit = xit;
- /**
- * Starts a chain for a Jasmine expectation.
- *
- * It is passed an Object that is the actual value and should chain to one of the many
- * jasmine.Matchers functions.
- *
- * @param {Object} actual Actual value to test against and expected value
- * @return {jasmine.Matchers}
- */
- var expect = function(actual) {
- return jasmine.getEnv().currentSpec.expect(actual);
- };
- if (isCommonJS) exports.expect = expect;
- /**
- * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs.
- *
- * @param {Function} func Function that defines part of a jasmine spec.
- */
- var runs = function(func) {
- jasmine.getEnv().currentSpec.runs(func);
- };
- if (isCommonJS) exports.runs = runs;
- /**
- * Waits a fixed time period before moving to the next block.
- *
- * @deprecated Use waitsFor() instead
- * @param {Number} timeout milliseconds to wait
- */
- var waits = function(timeout) {
- jasmine.getEnv().currentSpec.waits(timeout);
- };
- if (isCommonJS) exports.waits = waits;
- /**
- * Waits for the latchFunction to return true before proceeding to the next block.
- *
- * @param {Function} latchFunction
- * @param {String} optional_timeoutMessage
- * @param {Number} optional_timeout
- */
- var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
- jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments);
- };
- if (isCommonJS) exports.waitsFor = waitsFor;
- /**
- * A function that is called before each spec in a suite.
- *
- * Used for spec setup, including validating assumptions.
- *
- * @param {Function} beforeEachFunction
- */
- var beforeEach = function(beforeEachFunction) {
- jasmine.getEnv().beforeEach(beforeEachFunction);
- };
- if (isCommonJS) exports.beforeEach = beforeEach;
- /**
- * A function that is called after each spec in a suite.
- *
- * Used for restoring any state that is hijacked during spec execution.
- *
- * @param {Function} afterEachFunction
- */
- var afterEach = function(afterEachFunction) {
- jasmine.getEnv().afterEach(afterEachFunction);
- };
- if (isCommonJS) exports.afterEach = afterEach;
- /**
- * Defines a suite of specifications.
- *
- * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared
- * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization
- * of setup in some tests.
- *
- * @example
- * // TODO: a simple suite
- *
- * // TODO: a simple suite with a nested describe block
- *
- * @param {String} description A string, usually the class under test.
- * @param {Function} specDefinitions function that defines several specs.
- */
- var describe = function(description, specDefinitions) {
- return jasmine.getEnv().describe(description, specDefinitions);
- };
- if (isCommonJS) exports.describe = describe;
- /**
- * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development.
- *
- * @param {String} description A string, usually the class under test.
- * @param {Function} specDefinitions function that defines several specs.
- */
- var xdescribe = function(description, specDefinitions) {
- return jasmine.getEnv().xdescribe(description, specDefinitions);
- };
- if (isCommonJS) exports.xdescribe = xdescribe;
- // Provide the XMLHttpRequest class for IE 5.x-6.x:
- jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() {
- function tryIt(f) {
- try {
- return f();
- } catch(e) {
- }
- return null;
- }
- var xhr = tryIt(function() {
- return new ActiveXObject("Msxml2.XMLHTTP.6.0");
- }) ||
- tryIt(function() {
- return new ActiveXObject("Msxml2.XMLHTTP.3.0");
- }) ||
- tryIt(function() {
- return new ActiveXObject("Msxml2.XMLHTTP");
- }) ||
- tryIt(function() {
- return new ActiveXObject("Microsoft.XMLHTTP");
- });
- if (!xhr) throw new Error("This browser does not support XMLHttpRequest.");
- return xhr;
- } : XMLHttpRequest;
- /**
- * @namespace
- */
- jasmine.util = {};
- /**
- * Declare that a child class inherit it's prototype from the parent class.
- *
- * @private
- * @param {Function} childClass
- * @param {Function} parentClass
- */
- jasmine.util.inherit = function(childClass, parentClass) {
- /**
- * @private
- */
- var subclass = function() {
- };
- subclass.prototype = parentClass.prototype;
- childClass.prototype = new subclass();
- };
- jasmine.util.formatException = function(e) {
- var lineNumber;
- if (e.line) {
- lineNumber = e.line;
- }
- else if (e.lineNumber) {
- lineNumber = e.lineNumber;
- }
- var file;
- if (e.sourceURL) {
- file = e.sourceURL;
- }
- else if (e.fileName) {
- file = e.fileName;
- }
- var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString();
- if (file && lineNumber) {
- message += ' in ' + file + ' (line ' + lineNumber + ')';
- }
- return message;
- };
- jasmine.util.htmlEscape = function(str) {
- if (!str) return str;
- return str.replace(/&/g, '&')
- .replace(/</g, '<')
- .replace(/>/g, '>');
- };
- jasmine.util.argsToArray = function(args) {
- var arrayOfArgs = [];
- for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
- return arrayOfArgs;
- };
- jasmine.util.extend = function(destination, source) {
- for (var property in source) destination[property] = source[property];
- return destination;
- };
- /**
- * Base class for pretty printing for expectation results.
- */
- jasmine.PrettyPrinter = function() {
- this.ppNestLevel_ = 0;
- };
- /**
- * Formats a value in a nice, human-readable string.
- *
- * @param value
- */
- jasmine.PrettyPrinter.prototype.format = function(value) {
- this.ppNestLevel_++;
- try {
- if (value === jasmine.undefined) {
- this.emitScalar('undefined');
- } else if (value === null) {
- this.emitScalar('null');
- } else if (value === jasmine.getGlobal()) {
- this.emitScalar('<global>');
- } else if (value.jasmineToString) {
- this.emitScalar(value.jasmineToString());
- } else if (typeof value === 'string') {
- this.emitString(value);
- } else if (jasmine.isSpy(value)) {
- this.emitScalar("spy on " + value.identity);
- } else if (value instanceof RegExp) {
- this.emitScalar(value.toString());
- } else if (typeof value === 'function') {
- this.emitScalar('Function');
- } else if (typeof value.nodeType === 'number') {
- this.emitScalar('HTMLNode');
- } else if (value instanceof Date) {
- this.emitScalar('Date(' + value + ')');
- } else if (value.__Jasmine_been_here_before__) {
- this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>');
- } else if (jasmine.isArray_(value) || typeof value == 'object') {
- value.__Jasmine_been_here_before__ = true;
- if (jasmine.isArray_(value)) {
- this.emitArray(value);
- } else {
- this.emitObject(value);
- }
- delete value.__Jasmine_been_here_before__;
- } else {
- this.emitScalar(value.toString());
- }
- } finally {
- this.ppNestLevel_--;
- }
- };
- jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
- for (var property in obj) {
- if (!obj.hasOwnProperty(property)) continue;
- if (property == '__Jasmine_been_here_before__') continue;
- fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined &&
- obj.__lookupGetter__(property) !== null) : false);
- }
- };
- jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
- jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
- jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
- jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
- jasmine.StringPrettyPrinter = function() {
- jasmine.PrettyPrinter.call(this);
- this.string = '';
- };
- jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter);
- jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
- this.append(value);
- };
- jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
- this.append("'" + value + "'");
- };
- jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
- if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
- this.append("Array");
- return;
- }
- this.append('[ ');
- for (var i = 0; i < array.length; i++) {
- if (i > 0) {
- this.append(', ');
- }
- this.format(array[i]);
- }
- this.append(' ]');
- };
- jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
- if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
- this.append("Object");
- return;
- }
- var self = this;
- this.append('{ ');
- var first = true;
- this.iterateObject(obj, function(property, isGetter) {
- if (first) {
- first = false;
- } else {
- self.append(', ');
- }
- self.append(property);
- self.append(' : ');
- if (isGetter) {
- self.append('<getter>');
- } else {
- self.format(obj[property]);
- }
- });
- this.append(' }');
- };
- jasmine.StringPrettyPrinter.prototype.append = function(value) {
- this.string += value;
- };
- /**
- * Formats a value in a nice, human-readable string.
- *
- * @param value
- */
- jasmine.PrettyPrinter.prototype.format = function(value) {
- if (this.ppNestLevel_ > 40) {
- throw new Error('jasmine.PrettyPrinter: format() nested too deeply!');
- }
- this.ppNestLevel_++;
- try {
- if (value === jasmine.undefined) {
- this.emitScalar('undefined');
- } else if (value === null) {
- this.emitScalar('null');
- } else if (value === jasmine.getGlobal()) {
- this.emitScalar('<global>');
- } else if (value.expectedClass) { //override of value instanceof jasmine.Matchers.Any
- this.emitScalar(value.toString());
- } else if (typeof value === 'string') {
- this.emitString(value);
- } else if (jasmine.isSpy(value)) {
- this.emitScalar("spy on " + value.identity);
- } else if (value instanceof RegExp) {
- this.emitScalar(value.toString());
- } else if (typeof value === 'function') {
- this.emitScalar('Function');
- } else if (typeof value.nodeType === 'number') {
- this.emitScalar('HTMLNode');
- } else if (value instanceof Date) {
- this.emitScalar('Date(' + value + ')');
- } else if (value.__Jasmine_been_here_before__) {
- this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>');
- } else if (jasmine.isArray_(value) || typeof value == 'object') {
- value.__Jasmine_been_here_before__ = true;
- if (jasmine.isArray_(value)) {
- this.emitArray(value);
- } else {
- this.emitObject(value);
- }
- delete value.__Jasmine_been_here_before__;
- } else {
- this.emitScalar(value.toString());
- }
- } catch (e) {
- } finally {
- this.ppNestLevel_--;
- }
- };
- // Extend: creates whitespaces indent
- jasmine.StringPrettyPrinter.prototype.getIndent = function () {
- var whiteSpaces = "",
- i;
-
- for (i = 0; i < this.ws; i++) {
- whiteSpaces += " ";
- }
- return whiteSpaces;
- };
- // Override: pre-format object
- jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
- var self = this,
- first = true,
- indent;
-
- this.append('{\n');
- if(!this.ws) {
- this.ws = 0;
- }
- this.ws += 4;
- indent = this.getIndent();
- var i = 0;
- this.iterateObject(obj, function(property, isGetter) {
-
- if (first) {
- first = false;
- } else {
- self.append(',\n');
- }
- self.append(indent + property);
- self.append(' : ');
- if (isGetter) {
- self.append('<getter>');
- } else {
- if (typeof obj[property] !== "object") {
- self.format(obj[property]);
- } else {
- self.append("<Object>");
- }
- }
- });
-
- this.ws -= 4;
- indent = this.getIndent();
-
- this.append(indent + '\n'+ indent +'}');
- };
- /**
- * Basic browsers detection.
- */
- jasmine.browser = {};
- jasmine.browser.isIE = !!window.ActiveXObject;
- jasmine.browser.isIE6 = jasmine.browser.isIE && !window.XMLHttpRequest;
- jasmine.browser.isIE7 = jasmine.browser.isIE && !!window.XMLHttpRequest && !document.documentMode;
- jasmine.browser.isIE8 = jasmine.browser.isIE && !!window.XMLHttpRequest && !!document.documentMode && !window.performance;
- jasmine.browser.isIE9 = jasmine.browser.isIE && !!window.performance;
- jasmine.browser.isSafari3 = /safari/.test(navigator.userAgent.toLowerCase()) && /version\/3/.test(navigator.userAgent.toLowerCase());
- jasmine.browser.isOpera = !!window.opera;
- jasmine.browser.isOpera11 = jasmine.browser.isOpera && parseInt(window.opera.version(), 10) > 10;
- jasmine.array = {};
- /**
- * Checks whether or not the specified item exists in the array.
- * Array.prototype.indexOf is missing in Internet Explorer, unfortunately.
- * We always have to use this static method instead for consistency
- * @param {Array} array The array to check
- * @param {Mixed} item The item to look for
- * @param {Number} from (Optional) The index at which to begin the search
- * @return {Number} The index of item in the array (or -1 if it is not found)
- */
- jasmine.array.indexOf = function(array, item, from){
- if (array.indexOf) {
- return array.indexOf(item, from);
- }
-
- var i, length = array.length;
- for (i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++){
- if (array[i] === item) {
- return i;
- }
- }
- return -1;
- };
- /**
- * Removes the specified item from the array. If the item is not found nothing happens.
- * @param {Array} array The array
- * @param {Mixed} item The item to remove
- * @return {Array} The passed array itself
- */
- jasmine.array.remove = function(array, item) {
- var index = this.indexOf(array, item);
- if (index !== -1) {
- array.splice(index, 1);
- }
-
- return array;
- };/**
- * Creates an HTMLElement.
- * @param {Object/HTMLElement} config Ext DomHelper style element config object.
- * If no tag is specified (e.g., {tag:'input'}) then a div will be automatically generated with the specified attributes.
- * @return {HTMLElement} The created HTMLElement
- */
- jasmine.Dom = function(config) {
- var element, children, length, child, i, property;
-
- config = config || {};
-
- if (config.tagName) {
- return config;
- }
-
- element = document.createElement(config.tag || "div");
- children = config.children || [];
- length = children.length;
- delete config.tag;
-
- for (i = 0; i < length; i++) {
- child = children[i];
- element.appendChild(new jasmine.Dom(child));
- }
- delete config.children;
-
- if (config.cls) {
- jasmine.Dom.setCls(element, config.cls);
- delete config.cls;
- }
- if (config.html) {
- jasmine.Dom.setHTML(element, config.html);
- delete config.html;
- }
- if (config.style) {
- jasmine.Dom.setStyle(element, config.style);
- delete config.style;
- }
-
- for (property in config) {
- if (!config.hasOwnProperty(property)) {
- continue;
- }
- element[property] = config[property];
- }
- return element;
- };
- /**
- * Adds className to an HTMLElement.
- * @param {HTMLElement} element The HTMLElement
- * @param {String} cls The className string
- */
- jasmine.Dom.addCls = function (element, cls) {
- var split, length, i;
-
- if (!element.className) {
- jasmine.Dom.setCls(element, cls);
- return;
- }
-
- split = element.className.split(" ");
- length = split.length;
-
- for (i = 0; i < length; i++) {
- if (split[i] == cls) {
- return;
- }
- }
-
- element.className = element.className + " " + cls;
- };
- /**
- * Removes className to HTMLElement.
- * @param {HTMLElement} element The HTMLElement
- * @param {String} cls The className string
- */
- jasmine.Dom.removeCls = function(element, cls) {
- var split, length, classArray, i;
-
- if (!element.className) {
- return;
- }
-
- classArray = [];
- split = element.className.split(" ");
- length = split.length;
-
- for (i = 0; i < length; i++) {
- if (split[i] !== cls) {
- classArray.push(split[i]);
- }
- }
-
- element.className = classArray.join(" ");
- };
- /**
- * Checks if a dom element has a className.
- * @param {HTMLElement} element The HTMLElement
- * @param {String} cls The className string
- * @return {Boolean}
- */
- jasmine.Dom.hasCls = function(element, cls) {
- var split, length, classArray, i;
-
- if (!element.className) {
- return;
- }
-
- split = element.className.split(" ");
- length = split.length;
-
- for (i = 0; i < length; i++) {
- if (split[i] === cls) {
- return true;
- }
- }
-
- return false;
- };
- /**
- * Sets HTMLElement className.
- * @param {HTMLElement} element The HTMLElement
- * @param {String} cls The className string
- */
- jasmine.Dom.setCls = function(element, cls) {
- element.className = cls;
- };
- /**
- * Sets HTMLElement innerHTML
- * @param {HTMLElement} element The HTMLElement
- * @param {String} html The innerHTML text
- */
- jasmine.Dom.setHTML = function(element, html) {
- element.innerHTML = html;
- };
- /**
- * Sets HTMLElement style
- * @param {HTMLElement} element The HTMLElement
- * @param {String} style The style property to set
- */
- jasmine.Dom.setStyle = function(element, style) {
- var property;
- for (property in style) {
- if (style.hasOwnProperty(property)) {
- element.style[property] = style[property];
- }
- }
- };
- Test.OptionsImpl = function() {
- this.optionCheckBoxesEl = {};
- this.options = this.urlDecode(window.location.search.substring(1));
- this.options.remote = window.location.toString().search("http:") !== -1;
- this.startAutoReloadTask();
-
- };
- Test.OptionsImpl.prototype.get = function() {
- return this.options;
- };
- /**
- * Takes an object and converts it to an encoded URL.
- * @param {Object} o The object to encode
- * @return {String}
- */
- Test.OptionsImpl.prototype.urlEncode = function(object) {
- var buf = [],
- e = encodeURIComponent,
- value, property, length, i;
- for (property in object) {
- if(!object.hasOwnProperty(property)) {
- continue;
- }
- value = object[property];
- if (jasmine.isArray_(value)) {
- length = value.length;
- for (i = 0; i < length; i++) {
- buf.push(property + '=' + e(value[i]));
- }
- } else {
- buf.push(property + '=' + e(value));
- }
- }
- return buf.join('&');
- };
- Test.hashString = function (s, hash) {
- hash = hash || 0;
- // see http://www.cse.yorku.ca/~oz/hash.html
- for (var c, i = 0, n = s.length; i < n; ++i) {
- c = s.charCodeAt(i);
- hash = c + (hash << 6) + (hash << 16) - hash;
- }
- return hash;
- };
- /**
- * Takes an encoded URL and and converts it to an object. Example:
- * @param {String} string
- * @return {Object} A literal with members
- */
- Test.OptionsImpl.prototype.urlDecode = function(string) {
- var obj = {},
- pairs, d, name, value, pair, i, length;
-
- if (string != "") {
- pairs = string.split('&');
- d = decodeURIComponent;
- length = pairs.length;
- for (i = 0; i < length; i++) {
- pair = pairs[i].split('=');
- name = d(pair[0]);
- value = d(pair[1]);
- obj[name] = !obj[name] ? value : [].concat(obj[name]).concat(value);
- }
- }
- function parseStringOrId (str) {
- var id = parseInt(str, 10);
- if (String(id) !== str) {
- id = Test.hashString(str);
- }
- return id;
- }
-
- if (obj.specs) {
- obj.specs = jasmine.isArray_(obj.specs) ? obj.specs : [obj.specs];
- length = obj.specs.length;
- for (i = 0; i < length; i++) {
- obj.specs[i] = parseStringOrId(obj.specs[i]);
- }
- } else {
- obj.specs = [];
- }
-
- if (obj.suites) {
- obj.suites = jasmine.isArray_(obj.suites) ? obj.suites : [obj.suites];
- length = obj.suites.length;
- for (i = 0; i < length; i++) {
- obj.suites[i] = parseStringOrId(obj.suites[i]);
- }
- } else {
- obj.suites = [];
- }
-
- return obj;
- };
- /**
- * Renders option checkbox and label.
- * @param {String} name The option name.
- * @param {String} labelText The label text.
- * @return {HTMLElement} The option HTMLElement
- */
- Test.OptionsImpl.prototype.renderCheckbox = function(name, labelText) {
- var me = this,
- checkbox = new jasmine.Dom({
- tag: "input",
- cls: "option " + name,
- type: "checkbox",
- onclick: function() {
- me.onCheckboxClick.apply(me, arguments);
- }
- });
-
- me.optionCheckBoxesEl[name] = checkbox;
-
- return new jasmine.Dom({
- tag: "span",
- cls: "show",
- children: [checkbox,{
- tag: "label",
- html: labelText
- }]
- });
- };
- /**
- * Checks options checkboxs if needed.
- */
- Test.OptionsImpl.prototype.check = function() {
- var property, checkbox;
-
- for (property in this.options) {
- if (!this.options.hasOwnProperty(property)) {
- continue;
- }
- checkbox = this.optionCheckBoxesEl[property];
- if (checkbox) {
- checkbox.checked = this.options[property];
- }
- }
- };
- /**
- * Options checkbox check/uncked handler.
- * @param {HTMLElement} el The checkbox HTMLElement
- */
- Test.OptionsImpl.prototype.onCheckboxClick = function(event) {
- var el, opt, row, length, i;
- event = event || window.event;
- el = event.target || event.srcElement;
- opt = el.className.split(" ")[1];
- if (el.checked) {
- this.options[opt] = true;
- } else {
- delete this.options[opt];
- }
- };
- /**
- * Reloads current page with reporter options.
- */
- Test.OptionsImpl.prototype.reloadWindow = function(reset) {
- if (reset) {
- this.options.specs = [];
- this.options.suites = [];
- }
- window.location.search = this.urlEncode(this.options);
- };
- /**
- * Starts autoReload task.
- */
- Test.OptionsImpl.prototype.startAutoReloadTask = function() {
- var me = this;
- if (me.options.autoReload) {
- var interval = setInterval(function() {
- if (Test.SandBox.isRunning()) {
- clearInterval(interval);
-
- setTimeout(function() {
- me.reloadWindow();
- }, 2000);
- }
- }, 1500);
- }
- };
- Test.OptionsImpl.prototype.isChecked = function(o) {
- var specs = this.options.specs,
- suites = this.options.suites,
- id = o.id;
- if (o.suite) {
- return specs && jasmine.array.indexOf(specs, id) !== -1;
- } else {
- return suites && jasmine.array.indexOf(suites, id) !== -1;
- }
- return false;
- };
- Test.Options = new Test.OptionsImpl();Test.SandBoxImpl = function(){};
- Test.SandBoxImpl.prototype.domReady = function(fn) {
- if (document.addEventListener) {
- window.addEventListener('load', fn, false);
- } else {
- window.attachEvent('onload', fn, false);
- }
- };
- Test.SandBoxImpl.prototype.setup = function(config) {
- var me = this;
- me.requires = config.requires;
- me.domReady(function() {
- me.reporter = new Test.Reporter();
- me.createIframe();
- });
- };
- Test.SandBoxImpl.prototype.createIframe = function() {
- var me = this,
- iframe,
- win,
- doc;
- me.options = Test.Options.get();
- var src = me.options.quirksMode ? 'iframe-quirks.html?loadSpecs=true' : 'iframe.html?loadSpecs=true';
-
- src += '&compiled=' + !!me.options.compiled;
- if (me.options.specsset) {
- src += '&specsset=' + me.options.specsset;
- }
-
- iframe = new jasmine.Dom({
- tag: "iframe",
- cls: "sandboxIframe",
- name: "sandbox",
- frameBorder: 0,
- src: src
- });
- me.reporter.getIframeContainer().appendChild(iframe);
-
- win = iframe.contentWindow || window.frames[iframe.name];
- doc = iframe.contentDocument || win.document;
- this.iframe = iframe;
- this.win = win;
- this.doc = doc;
- };
- Test.SandBoxImpl.prototype.getIframe = function() {
- return this.iframe;
- };
- Test.SandBoxImpl.prototype.getWin = function() {
- return this.win;
- };
- Test.SandBoxImpl.prototype.getDoc = function() {
- return this.doc;
- };
- Test.SandBoxImpl.prototype.getBody = function() {
- return this.getDoc().body;
- };
- Test.SandBoxImpl.prototype.getHead = function() {
- return this.getDoc().getElementsByTagName("head")[0];
- };
- Test.SandBoxImpl.prototype.save = function(spec) {
- var doc = this.getDoc(),
- sb = doc.createElement("div"),
- body = this.getBody(),
- children = body && body.childNodes || [],
- length = children.length,
- i = 0,
- child,
- lwas = this.lengthWas || (this.lengthWas = 0);
- if (!this.options || !this.options.disableBodyClean) {
- //this.clearComponents();
- //this.clearDomElements();
- }
- if (length != lwas) {
- if (!window.headless) {
- this.reporter.log(">> Warning the document.body dom element contains childNodes after spec execution !<br/>" +
- "Spec : " + jasmine.util.htmlEscape(spec.getFullName()) + ' <a href="?' +
- Test.Options.urlEncode({specs: [spec.id], suites:[], disableBodyClean: true}) + '">Load this spec only and disable body autoclean</a><br/>',
- "warning");
- } else {
- this.reporter.log("Warning: " + spec.getFullName() + "doesn't clean properly the document.body.");
- }
- this.lengthWas = length;
- }
- };
- Test.SandBoxImpl.prototype.clearDomElements = function() {
- var doc = this.getDoc(),
- bd = this.getBody(),
- children = bd.childNodes,
- length = children.length,
- i, child;
- if (!this.options.disableBodyClean) {
- for (i = 0; i < length; i++) {
- child = children[i];
- if (child) {
- bd.removeChild(child);
- }
- }
- }
- };
- Test.SandBoxImpl.prototype.clearComponents = function() {
- var me = this,
- win = me.getWin(),
- comps, c, len, i;
- if(win.Ext && win.Ext.ComponentManager) {
- comps = win.Ext.ComponentManager.all.getArray();
- len = comps.length;
- for(i=0; i<len; i++) {
- c = comps[i];
- c.destroy();
- }
- }
- };
- Test.SandBoxImpl.prototype.isRunning = function() {
- return !this.getWin().jasmine.getEnv().currentRunner_.queue.isRunning();
- };
- Test.SandBoxImpl.prototype.iScope = function(o) {
- if (typeof o === "function") {
- o = "(" + o.toString() + ")();";
- }
- return Test.SandBox.getWin().eval(o);
- };
- Test.SandBox = new Test.SandBoxImpl();
- var iScope = Test.SandBox.iScope; /**
- * @class Test.CodeHighLighter
- * A javascript simple source code higlighter and beautifier (optional).
- */
- Test.CodeHighLighter = function(config) {
- /**
- * @cfg {String} source The source string to process.
- */
- this.source = config.source;
- this.lineNumber = config.lineNumber;
- this.linesFromJsCoverage = config.linesFromJsCoverage;
-
- this.beautify = config.beautify || this.lineNumber === undefined;
- this.highLightCode = config.highLightCode === false ? false : true;
-
- this.matchedComments = [];
- this.matchedStrings = [];
- };
- /**
- * Regular expressions.
- */
- Test.CodeHighLighter.prototype.regExps = {
- strings: /"([^\\"\n]|\\.)*"|'([^\\'\n]|\\.)*'|"([^\\"\n]|\\\n)*"|'([^\\'\n]|\\\n)*'/gm,
- comments: /\/\/.*$|\/\*[\s\S]*?\*\//gm,
- operators: /([\+\-\*\/=\?!]{1,3}|[\-\+]{1,2})/g,
- numbers: /\b([0-9]+)\b/g,
- keywords: [/\b(break)\b/g, /\b(case)\b/g, /\b(catch)\b/g, /\b(continue)\b/g, /\b(default)\b/g,
- /\b(delete)\b/g, /\b(do)\b/g, /\b(else)\b/g, /\b(false)\b/g, /\b(for)\b/g, /\b(function)\b/g,
- /\b(if)\b/g, /\b(in)\b/g, /\b(instanceof)\b/g, /\b(new)\b/g, /\b(null)\b/g,
- /\b(return)\b/g, /\b(switch)\b/g, /\b(this)\b/g, /\b(throw)\b/g, /\b(true)\b/g,
- /\b(try)\b/g,/\b(typeof)\b/g, /\b(var)\b/g, /\b(while)\b/g, /\b(with)\b/g],
- commasInsideParenthesis: /\(([^\(\)\{\}])+\)/g,
- arrayWithOneElement: /\[\n([^,\]]*)\n\]/g,
- commaBracket: /,\n\s*\{/g,
- multipleWhiteSpaces: /(\s+)/g,
- semiColon: /;/g,
- comma: /,/g,
- openedBrackets: /([\{\[])/g,
- closedBrackets: /([\}\]])/g,
- emptyObject: /\{\n\s*\n\}/g,
- openedBracketsWithNewLine: /[\{\[]$/g,
- closedBracketsWithNewLine: /^\s*[\}\]]/g,
- unwantedNewLines: /\n([\n,;\)])/g,
- newLine: /\n/g,
- firstSpaces: /^(\s)+/
- };
- /**
- * Populates an array of matched objects.
- * @param {String} value The match result.
- * @param {Number} index The index of the match.
- * @param {Array} matchedObjects The array of matches to populate.
- * @param {String} css The css to apply to the match.
- * @return {Boolean} Returns <tt>true</tt> is the match is inside another.
- */
- Test.CodeHighLighter.prototype.matchObjects = function(value, index, matchedObjects, css) {
- matchedObjects.push({
- origValue: value,
- value: '<span class="jsHl'+ css +'">' + jasmine.util.htmlEscape(value).replace("$","$\b") + '</span>',
- start: index,
- end: index + value.length
- });
- };
- /**
- * Checks if a match is inside another matches.
- * @param {Object} matchedObject The checked match.
- * @param {Array} matchedOthers The array that contains other matches.
- * @return {Boolean} Returns <tt>true</tt> is the match is inside another.
- */
- Test.CodeHighLighter.prototype.isInside = function(matchedObject, matchedOthers) {
- var start = matchedObject.start,
- end = matchedObject.end,
- length = matchedOthers.length,
- matchedOther, i;
- for (i = 0; i < length; i++) {
- matchedOther = matchedOthers[i];
- if (matchedOther.start < start && start < matchedOther.end) {
- return true;
- }
- }
- return false;
- };
- /**
- * This function get rid of any matches that are inside of other matches.
- * If a match isn't inside another it is replaced by a string in {@link #source}
- * in order to protect it from {@link #processOperatorsNumbersKeywords} replace tricks.
- * @param {Array} matchedObjects The array of matches to check.
- * @param {Array} matchedOthers The array that contains other matches.
- * @param {String} protect The replacement string
- */
- Test.CodeHighLighter.prototype.fixOverlaps = function(matchedObjects, matchedOthers, protect) {
- var result = [],
- length = matchedObjects.length,
- matchedObject,
- i;
-
- for (i = 0; i < length; i++) {
- matchedObject = matchedObjects[i];
- if (!this.isInside(matchedObject, matchedOthers)) {
- this.source = this.source.replace(matchedObject.origValue, protect);
- result.push(matchedObject);
- }
- }
- return result;
- };
- /**
- * Replaces Strings and Comments in javascript source code.
- */
- Test.CodeHighLighter.prototype.saveStringsAndComments = function() {
- var commentsRe = this.regExps.comments,
- stringsRe = this.regExps.strings,
- exec;
-
-
- while((exec = commentsRe.exec(this.source))) {
- this.matchObjects(exec[0], exec.index, this.matchedComments, "Comment");
- }
-
- while((exec = stringsRe.exec(this.source))) {
- this.matchObjects(exec[0], exec.index, this.matchedStrings, "String");
- }
- this.matchedComments = this.fixOverlaps(this.matchedComments, this.matchedStrings, "%%%%comment%%%%");
- this.matchedStrings = this.fixOverlaps(this.matchedStrings, this.matchedComments, '%%%%string%%%%');
- };
- /**
- * Process strings and comments saved by {@link #saveStringsAndComments}.
- */
- Test.CodeHighLighter.prototype.processStringsAndComments = function() {
- var matches = this.matchedComments,
- length = matches ? matches.length : 0,
- value, i;
- for (i = 0; i < length; i++) {
- value = matches[i].value;
- this.source = this.source.replace("%%%%comment%%%%", value);
- }
-
- matches = this.matchedStrings;
- length = matches ? matches.length : 0;
-
- for (i = 0; i < length; i++) {
- value = matches[i].value;
- this.source = this.source.replace('%%%%string%%%%', value);
- }
- };
- /**
- * Highlight operators, numbers and keywords.
- */
- Test.CodeHighLighter.prototype.processOperatorsNumbersKeywords = function() {
- var regexps = this.regExps,
- keywords = regexps.keywords,
- length = keywords.length,
- i;
-
- this.source = jasmine.util.htmlEscape(this.source).replace(
- regexps.operators, '<span class="jsHlOperator">$1</span>').replace(
- regexps.numbers, '<span class="jsHlNumber">$1</span>');
-
- for (i = 0; i < length; i++) {
- this.source = this.source.replace(keywords[i], '<span class="jsHlKeyword">$1</span>');
- }
- };
-
- /**
- * Format and highligth javascript sources.
- * @return The HTML formatted and highlighted code
- */
- Test.CodeHighLighter.prototype.process = function() {
- this.saveStringsAndComments();
-
- if (this.beautify) {
- this.prepareIndent();
- this.doIndent();
- }
-
- this.processOperatorsNumbersKeywords();
- this.processStringsAndComments();
- return this.source;
- };
- /**
- * Render sources with line numbers.
- * @return The HTML formatted and highlighted code
- */
- Test.CodeHighLighter.prototype.renderJsSources = function() {
- var result = 'No code found.',
- linesFromJsCoverage = this.linesFromJsCoverage,
- lineNumber = this.lineNumber,
- source = this.source,
- lines, line, i, errorCls, length, lineNumberCls;
- if (source) {
- source = this.highLightCode ? this.process() : source;
- lines = source.split("\n");
- length = lines.length;
-
- result = '<table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="lineNumbers">';
- for (i = 0; i < length; i++) {
- errorCls = "";
- lineNumberCls = "";
- if (lineNumber) {
- errorCls = i === (lineNumber - 1) ? " error" : "";
- }
- if (linesFromJsCoverage) {
- lineNumberCls = !isNaN(linesFromJsCoverage[i + 1]) ? " lineNumberGreen" : "";
- lineNumberCls = linesFromJsCoverage[i + 1] === 0 ? " lineNumberRed" : lineNumberCls;
- }
- result += '<div class="lineNumber' + errorCls + lineNumberCls + '">' + (i + 1) +'</div>';
- }
- result += '</td><td><pre class="code">'+ source +'</pre></td></tr></tbody></table>';
- }
-
- this.source = result;
- return this.source;
- };
- /**
- * Prepares source code. It crops double whitespace and append new lines.
- * This function is used generally to preformat the code that come from a
- * Function.prototype.toString.
- */
- Test.CodeHighLighter.prototype.prepareIndent = function() {
- var regexps = this.regExps,
- matches, length, i, m;
-
- this.source = this.source.replace(
- regexps.multipleWhiteSpaces, " ").replace(
- regexps.semiColon, ";\n").replace(
- regexps.comma, ",\n").replace(
- regexps.openedBrackets, "$1\n").replace(
- regexps.closedBrackets, "\n$1\n");
-
- // remove newline after commas inside code parenthesis
- matches = this.source.match(regexps.commasInsideParenthesis);
- length = matches ? matches.length : 0;
- for (i = 0; i < length; i++) {
- m = matches[i];
- this.source = this.source.replace(m, m.replace(regexps.newLine, ""));
- }
-
- // fixes various bad formatting
- this.source = this.source.replace(regexps.arrayWithOneElement, "[$1]").replace(
- regexps.emptyObject, "{}").replace(
- regexps.commaBracket, ", {").replace(
- regexps.unwantedNewLines, "$1");
- };
- /**
- * Creates a string composed of n whitespaces
- * @param {Number} number The number of white spaces.
- * @return {String} A multiple whitespace string.
- */
- Test.CodeHighLighter.prototype.addWhiteSpaces = function (number) {
- var whiteSpaces = "",
- i;
-
- for (i = 0; i < number; i++) {
- whiteSpaces += " ";
- }
- return whiteSpaces;
- };
- /**
- * Indents pre-formatted source code.
- */
- Test.CodeHighLighter.prototype.doIndent = function() {
- var regexps = this.regExps,
- results = [],
- indent = 0,
- sources = this.source.split("\n"),
- length = sources.length,
- whiteSpaces = "",
- source, i;
- for (i = 0; i < length; i++) {
- source = sources[i].replace(regexps.firstSpaces, '');
- if (source !== "") {
- if (source.search(regexps.closedBracketsWithNewLine) !== -1) {
- indent = Math.max(indent - 4, 0);
- whiteSpaces = this.addWhiteSpaces(indent);
- }
- results.push(whiteSpaces + source);
- if (source.search(regexps.openedBracketsWithNewLine) !== -1) {
- indent += 4;
- whiteSpaces = this.addWhiteSpaces(indent);
- }
- }
- }
- this.source = results.join("\n");
- };
- /**
- * Init allowedGlobals array.
- */
- Test.BadGlobalsImpl = function(reporter) {
- this.results = [];
- };
- Test.BadGlobalsImpl.prototype.setup = function() {
- var me = this,
- win = Test.SandBox.getWin(),
- property;
-
- // whitelist support
- win.addGlobal = function() {
- me.addGlobal.apply(me, arguments);
- };
-
- me.allowedGlobals = {};
- for (property in win) {
- me.allowedGlobals[property] = true;
- }
- // add firebug globals variables to white list
- me.allowedGlobals._firebug = true;
- me.allowedGlobals._createFirebugConsole = true;
- me.allowedGlobals.loadFirebugConsole = true;
- me.allowedGlobals.console = true;
- };
- /**
- * Append to suite HTMLElement warning messages if improper global variables are found.
- * @param {HTMLElement} suiteEl The suite HTMLElement.
- */
- Test.BadGlobalsImpl.prototype.report = function(info, suite) {
- var allowedGlobals = this.allowedGlobals,
- win = Test.SandBox.getWin(),
- property, message, value;
-
- for (property in win) {
- if (!allowedGlobals[property]) {
- value = jasmine.pp(win[property]);
- message = ">> Bad global variable found in " + (suite ? suite.description : "global scope") + "<br/>" + property + " = " + value;
- info.log(message, "warning");
- this.results[property] = {
- where: (suite ? ('in suite' + suite.description) : "global scope"),
- value: value
- };
- allowedGlobals[property] = true;
- }
- }
- };
- Test.BadGlobalsImpl.prototype.addGlobal = function(property) {
- this.allowedGlobals[property] = true;
- };
- if (!jasmine.browser.isIE && !jasmine.browser.isOpera) {
- Test.BadGlobals = new Test.BadGlobalsImpl();
- }/**
- * @singleton Test.jsCoverage
- * The jscoverage manager.
- */
- Test.jsCoverage = {
- executed: 0,
- coverage: {},
- isEnabled: function() {
- return !!Test.SandBox.getWin()._$jscoverage;
- },
- getCoverage: function() {
- return this.coverage;
- },
-
- getSandBoxCoverage: function() {
- return Test.SandBox.getWin()._$jscoverage;
- },
- /**
- * Adds suite to the jscoverage manager.
- * @param {jasmine.Suite} The jasmine suite.
- */
- add: function(suite) {
- var coverage = this.getSandBoxCoverage(),
- filename, file, property, statement;
-
- if (!coverage) {
- return;
- }
- filename = this.getFileName(suite.coverageFile);
- file = coverage[filename];
- if (coverage && file) {
- for (property in file) {
- if (!file.hasOwnProperty(property)) {
- continue;
- }
- statement = file[property];
- }
- }
- },
- /**
- * This methods try to find the corresponding javascript source file.
- * @param {String} The filename.
- */
- getFileName: function(filename) {
- var coverage = this.getSandBoxCoverage(),
- property;
-
- if (!coverage || !filename) {
- return;
- }
-
- if (coverage[filename]) {
- return filename;
- }
-
- for (property in coverage) {
- if (property.search(filename) !== -1) {
- return property;
- }
- }
- },
- /**
- * Updates suite coverage results after execution.
- * @param {jasmine.Suite} The jasmine suite.
- */
- update: function(suite) {
- var coverage = this.getSandBoxCoverage(),
- statements = 0,
- executed = 0,
- property, statement, filename, file;
-
- if (!coverage) {
- return;
- }
-
- filename = this.getFileName(suite.coverageFile);
- file = coverage[filename];
-
- if (file) {
- suite.jscoverage = {
- file: []
- };
-
- for (property in file) {
- if (!file.hasOwnProperty(property)) {
- continue;
- }
- statement = file[property];
-
- suite.jscoverage.file[property] = statement;
-
- if (!isNaN(property) && statement !== undefined) {
- statements = statements + 1;
- if (statement !== 0) {
- this.executed = this.executed + 1;
- executed = executed + 1;
- }
- }
- }
- suite.jscoverage.percentage = ((executed/statements) * 100).toFixed(2);
- suite.jscoverage.statements = statements;
- suite.jscoverage.executed = executed;
- this.coverage[filename] = suite.jscoverage.file;
- this.coverage[filename].percentage = suite.jscoverage.percentage;
- this.coverage[filename].statements = suite.jscoverage.statements;
- this.coverage[filename].executed = suite.jscoverage.executed;
- }
- },
- /**
- * Returns suite coverage text.
- * @param {jasmine.Suite} The jasmine suite.
- * @return {String} The Code coverage text<
- */
- getSuiteCoverage: function(suite) {
- if (suite.jscoverage) {
- return " - Code coverage: " + suite.jscoverage.percentage + "%";
- }
- return '';
- },
- /**
- * Gets total code coverage.
- * @return {String} A string with total code coverage.
- */
- getTotal: function() {
- if (this.percentage) {
- return " - Code coverage: " + this.percentage + "%";
- }
-
- return '';
- },
- updateTotal: function() {
- var coverage = this.getSandBoxCoverage(),
- statements = 0,
- file, filename, statement, property, fstatements, fexecuted, create;
-
- if(!coverage) {
- return "";
- }
-
- for (filename in coverage) {
- if (!coverage.hasOwnProperty(filename)) {
- continue;
- }
- file = coverage[filename];
- fstatements = 0;
- fexecuted = 0;
-
- create = !this.coverage[filename];
- if (create) {
- this.coverage[filename] = [];
- }
- for (property in file) {
- if (!file.hasOwnProperty(property)) {
- continue;
- }
- statement = file[property];
-
- if (!isNaN(property)) {
- if (statement !== undefined) {
- statements = statements + 1;
- fstatements = fstatements + 1;
- }
- if (create) {
- this.coverage[filename][property] = 0;
- }
- }
- }
-
- if (create) {
- this.coverage[filename].source = file.source;
- this.coverage[filename].statements = fstatements;
- this.coverage[filename].executed = fexecuted;
- this.coverage[filename].percentage = ((fexecuted/fstatements) * 100).toFixed(2);
- }
- }
- this.statements = statements;
- this.percentage = ((this.executed/statements) * 100).toFixed(2);
- }
-
- };Test.panel = {};
- /**
- * Renders Jasmine Blocks executed by spec.
- * @param {Jasmine.spec} spec The spec.
- * @param {HTMLElement} panelsEl The HTMLElement which encapsulate the tools panels.
- */
- Test.panel.Blocks = function(config) {
- var blocks = config.spec.queue.blocks,
- length = blocks.length,
- cls = "panel blocks",
- children = [],
- i, block, codeHighLighter;
- for (i = 0; i < length; i++) {
- block = blocks[i];
- if (block.func) {
- children.push({
- cls: "blockTitle " + (block.func.typeName || "specSources"),
- html: block.func.typeName || 'it("' + jasmine.util.htmlEscape(config.spec.description) + '")'
- });
- codeHighLighter = new Test.CodeHighLighter({
- source: block.func.toString()
- });
- children.push({
- cls: "sources",
- html: codeHighLighter.renderJsSources()
- });
- }
- }
-
- this.el = new jasmine.Dom({
- cls: cls,
- children: children
- });
- return this;
- };
- Test.panel.Blocks.prototype.remove = function() {
- this.el.parentNode.removeChild(this.el);
- };/**
- * Renders spec dom sandbox tool.
- * @param {Jasmine.spec} spec The spec.
- * @param {HTMLElement} panelsEl The HTMLElement which encapsulate the tools panels.
- */
- Test.panel.Sandbox = function(config) {
- this.persist = true;
- this.render();
- return this;
- };
- /**
- * Renders spec dom sandbox innerHTML.
- * @return {HTMElement} The formatted dom sandbox innerHTML.
- */
- Test.panel.Sandbox.prototype.render = function() {
- this.el = new jasmine.Dom({
- cls: "panel sandbox hideMe"
- });
- };/**
- * Renders infos panel.
- */
- Test.panel.Infos = function() {
- this.el = new jasmine.Dom({
- tag: "div",
- cls: "panel infos",
- children: [{
- cls: "logs"
- }]
- });
- this.logs = this.el.childNodes[0];
- this.persist = true;
- return this;
- };
- /**
- * Print a message into console.
- * @param {String} message The message.
- * @param {String} cls (optional) an extra cls to add to the message.
- */
- Test.panel.Infos.prototype.log = function(message, cls) {
- var log = this.logs.appendChild(new jasmine.Dom({
- cls: "infoMessage",
- html: message
- }));
-
- if (cls) {
- jasmine.Dom.addCls(log, cls);
- }
- };/**
- * @class jasmine.panel.jsCoverage
- * Creates and renders a per spec jscoverage panel.
- * @param {Object} config The configuration object.
- */
- Test.panel.jsCoverage = function(config) {
- this.el = new jasmine.Dom({
- tag: "div",
- cls: "panel jsCoverage",
- children: [{
- cls: "sources",
- html: new Test.CodeHighLighter({
- source: config.suite.jscoverage.file.source.join("\n"),
- linesFromJsCoverage: config.suite.jscoverage.file,
- highLightCode: false
- }).renderJsSources()
- }]
- });
- return this;
- };
- Test.panel.jsCoverage.prototype.remove = function() {
- this.el.parentNode.removeChild(this.el);
- };/**
- * @class jasmine.panel.jsCoverageSummary
- * Creates and renders the persistant jscoverage summary panel.
- * @param {Object} config The configuration object.
- */
- Test.panel.jsCoverageSummary = function(config) {
- var me = this;
-
- me.el = new jasmine.Dom({
- tag: "div",
- cls: "panel jsCoverageSummary hideMe",
- onclick: function() {
- me.onClick.apply(me, arguments);
- },
- children: [{
- cls: "sbody"
- }]
- });
-
- me.body = me.el.childNodes[0];
- me.persist = true;
- this.renderSummary();
- return me;
- };
- /**
- * Renders summary view.
- */
- Test.panel.jsCoverageSummary.prototype.renderSummary = function() {
- var coverage = Test.jsCoverage.getCoverage(),
- filename, result;
-
- if (!this.summary) {
- result = '<table class="summary" border="0" cellpadding="0" cellspacing="0"><tbody>';
- result += '<tr class="line header"><td class="fileName">File</td><td class="statements">Statements</td><td class="executed">Executed</td><td class="percentage">Percentage</td></tr>';
- result += '<tr class="line total">';
- result += '<td class="fileName">Total</td>';
- result += '<td class="statements">' + Test.jsCoverage.statements + "</td>";
- result += '<td class="executed">' + Test.jsCoverage.executed + "</td>";
- result += '<td class="percentage">' + this.renderPercentage(Test.jsCoverage.percentage) + "</td>";
- result += '</tr>';
-
- for (filename in coverage) {
- if (!coverage.hasOwnProperty(filename)) {
- continue;
- }
- result += '<tr class="line">';
- result += '<td class="fileName"><a>' + filename + "</a></td>";
- result += '<td class="statements">' + coverage[filename].statements + "</td>";
- result += '<td class="executed">' + coverage[filename].executed + "</td>";
- result += '<td class="percentage">' + this.renderPercentage(coverage[filename].percentage) + "</td>";
- result += '</tr>';
- }
- result += '</tbody></table>';
- this.summary = result;
- }
- this.body.innerHTML = this.summary;
- };
- /**
- * Renders percentage progress bar.
- * @return {String} The progressbar html.
- */
- Test.panel.jsCoverageSummary.prototype.renderPercentage = function(percent) {
- var result = percent + '%<div class="limit" style="width:300px;">';
- result += '<div class="result" style="width:' + 3 * percent + 'px;"></div>';
-
- result += '</div>';
- return result;
- };
- /**
- * Renders percentage progress bar.
- * @return {String} The progressbar html.
- */
- Test.panel.jsCoverageSummary.prototype.onClick = function(event) {
- var el;
- event = event || window.event;
- el = event.target || event.srcElement;
- if (el.tagName === "A") {
- this.renderSource(Test.jsCoverage.getCoverage()[el.innerHTML]);
- }
-
- if (jasmine.Dom.hasCls(el,"back")) {
- this.renderSummary();
- }
- };
- /**
- * Renders file source.
- */
- Test.panel.jsCoverageSummary.prototype.renderSource = function(coverage) {
- this.body.innerHTML = "";
- this.body.appendChild(new jasmine.Dom({
- cls: "back",
- html: "Back"
- }));
-
- this.body.appendChild(new jasmine.Dom({
- cls: "sources",
- html: new Test.CodeHighLighter({
- source: coverage.source.join("\n"),
- linesFromJsCoverage: coverage,
- highLightCode: false
- }).renderJsSources()
- }));
- };/**
- * Renders stack trace tool.
- * @param {Jasmine.spec} The jasmine spec.
- * @return {HTMLElement} The created HTMLElement.
- */
- Test.panel.StackTrace = function(config) {
- this.spec = config.spec;
- this.badLinesEls = [];
-
- var resultItems = this.spec.results().getItems(),
- length = resultItems.length,
- result,
- error,
- lines,
- i;
- if (jasmine.browser.isIE || !this.spec.hasError) {
- return this;
- }
-
- for (i = 0; i < length; i++) {
- result = resultItems[i];
- if (result.type == "expect" && result.passed && !result.passed()) {
- if (result.error) {
- error = result.error;
- break;
- }
- }
- }
-
- if (error) {
- lines = this.extractStackTrace(error);
- this.el = new jasmine.Dom({
- tag: "div",
- cls: "panel stackTrace",
- children: this.renderStackLines(lines)
- });
- }
- return this;
- };
- /**
- * Extracts error stack trace.
- * @param {Error} e The javascript error object.
- * @return {Array} An array which contains all stack trace files and lineNumbers.
- */
- Test.panel.StackTrace.prototype.extractStackTrace = function(error) {
- var stack = error.stack || error.stackTrace,
- results = [],
- lines, line, length, i, extract, file, lineNumber;
-
- if (stack) {
- lines = stack.split("\n");
- length = lines.length;
- for(i = 0; i < length; i++) {
- line = lines[i];
- if (line.search("jasmine.js") === -1) {
- extract = this.extractFileAndLine(line);
- if (extract) {
- results.push(extract);
- }
- }
- }
- } else {
- file = error.sourceURL || error.fileName;
- lineNumber = error.line || error.lineNumber;
- if (file && lineNumber) {
- results.push({
- file: file,
- lineNumber: lineNumber
- });
- }
- }
- return results;
- };
- /**
- * Extracts filename and line number from a stack trace line.
- * @param {String} line The stack trace line.
- * @return {Object} An object containing the filename and the line number or null.
- */
- Test.panel.StackTrace.prototype.extractRe = /((http:\/\/|file:\/\/\/).*\.js)[^:]*:(\d*)/;
- Test.panel.StackTrace.prototype.extractFileAndLine = function(line) {
- var result = line.match(this.extractRe);
- if (!result) {
- return null;
- }
- return {
- file: result[1],
- lineNumber: result[3]
- };
- };
- /**
- * Render stack trace lines.
- * @param {String} file The filename.
- * @param {String/Number} lineNumber The line number.
- * @return {Array} An array containing all strace trace HTMLElements.
- */
- Test.panel.StackTrace.prototype.renderStackLines = function(lines) {
- var els = [],
- length = lines.length,
- el, line, i, file, lineNumber;
- for (i = 0; i < length; i++) {
- line = lines[i];
- file = line.file;
- lineNumber = parseInt(line.lineNumber, 0);
- el = new jasmine.Dom({
- cls: "stackTraceLine",
- children: [{
- cls: "fileName",
- html: "File: "+ file + " (line " + lineNumber + ")"
- },{
- cls: "sources",
- html: this.renderTraceFileSource(file, lineNumber)
- }]
- });
-
- this.badLinesEls.push({
- el: el.childNodes[1],
- line: lineNumber
- });
- els.push(el);
- }
-
- return els;
- };
- /**
- * Downloads source file.
- * @param {String} url The filename url.
- * @return {String} The file source or null.
- */
- Test.panel.StackTrace.prototype.getFile = function(file) {
- var request;
- if (jasmine.browser.isIE || Test.Options.remote) {
- return null;
- }
- this.downloadedFiles = this.downloadedFiles || {};
- if (!this.downloadedFiles[file]) {
- request = new XMLHttpRequest();
-
- if (!request) {
- return null;
- }
- request.open("GET", file + "?" + (new Date()).getTime(), false);
- request.send("");
- this.downloadedFiles[file] = request.responseText;
- }
-
- return this.downloadedFiles[file];
- };
- /**
- * Renders stack trace source file.
- * @param {String} file The filename.
- * @param {String/Number} lineNumber The line number.
- * @return {HTMLElement} The javascript source file HTMLElement.
- */
- Test.panel.StackTrace.prototype.jscoverageFileRe = /(http:\/\/|file:\/\/\/)[^\/]*/;
- Test.panel.StackTrace.prototype.renderTraceFileSource = function (file, lineNumber) {
- var highLightCode = true,
- source, instrumented_file, i, length, line;
- if (Test.SandBox.getWin()._$jscoverage) {
- instrumented_file = SandBox.getWin()._$jscoverage[file.replace(this.jscoverageFileRe, "")];
- if (instrumented_file) {
- highLightCode = false;
- source = instrumented_file.source.join("\n");
- linesFromJsCoverage = {};
- length = instrumented_file.length;
- for (i = 0; i < length; i++) {
- line = instrumented_file[i];
- if (line === 0) {
- linesFromJsCoverage[i-1] = true;
- }
- }
- }
- }
- source = source || this.getFile(file);
-
- return new Test.CodeHighLighter({
- source: source,
- highLightCode: highLightCode,
- lineNumber: lineNumber
- }).renderJsSources();
- };
- /**
- * Ensure that line which contains the error is visible without scroll.
- */
- Test.panel.StackTrace.prototype.afterRender = function() {
- var length = this.badLinesEls.length,
- badLine, firstChild, el, i, lineHeigth, visiblesLines;
- for (i = 0; i < length; i++) {
- badLine = this.badLinesEls[i];
- el = badLine.el;
- lineHeigth = 16;
- visiblesLines = el.clientHeight/lineHeigth;
- el.scrollTop = Math.max(badLine.line - visiblesLines/2, 0) * lineHeigth;
- }
-
- this.badLinesEls = [];
- };
- Test.panel.StackTrace.prototype.remove = function() {
- this.el.parentNode.removeChild(this.el);
- };/**
- * @class Test.panel.TabPanel
- * Renders inspection tools htmlElement.
- * @param {Object} config The configuration object.
- */
- Test.panel.TabPanel = function(config) {
- var me = this;
-
- me.options = Test.Options.get();
-
- me.spec = config.spec;
- me.container = config.container;
- me.el = new jasmine.Dom({
- cls: "tabpanel",
- onclick: function() {
- me.onTabPanelClick.apply(me, arguments);
- },
- children: [{
- cls: "toolBar"
- },{
- cls: "panels"
- }]
- });
-
- me.toolbar = me.el.childNodes[0];
- me.body = me.el.childNodes[1];
- me.children = [];
- me.tabs = [];
-
-
- me.container.appendChild(me.el);
- me.renderToolBar();
- me.add(new Test.panel.Infos({}));
- me.add(new Test.panel.Sandbox({}));
-
- if (me.options.panel) {
- me.activatePanel(me.options.panel);
- }
-
- return me;
- };
- /**
- * Adds a panel.
- * @param {Object} panel the panel to be added to this tabPanel.
- */
- Test.panel.TabPanel.prototype.add = function(panel) {
- if (panel.el) {
- this.body.appendChild(panel.el);
- }
- if (panel.afterRender) {
- panel.afterRender();
- }
- this.children.push(panel);
-
- if (panel.afterRender) {
- panel.afterRender();
- }
- };
- /**
- * Adds a tab
- * @param {Object} panel the panel to be added to this tabPanel.
- */
- Test.panel.TabPanel.prototype.addTab = function(cls, name, persist) {
- var el = this.toolbar.appendChild(new jasmine.Dom({
- tag: "span",
- cls: "toolbarTab " + cls,
- html: name
- }));
-
- this.tabs.push({
- el: el,
- persist: persist
- });
- };
- /**
- * Activate a tool panel and render it if needed.
- * @param {String} cls The panel className.
- */
- Test.panel.TabPanel.prototype.activatePanel = function(cls) {
- var children = this.children,
- length = children.length,
- rendered = false,
- child, i;
-
- for(i = 0; i < length; i++) {
- child = children[i].el;
- jasmine.Dom.addCls(child, "hideMe");
- if (jasmine.Dom.hasCls(child, cls)) {
- jasmine.Dom.removeCls(child, "hideMe");
- if (children[i].persist && cls !== "jsCoverageSummary") {
- this.options.panel = cls;
- } else {
- delete this.options.panel;
- }
- rendered = true;
- }
- }
- if (rendered) {
- return;
- }
-
- if (this.spec) {
- if (cls === "blocks") {
- this.add(new Test.panel.Blocks({
- spec: this.spec
- }));
- }
- if (cls === "stackTrace") {
- this.add(new Test.panel.StackTrace({
- spec: this.spec
- }));
- }
- }
-
- if (this.suite && this.suite.jscoverage) {
- if (cls === "jsCoverage") {
- this.add(new Test.panel.jsCoverage({
- suite: this.suite
- }));
- }
- }
- };
- /**
- * Reporter HTMLElement click dispatcher.
- * @param {Event} event The event
- */
- Test.panel.TabPanel.prototype.onTabPanelClick = function(event) {
- var el;
- event = event || window.event;
- el = event.target || event.srcElement;
- if (jasmine.Dom.hasCls(el, "toolbarTab")) {
- this.onTabClick(el);
- }
- };
- /**
- * Handle spec tools tab click.
- * @param {HTMLElement} el The tab HTMLElement.
- */
- Test.panel.TabPanel.prototype.onTabClick = function(el) {
- var tools, panels, length, child, i;
-
- jasmine.Dom.addCls(el, "selected");
- tools = this.toolbar.childNodes;
- panels = this.body.childNodes;
- length = tools.length;
- for(i = 0; i < length; i++) {
- child = tools[i];
- if (child != el) {
- jasmine.Dom.removeCls(child, "selected");
- }
- }
- this.activatePanel(el.className.split(" ")[1]);
- };
- /**
- * Renders inspection tabpanel toolbar which contain tabs.
- * @param {jasmine.Spec} spec The jasmine spec.
- * @param {HTMLElement} toolBarEl The toolbar HTMLElement
- */
- Test.panel.TabPanel.prototype.renderToolBar = function() {
- var spec = this.spec,
- suite = this.suite,
- toolbar = this.toolbar;
-
- if (this.tabs.length === 0) {
- this.addTab("infos selected", "Console", true);
- this.addTab("sandbox", "Iframe", true);
- } else {
- jasmine.Dom.addCls(this.tabs[0].el, "selected");
- }
-
- if (spec) {
- this.addTab("blocks", "Blocks");
-
- if (!jasmine.browser.isIE && !jasmine.browser.isOpera && this.spec.hasError) {
- this.addTab("stackTrace", "Stack Trace");
- }
- }
-
- if (suite && suite.jscoverage) {
- this.addTab("jsCoverage", "Suite Coverage");
- }
- };
- /**
- * Removes all non-persistant tabs.
- */
- Test.panel.TabPanel.prototype.resetToolBar = function() {
- var children = this.tabs,
- length = children.length,
- child, i;
- for (i = length - 1; i >= 0; i--) {
- child = children[i];
- if (!child.persist) {
- this.toolbar.removeChild(child.el);
- jasmine.array.remove(children, child);
- }
- jasmine.Dom.removeCls(child.el, "selected");
- }
-
- this.renderToolBar();
- };
- /**
- * Removes all non-persistant panels.
- */
- Test.panel.TabPanel.prototype.resetPanels = function() {
- var children = this.children,
- length = children.length,
- child, i;
- for (i = length - 1; i >= 0; i--) {
- child = children[i];
- if (!child.persist) {
- child.remove();
- jasmine.array.remove(children, child);
- }
- jasmine.Dom.addCls(child.el, "hideMe");
- }
-
- if (children[0]) {
- jasmine.Dom.removeCls(children[0].el, "hideMe");
- }
- };
- /**
- * Sets TabPanel current spec.
- */
- Test.panel.TabPanel.prototype.setSpec = function(spec) {
- this.spec = spec;
- delete this.suite;
- this.resetToolBar();
- this.resetPanels();
- };
- /**
- * Sets TabPanel current suite.
- */
- Test.panel.TabPanel.prototype.setSuite = function(suite) {
- this.suite = suite;
- delete this.spec;
- this.resetToolBar();
- this.resetPanels();
- };
- /**
- * Resize TabPanel dom element.
- */
- Test.panel.TabPanel.prototype.resize = function(val) {
- this.el.style.height = val + "px";
- this.body.style.height = val - 40 + "px";
- };
- /**
- * Adds jscoverage persistant panel.
- */
- Test.panel.TabPanel.prototype.addCoverageSummary = function() {
- this.addTab("jsCoverageSummary", "Coverage Summary", true);
- this.add(new Test.panel.jsCoverageSummary({}));
- };/**
- * @class Test.panel.TreeGrid
- * Creates and renders reporter treegrid.
- * @param {Object} config The configuration object.
- */
- Test.panel.TreeGrid = function(config) {
- var me = this;
- me.options = Test.Options.get();
-
- me.el = document.body.appendChild(new jasmine.Dom({
- tag: "div",
- cls: "treegrid",
- onmousedown: function() {
- me.onMouseDown.apply(me, arguments);
- },
- onmouseup: function() {
- me.onMouseUp.apply(me, arguments);
- },
- onmousemove: function() {
- me.onMouseMove.apply(me, arguments);
- },
- children: [{
- cls: "header",
- children: [{
- cls: "logo",
- html: "Sencha"
- },{
- cls: "statusMessage"
- },{
- cls: "toolBar",
- children: [{
- tag: "span",
- cls: "options",
- children: [
- Test.Options.renderCheckbox("showPassed", "Show passed"),
- Test.Options.renderCheckbox("showDisabled", "Show disabled"),
- Test.Options.renderCheckbox("collapseAll", "Collapse all"),
- Test.Options.renderCheckbox("disableBodyClean", "Disable Body Autoclean"),
- Test.Options.renderCheckbox("disableCacheBuster", "Disable CacheBuster"),
- Test.Options.renderCheckbox("showTimings", "Show Timings"),
- Test.Options.renderCheckbox("verbose", "Show jasmine logs"),
- Test.Options.renderCheckbox("autoReload", "Automatic reload"),
- Test.Options.renderCheckbox("quirksMode", "Quirks Mode")
- ]
- },{
- tag: "a",
- cls: "actionLink",
- html: "Run checked",
- onclick: function() {
- Test.Options.reloadWindow();
- }
- },{
- tag: "a",
- cls: "actionLink",
- html: "Run all",
- onclick: function() {
- Test.Options.reloadWindow(true);
- }
- }]
- }]
- },{
- tag: "div",
- cls: "tbody",
- onclick: function() {
- me.onBodyClick.apply(me, arguments);
- }
- }, {
- cls: "resizer",
- html: "......"
- }]
- }));
- me.tabPanel = new Test.panel.TabPanel({
- container: me.el
- });
-
- Test.Options.check();
- me.header = me.el.childNodes[0];
- me.statusMessage = me.header.childNodes[1];
- me.toolBar = me.header.childNodes[2];
- me.body = me.el.childNodes[1];
- me.resizer = me.el.childNodes[2];
-
- me.suites = {};
- me.specs = {};
- me.suitesEls = {};
- me.specsEls = {};
- if (me.options.resizer) {
- me.tabPanel.resize(parseInt(me.options.resizer, 10));
- }
- me.resizeBody();
- window.onresize = function() {
- me.resizeBody();
- };
- };
- /**
- * Renders suite htmlElement.
- * @param {jasmine.Suite} suite The jasmine suite.
- * @return {HTMLElement} The suite HTMLElement
- */
- Test.panel.TreeGrid.prototype.addSuite = function(suite) {
- var options = {},
- parent = suite.parentSuite,
- padding = 18,
- prefix = suite.isDisabled() ? "xdescribe :" : "describe: ",
- cls = "noexpand",
- row, property;
-
- if (suite.children_.length !== 0) {
- cls = this.options.collapseAll ? "expand" : "collapse";
- }
-
- if (parent) {
- this.suitesEls[parent.id] || this.addSuite(parent);
- while(parent) {
- padding += 18;
- parent = parent.parentSuite;
- }
- }
- row = this.createRow(this.options.collapseAll && suite.parentSuite, suite);
- for (property in this.options) {
- if (!this.options.hasOwnProperty(property)) {
- continue;
- }
- options[property] = this.options[property];
- }
- options.suite = suite.id;
- delete options.spec;
-
- this.suitesEls[suite.id] = new jasmine.Dom({
- tag: "div",
- id: "suite-" + suite.id,
- cls: "suite " + (suite.isDisabled() ? "disabled" : ""),
- style: {
- "paddingLeft": padding + "px"
- },
- children: [{
- cls: cls
- },{
- tag: "span",
- cls: "description",
- html: prefix + suite.description
- }]
- });
-
- row.appendChild(this.suitesEls[suite.id]);
- var clear = new jasmine.Dom({ tag: 'div' });
- clear.style.clear = 'both';
- row.appendChild(clear);
- this.suites[suite.id] = suite;
-
- return this.suitesEls[suite.id];
- };
- /**
- * Updates suite dom element by adding a code coverage percentage to it's description.
- * @param {HTMLElement} The suite dom element.
- * @param {jasmine.Suite} The jasmine suite.
- */
- Test.panel.TreeGrid.prototype.updateSuiteEl = function(suite, text) {
- var description = this.suitesEls[suite.id].childNodes[1];
- jasmine.Dom.setHTML(description, description.innerHTML + text);
- };
- /**
- * Renders spec htmlElement.
- * @param {jasmine.Spec} spec The jasmine spec.
- * @return {HTMLElement} The spec HTMLElement
- */
- Test.panel.TreeGrid.prototype.addSpec = function(spec) {
- var options = {},
- padding = 18,
- suite = spec.suite,
- suffix = spec.time ? " (" + spec.time + "s)" : "",
- row, prefix, status, property, specEl, resultPanel;
-
- if (spec.isEnabled()) {
- prefix = "it ";
- status = spec.results().passed() ? "passed" : "failed";
- } else {
- prefix = "xit ";
- status = "disabled";
- }
-
- if (suite) {
- this.suitesEls[suite.id] || this.addSuite(suite);
- while(suite) {
- padding += 18;
- suite = suite.parentSuite;
- }
- }
-
- row = this.createRow(this.options.collapseAll, spec);
- for (property in this.options) {
- if (this.options.hasOwnProperty(property)) {
- options[property] = this.options[property];
- }
- }
- options.spec = spec.id;
- delete options.suite;
-
- specEl = {
- id: "spec-" + spec.id,
- cls: "spec " + status,
- style: {
- "paddingLeft": padding + "px"
- },
- children: [{
- cls: this.options.collapseAll ? "expand" : "collapse"
- },{
- tag: "span",
- cls: "description",
- html: prefix + spec.description + suffix
- }]
- };
- resultPanel = this.renderSpecResults(spec);
- if (this.options.collapseAll) {
- resultPanel.style.display = "none";
- }
-
- if (resultPanel.innerHTML === "") {
- specEl.children[0].cls = "noexpand";
- }
-
- specEl.children.push(resultPanel);
-
- specEl = new jasmine.Dom(specEl);
- this.specsEls[spec.id] = specEl;
- this.specs[spec.id] = spec;
- row.appendChild(specEl);
- jasmine.Dom.addCls(row, status);
- var clear = new jasmine.Dom({ tag: 'div' });
- clear.style.clear = 'both';
- row.appendChild(clear);
- };
- /**
- * Returns a suite by id.
- * @param {String/Number} id The suite id.
- * @return {jasmine.Suite} The jasmine suite.
- */
- Test.panel.TreeGrid.prototype.getSuite = function(id) {
- return this.suites[parseInt(id, 10)];
- };
- /**
- * Returns a spec by id.
- * @param {String/Number} id The spec id.
- * @return {jasmine.Spec} The jasmine spec.
- */
- Test.panel.TreeGrid.prototype.getSpec = function(id) {
- return this.specs[parseInt(id, 10)];
- };
- /**
- * Body elements click event dispatcher.
- */
- Test.panel.TreeGrid.prototype.onBodyClick = function(event) {
- event = event || window.event;
- var el = event.target || event.srcElement,
- cls = el.className,
- i;
-
- if (cls) {
- if (jasmine.Dom.hasCls(el, "collapse")) {
- this.onCollapse(el);
- return;
- }
- if (jasmine.Dom.hasCls(el, "expand")) {
- this.onExpand(el);
- return;
- }
- if (jasmine.Dom.hasCls(el, "select-checkbox")) {
- this.onCheck(el);
- return;
- }
- for (i = 0; i < 6; i++) {
- if (cls && jasmine.Dom.hasCls(el, "row")) {
- this.onRowClick(el);
- return;
- }
- el = el.parentNode;
- if (!el) {
- break;
- }
- cls = el.className;
- }
- }
- };
- /**
- * Checkboxes listener.
- */
- Test.panel.TreeGrid.prototype.onCheck = function(el) {
- var next = el.parentNode.nextSibling,
- id;
- if (jasmine.Dom.hasCls(next,"spec")) {
- id = parseInt(next.id.replace("spec-", ""), 10);
- if (el.checked) {
- if (jasmine.array.indexOf(this.options.specs, id) === -1) {
- this.options.specs.push(id);
- }
- } else {
- jasmine.array.remove(this.options.specs, id);
- }
- } else {
- id = parseInt(next.id.replace("suite-", ""), 10);
- if (el.checked) {
- if (jasmine.array.indexOf(this.options.suites, id) === -1) {
- this.options.suites.push(id);
- }
- } else {
- jasmine.array.remove(this.options.suites, id);
- }
- }
- };
- /**
- * Returns row dom element by spec or suite.
- * @param {jasmine.Suite/jasmine.Spec} o A suite or a spec.
- * @return {HTMLElement} The row dom element.
- */
- Test.panel.TreeGrid.prototype.getRow = function(o) {
- if (!o.suite && this.suitesEls[o.id]) {
- return this.suitesEls[o.id].parentNode;
- } else if (this.specsEls[o.id]) {
- return this.specsEls[o.id].parentNode;
- }
- };
- /**
- * Iterates nested rows calling the supplied function.
- * @param {HTMLElement} row The row.
- * @param {Function} fn The function.
- * @param {Boolean} recursive recurse in all children suite (default to true)
- */
- Test.panel.TreeGrid.prototype.onEachRow = function(row, fn, recursive) {
- var me = this,
- id = row.childNodes[1].id,
- traverse = function(s, func) {
- var children = s.children_,
- i, child, length, r;
-
- if (children) {
- length = children.length;
- for (i = 0; i < length; i++) {
- child = children[i];
- r = me.getRow(child);
- if (r) {
- func.call(me, r, child);
- if (child.children_ && recursive !== false) {
- traverse(child, func);
- }
- }
- }
- }
- },
- spec, suite;
-
- if (id.search("suite") !== -1) {
- suite = this.getSuite(id.replace("suite-", ""));
- traverse(suite, fn);
- } else {
- spec = this.getSpec(id.replace("spec-", ""));
- traverse(spec, fn);
- }
- };
- /**
- * Collapse click handler.
- */
- Test.panel.TreeGrid.prototype.onCollapse = function(el) {
- el = el.parentNode;
- jasmine.Dom.setCls(el.childNodes[0], "expand");
-
- if (jasmine.Dom.hasCls(el, "suite")) {
- this.onEachRow(el.parentNode, function(row, o) {
- var childNode = row.childNodes[1],
- icon = childNode.childNodes[0],
- content = childNode.childNodes[2];
-
- row.style.display = "none";
- if (jasmine.Dom.hasCls(icon, "collapse")) {
- jasmine.Dom.setCls(icon, "expand");
- }
- if (o.suite) {
- content.style.display = "none";
- }
- });
- } else {
- el.childNodes[2].style.display = "none";
- }
- };
- /**
- * Expand click handler.
- */
- Test.panel.TreeGrid.prototype.onExpand = function(el) {
- el = el.parentNode;
- jasmine.Dom.setCls(el.childNodes[0], "collapse");
-
- if (jasmine.Dom.hasCls(el, "suite")) {
- this.onEachRow(el.parentNode, function(row, o) {
- row.style.display = "block";
- }, false);
- } else {
- el.childNodes[2].style.display = "block";
- }
- };
- /**
- * Row click click handler.
- */
- Test.panel.TreeGrid.prototype.onRowClick = function(el) {
- var rows = el.parentNode.childNodes,
- length = rows.length,
- id, i;
-
- for (i = 0; i < length; i++) {
- jasmine.Dom.removeCls(rows[i], "selected");
- }
-
- jasmine.Dom.addCls(el, "row selected");
- id = el.childNodes[1].id;
-
- if (id.search("spec") !== -1) {
- this.tabPanel.setSpec(this.getSpec(id.replace("spec-", "")));
- }
- if (id.search("suite") !== -1) {
- this.tabPanel.setSuite(this.getSuite(id.replace("suite-", "")));
- }
- };
- /**
- * Creates row dom element.
- * @param {Boolean} hide Sets the row visibility.
- * @param {jasmine.Suite/jasmine.Spec} The suite or the spec.
- * @return {HTMLElement} The row.
- */
- Test.panel.TreeGrid.prototype.createRow = function(hide, o) {
- var row = this.body.appendChild(new jasmine.Dom({
- tag: "div",
- cls: "row",
- style: {
- display: hide ? "none" : "block"
- },
- children: [{
- cls: "checkbox-col",
- children: [{
- tag: "input",
- cls: "select-checkbox",
- type: "checkbox"
- }]
- }]
- }));
-
- if (Test.Options.isChecked(o)) {
- row.childNodes[0].childNodes[0].checked = true;
- }
-
- return row;
- };
- /**
- * Resizer
- */
-
- /**
- * MouseDown event listener. (resizing starts)
- */
- Test.panel.TreeGrid.prototype.onMouseDown = function(event) {
- var el;
-
- event = event || window.event;
- el = event.target || event.srcElement;
- if (jasmine.Dom.hasCls(el, "resizer")) {
- if (event.preventDefault) {
- event.preventDefault();
- } else {
- event.returnValue = false;
- }
-
- this.pageY = event.pageY || event.clientY;
- this.startHeight = this.tabPanel.el.clientHeight;
- document.body.style.cursor = "row-resize";
- }
- };
- /**
- * MouseDown event listener. (resize in progress)
- */
- Test.panel.TreeGrid.prototype.onMouseMove = function(event) {
- var el, diff;
- if (this.pageY) {
- event = event || window.event;
- el = event.target || event.srcElement;
- diff = Math.max(200, this.startHeight - ((event.pageY || event.clientY)- this.pageY));
- diff = Math.min(diff, document.body.clientHeight - 200);
-
- this.tabPanel.resize(diff);
- this.options.resizer = diff;
- this.resizeBody();
- }
- };
- /**
- * MouseUp event listener. (resize ends)
- */
- Test.panel.TreeGrid.prototype.onMouseUp = function(event) {
- document.body.style.cursor = "auto";
- delete this.pageY;
- };
- /**
- * Returns treegrid innerHeight.
- * @return {Number} The innerHeight.
- */
- Test.panel.TreeGrid.prototype.getInnerHeight = function() {
- return (window.innerHeight || document.documentElement.clientHeight) - this.header.offsetTop * 2;
- };
- /**
- * Resizes treegrid.
- */
- Test.panel.TreeGrid.prototype.resizeBody = function() {
- var height = this.getInnerHeight();
-
- height -= this.resizer.offsetHeight + this.tabPanel.el.offsetHeight + this.header.offsetHeight;
- height -= 2;
- height = Math.max(30, height);
- this.body.style.height = height + 'px';
- };
- /**
- * End of Resizer
- */
-
- /**
- * Renders specs results.
- * @param {jasmine.Spec} spec The spec.
- * @return {HTMLElement} The spec results dom element.
- */
- Test.panel.TreeGrid.prototype.renderSpecResults = function(spec) {
- var resultItems = spec.results().getItems(),
- length = resultItems.length,
- resultsEl,
- resultEl,
- result,
- i;
-
- resultsEl = new jasmine.Dom({
- cls: "results"
- });
-
- for (i = 0; i < length; i++) {
- result = resultItems[i];
- if (result.type === "expect" && result.passed) {
-
- if (!result.passed()) {
- resultEl = this.renderFailedResult(result);
- } else {
- resultEl = this.renderPassedResult(result);
- }
-
- if (i === 0) {
- jasmine.Dom.addCls(resultEl, "first");
- }
-
- resultsEl.appendChild(resultEl);
-
- if (result.error) {
- break;
- }
- }
- }
- return resultsEl;
- };
- /**
- * Renders failed spec result.
- * @param {Object} result The spec result.
- * @return {HTMLElement} The spec result message HTMLElement
- */
- Test.panel.TreeGrid.prototype.renderFailedResult = function(result) {
- var message = result.message,
- children;
- children = [{
- cls: "prettyPrint",
- html: jasmine.util.htmlEscape(message)
- }];
-
- return new jasmine.Dom({
- cls: "resultMessage fail",
- children: children
- });
- };
- /**
- * Renders failed spec result.
- * @param {Object} result The spec result.
- * @return {HTMLElement} The spec result message HTMLElement
- */
- Test.panel.TreeGrid.prototype.renderPassedResult = function(result) {
- var children = [{
- cls: "prettyPrint",
- html: "Actual: " + jasmine.pp(result.actual) + "\nExpected: " + jasmine.pp(result.expected) + "\nMatcher: " + result.matcherName + "."
- }];
-
- return new jasmine.Dom({
- cls: "resultMessage pass",
- children: children
- });
- };
- /**
- * Returns tabPanel console.
- */
- Test.panel.TreeGrid.prototype.getInfoPanel = function() {
- return this.tabPanel.children[0];
- };
- /**
- * Print a message into info console.
- * @param {String} message The message.
- * @param {String} cls (optional) an extra cls to add to the message.
- */
- Test.panel.TreeGrid.prototype.log = function(message, cls) {
- this.getInfoPanel().log(message, cls);
- };
- /**
- * Sets statubar message, this method can also add a className.
- * @param {String} message The message.
- * @param {String} cls The className (optional).
- */
- Test.panel.TreeGrid.prototype.setStatus = function(message, cls) {
- jasmine.Dom.setHTML(this.statusMessage, message);
- if (cls) {
- jasmine.Dom.addCls(this.statusMessage, cls);
- }
- };/**
- * @class Test.Reporter
- * The Sencha Unit Tests Reporter
- */
- Test.Reporter = function(config) {
- config = config || {};
- this.options = Test.Options.get();
- this.runnedSpecsCount = 0;
- this.failedSpecsCount = 0;
- this.disabledSpecsCount = 0;
- this.optionCheckBoxesEl = {};
- this.treeGrid = new Test.panel.TreeGrid({});
-
- };
- /**
- * Called before runner execution.
- * @param {jasmine.Runner} runner The Jasmine Runner
- */
- Test.Reporter.prototype.reportRunnerStarting = function(runner) {
- this.runner = runner;
- this.startedAt = new Date();
- if (Test.BadGlobals) {
- Test.BadGlobals.setup();
- }
- this.logger = this.treeGrid;
-
- this.log(">> Started at " + this.startedAt.toString(), "info");
-
- if (!this.options.remote) {
- this.log(">> Warning! Because you access TestReporter locally, stack trace report isn't available.", "warning");
- }
- this.runner.filter(this.options.suites, this.options.specs);
- if (Test.BadGlobals) {
- Test.BadGlobals.report(this.logger);
- }
- };
- /**
- * Called after Jasmine runner execution ends.
- * @param {jasmine.Runner} runner The Jasmine Runner
- */
- Test.Reporter.prototype.reportRunnerResults = function(runner) {
- Test.jsCoverage.updateTotal();
- this.renderResults(runner);
- };
- /**
- * Called before spec execution.
- * @param {jasmine.Runner} suite The Jasmine spec
- */
- Test.Reporter.prototype.reportSuiteStarting = function(suite) {
- if (this.options.showTimings) {
- suite.startedAt = new Date();
- }
- if (Test.jsCoverage.isEnabled()) {
- Test.jsCoverage.add(suite);
- }
- };
- /**
- * Called after suite execution ends.
- * @param {jasmine.Runner} suite A Jasmine suite
- */
- Test.Reporter.prototype.reportSuiteResults = function(suite) {
- var suiteEl = this.treeGrid ? this.treeGrid.suitesEls[suite.id] : undefined,
- status;
- if (suite.isEnabled()) {
- if (this.options.showTimings) {
- suite.time = (((new Date()).getTime() - suite.startedAt.getTime())/ 1000).toFixed(3);
- }
-
- Test.jsCoverage.update(suite);
-
- if (!suite.parentSuite && Test.BadGlobals) {
- Test.BadGlobals.report(this.logger, suite);
- }
-
- if (this.treeGrid && this.options.showPassed && !suiteEl) {
- suiteEl = this.treeGrid.addSuite(suite);
- }
-
- if (suiteEl) {
- status = suite.results().passed() ? "passed" : "failed";
- jasmine.Dom.addCls(suiteEl, status);
- jasmine.Dom.addCls(suiteEl.parentNode, status);
- if (Test.jsCoverage.isEnabled()) {
- this.treeGrid.updateSuiteEl(suite, Test.jsCoverage.getSuiteCoverage(suite));
- }
-
- if (suite.time) {
- this.treeGrid.updateSuiteEl(suite, " (" + suite.time + "s)");
- }
- }
-
- } else if (this.treeGrid && this.options.showDisabled && !suiteEl) {
- this.treeGrid.addSuite(suite);
- }
-
- };
- /**
- * Called before spec execution.
- * @param {jasmine.Runner} suite The Jasmine spec
- */
- Test.Reporter.prototype.reportSpecStarting = function(spec) {
- this.currentSpec = spec;
- if (spec.isEnabled()) {
- if (this.options.showTimings) {
- spec.startedAt = new Date();
- }
- this.treeGrid.setStatus("Running: " + jasmine.util.htmlEscape(spec.getFullName()));
- }
- };
- /**
- * Called after spec execution.
- * @param {jasmine.Runner} suite The Jasmine spec
- */
- Test.Reporter.prototype.reportSpecResults = function(spec) {
- var results, status;
- if (spec.isEnabled()) {
- if (this.options.showTimings) {
- spec.time = (((new Date()).getTime() - spec.startedAt.getTime())/ 1000).toFixed(3);
- }
- results = spec.results();
- status = results.passed() ? "passed" : "failed";
- if(status === "failed") {
- this.failedSpecsCount = this.failedSpecsCount + 1;
- }
-
- if ((status === "failed" || this.options.showPassed) && spec.isEnabled() && this.treeGrid) {
- this.treeGrid.addSpec(spec);
- }
- Test.SandBox.save(spec);
-
- this.runnedSpecsCount = this.runnedSpecsCount + 1;
- } else {
- this.disabledSpecsCount = this.disabledSpecsCount + 1;
- if (this.treeGrid && this.options.showDisabled) {
- this.treeGrid.addSpec(spec);
- }
- }
- };
- /**
- * Updates runner message with failed and passed specs
- * @param {jasmine.Runner} runner The jasmine runner.
- */
- Test.Reporter.prototype.renderResults = function(runner) {
- var cls = (this.failedSpecsCount > 0) ? "failed" : "passed",
- runTime,
- message;
-
- runTime = (new Date().getTime() - this.startedAt.getTime()) / 1000;
- message = this.runnedSpecsCount + " spec" +
- (this.runnedSpecsCount === 1 ? "" : "s" ) + " ran, " +
- this.failedSpecsCount + " failure" +
- (this.failedSpecsCount === 1 ? "" : "s") +
- " and " + this.disabledSpecsCount + " disabled";
-
- message += " in " + runTime + "s";
-
- message += Test.jsCoverage.getTotal() + ".";
-
- if (this.treeGrid) {
- if (Test.SandBox.getWin()._$jscoverage) {
- this.treeGrid.tabPanel.addCoverageSummary();
- }
- this.treeGrid.setStatus(message, cls);
- }
- this.log(">> Finished at " + new Date().toString(), "info");
- };
- Test.Reporter.prototype.log = function() {
- if (this.options.verbose || arguments.length === 2) {
- this.logger.log.apply(this.logger, arguments);
- }
- };
- Test.Reporter.prototype.getIframeContainer = function() {
- if (this.treeGrid) {
- return this.treeGrid.tabPanel.children[1].el;
- }
- return document.body;
- };
|