Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

devtoolsdriver.js 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. const fs_1 = __importDefault(require("fs"));
  7. const path_1 = __importDefault(require("path"));
  8. const uuid_1 = require("uuid");
  9. const logger_1 = __importDefault(require("@wdio/logger"));
  10. const elementstore_1 = __importDefault(require("./elementstore"));
  11. const utils_1 = require("./utils");
  12. const constants_1 = require("./constants");
  13. const log = logger_1.default('devtools');
  14. class DevToolsDriver {
  15. constructor(browser, pages) {
  16. this.commands = {};
  17. this.elementStore = new elementstore_1.default();
  18. this.windows = new Map();
  19. this.timeouts = new Map();
  20. this.activeDialog = undefined;
  21. this.browser = browser;
  22. const dir = path_1.default.resolve(__dirname, 'commands');
  23. const files = fs_1.default.readdirSync(dir).filter((file) => (file.endsWith('.js') ||
  24. (file.endsWith('.ts') &&
  25. !file.endsWith('.d.ts'))));
  26. for (let filename of files) {
  27. const commandName = path_1.default.basename(filename, path_1.default.extname(filename));
  28. if (!commandName) {
  29. throw new Error('Couldn\'t determine command name');
  30. }
  31. this.commands[commandName] = DevToolsDriver.requireCommand(path_1.default.join(dir, commandName));
  32. }
  33. for (const page of pages) {
  34. const pageId = uuid_1.v4();
  35. this.windows.set(pageId, page);
  36. this.currentFrame = page;
  37. this.currentWindowHandle = pageId;
  38. }
  39. this.setTimeouts(constants_1.DEFAULT_IMPLICIT_TIMEOUT, constants_1.DEFAULT_PAGELOAD_TIMEOUT, constants_1.DEFAULT_SCRIPT_TIMEOUT);
  40. const page = this.getPageHandle();
  41. if (page) {
  42. page.on('dialog', this.dialogHandler.bind(this));
  43. page.on('framenavigated', this.framenavigatedHandler.bind(this));
  44. }
  45. }
  46. static requireCommand(filePath) {
  47. return require(filePath).default;
  48. }
  49. register(commandInfo) {
  50. const self = this;
  51. const { command, ref, parameters, variables = [] } = commandInfo;
  52. if (typeof this.commands[command] !== 'function') {
  53. return () => { throw new Error(`Command "${command}" is not yet implemented`); };
  54. }
  55. let retries = 0;
  56. const wrappedCommand = async function (...args) {
  57. await self.checkPendingNavigations();
  58. const params = utils_1.validate(command, parameters, variables, ref, args);
  59. let result;
  60. try {
  61. this.emit('command', { command, params, retries });
  62. result = await self.commands[command].call(self, params);
  63. }
  64. catch (err) {
  65. if (err.message.includes('most likely because of a navigation')) {
  66. log.debug('Command failed due to unfinished page transition, retrying...');
  67. const page = self.getPageHandle();
  68. await new Promise((resolve, reject) => {
  69. const pageloadTimeout = setTimeout(() => reject(new Error('page load timeout')), self.timeouts.get('pageLoad'));
  70. page.once('load', () => {
  71. clearTimeout(pageloadTimeout);
  72. resolve();
  73. });
  74. });
  75. ++retries;
  76. return wrappedCommand.apply(this, args);
  77. }
  78. throw utils_1.sanitizeError(err);
  79. }
  80. this.emit('result', { command, params, retries, result: { value: result } });
  81. if (typeof result !== 'undefined') {
  82. const isScreenshot = (command.toLowerCase().includes('screenshot') &&
  83. typeof result === 'string' &&
  84. result.length > 64);
  85. log.info('RESULT', isScreenshot ? `${result.substr(0, 61)}...` : result);
  86. }
  87. return result;
  88. };
  89. return wrappedCommand;
  90. }
  91. dialogHandler(dialog) {
  92. this.activeDialog = dialog;
  93. }
  94. framenavigatedHandler(frame) {
  95. this.currentFrameUrl = frame.url();
  96. this.elementStore.clear();
  97. }
  98. setTimeouts(implicit, pageLoad, script) {
  99. if (typeof implicit === 'number') {
  100. this.timeouts.set('implicit', implicit);
  101. }
  102. if (typeof pageLoad === 'number') {
  103. this.timeouts.set('pageLoad', pageLoad);
  104. }
  105. if (typeof script === 'number') {
  106. this.timeouts.set('script', script);
  107. }
  108. const page = this.getPageHandle();
  109. const pageloadTimeout = this.timeouts.get('pageLoad');
  110. if (page && pageloadTimeout) {
  111. page.setDefaultTimeout(pageloadTimeout);
  112. }
  113. }
  114. getPageHandle(isInFrame = false) {
  115. if (isInFrame && this.currentFrame) {
  116. return this.currentFrame;
  117. }
  118. if (!this.currentWindowHandle) {
  119. throw new Error('no current window handle registered');
  120. }
  121. const pageHandle = this.windows.get(this.currentWindowHandle);
  122. if (!pageHandle) {
  123. throw new Error('Couldn\'t find page handle');
  124. }
  125. return pageHandle;
  126. }
  127. async checkPendingNavigations(pendingNavigationStart = Date.now()) {
  128. let page = this.getPageHandle();
  129. if (this.activeDialog || !page) {
  130. return;
  131. }
  132. if (!page.mainFrame) {
  133. const pages = await this.browser.pages();
  134. const mainFrame = pages.find((browserPage) => (browserPage.frames().find((frame) => page === frame)));
  135. if (mainFrame) {
  136. page = mainFrame;
  137. }
  138. }
  139. const pageloadTimeout = this.timeouts.get('pageLoad');
  140. const pageloadTimeoutReached = pageloadTimeout != null
  141. ? Date.now() - pendingNavigationStart > pageloadTimeout
  142. : false;
  143. try {
  144. const executionContext = await page.mainFrame().executionContext();
  145. await executionContext.evaluate('1');
  146. const readyState = await executionContext.evaluate('document.readyState');
  147. if (readyState === 'complete' || pageloadTimeoutReached) {
  148. return;
  149. }
  150. }
  151. catch (err) {
  152. if (pageloadTimeoutReached) {
  153. throw err;
  154. }
  155. }
  156. await new Promise(resolve => setTimeout(resolve, Math.min(100, typeof pageloadTimeout === 'number' ? pageloadTimeout / 10 : 100)));
  157. await this.checkPendingNavigations(pendingNavigationStart);
  158. }
  159. }
  160. exports.default = DevToolsDriver;