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 | }); |
---|