      1 pockets.test = {};
      2
      3 pockets.test.domPrettyPrint = true;
      4
      5
      6 /* Make jasmine consider bound functions */
      7
      8 pockets.test.bind = function() {
      9   if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
     10   var boundFn = function() {
     11     return boundFn.method.apply(boundFn.object, boundFn.args.concat($A(arguments)));
     12   };
     13   boundFn.method = this;
     14   boundFn.args = $A(arguments);
     15   boundFn.object = boundFn.args.shift();
     16   boundFn["__isPocketsBoundFn__"] = true;
     17   return boundFn;
     18 };
     19
     20 pockets.test.testFunctionEquality = function(a, b, env, mismatchKeys, mismatchValues) {
     21   if (typeof a === "function" && typeof b === "function" && a["__isPocketsBoundFn__"] && b["__isPocketsBoundFn__"]) {
     22     if (a.object !== b.object) {
     23       mismatchValues.push("'this' object of bound functions didn't match");
     24       return false;
     25     }
     26     if (a.method !== b.method) {
     27       mismatchValues.push("method of bound functions didn't match");
     28       return false;
     29     }
     30     return env.equals_(a.args, b.args, mismatchKeys, mismatchValues);
     31   }
     32   return undefined;
     33 };
     34
     35 Function.prototype.bind = pockets.test.bind;
     36 jasmine.getEnv().addEqualityTester(pockets.test.testFunctionEquality);
     37
     38
     39 /* Test runner bootstrapping: swap in our own AppAssistant,
     40  * which will remove itself immediately and run tests if requested
     41  */
     42
     43 pockets.originalAppAssistant_ = window['AppAssistant'];
     44 pockets.originalStageAssistant = window['StageAssistant'];
     45 pockets.isTestingPockets_ = window['AppAssistant'] && AppAssistant.isPockets;
     46
     47 AppAssistant = function(appController) {
     48   var launchParameters = Mojo.getLaunchParameters();
     49   var runTests = launchParameters['runTests'];
     50   var reloadCSS = launchParameters['reloadCSS'];
     51
     52   window['AppAssistant'] = pockets.originalAppAssistant_;
     53   var realAppAssistant = new pockets.originalAppAssistant_(appController);
     54
     55   if (runTests) {
     56     window['StageAssistant'] = function() {
     57       window['StageAssistant'] = pockets.originalStageAssistant;
     58     };
     59
     60     StageAssistant.prototype.setup = function() {
     61       pockets.runTests(pockets.isTestingPockets_, this.controller);
     62     };
     63
     64     if (Mojo.appInfo.noWindow) {
     65       if (pockets.inPalmHost()) {
     66         // from Mojo.Controller.setup inside if (!Mojo.Controller.appInfo.noWindow)...
     67         Mojo.Controller.setupStageController(window);
     68         Mojo.Power.setup(Mojo.Controller.appController.assistant, Mojo.Controller.appInfo.id);
     69       } else {
     70         appController.createStageWithCallback({
     71           name: 'pockets-test-runner',
     72           assistantName: 'DefaultStageAssistant',
     73           lightweight: true
     74         }, function(stageController) {
     75           pockets.runTests(pockets.isTestingPockets_, stageController);
     76
     77         });
     78       }
     79     }
     80   } else {
     81     var originalHandleLaunch = realAppAssistant.handleLaunch;
     82     realAppAssistant.handleLaunch = function(launchParams) {
     83       if (launchParams["reloadCss"]) {
     84         Mojo.Log.info("reloading css...");
     85         var links = document.getElementsByTagName("link");
     86         for (var i = 0; i < links.length; i++) {
     87           if (links[i].rel === "stylesheet") {
     88             if (links[i].href.indexOf("?") === -1) {
     89               links[i].href += "?";
     90             }
     91             links[i].href += "x";
     92           }
     93         }
     94
     95         return;
     96       }
     97
     98       if (originalHandleLaunch) {
     99         return originalHandleLaunch.apply(this, arguments);
    100       }
    101     };
    102   }
    103
    104   return realAppAssistant;
    105 };
    106
    107 pockets.inTestRunner = function() {
    108   return jasmine && jasmine.getEnv().currentlyRunningTests;
    109 };
    110
    111 /** Override these methods if you would like to change your stage/app controller defaults. */
    112 pockets.stubStageController = function() {
    113   return new pockets.test.FakeStageController(null);
    114 };
    115
    116 pockets.stubAppController = function() {
    117   return new pockets.test.FakeAppController(null);
    118 };
    119
    120 pockets.test.FakeStageController = function(stageAssistant) {
    121   this.window = pockets.test.ui.getTestWindow(); //stageController must contain a reference to a window.
    122
    123   this.iAmAPocketsStubStageController = true,
    124   this.pushScene = Mojo.doNothing;
    125   this.swapScene = Mojo.doNothing;
    126   this.swapToRoot = Mojo.doNothing;
    127   this.sendEventToCommanders = Mojo.doNothing;
    128   this.popScene = Mojo.doNothing;
    129   this.activeScene = Mojo.doNothing;
    130   this.assistant = stageAssistant;
    131   this.setup = Mojo.doNothing;
    132   this._appController = pockets.stubAppController();
    133 };
    134
    135 pockets.test.FakeStageController.prototype = Mojo.Controller.StageController.prototype;
    136
    137 pockets.test.FakeAppController = function(appAssistant) {
    138   this.assistant = appAssistant;
    139 };
    140
    141 pockets.test._createSceneDom = function (sceneId, sceneHTML) {
    142   // be careful refactoring this! scroller-based tests (some lists, etc) will fail if this is not done correctly.
    143   var fakeSceneElement = Mojo.View.convertToNode('<div id="mojo-scene-' + sceneId + '" >' + sceneHTML + '</div>', document);
    144   var scrollerId = sceneId + "-scene-scroller";
    145   var scrollerContent = "<div id='" + scrollerId + "' x-mojo-element='Scroller'></div>";
    146   pockets.test.ui.getTestWindow().document.body.insert(scrollerContent);
    147   var scroller = pockets.test.ui.getTestWindow().document.getElementById(scrollerId);
    148   scroller.appendChild(fakeSceneElement);
    149   return fakeSceneElement;
    150 };
    151
    152 /**
    153  * Creates a scene Assistant with a controller and rendered scene, but doesn't set it up or activate it.
    154  * @return {Object} The scene assistant that was created by Mojo.
    155  */
    156 pockets.test.createGenericAssistant = function() {
    157   var assistantHTML = "";
    158   var genericAssistant = Class.create({});
    159   var sceneArguments = {
    160     name: "generic",
    161     disableSceneScroller: false,
    162     assistantConstructor: genericAssistant
    163   };
    164   var stageController = pockets.stubStageController();
    165   var fakeSceneElement = pockets.test._createSceneDom("generic", assistantHTML);
    166
    167   jasmine.getEnv().currentSpec.after(function() {
    168     pockets.test.ui.getTestWindow().document.body.innerHTML = '';
    169   });
    170
    171   return new Mojo.Controller.SceneController(stageController, fakeSceneElement, sceneArguments, []).assistant;
    172 };
    173
    174 /**
    175  * Creates a scene Assistant with a controller and rendered scene, but doesn't set it up or activate it.
    176  * @param {String} sceneId
    177  * @param {Array} assistantArguments Arguments to pass to the assistant
    178  * @return {Object} The scene assistant that was created by Mojo.
    179  */
    180 pockets.test.createSceneAssistant = function(sceneId, assistantArguments) {
    181   if (! Object.isArray(assistantArguments || [])) {
    182     throw new Error("expect array for assistant arguments");
    183   }
    184
    185   var assistantHTML = Mojo.View.render({
    186     template : sceneId + '/' + sceneId + '-scene'
    187   });
    188   var sceneArguments = {
    189     name: sceneId,
    190     disableSceneScroller: false
    191   };
    192   var stageController = pockets.stubStageController();
    193   var fakeSceneElement = pockets.test._createSceneDom(sceneId, assistantHTML);
    194
    195   jasmine.getEnv().currentSpec.after(function() {
    196     pockets.test.ui.getTestWindow().document.body.innerHTML = '';
    197   });
    198
    199   return new Mojo.Controller.SceneController(stageController, fakeSceneElement, sceneArguments, assistantArguments).assistant;
    200 };
    201
    202 /**
    203  * Creates a scene Assistant with a controller and rendered scene, but doesn't set it up or activate it.
    204  * @param {String} sceneId
    205  * @param {Array} assistantArguments Arguments to pass to the assistant
    206  * @return {Object} The scene assistant that was created by Mojo.
    207  */
    208 pockets.test.createSceneAssistantNoTemplate = function(sceneId, assistantArguments) {
    209   if (! Object.isArray(assistantArguments || [])) {
    210     throw new Error("expect array for assistant arguments");
    211   }
    212
    213   var assistantHTML = "";
    214   var sceneArguments = {
    215     name: sceneId,
    216     disableSceneScroller: false
    217   };
    218   var stageController = pockets.stubStageController();
    219   var fakeSceneElement = pockets.test._createSceneDom(sceneId, assistantHTML);
    220
    221   jasmine.getEnv().currentSpec.after(function() {
    222     pockets.test.ui.getTestWindow().document.body.innerHTML = '';
    223   });
    224
    225
    226   return new Mojo.Controller.SceneController(stageController, fakeSceneElement, sceneArguments, assistantArguments).assistant;
    227 };
    228
    229 pockets.test.setupAndActivate = function(sceneAssistant) {
    230   var sceneController = sceneAssistant.controller;
    231   sceneController.stageController.setup();
    232   sceneController.setup();
    233   pockets.test.setSceneVisibility(sceneController, true);
    234   if (sceneAssistant.aboutToActivate) {sceneAssistant.aboutToActivate();}
    235   sceneController.activate();
    236   expect(sceneController.sceneElement.innerHTML).toNotMatch("template load failed");
    237 };
    238
    239 pockets.test.setSceneVisibility = function(sceneController, visible) {
    240   var targetElement;
    241
    242   if (sceneController.sceneScroller) {
    243     targetElement = sceneController.sceneScroller;
    244   } else {
    245     targetElement = sceneController.sceneElement;
    246   }
    247
    248   if (visible) {
    249     if (!targetElement.visible()) {
    250       targetElement.show();
    251     }
    252     sceneController.showWidgetContainer(targetElement);
    253   }
    254
    255   if (!visible && targetElement.visible()) {
    256     sceneController.hideWidgetContainer(targetElement);
    257     targetElement.hide();
    258   }
    259 };
    260
    261 pockets.ReportingBridge = function() {
    262   this.suiteInfo = [];
    263   this.specResults = {};
    264   this.suiteInfoReady = false;
    265   this.freshlyLaunched = true;
    266   this.finished = false;
    267 };
    268
    269 pockets.ReportingBridge.prototype.transferSpecResults = function(specId) {
    270   var results = this.specResults[specId];
    271   if (results) delete this.specResults[specId];
    272   return results;
    273 };
    274
    275 pockets.runTests = function(isTestingPockets, stageController) {
    276   stageController.isTestingPockets = isTestingPockets;
    277   if (isTestingPockets) {
    278     stageController.group = 'pockets';
    279     stageController.pocketsDocumentPath = 'app/views';
    280     stageController.appTestsRunUrl = '../..' + TestAssistant.focusUrl();
    281     stageController.pocketsTestsRunUrl = '.' + TestAssistant.focusUrl();
    282     stageController.pushScene('test', '', stageController.window.reportingBridge);
    283   } else {
    284     stageController.group = 'app';
    285     stageController.pocketsDocumentPath = 'vendor/pockets/app/views';
    286     stageController.appTestsRunUrl = '.' + TestAssistant.focusUrl();
    287     stageController.pocketsTestsRunUrl = 'vendor/pockets' + TestAssistant.focusUrl();
    288     stageController.pushScene({
    289       name: 'test',
    290       sceneTemplate:'../../vendor/pockets/app/views/test/test-scene'
    291     },
    292       '../../vendor/pockets/app/views/', stageController.window.reportingBridge);
    293   }
    294 };
    295
    296 pockets.test.getReportingBridge = function() {
    297   try {
    298     var scene = Mojo.Controller.getAppController().getActiveStageController().getScenes()[0];
    299     return scene.assistant.reportingBridge;
    300   } catch(e) {
    301     return null;
    302   }
    303 };
    304
    305 pockets.explode = function() {
    306   throw "pockets.explode does not expect to be called";
    307 };
    308
    309 pockets.getWidgetController = function(widgetDomElement) {
    310   return widgetDomElement._mojoController;
    311 };
    312
    313 pockets.getWidget = function(widgetDomElement) {
    314   return pockets.getWidgetController(widgetDomElement).assistant;
    315 };
    316