angular_wait_barrier.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. const webdriver_logger_1 = require("./webdriver_logger");
  4. const angularWaits = require('./client_scripts/wait.js');
  5. /**
  6. * A barrier that uses Angular's Testability API to block commands until the application is stable.
  7. */
  8. class AngularWaitBarrier {
  9. constructor(client) {
  10. this.client = client;
  11. this.enabled = true;
  12. this.rootSelector = '';
  13. }
  14. /**
  15. * A CSS Selector for a DOM element within your Angular application.
  16. * BlockingProxy will attempt to automatically find your application, but it is
  17. * necessary to set rootElement in certain cases.
  18. *
  19. * In Angular 1, BlockingProxy will use the element your app bootstrapped to by
  20. * default. If that doesn't work, it will then search for hooks in `body` or
  21. * `ng-app` elements (details here: https://git.io/v1b2r).
  22. *
  23. * In later versions of Angular, BlockingProxy will try to hook into all angular
  24. * apps on the page. Use rootElement to limit the scope of which apps
  25. * BlockingProxy waits for and searches within.
  26. *
  27. * @param rootSelector A selector for the root element of the Angular app.
  28. */
  29. setRootSelector(selector) {
  30. this.rootSelector = selector;
  31. }
  32. waitForAngularData() {
  33. return JSON.stringify({
  34. script: 'return (' + angularWaits.NG_WAIT_FN + ').apply(null, arguments);',
  35. args: [this.rootSelector]
  36. });
  37. }
  38. /**
  39. * Turn on WebDriver logging.
  40. *
  41. * @param logDir The directory to create logs in.
  42. */
  43. enableLogging(logDir) {
  44. if (!this.logger) {
  45. this.logger = new webdriver_logger_1.WebDriverLogger();
  46. }
  47. this.logger.setLogDir(logDir);
  48. }
  49. /**
  50. * Override the logger instance. Only used for testing.
  51. */
  52. setLogger(logger) {
  53. this.logger = logger;
  54. }
  55. sendRequestToStabilize(command) {
  56. return this.client.executeAsync(command.sessionId, this.waitForAngularData()).then((value) => {
  57. // waitForAngular only returns a value if there was an error
  58. // in the browser.
  59. if (value) {
  60. throw new Error('Error from waitForAngular: ' + value);
  61. }
  62. });
  63. }
  64. shouldStabilize(command) {
  65. const url = command.url;
  66. if (!this.enabled) {
  67. return false;
  68. }
  69. // TODO - should this implement some state, and be smart about whether
  70. // stabilization is necessary or not? Would that be as simple as GET/POST?
  71. // e.g. two gets in a row don't require a wait btwn.
  72. //
  73. // See https://code.google.com/p/selenium/wiki/JsonWireProtocol for
  74. // descriptions of the paths.
  75. // We shouldn't stabilize if we haven't loaded the page yet.
  76. const parts = url.split('/');
  77. if (parts.length < 4) {
  78. return false;
  79. }
  80. const commandsToWaitFor = [
  81. 'executeScript', 'screenshot', 'source', 'title', 'element', 'elements', 'execute', 'keys',
  82. 'moveto', 'click', 'buttondown', 'buttonup', 'doubleclick', 'touch', 'get'
  83. ];
  84. if (commandsToWaitFor.indexOf(parts[3]) != -1) {
  85. return true;
  86. }
  87. return false;
  88. }
  89. onCommand(command) {
  90. if (this.logger) {
  91. command.on('data', () => {
  92. this.logger.logWebDriverCommand(command);
  93. });
  94. }
  95. if (this.shouldStabilize(command)) {
  96. const started = Date.now();
  97. return this.sendRequestToStabilize(command).then(() => {
  98. const ended = Date.now();
  99. if (this.logger) {
  100. this.logger.logEvent('Waiting for Angular', command.sessionId, (ended - started));
  101. }
  102. });
  103. }
  104. return Promise.resolve(null);
  105. }
  106. }
  107. exports.AngularWaitBarrier = AngularWaitBarrier;
  108. //# sourceMappingURL=angular_wait_barrier.js.map