suggestionsBrowserKey.mjs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. import { describe, it, before, after } from 'mocha'
  2. import { expect } from 'chai'
  3. import { By, Condition } from 'selenium-webdriver'
  4. import {
  5. DEFAULT_UI_WAIT_MS,
  6. getRootAndWait,
  7. getActionButton,
  8. takeScreenshotOnFailure,
  9. waitForDashboardLoaded,
  10. waitForLogsPage,
  11. waitForArgumentFormPage,
  12. waitForArgumentFormReady,
  13. waitForExecutionComplete,
  14. } from '../../lib/elements.js'
  15. async function clickBackFromLogsPage() {
  16. const goBackButtons = await webdriver.findElements(By.css('button[title="Go back"]'))
  17. if (goBackButtons.length > 0) {
  18. await goBackButtons[0].click()
  19. return 'history'
  20. }
  21. const dashboardBackButtons = await webdriver.findElements(By.css('button[title^="Back to "]'))
  22. if (dashboardBackButtons.length > 0) {
  23. await dashboardBackButtons[0].click()
  24. return 'dashboard'
  25. }
  26. throw new Error('No back button found on execution logs page')
  27. }
  28. async function ensureOnDashboard() {
  29. let url = await webdriver.getCurrentUrl()
  30. if (url.includes('/logs/')) {
  31. const backType = await clickBackFromLogsPage()
  32. if (backType === 'history') {
  33. await webdriver.wait(
  34. new Condition('wait for argument form after logs back', async () => {
  35. const currentUrl = await webdriver.getCurrentUrl()
  36. return currentUrl.includes('/argumentForm')
  37. }),
  38. DEFAULT_UI_WAIT_MS
  39. )
  40. url = await webdriver.getCurrentUrl()
  41. } else {
  42. await waitForDashboardLoaded()
  43. url = await webdriver.getCurrentUrl()
  44. }
  45. }
  46. if (url.includes('/argumentForm')) {
  47. const cancelButton = await webdriver.findElement(By.css('button[name="cancel"]'))
  48. await cancelButton.click()
  49. await waitForDashboardLoaded()
  50. }
  51. const actionButtons = await webdriver.findElements(By.css('[title="Test suggestionsBrowserKey"]'))
  52. if (actionButtons.length === 1) {
  53. return
  54. }
  55. await getRootAndWait()
  56. }
  57. async function openArgumentForm() {
  58. await ensureOnDashboard()
  59. const btn = await getActionButton(webdriver, 'Test suggestionsBrowserKey')
  60. await btn.click()
  61. await waitForArgumentFormPage()
  62. await waitForArgumentFormReady()
  63. }
  64. async function getTestInput() {
  65. return await webdriver.findElement(By.id('testInput'))
  66. }
  67. async function getTestInput2() {
  68. return await webdriver.findElement(By.id('testInput2'))
  69. }
  70. async function getDatalistOptions(inputName = 'testInput') {
  71. return await webdriver.findElements(By.css(`datalist#${inputName}-choices option`))
  72. }
  73. async function submitForm() {
  74. const submitButton = await webdriver.findElement(By.css('button[name="start"]'))
  75. await submitButton.click()
  76. }
  77. async function getLocalStorageItem(key) {
  78. return await webdriver.executeScript(`return localStorage.getItem('${key}')`)
  79. }
  80. async function clearLocalStorage() {
  81. await webdriver.executeScript('return localStorage.clear()')
  82. }
  83. describe('config: suggestionsBrowserKey', function () {
  84. before(async function () {
  85. await runner.start('suggestionsBrowserKey')
  86. await getRootAndWait()
  87. })
  88. after(async () => {
  89. await runner.stop()
  90. })
  91. afterEach(function () {
  92. takeScreenshotOnFailure(this.currentTest, webdriver)
  93. })
  94. it('Input fields with suggestionsBrowserKey are rendered', async function () {
  95. await openArgumentForm()
  96. const input1 = await getTestInput()
  97. expect(await input1.getTagName()).to.equal('input')
  98. expect(await input1.getAttribute('type')).to.equal('text')
  99. const label1 = await webdriver.findElement(By.css('label[for="testInput"]'))
  100. expect(await label1.getText()).to.contain('Test Input')
  101. const input2 = await getTestInput2()
  102. expect(await input2.getTagName()).to.equal('input')
  103. expect(await input2.getAttribute('type')).to.equal('text')
  104. const label2 = await webdriver.findElement(By.css('label[for="testInput2"]'))
  105. expect(await label2.getText()).to.contain('Test Input 2')
  106. })
  107. it('Submitting form saves value to localStorage', async function () {
  108. await clearLocalStorage()
  109. await openArgumentForm()
  110. const input = await getTestInput()
  111. // Use default argument type "ascii" (alphanumeric only) so tests pass when
  112. // config does not set a looser type (e.g. CI merge base without type lines).
  113. const testValue = 'testvalue123'
  114. await input.clear()
  115. await input.sendKeys(testValue)
  116. await submitForm()
  117. await waitForLogsPage()
  118. await waitForExecutionComplete()
  119. const stored = await getLocalStorageItem('olivetin-suggestions-test-suggestions-key')
  120. expect(stored).to.not.be.null
  121. const suggestions = JSON.parse(stored)
  122. expect(suggestions).to.be.an('array')
  123. expect(suggestions).to.include(testValue)
  124. })
  125. it('Previously saved values appear in datalist', async function () {
  126. const testValue = 'savedsuggestion456'
  127. await webdriver.executeScript(`
  128. const key = 'olivetin-suggestions-test-suggestions-key';
  129. localStorage.setItem(key, JSON.stringify(['${testValue}']));
  130. `)
  131. await openArgumentForm()
  132. const datalist = await webdriver.findElement(By.id('testInput-choices'))
  133. expect(datalist).to.not.be.null
  134. const options = await getDatalistOptions()
  135. expect(options.length).to.be.greaterThan(0)
  136. let foundValue = false
  137. for (const option of options) {
  138. const value = await option.getAttribute('value')
  139. if (value === testValue) {
  140. foundValue = true
  141. break
  142. }
  143. }
  144. expect(foundValue).to.be.true
  145. })
  146. it('Multiple submissions accumulate suggestions', async function () {
  147. await clearLocalStorage()
  148. await openArgumentForm()
  149. const input1 = await getTestInput()
  150. await input1.clear()
  151. await input1.sendKeys('firstvalue')
  152. await submitForm()
  153. await waitForLogsPage()
  154. await waitForExecutionComplete()
  155. await openArgumentForm()
  156. const input2 = await getTestInput()
  157. await input2.clear()
  158. await input2.sendKeys('secondvalue')
  159. await submitForm()
  160. await waitForLogsPage()
  161. await waitForExecutionComplete()
  162. const stored = await getLocalStorageItem('olivetin-suggestions-test-suggestions-key')
  163. expect(stored).to.not.be.null
  164. const suggestions = JSON.parse(stored)
  165. expect(suggestions).to.be.an('array')
  166. expect(suggestions).to.include('firstvalue')
  167. expect(suggestions).to.include('secondvalue')
  168. expect(suggestions[0]).to.equal('secondvalue')
  169. })
  170. it('Empty values are not saved to localStorage', async function () {
  171. await clearLocalStorage()
  172. await openArgumentForm()
  173. const input = await getTestInput()
  174. await input.clear()
  175. await submitForm()
  176. await waitForLogsPage()
  177. await waitForExecutionComplete()
  178. const stored = await getLocalStorageItem('olivetin-suggestions-test-suggestions-key')
  179. if (stored !== null) {
  180. const suggestions = JSON.parse(stored)
  181. expect(suggestions).to.be.an('array')
  182. expect(suggestions).to.have.length(0)
  183. }
  184. })
  185. it('Suggestions are shared across inputs with the same suggestionsBrowserKey', async function () {
  186. this.timeout(12000)
  187. await clearLocalStorage()
  188. await openArgumentForm()
  189. const input1 = await getTestInput()
  190. await input1.clear()
  191. await input1.sendKeys('sharedfrominput1')
  192. await submitForm()
  193. await waitForLogsPage()
  194. await waitForExecutionComplete()
  195. await openArgumentForm()
  196. const datalist1 = await webdriver.findElement(By.id('testInput-choices'))
  197. expect(datalist1).to.not.be.null
  198. const options1 = await getDatalistOptions('testInput')
  199. let foundInInput1 = false
  200. for (const option of options1) {
  201. const value = await option.getAttribute('value')
  202. if (value === 'sharedfrominput1') {
  203. foundInInput1 = true
  204. break
  205. }
  206. }
  207. expect(foundInInput1).to.be.true
  208. const datalist2 = await webdriver.findElement(By.id('testInput2-choices'))
  209. expect(datalist2).to.not.be.null
  210. const options2 = await getDatalistOptions('testInput2')
  211. let foundInInput2 = false
  212. for (const option of options2) {
  213. const value = await option.getAttribute('value')
  214. if (value === 'sharedfrominput1') {
  215. foundInInput2 = true
  216. break
  217. }
  218. }
  219. expect(foundInInput2).to.be.true
  220. const input2 = await getTestInput2()
  221. await input2.clear()
  222. await input2.sendKeys('sharedfrominput2')
  223. await submitForm()
  224. await waitForLogsPage()
  225. await waitForExecutionComplete()
  226. await openArgumentForm()
  227. const options1After = await getDatalistOptions('testInput')
  228. let foundValue1 = false
  229. let foundValue2 = false
  230. for (const option of options1After) {
  231. const value = await option.getAttribute('value')
  232. if (value === 'sharedfrominput1') {
  233. foundValue1 = true
  234. }
  235. if (value === 'sharedfrominput2') {
  236. foundValue2 = true
  237. }
  238. }
  239. expect(foundValue1).to.be.true
  240. expect(foundValue2).to.be.true
  241. const options2After = await getDatalistOptions('testInput2')
  242. foundValue1 = false
  243. foundValue2 = false
  244. for (const option of options2After) {
  245. const value = await option.getAttribute('value')
  246. if (value === 'sharedfrominput1') {
  247. foundValue1 = true
  248. }
  249. if (value === 'sharedfrominput2') {
  250. foundValue2 = true
  251. }
  252. }
  253. expect(foundValue1).to.be.true
  254. expect(foundValue2).to.be.true
  255. })
  256. })