robotx.js 5.8 KB

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