[483] | 1 | define([ |
---|
| 2 | "require", |
---|
| 3 | "doh/main", |
---|
| 4 | "./aspect", |
---|
| 5 | "./dom-construct", |
---|
| 6 | "./dom-style", |
---|
| 7 | "./_base/kernel", |
---|
| 8 | "./_base/lang", |
---|
| 9 | "./on", |
---|
| 10 | "./robot", |
---|
| 11 | "./sniff", |
---|
| 12 | "./_base/window" |
---|
| 13 | ], function(require, doh, aspect, construct, style, kernel, lang, on, robot, has, win){ |
---|
| 14 | |
---|
| 15 | kernel.experimental("dojo.robotx"); |
---|
| 16 | |
---|
| 17 | // module: |
---|
| 18 | // dojo.robotx |
---|
| 19 | // description: |
---|
| 20 | // loads an external app into an iframe and points dojo.doc to the iframe document, allowing the robot to control it |
---|
| 21 | // to use: set robotURL in djConfig to the URL you want to load |
---|
| 22 | // dojo.require this file |
---|
| 23 | |
---|
| 24 | // The iframe containing the external app |
---|
| 25 | var iframe = null; |
---|
| 26 | |
---|
| 27 | // On IE6/7, a firebug console will appear. Scrunch it a bit to leave room for the external test file. |
---|
| 28 | kernel.config.debugHeight = kernel.config.debugHeight || 200; |
---|
| 29 | |
---|
| 30 | |
---|
| 31 | // urlLoaded is a Deferred that will be resolved whenever the iframe passed to initRobot() finishes loading, or reloads |
---|
| 32 | var urlLoaded; |
---|
| 33 | |
---|
| 34 | function attachIframe(url){ |
---|
| 35 | // summary: |
---|
| 36 | // Create iframe to load external app at specified url. Iframe gets onload handler to call onIframeLoad() |
---|
| 37 | // when specified URL finishes loading, and also if the iframe loads a different URL in the future. |
---|
| 38 | // returns: |
---|
| 39 | // A Deferred that fires when everything has finished initializing |
---|
| 40 | |
---|
| 41 | require(["./domReady!"], function(){ |
---|
| 42 | var emptyStyle = { |
---|
| 43 | overflow: "hidden", |
---|
| 44 | margin: "0px", |
---|
| 45 | borderWidth: "0px", |
---|
| 46 | height: "100%", |
---|
| 47 | width: "100%" |
---|
| 48 | }; |
---|
| 49 | style.set(document.documentElement, emptyStyle); |
---|
| 50 | style.set(document.body, emptyStyle); |
---|
| 51 | |
---|
| 52 | // Create the iframe for the external document. Put it above the firebug-lite div (if such a div exists). |
---|
| 53 | // console.log("creating iframe for external document"); |
---|
| 54 | iframe = document.createElement("iframe"); |
---|
| 55 | iframe.setAttribute("ALLOWTRANSPARENCY","true"); |
---|
| 56 | iframe.scrolling = has("ie") ? "yes" : "auto"; |
---|
| 57 | var scrollRoot = document.compatMode == "BackCompat" ? document.body : document.documentElement; |
---|
| 58 | var consoleHeight = (document.getElementById("firebug") || {}).offsetHeight || 0; |
---|
| 59 | style.set(iframe, { |
---|
| 60 | border: "0px none", |
---|
| 61 | padding: "0px", |
---|
| 62 | margin: "0px", |
---|
| 63 | width: "100%", |
---|
| 64 | height: consoleHeight ? (scrollRoot.clientHeight - consoleHeight)+"px" : "100%" |
---|
| 65 | }); |
---|
| 66 | iframe.src = url; |
---|
| 67 | |
---|
| 68 | // Code to handle load event on iframe. Seems like this should happen before setting iframe src on line above? |
---|
| 69 | // Also, can't we use on() in all cases, even for old IE? |
---|
| 70 | if(iframe.attachEvent !== undefined){ |
---|
| 71 | iframe.attachEvent("onload", onIframeLoad); |
---|
| 72 | }else{ |
---|
| 73 | on(iframe, "load", onIframeLoad); |
---|
| 74 | } |
---|
| 75 | |
---|
| 76 | construct.place(iframe, win.body(), "first"); |
---|
| 77 | }); |
---|
| 78 | } |
---|
| 79 | |
---|
| 80 | function onIframeLoad(){ |
---|
| 81 | // summary: |
---|
| 82 | // Load handler when iframe specified to initRobot() finishes loading, or when it reloads. |
---|
| 83 | // It resolves the urlLoaded Deferred to make the rests of the tests runs. |
---|
| 84 | |
---|
| 85 | robot._updateDocument(); |
---|
| 86 | |
---|
| 87 | // If dojo is present in the test case, then at least make a best effort to wait for it to load. |
---|
| 88 | // The test must handle other race conditions like initial data queries or asynchronous parses by itself. |
---|
| 89 | if(iframe.contentWindow.require){ |
---|
| 90 | iframe.contentWindow.require(["dojo/ready"], function(ready){ |
---|
| 91 | ready(Infinity, function(){ |
---|
| 92 | setTimeout(function(){ |
---|
| 93 | urlLoaded.resolve(true); |
---|
| 94 | }, 500); // 500ms fudge factor; otherwise focus doesn't work on IE8, see ValidationTextBox.js, TimeTextBox.js, etc. |
---|
| 95 | }); |
---|
| 96 | }); |
---|
| 97 | }else{ |
---|
| 98 | urlLoaded.resolve(true); |
---|
| 99 | } |
---|
| 100 | } |
---|
| 101 | |
---|
| 102 | lang.mixin(robot, { |
---|
| 103 | _updateDocument: function(){ |
---|
| 104 | // summary: |
---|
| 105 | // Called every time a new page is loaded into the iframe, to setup variables |
---|
| 106 | // Point dojo.global, dojo.publish, etc. to refer to iframe. |
---|
| 107 | // Remove for 2.0? |
---|
| 108 | |
---|
| 109 | kernel.setContext(iframe.contentWindow, iframe.contentWindow.document); |
---|
| 110 | |
---|
| 111 | // Also set pointers inside robot, for easy access via AMD (where there is no dojo variable) |
---|
| 112 | robot.window = iframe.contentWindow; |
---|
| 113 | robot.doc = iframe.contentWindow.document; |
---|
| 114 | |
---|
| 115 | // TODO: shouldn't this wait until dojo has finished loading in the iframe? See require code in onIframeLoad(). |
---|
| 116 | var win = kernel.global; |
---|
| 117 | if(win.dojo){ |
---|
| 118 | // allow the tests to subscribe to topics published by the iframe |
---|
| 119 | kernel.publish = win.dojo.publish; |
---|
| 120 | kernel.subscribe = win.dojo.subscribe; |
---|
| 121 | kernel.connectPublisher = win.dojo.connectPublisher; |
---|
| 122 | } |
---|
| 123 | }, |
---|
| 124 | |
---|
| 125 | initRobot: function(/*String*/ url){ |
---|
| 126 | // summary: |
---|
| 127 | // Opens the application at the specified URL for testing, redirecting dojo to point to the application |
---|
| 128 | // environment instead of the test environment. |
---|
| 129 | // url: |
---|
| 130 | // URL to open. Any of the test's dojo.doc calls (e.g. dojo.byId()), and any dijit.registry calls |
---|
| 131 | // (e.g. dijit.byId()) will point to elements and widgets inside this application. |
---|
| 132 | |
---|
| 133 | doh.registerGroup("initialize robot", { |
---|
| 134 | name: "load " + url, |
---|
| 135 | timeout: 100000, // could take more than 10s so setting to 100s |
---|
| 136 | runTest: function(){ |
---|
| 137 | // Setup module level urlLoaded Deferred that will be resolved by onIframeLoad(), after the iframe |
---|
| 138 | // has finished loading |
---|
| 139 | urlLoaded = new doh.Deferred(); |
---|
| 140 | attachIframe(url); |
---|
| 141 | |
---|
| 142 | return urlLoaded; |
---|
| 143 | } |
---|
| 144 | }); |
---|
| 145 | }, |
---|
| 146 | |
---|
| 147 | waitForPageToLoad: function(/*Function*/ submitActions){ |
---|
| 148 | // summary: |
---|
| 149 | // Notifies DOH that the doh.robot is about to make a page change in the application it is driving, |
---|
| 150 | // returning a doh.Deferred object the user should return in their runTest function as part of a DOH test. |
---|
| 151 | // example: |
---|
| 152 | // | runTest: function(){ |
---|
| 153 | // | return waitForPageLoad(function(){ doh.robot.keyPress(keys.ENTER, 500); }); |
---|
| 154 | // | } |
---|
| 155 | // submitActions: |
---|
| 156 | // The doh.robot will execute the actions the test passes into the submitActions argument (like clicking the submit button), |
---|
| 157 | // expecting these actions to create a page change (like a form submit). |
---|
| 158 | // After these actions execute and the resulting page loads, the next test will start. |
---|
| 159 | |
---|
| 160 | // Setup a new Deferred that onIframeLoad() will resolve when the iframe finishes loading |
---|
| 161 | urlLoaded = new doh.Deferred(); |
---|
| 162 | |
---|
| 163 | submitActions(); |
---|
| 164 | |
---|
| 165 | return urlLoaded; |
---|
| 166 | } |
---|
| 167 | |
---|
| 168 | }); |
---|
| 169 | |
---|
| 170 | return robot; |
---|
| 171 | }); |
---|