UNPKG

siesta-lite

Version:

Stress-free JavaScript unit testing and functional testing tool, works in NodeJS and browsers

1,177 lines (954 loc) 92.8 kB
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>The source code</title> <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" /> <script type="text/javascript" src="../resources/prettify/prettify.js"></script> <style type="text/css"> .highlight { display: block; background-color: #ddd; } </style> <script type="text/javascript"> function highlight() { document.getElementById(location.hash.replace(/#/, "")).className = "highlight"; } </script> </head> <body onload="prettyPrint(); highlight();"> <pre class="prettyprint lang-js">/* Siesta 5.6.1 Copyright(c) 2009-2022 Bryntum AB https://bryntum.com/contact https://bryntum.com/products/siesta/license */ <span id='Siesta-Project'>/** </span> @class Siesta.Project `Siesta.Project` is an abstract base project class in Siesta hierarchy. This class provides no UI, you should use one of it subclasses, for example {@link Siesta.Project.Browser} or {@link Siesta.Project.Browser.ExtJS} This file is a reference only, for a getting start guide and manual, please refer to &lt;a href=&quot;#!/guide/getting_started_browser&quot;&gt;Siesta getting started in browser environment&lt;/a&gt; guide. Synopsys ======== var project = new Siesta.Project.Browser.ExtJS(); project.configure({ title : &#39;Awesome Test Suite&#39;, transparentEx : true, autoCheckGlobals : true, expectedGlobals : [ &#39;Ext&#39;, &#39;Sch&#39; ], preload : [ &quot;http://cdn.sencha.io/ext-4.0.2a/ext-all-debug.js&quot;, &quot;../awesome-project-all.js&quot;, { text : &quot;console.log(&#39;preload completed&#39;)&quot; } ] }) project.plan( // simple string - url relative to project file &#39;sanity.t.js&#39;, // test file descriptor with own configuration options { url : &#39;basic.t.js&#39;, // replace `preload` option of project preload : [ &quot;http://cdn.sencha.io/ext-4.0.6/ext-all-debug.js&quot;, &quot;../awesome-project-all.js&quot; ] }, // groups (&quot;folders&quot;) of test files (possibly with own options) { group : &#39;Sanity&#39;, autoCheckGlobals : false, items : [ &#39;data/crud.t.js&#39;, ... ] }, ... ) */ Class(&#39;Siesta.Project&#39;, { does : [ JooseX.Observable, Siesta.Util.Role.CanGetType, Siesta.Util.Role.CanDetectES6 ], has : { <span id='Siesta-Project-cfg-title'> /** </span> * @cfg {String} title The title of the test suite. Can contain HTML. When provided in the test file descriptor - will change the name of test in the project UI. */ title : null, <span id='Siesta-Project-cfg-desc'> /** </span> * @cfg {String} desc The description of the test. Can contain HTML. When provided, will be shown as the tooltip in the tests grid. */ desc : null, <span id='Siesta-Project-cfg-testClass'> /** </span> * @cfg {Class} testClass The test class which will be used for creating test instances, defaults to {@link Siesta.Test}. * You can subclass {@link Siesta.Test} and provide a new class. * * This option can be also specified in the test file descriptor. */ testClass : Siesta.Test, contentManagerClass : Siesta.Content.Manager, // fields of test descriptor: // - id - either `url` or wbs + group - computed // - url // - isMissing - true if test file is missing // - testCode - a test code source (can be provided by user) // - testConfig - config object provided to the StartTest // - index - (in the group) computed // - scopeProvider // - scopeProviderConfig // - preload // - alsoPreload // - parent - parent descriptor (or project for top-most ones) - computed // - preset - computed by project - instance of Siesta.Content.Preset // - forceDOMVisible - true to show the &lt;iframe&gt; on top of all others when running this test // (required for IE when using &quot;document.getElementFromPoint()&quot;) // OR - object // - group - group name // - items - array of test descriptors // - expanded - initial state of the group (true by default) descriptors : Joose.I.Array, descriptorsById : Joose.I.Object, launchCounter : 0, launches : Joose.I.Object, scopesByURL : Joose.I.Object, testsByURL : Joose.I.Object, <span id='Siesta-Project-cfg-transparentEx'> /** </span> * @cfg {Boolean} transparentEx When set to `true` project will not try to catch any exception, thrown from the test code. * This is very useful for debugging - you can for example use the &quot;break on error&quot; option in Firebug. * But, using this option may naturally lead to unhandled exceptions, which may leave the project in incosistent state - * refresh the browser page in such case. * * Defaults to `false` - project will do its best to detect any exception thrown from the test code. * * This option can be also specified in the test file descriptor. */ transparentEx : false, scopeProviderConfig : null, scopeProvider : null, <span id='Siesta-Project-cfg-runCore'> /** </span> * @cfg {String} runCore Either `parallel` or `sequential`. Indicates how the individual tests should be run - several at once or one-by-one. * Default value is &quot;parallel&quot;. You do not need to change this option usually. */ runCore : &#39;parallel&#39;, <span id='Siesta-Project-cfg-maxThreads'> /** </span> * @cfg {Number} maxThreads The maximum number of tests running at the same time. Only applicable for `parallel` run-core. */ maxThreads : 4, <span id='Siesta-Project-cfg-autoCheckGlobals'> /** </span> * @cfg {Boolean} autoCheckGlobals When set to `true`, project will automatically issue an {@link Siesta.Test#verifyGlobals} assertion at the end of each test, * so you won&#39;t have to manually specify it each time. The assertion will be triggered only if test completed successfully. Default value is `false`. * See also {@link #expectedGlobals} configuration option and {@link Siesta.Test#expectGlobals} method. * * This option will be always disabled in Opera, since every DOM element with `id` is being added as a global symbol in it. * * This option can be also specified in the test file descriptor. */ autoCheckGlobals : false, disableGlobalsCheck : false, <span id='Siesta-Project-cfg-expectedGlobals'> /** </span> * @cfg {Array} expectedGlobals An array of strings or regular expressions which are likely to present in the scope of each test. There is no need to provide the name * of built-in globals - project will automatically scan them from the empty context. Only provide the names of global properties which will be created * by your preload code. * * For example * project.configure({ title : &#39;Ext Scheduler Test Suite&#39;, autoCheckGlobals : true, expectedGlobals : [ &#39;Ext&#39;, &#39;MyProject&#39;, /jQuery\d+/, // Can use RegExp too! ], ... }) * This option can be also specified in the test file descriptor. */ expectedGlobals : Joose.I.Array, // will be populated by `populateCleanScopeGlobals` cleanScopeGlobals : Joose.I.Array, <span id='Siesta-Project-cfg-preload'> /** </span> * @cfg {Array} preload * * The array which contains the *preload descriptors* describing which files/code should be preloaded into the scope of each test. * * Preload descriptor can be: * * - a string, containing an url to load (cross-domain urls are ok, if url ends with &quot;.css&quot; it will be loaded as CSS) * - an object `{ type : &#39;css/js&#39;, url : &#39;...&#39; }` allowing to specify the CSS files with different extension * - an object `{ type : &#39;css/js&#39;, content : &#39;...&#39; }` allowing to specify the inline content for script / style. The content should only be the tag content - not the tag itself, it&#39;ll be created by Siesta. * - an object `{ text : &#39;...&#39; }` which is a shortcut for `{ type : &#39;js&#39;, content : &#39;...&#39; }` * * `preload` array can contain other nested arrays which will be flattened recursively. Any &quot;empty&quot; values * (like `null`, empty string, false etc) will be ignored. * * For example: * project.configure({ title : &#39;Ext Scheduler Test Suite&#39;, preload : [ &#39;http://cdn.sencha.io/ext-4.0.2a/resources/css/ext-all.css&#39;, &#39;http://cdn.sencha.io/ext-4.0.2a/ext-all-debug.js&#39;, { text : &#39;MySpecialGlobalFunc = function () { if (typeof console != &quot;undefined&quot;) ... }&#39; }, // simple conditional preload someCondition ? [ &#39;http://mydomain.com/file.css&#39;, &#39;http://mydomain.com/file.js&#39; ] : null ], ... }) * This option can be also specified in the test file descriptor. **Note**, that if test descriptor has non-empty * {@link Siesta.Project.Browser#pageUrl pageUrl} option, then *it will not inherit* the `preload` option * from parent descriptors or project, **unless** it has the `preload` config set to string `inherit`. * If both `pageUrl` and `preload` are set on the project level, `preload` value still will be inherited. For example: * project.configure({ pageUrl : &#39;general-page.html&#39;, preload : [ &#39;my-file.js&#39; ], ... }) project.plan( // this test will inherit both `pageUrl` and `preload` &#39;test1.js&#39;, { // no preloads inherited pageUrl : &#39;host-page.html&#39;, url : &#39;test2.js&#39; }, { // inherit `preload` value from the upper level - [ &#39;my-file.js&#39; ] pageUrl : &#39;host-page.html&#39;, preload : &#39;inherit&#39;, url : &#39;test3.js&#39; }, { group : &#39;Some group&#39;, pageUrl : &#39;host-page2.html&#39;, preload : &#39;inherit&#39;, items : [ { // inherit `pageUrl` value from the group // inherit `preload` value from the upper level - [ &#39;my-file.js&#39; ] url : &#39;test3.js&#39; } ] } ) * When loading ES6 modules, one need to indicate this using the `isEcmaModule` property of the preload descriptor. * In this case, the module `&lt;script&gt;` tag will be created with the `type` attribute set to `module`, instead of `text/javascript`. * project.configure({ preload : [ { type : &#39;js&#39;, url : &#39;some_file.js&#39;, isEcmaModule : true }, { type : &#39;js&#39;, content : &#39;import {something} from &quot;another/module.js&quot;&#39;, isEcmaModule : true } ], ... }) * * */ preload : Joose.I.Array, <span id='Siesta-Project-cfg-alsoPreload'> /** </span> * @cfg {Array} alsoPreload The array with preload descriptors describing which files/code should be preloaded **additionally**. * * This option can be also specified in the test file descriptor. */ <span id='Siesta-Project-cfg-listeners'> /** </span> * @cfg {Object} listeners The object which keys corresponds to event names and values - to event handlers. If provided, the special key &quot;scope&quot; will be treated as the * scope for all event handlers, otherwise the project itself will be used as scope. * * Note, that the events from individual {@link Siesta.Test test cases} instances will bubble up to the project - you can listen to all of them in one place: * project.configure({ title : &#39;Awesome Test Suite&#39;, preload : [ &#39;http://cdn.sencha.io/ext-4.1.0-gpl/resources/css/ext-all.css&#39;, &#39;http://cdn.sencha.io/ext-4.1.0-gpl/ext-all-debug.js&#39;, &#39;preload.js&#39; ], listeners : { testsuitestart : function (event, project) { log(&#39;Test suite is starting: &#39; + project.title) }, testsuiteend : function (event, project) { log(&#39;Test suite is finishing: &#39; + project.title) }, teststart : function (event, test) { log(&#39;Test case is starting: &#39; + test.url) }, testupdate : function (event, test, result) { log(&#39;Test case [&#39; + test.url + &#39;] has been updated: &#39; + result.description + (result.annotation ? &#39;, &#39; + result.annotation : &#39;&#39;)) }, testfailedwithexception : function (event, test) { log(&#39;Test case [&#39; + test.url + &#39;] has failed with exception: &#39; + test.failedException) }, testfinalize : function (event, test) { log(&#39;Test case [&#39; + test.url + &#39;] has completed&#39;) } } }) */ <span id='Siesta-Project-cfg-cachePreload'> /** </span> * @cfg {Boolean} cachePreload When set to `true`, project will cache the content of the preload files and provide it for each test, instead of loading it * from network each time. This option may give a slight speedup in tests execution (especially when running the suite from the remote server), but see the * caveats below. Default value is `false`. * * Caveats: this option doesn&#39;t work very well for CSS (due to broken relative urls for images). Also its not &quot;debugging-friendly&quot; - as you will not be able * to setup breakpoints for cached code. */ cachePreload : false, mainPreset : null, emptyPreset : null, <span id='Siesta-Project-cfg-keepNLastResults'> /** </span> * @cfg {Number} keepNLastResults * * Indicates the number of the test results which still should be kept, for user examination. * Results are cleared when their total number exceed this value, based on FIFO order. */ keepNLastResults : 2, lastResultsURLs : Joose.I.Array, lastResultsByURL : Joose.I.Object, <span id='Siesta-Project-cfg-breakOnFail'> /** </span> * @cfg {Boolean} breakOnFail When set to `true`, the project will not start launching any further tests after * detecting a failed assertion. When running in automation mode, test suite will be finalized immediately, * ignoring the --rerun-failed option. * * Default value is `false`. */ breakOnFail : false, <span id='Siesta-Project-cfg-breakTestOnFail'> /** </span> * @cfg {Boolean} breakTestOnFail When set to `true`, the whole test file will be finalized after the 1st * failed assertion is generated in any of its sub-tests (`it/describe` sections). The test finalization * is performed by throwing an exception, if {@link #transparentEx} is not enabled you will see it * in the console/debugger. * * To break the currently running sub-test only (`it/describe` section) see {@link #breakSubTestOnFail}. * * This option can be also specified in the test file descriptor. * * Default value is `false`. */ breakTestOnFail : false, <span id='Siesta-Project-cfg-breakSubTestOnFail'> /** </span> * @cfg {Boolean} breakSubTestOnFail When set to `true`, the currently running sub test (`it/describe` section) * will be finalized after the 1st failed assertion is generated. The test finalization * is performed by throwing an exception, if {@link #transparentEx} is not enabled you will see it * in the console/debugger. * * To break the whole currently test file see {@link #breakTestOnFail}. * * This option can be also specified in the test file descriptor. * * Default value is `false`. */ breakSubTestOnFail : false, <span id='Siesta-Project-cfg-overrideSetTimeout'> /** </span> * @cfg {Boolean} overrideSetTimeout When set to `true`, the tests will override the native &quot;setTimeout&quot; from the context of each test * for asynchronous code tracking. If setting it to `false`, you will need to use `beginAsync/endAsync` calls to indicate that test is still running. * * Note, that this option may not work reliably, when used for several sub tests launched simultaneously (for example * for several sibling {@link Siesta.Test#todo} sections. * * This option can be also specified in the test file descriptor. Defaults to `false`. */ overrideSetTimeout : false, <span id='Siesta-Project-cfg-needDone'> /** </span> * @cfg {Boolean} needDone When set to `true`, the tests will must indicate that that they have reached the correct * exit point with `t.done()` call, after which, adding any assertions is not allowed. * Using this option will ensure that test did not exit prematurely with some exception silently caught. * * This option can be also specified in the test file descriptor. */ needDone : false, // the default timeout for tests will be increased when launching more than this number of files increaseTimeoutThreshold : 8, // the start and end dates for the most recent `launch` method startDate : null, endDate : null, <span id='Siesta-Project-cfg-waitForTimeout'> /** </span> * @cfg {Number} waitForTimeout Default timeout for `waitFor` (in milliseconds). Default value is 10000. * * This option can be also specified in the test file descriptor. */ waitForTimeout : 10000, <span id='Siesta-Project-cfg-defaultTimeout'> /** </span> * @cfg {Number} defaultTimeout Default timeout for `beginAsync` operation (in milliseconds). Default value is 15000. * * This option can be also specified in the test file descriptor. */ defaultTimeout : 15000, <span id='Siesta-Project-cfg-subTestTimeout'> /** </span> * @cfg {Number} subTestTimeout Default timeout for sub tests. Default value is twice bigger than {@link #defaultTimeout}. * * This option can be also specified in the test file descriptor. */ subTestTimeout : null, <span id='Siesta-Project-cfg-isReadyTimeout'> /** </span> * @cfg {Number} isReadyTimeout Default timeout for test start (in milliseconds). Default value is 15000. See {@link Siesta.Test#isReady} for details. * * This option can be also specified in the test file descriptor. */ isReadyTimeout : 10000, <span id='Siesta-Project-cfg-pauseBetweenTests'> /** </span> * @cfg {Number} pauseBetweenTests Default timeout between tests (in milliseconds). Increase this settings for big test suites, to give browser time for memory cleanup. */ pauseBetweenTests : 10, <span id='Siesta-Project-cfg-failOnExclusiveSpecsWhenAutomated'> /** </span> * @cfg {Boolean} failOnExclusiveSpecsWhenAutomated When this option is enabled and Siesta is running in automation mode * (using WebDriver or Puppeteer launcher) any exclusive BDD specs found (like {@link Siesta.Test#iit t.iit} or {@link Siesta.Test#ddescribe t.ddescribe} * will cause a failing assertion. The idea behind this setting is that such &quot;exclusive&quot; specs should only be used during debugging * and are often mistakenly committed in the codebase, leaving other specs not executed. * * This option can be also specified in the test file descriptor. */ failOnExclusiveSpecsWhenAutomated : false, <span id='Siesta-Project-cfg-snooze'> /** </span> * @cfg {Date/String} snooze * * Either a `Date` instance or a string, recognized by the [Date constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse). * * If test is running prior the specified date, the whole test will be made a &quot;todo&quot;. See the {@link Siesta.Test#snooze} method. * * Example: * project.plan( { group : &#39;Some group&#39;, snooze : &#39;2016-10-11&#39;, items : [ ... ] } ) * * This option can be also specified in the test file descriptor. */ snooze : null, <span id='Siesta-Project-cfg-referenceUrl'> /** </span> * @cfg {String} referenceUrl * * The url, containing additional information about the test. This option is inherited from the group configs, * as other options. In the Siesta user interface, `CTRL+click` on the * test row will open a new browser window, pointing to this url. Can be used to link the test with some external * resource like ticket, screenshot, etc. project.plan( { url : &#39;my_test.t.js&#39;, referenceUrl : &#39;http://jira.com/jira_issue&#39; } ) * This option can be also specified in the test file descriptor. */ referenceUrl : null, <span id='Siesta-Project-cfg-suppressPassedWaitForAssertion'> /** </span> * @cfg {Boolean} suppressPassedWaitForAssertion * * When enabled, the passed &quot;waitFor&quot; assertions won&#39;t be included in the tests. * * This option can be also specified in the test file descriptor. */ suppressPassedWaitForAssertion : false, <span id='Siesta-Project-cfg-isEcmaModule'> /** </span> * @cfg {Boolean} isEcmaModule * * This option can be specified in the test file descriptor and/or as the global project config. In the latter case it will affect all tests. * * When enabled, the test script file (the one containing the `StartTest()` function) will be loaded using * `&lt;script type=&quot;module&quot;&gt;` instead of `&lt;script type=&quot;text/javascript&quot;&gt;` * * See also a note in the {@link Siesta.Project#preload preload} config. */ isEcmaModule : null, setupDone : false, sourceLineForAllAssertions : false, currentLaunchId : null, isAutomated : false, autoLaunchTests : true, configSynonyms : function () { return this.processConfigSynonyms(this.buildConfigSynonyms()) }, uniqueCounter : 0, valueToHashIndicies : Joose.I.Object, // lazy attribute, should be accessed with &quot;getSandboxHashStructure&quot; method sandboxHashStructure : { lazy : &#39;this.buildSandboxHashStructure&#39; }, <span id='Siesta-Project-cfg-sandbox'> /** </span> * @cfg {Boolean} sandbox * * This option controls whether the individual tests should be run in isolation from each other. By default it is enabled, * and every test file will be run inside of the newly created iframe (or in the separate Node.js process), so that it can not interfere with * any other test. Such setup gives you predictable starting state for every test, removes the need for any kind of * cleanup at the end of the test and is more robust in general. * * However, the setup of the new sandbox creates some overhead. If you are sure that your tests * do not modify any global state (like global variable that can affect the other test) you may want to run * all of them in the same context, saving the setup time. In this case, you may want to disable this option. * * Siesta collects all tests with this option disabled and split them into chunks. Every chunk will have exactly * the same values for the configs that influence the initial setup of the page: {@link #preload}, {@link #alsoPreload}, * {@link #pageUrl}, {@link Siesta.Test.ExtJS#requires} and some others. The tests inside of every * chunk will be run sequentially, in the same sandbox. * * **Important**: The 1st test in every chunk will be run normally. Starting from the 2nd one, tests * will skip the {@link Siesta.Test#isReady} check and {@link Siesta.Test#setup} methods. This is because all the * setup is supposed to be already done by the 1st test. This behavior may change (or made configurable) in the future. * * This option can be specified in the test file descriptor. * * See also {@link #sandboxBoundaryByGroup}, {@link #sandboxCleanup} */ sandbox : true, <span id='Siesta-Project-cfg-sandboxBoundaryByGroup'> /** </span> * @cfg {Boolean} sandboxBoundaryByGroup * * Only applicable for tests with the {@link #sandbox} option *disabled*. * * when this option is enabled, the tests to be run in the same context will be guaranteed to reside in the same group. * If a new test group starts (even with the same &quot;preload&quot; config) - a fresh context for that group will be created * by Siesta. * * For example, in the following setup, both &quot;Group 1&quot; and &quot;Group 2&quot; have sandboxing disabled and the * same &quot;preload&quot; config. If `sandboxBoundaryByGroup` will be disabled all 4 individual tests will be run * in the same context. If `sandboxBoundaryByGroup` will be enabled, separate fresh context will be created * for the tests from each group. * project.configure({ preload : [ ... ] }); project.plan( { group : &#39;Group 1&#39;, sandbox : false, items : [ &#39;010-basics/010_sanity.t.js&#39;, &#39;010-basics/020_jshint.t.js&#39; ] }, { group : &#39;Group 2&#39;, sandbox : false, items : [ &#39;020-basics/010_sanity.t.js&#39;, &#39;020-basics/030_bdd.t.js&#39; ] }, ... ) * */ sandboxBoundaryByGroup : true, <span id='Siesta-Project-cfg-sandboxCleanup'> /** </span> * @cfg {Boolean} sandboxCleanup * * Only applicable for tests with the {@link #sandbox} option *disabled*. When enabled, test that runs * in shared sandbox (the sandbox in which another test just has been run) will perform a cleanup. * * By default it will remove any &quot;unexpected&quot; globals (see {@link #expectedGlobals}) and clear the DOM. * * If you will disable this option, every new test in the &quot;groups&quot; will start from the state previous test * has finished the execution. This will allow you split one big test scenario into several files * * This option can be specified in the test file descriptor. */ sandboxCleanup : true, <span id='Siesta-Project-cfg-debuggerOnFail'> /** </span> * @cfg {Boolean} debuggerOnFail When set to `true`, the project will issue a `debugger` statement after detecting a failed assertion, allowing you * to inspect the internal state of the test in the browser&#39;s debugger. Default value is `false`. */ debuggerOnFail : false, <span id='Siesta-Project-cfg-debuggerOnStart'> /** </span> * @cfg {Boolean} debuggerOnStart When set to `true`, the project will issue a `debugger` statement before launching any test. Default value is `false`. */ debuggerOnStart : false, <span id='Siesta-Project-cfg-ignoreException'> /** </span> * @cfg {RegExp/String} ignoreException If this option provided, Siesta will ignore any exceptions, stringified value of which matches this option. * If this option is provided as string, it is passed to the `RegExp` constructor. * * This option is supposed to be used only for some &quot;strange&quot; exceptions, originated from the browser itself. For the exceptions * from the test code behavior of this option is undefined. * * Can also be specified in the test file descriptor. */ ignoreException : null }, methods : { initialize : function () { var me = this me.on(&#39;testupdate&#39;, function (event, test, result, parentResult) { me.onTestUpdate(test, result, parentResult); }) me.on(&#39;testfailedwithexception&#39;, function (event, test, exception, stack) { me.onTestFail(test, exception, stack); }) me.on(&#39;teststart&#39;, function (event, test) { me.onTestStart(test); }) me.on(&#39;testfinalize&#39;, function (event, test) { me.onTestEnd(test); }) }, buildConfigSynonyms : function () { return {} }, // creates a reference from every synonym to a full list of synonyms, including the main name itself // { &#39;main&#39; : [ &#39;main&#39;, &#39;syn1&#39;, &#39;syn2&#39; ], &#39;syn1&#39; : [ &#39;main&#39;, &#39;syn1&#39;, &#39;syn2&#39; ], &#39;syn2&#39; : [ &#39;main&#39;, &#39;syn1&#39;, &#39;syn2&#39; ] } processConfigSynonyms : function (synonyms) { var result = {} Joose.O.each(synonyms, function (synonymsList, mainName) { if (synonymsList instanceof Array) synonymsList.unshift(mainName) else synonymsList = [ mainName, synonymsList ] Joose.A.each(synonymsList, function (synonym) { result[ synonym ] = synonymsList }) }) return result }, onTestUpdate : function (test, result, parentResult) { }, onTestFail : function (test, exception, stack) { }, onTestStart : function (test) { }, onTestEnd : function (test) { }, onTestSuiteStart : function (descriptors, contentManager, launchState) { this.startDate = new Date() <span id='Siesta-Project-event-testsuitestart'> /** </span> * This event is fired when the test suite starts. Note, that when running the test suite in the browser, this event can be fired several times * (for each group of tests you&#39;ve launched). * * You can subscribe to it, using regular ExtJS syntax: * * project.on(&#39;testsuitestart&#39;, function (event, project) {}, scope, { single : true }) * * See also the &quot;/examples/events&quot; * * @event testsuitestart * @member Siesta.Project * @param {JooseX.Observable.Event} event The event instance * @param {Siesta.Project} project The project that just has started */ this.fireEvent(&#39;testsuitestart&#39;, this, launchState) }, onTestSuiteEnd : function (descriptors, contentManager, launchState) { this.endDate = new Date() <span id='Siesta-Project-event-testsuiteend'> /** </span> * This event is fired when the test suite ends. Note, that when running the test suite in the browser, this event can be fired several times * (for each group of tests you&#39;ve launched). * * @event testsuiteend * @member Siesta.Project * @param {JooseX.Observable.Event} event The event instance * @param {Siesta.Project} project The project that just has ended */ this.fireEvent(&#39;testsuiteend&#39;, this, launchState) }, onBeforeScopePreload : function (scopeProvider, url) { this.fireEvent(&#39;beforescopepreload&#39;, scopeProvider, url) }, onAfterScopePreload : function (scopeProvider, url) { this.fireEvent(&#39;afterscopepreload&#39;, scopeProvider, url) }, onCachingError : function (descriptors, contentManager) { }, <span id='Siesta-Project-method-configure'> /** </span> * This method configures the project instance. It just copies the passed configuration option into project instance. * * @param {Object} config - configuration options (values of attributes for this class) */ configure : function (config) { Joose.O.copy(config, this) var me = this if (config.listeners) Joose.O.each(config.listeners, function (value, name) { if (name == &#39;scope&#39;) return me.on(name, value, config.scope || me) }) }, // backward compat processPreloadArray : function (preload) { var me = this preload = this.flattenArray(preload, true) Joose.A.each(preload, function (obj, index) { // do not process { text : &quot;&quot; } preload descriptors if (Object(obj) === obj) { if (obj.url) obj.url = me.normalizeURL(obj.url) } else preload[ index ] = me.normalizeURL(obj) }) return preload }, populateCleanScopeGlobals : function (scopeProvider, callback) { var scopeProviderClass = eval(scopeProvider) var cleanScope = new scopeProviderClass() var cleanScopeGlobals = this.cleanScopeGlobals // we can also use &quot;create&quot; and not &quot;setup&quot; here // create will only create the iframe (in browsers) and will not try to update its content // the latter crashes IE8 cleanScope.setup(function () { for (var name in cleanScope.scope) cleanScopeGlobals.push(name) callback() // this setTimeout seems to stop the spinning loading indicator in FF // accorting to https://github.com/3rd-Eden/Socket.IO/commit/bad600fb1fb70238f42767c56f01256470fa3c15 // it only works *after* onload (this callback will be called *in* onload) setTimeout(function () { // will remove the iframe (in case of browser project) from DOM and stop loading indicator cleanScope.cleanup() }, 0) }) }, startSingle : function (desc, callback) { var me = this this.__counter__ = this.__counter__ || 0 var startSingle = function () { me.launch([ me.normalizeDescriptor(desc, me, me.__counter__++) ], callback) } me.setupDone ? startSingle() : this.setup(startSingle) }, setup : function (callback) { var me = this this.mainPreset = new Siesta.Content.Preset({ preload : this.processPreloadArray(this.preload) }) this.emptyPreset = new Siesta.Content.Preset() // A system level descriptor used by the recorder me.descriptors.push({ isSystemDescriptor : true, url : &#39;/&#39; }); me.normalizeDescriptors(me.descriptors) this.populateCleanScopeGlobals(this.scopeProvider, callback) }, <span id='Siesta-Project-method-plan'> /** </span> * This method adds *test file descriptors* (test files), to the project. It can be called several times. * * A test file descritor is one of the following: * * - a string, containing a test file url. The url should be unique among all tests. If you need to re-use the same test * file, you can add an arbitrary query string to it: `my_test.t.js?copy=1` * - an object containing the `url` property `{ url : &#39;...&#39;, option1 : &#39;value1&#39;, option2 : &#39;value2&#39; }`. The `url` property should point to the test file. * Other properties can contain values of some configuration options of the project (marked accordingly). In this case, they will **override** the corresponding values, * provided to project or parent descriptor. * - an object `{ group : &#39;groupName&#39;, items : [], expanded : true, option1 : &#39;value1&#39; }` specifying the folder of test files. The `expanded` property * sets the initial state of the folder - &quot;collapsed/expanded&quot;. The `items` property can contain an array of test file descriptors. * Other properties will override the applicable project options **for all child descriptors**. * * If test descriptor is `null` or other &quot;falsy&quot; value it is ignored. * * Groups (folder) may contain nested groups. Number of nesting levels is not limited. * * For example, one may easily have a special group of test files, having its own `preload` configuration (for example for testing on-demand loading). In the same * time some test in that group may have its own preload, overriding others. project.configure({ title : &#39;Ext Scheduler Test Suite&#39;, preload : [ &#39;http://cdn.sencha.io/ext-4.0.2a/resources/css/ext-all.css&#39;, &#39;http://cdn.sencha.io/ext-4.0.2a/ext-all-debug.js&#39;, &#39;../awesome-app-all-debug.js&#39; ], ... }) project.plan( // regular file &#39;data/crud.t.js&#39;, // a group with own &quot;preload&quot; config for its items { group : &#39;On-demand loading&#39;, preload : [ &#39;http://cdn.sencha.io/ext-4.0.2a/resources/css/ext-all.css&#39;, &#39;http://cdn.sencha.io/ext-4.0.2a/ext-all-debug.js&#39;, ], items : [ &#39;ondemand/sanity.t.js&#39;, &#39;ondemand/special-test.t.js&#39;, // a test descriptor with its own &quot;preload&quot; config (have the most priority) { url : &#39;ondemand/4-0-6-compat.t.js&#39;, preload : [ &#39;http://cdn.sencha.io/ext-4.0.6/resources/css/ext-all.css&#39;, &#39;http://cdn.sencha.io/ext-4.0.6/ext-all-debug.js&#39;, ] }, // sub-group { group : &#39;Sub-group&#39;, items : [ ... ] } ] }, ... ) * Additionally, you can provide a test descriptor in the test file itself, adding it as the 1st or 2nd argument for `StartTest` call: * StartTest({ autoCheckGlobals : false, alsoPreload : [ &#39;some_additional_preload.js&#39; ] }, function (t) { ... }) * * Values from this object takes the highest priority and will override any other configuration. * * Test descriptor may contain special property - `config` which will be applied to the test instance created. Be careful not to overwrite * standard properties and methods! * project.plan( { url : &#39;ondemand/4-0-6-compat.t.js&#39;, config : { myProperty1 : &#39;value1&#39;, myProperty2 : &#39;value2&#39; } }, ... ) StartTest(function (t) { if (t.myProperty1 == &#39;value1&#39;) { // do this } ... }) * * @param {Array/Mixed} descriptor1 or an array of descriptors * @param {Mixed} descriptor2 * @param {Mixed} descriptorN */ plan : function () { var descriptors = this.flattenArray(arguments) // A system level descriptor used by the recorder this.descriptors.push.apply(this.descriptors, descriptors) }, <span id='Siesta-Project-method-start'> /** </span> * This method will launch a test suite. * * For backward compatibility, it also calls {@link #plan} with its arguments. */ start : function () { var me = Siesta.my.activeHarness = this me.plan(this.flattenArray(arguments)) this.setup(function () { me.setupDone = true me.fireEvent(&#39;setupdone&#39;) if (me.autoLaunchTests) me.launch(me.descriptors) }) }, <span id='Siesta-Project-method-startFromUrl'> /** </span> * This method will read the content of the provided `url` then will try to parse it as JSON * and pass to the regular {@link #start} method. The file on the `url` should contain * a valid JSON array object with test descriptors. * * You can use this method in conjunction with the `bin/discover` utility, which can * auto-discover the test files and generate a starter file for you. In such setup, it is convenient * to specify the test configs in the test file itself (see {@link #start} method for details). * However, in such setup, you can not use conditional processing of the descriptors set, so * you decide what fits best to your needs. * * @param {String} url */ startFromUrl : function (url) { var contentManager = new this.contentManagerClass({ project : this, presets : [ new Siesta.Content.Preset({ preload : [ url ] }) ] }) var me = this contentManager.cache(function () { var content = contentManager.getContentOf(url) try { var descriptors = JSON.parse(content) } catch (e) { alert(&quot;The content of: &quot; + url + &quot; is not a valid JSON&quot;) return } if (me.typeOf(descriptors) == &#39;Array&#39;) me.start(descriptors) else { alert(&quot;The content of: &quot; + url + &quot; is not an array&quot;) } }, function () { alert(&quot;Can not load the content of: &quot; + url) }) }, // good to have this as a separate method for testing normalizeDescriptors : function (descArray) { var me = this var descriptors = [] Joose.A.each(descArray, function (desc, index) { if (desc) descriptors.push(me.normalizeDescriptor(desc, me, index)) }) me.descriptors = descriptors }, launch : function (descriptors, callback, errback) { var launchId = this.currentLaunchId = ++this.launchCounter var me = this //console.time(&#39;launch&#39;) //console.time(&#39;launch-till-preload&#39;) //console.time(&#39;launch-after-preload&#39;) // no folders, only leafs var flattenDescriptors = this.flattenDescriptors(descriptors) // the preset for the test scripts files var testScriptsPreset = new Siesta.Content.Preset() var presets = [ testScriptsPreset, this.mainPreset ] var notLaunchedByAutomationId = {} Joose.A.each(flattenDescriptors, function (desc) { if (desc.preset != me.mainPreset &amp;&amp; desc.preset != me.emptyPreset) presets.push(desc.preset) if (!desc.testCode) testScriptsPreset.addResource(desc.url) me.deleteTestByURL(desc.url) // only used in automation, where the `desc.automationElementId` is populated notLaunchedByAutomationId[ desc.automationElementId ] = 1 }) // cache either everything (this.cachePreload) or only the test files (to be able to show missing files / show content) var contentManager = new this.contentManagerClass({ project : this, presets : [ testScriptsPreset ].concat(this.cachePreload ? presets : []) }) var launchState = this.launches[ launchId ] = { launchId : launchId, increaseTimeout : this.runCore == &#39;parallel&#39; &amp;&amp; flattenDescriptors.length &gt; this.increaseTimeoutThreshold, descriptors : flattenDescriptors, contentManager : contentManager, needToStop : false, notLaunchedByAutomationId : notLaunchedByAutomationId } //console.time(&#39;caching&#39;) me.onTestSuiteStart(descriptors, contentManager, launchState) contentManager.cache(function () { //console.timeEnd(&#39;caching&#39;) Joose.A.each(flattenDescriptors, function (desc) { var url = desc.url if (contentManager.hasContentOf(url)) { // the test descriptor defined in the test file itself, takes the highest precendence var testConfig = desc.testConfig = Siesta.getConfigForTestScript(contentManager.getContentOf(url)) // if testConfig contains the &quot;preload&quot; or &quot;alsoPreload&quot; key - then we need to update the preset of the descriptor if (testConfig &amp;&amp; (testConfig.preload || testConfig.alsoPreload)) desc.preset = me.getDescriptorPreset(desc) } else // if test code is provided, then test is considered not missing // allow subclasses to define there own logic when found missing test file if (!desc.testCode) me.markMissingFile(desc) me.normalizeScopeProvider(desc) }) me.fireEvent(&#39;testsuitelaunch&#39;, descriptors, contentManager, launchState) me.runCoreGeneral(flattenDescriptors, contentManager, launchState, launchState.callback = function () { me.onTestSuiteEnd(descriptors, contentManager, launchState) callback &amp;&amp