4
0

elements.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. import { By } from 'selenium-webdriver'
  2. import fs from 'fs'
  3. import { expect } from 'chai'
  4. import { Condition } from 'selenium-webdriver'
  5. export const DEFAULT_UI_WAIT_MS = 3000
  6. const executionDialogStatusBy = By.css('.execution-dialog-status')
  7. export async function getActionButtons () {
  8. // Currently, only the active dashboard's contents are rendered,
  9. // so we don't need to scope the selector by dashboard title.
  10. return await webdriver.findElements(By.css('.action-button button'))
  11. }
  12. export async function getExecutionDialogOutput() {
  13. await webdriver.wait(new Condition('Dialog with long int is visible', async () => {
  14. const dialog = await webdriver.findElement({ id: 'execution-results-popup' })
  15. return await dialog.isDisplayed()
  16. }));
  17. const ret = await webdriver.executeScript('return window.logEntries.get(window.executionDialog.executionTrackingId).output')
  18. return ret
  19. }
  20. export async function closeExecutionDialog() {
  21. const btnClose = await webdriver.findElements(By.css('[title="Close"]'))
  22. await btnClose[0].click()
  23. }
  24. export function takeScreenshotOnFailure (test, webdriver) {
  25. if (test.state === 'failed') {
  26. const title = test.fullTitle();
  27. console.log(`Test failed, taking screenshot: ${title}`);
  28. takeScreenshot(webdriver, title);
  29. }
  30. }
  31. export function takeScreenshot (webdriver, title) {
  32. return webdriver.takeScreenshot().then((img) => {
  33. fs.mkdirSync('screenshots', { recursive: true });
  34. title = title.replaceAll('config: ', '')
  35. title = title.replaceAll(/[\(\)\|\*\<\>\:]/g, "_")
  36. title = title + '.failed-test'
  37. fs.writeFileSync('screenshots/' + title + '.png', img, 'base64')
  38. })
  39. }
  40. export async function waitForDashboardLoaded(timeoutMs = DEFAULT_UI_WAIT_MS, expectedTitle = null) {
  41. await webdriver.wait(new Condition('wait for loaded-dashboard', async function () {
  42. const body = await webdriver.findElement(By.tagName('body'))
  43. const attr = await body.getAttribute('loaded-dashboard')
  44. console.log('loaded-dashboard: ', attr)
  45. if (attr == null || attr === '') {
  46. return false
  47. }
  48. if (expectedTitle != null) {
  49. return attr === expectedTitle
  50. }
  51. return true
  52. }), timeoutMs)
  53. }
  54. export async function waitForLogsPage(timeoutMs = DEFAULT_UI_WAIT_MS) {
  55. await webdriver.wait(new Condition('wait for logs page', async () => {
  56. const url = await webdriver.getCurrentUrl()
  57. return url.includes('/logs/') && !url.endsWith('/logs')
  58. }), timeoutMs)
  59. }
  60. export async function waitForArgumentFormPage(timeoutMs = DEFAULT_UI_WAIT_MS) {
  61. await webdriver.wait(new Condition('wait for argument form page', async () => {
  62. const url = await webdriver.getCurrentUrl()
  63. return url.includes('/actionBinding/') && url.includes('/argumentForm')
  64. }), timeoutMs)
  65. }
  66. export async function waitForArgumentFormReady(timeoutMs = DEFAULT_UI_WAIT_MS) {
  67. await webdriver.wait(new Condition('wait for argument form ready', async () => {
  68. const body = await webdriver.findElement(By.tagName('body'))
  69. const attr = await body.getAttribute('loaded-argument-form')
  70. return attr != null && attr !== ''
  71. }), timeoutMs)
  72. }
  73. export async function waitForExecutionComplete(timeoutMs = DEFAULT_UI_WAIT_MS) {
  74. await webdriver.wait(new Condition('wait for execution status', async () => {
  75. const statusElements = await webdriver.findElements(executionDialogStatusBy)
  76. return statusElements.length > 0
  77. }), timeoutMs)
  78. await webdriver.wait(new Condition('wait for execution to finish', async () => {
  79. try {
  80. const statusElement = await webdriver.findElement(executionDialogStatusBy)
  81. const statusText = await statusElement.getText()
  82. return !statusText.includes('Still running') && !statusText.includes('Queued')
  83. } catch (e) {
  84. return false
  85. }
  86. }), timeoutMs)
  87. }
  88. export async function getRootAndWait() {
  89. await webdriver.get(runner.baseUrl())
  90. await waitForDashboardLoaded()
  91. }
  92. export async function closeSidebar() {
  93. await webdriver.findElement(By.id('sidebar-toggler-button')).click()
  94. const sidebar = await webdriver.findElement(By.id('mainnav'))
  95. const neededLeft = '-250px' // Assuming sidebar is closed at this position
  96. let lastLeft = ''
  97. await webdriver.wait(new Condition('wait for sidebar to close', async function() {
  98. const left = await sidebar.getCssValue('left')
  99. if (left !== lastLeft) {
  100. lastLeft = left
  101. console.log('Sidebar left changed to: ', left)
  102. return false
  103. } else {
  104. console.log('Sidebar closed, left is: *' + left, left === neededLeft ? ' (as expected)' : '')
  105. return left === neededLeft
  106. }
  107. }), DEFAULT_UI_WAIT_MS)
  108. }
  109. export async function openSidebar() {
  110. await webdriver.findElement(By.id('sidebar-toggler-button')).click()
  111. const sidebar = await webdriver.findElement(By.id('mainnav'))
  112. let lastLeft = 0
  113. await webdriver.wait(new Condition('wait for sidebar to open', async function() {
  114. const left = await sidebar.getCssValue('left')
  115. if (left !== lastLeft) {
  116. lastLeft = left
  117. console.log('Sidebar left changed to: ', left)
  118. return false
  119. } else {
  120. console.log('Sidebar opened, left is: ', left)
  121. return true
  122. }
  123. }), DEFAULT_UI_WAIT_MS)
  124. }
  125. export async function getNavigationLinks() {
  126. const navigationLinks = await webdriver.findElements(By.css('.navigation-links li'))
  127. return navigationLinks
  128. }
  129. export async function requireExecutionDialogStatus (webdriver, expected) {
  130. await webdriver.wait(new Condition('wait for action to be running', async function () {
  131. const dialogStatus = await webdriver.findElement(executionDialogStatusBy)
  132. const actual = await dialogStatus.getText()
  133. if (actual === expected) {
  134. return true
  135. } else {
  136. console.log('Waiting for domStatus text to be: ', expected, ', it is currently: ', actual)
  137. return false
  138. }
  139. }), DEFAULT_UI_WAIT_MS)
  140. }
  141. export async function findExecutionDialog (webdriver) {
  142. return webdriver.findElement(By.id('execution-results-popup'))
  143. }
  144. export async function getActionButton (webdriver, title) {
  145. const buttons = await webdriver.findElements(By.css('[title="' + title + '"]'))
  146. expect(buttons).to.have.length(1)
  147. return buttons[0]
  148. }
  149. export async function getTerminalBuffer() {
  150. try {
  151. const output = await webdriver.executeScript(`
  152. if (window.terminal && window.terminal.getBufferAsString) {
  153. return window.terminal.getBufferAsString();
  154. }
  155. return null;
  156. `)
  157. return output
  158. } catch (e) {
  159. console.log('[getTerminalBuffer] Error:', e.message)
  160. return null
  161. }
  162. }