e2eUtils.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import puppeteer from 'puppeteer'
  2. export const E2E_TIMEOUT = 30 * 1000
  3. const puppeteerOptions = process.env.CI
  4. ? { args: ['--no-sandbox', '--disable-setuid-sandbox'] }
  5. : {}
  6. export function setupPuppeteer() {
  7. let browser: puppeteer.Browser
  8. let page: puppeteer.Page
  9. beforeEach(async () => {
  10. browser = await puppeteer.launch(puppeteerOptions)
  11. page = await browser.newPage()
  12. page.on('console', e => {
  13. if (e.type() === 'error') {
  14. const err = e.args()[0] as any
  15. console.error(
  16. `Error from Puppeteer-loaded page:\n`,
  17. err._remoteObject.description
  18. )
  19. }
  20. })
  21. })
  22. afterEach(async () => {
  23. await browser.close()
  24. })
  25. async function click(selector: string, options?: puppeteer.ClickOptions) {
  26. await page.click(selector, options)
  27. }
  28. async function count(selector: string) {
  29. return (await page.$$(selector)).length
  30. }
  31. async function text(selector: string) {
  32. return await page.$eval(selector, node => node.textContent)
  33. }
  34. async function value(selector: string) {
  35. return await page.$eval(selector, node => (node as HTMLInputElement).value)
  36. }
  37. async function html(selector: string) {
  38. return await page.$eval(selector, node => node.innerHTML)
  39. }
  40. async function classList(selector: string) {
  41. return await page.$eval(selector, (node: any) => [...node.classList])
  42. }
  43. async function children(selector: string) {
  44. return await page.$eval(selector, (node: any) => [...node.children])
  45. }
  46. async function isVisible(selector: string) {
  47. const display = await page.$eval(selector, node => {
  48. return window.getComputedStyle(node).display
  49. })
  50. return display !== 'none'
  51. }
  52. async function isChecked(selector: string) {
  53. return await page.$eval(
  54. selector,
  55. node => (node as HTMLInputElement).checked
  56. )
  57. }
  58. async function isFocused(selector: string) {
  59. return await page.$eval(selector, node => node === document.activeElement)
  60. }
  61. async function setValue(selector: string, value: string) {
  62. await page.$eval(
  63. selector,
  64. (node, value) => {
  65. ;(node as HTMLInputElement).value = value
  66. node.dispatchEvent(new Event('input'))
  67. },
  68. value
  69. )
  70. }
  71. async function typeValue(selector: string, value: string) {
  72. const el = (await page.$(selector))!
  73. await el.evaluate(node => ((node as HTMLInputElement).value = ''))
  74. await el.type(value)
  75. }
  76. async function enterValue(selector: string, value: string) {
  77. const el = (await page.$(selector))!
  78. await el.evaluate(node => ((node as HTMLInputElement).value = ''))
  79. await el.type(value)
  80. await el.press('Enter')
  81. }
  82. async function clearValue(selector: string) {
  83. return await page.$eval(
  84. selector,
  85. node => ((node as HTMLInputElement).value = '')
  86. )
  87. }
  88. function timeout(time: number) {
  89. return page.evaluate(time => {
  90. return new Promise(r => {
  91. setTimeout(r, time)
  92. })
  93. }, time)
  94. }
  95. function nextFrame() {
  96. return page.evaluate(() => {
  97. return new Promise(resolve => {
  98. requestAnimationFrame(() => {
  99. requestAnimationFrame(resolve)
  100. })
  101. })
  102. })
  103. }
  104. return {
  105. page: () => page,
  106. click,
  107. count,
  108. text,
  109. value,
  110. html,
  111. classList,
  112. children,
  113. isVisible,
  114. isChecked,
  115. isFocused,
  116. setValue,
  117. typeValue,
  118. enterValue,
  119. clearValue,
  120. timeout,
  121. nextFrame
  122. }
  123. }