4
0

quote-response.spec.ts 4.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import { type Browser, expect, type Page, test } from '@playwright/test'
  2. import { settle } from '../../support/hydration'
  3. import { addQuotePart, newQuote, quoteShareLink, saveQuote } from '../../support/quote'
  4. /**
  5. * A customer's answer to a quote, followed from the bell to the quote.
  6. *
  7. * A workshop reported that clicking "Quote Changes Requested" in the
  8. * notification panel did nothing, when they expected the quote to open with
  9. * the customer's request on it. Both ways a desk meets the notification are
  10. * walked: opened later from another page, and arriving live while the quote
  11. * itself is already on screen.
  12. */
  13. test.describe.configure({ mode: 'serial' })
  14. const stamp = Date.now()
  15. /** A shared quote the customer can answer, open in the editor. */
  16. async function sharedQuote(page: Page, title: string) {
  17. const quoteUrl = await newQuote(page, title)
  18. await addQuotePart(page, { name: `E2E notification part ${stamp}`, quantity: 1, unitPrice: 300 })
  19. await saveQuote(page)
  20. const shareUrl = await quoteShareLink(page)
  21. return { quoteUrl, shareUrl }
  22. }
  23. /** The customer asks for a change on the public page, signed out. */
  24. async function requestChanges(browser: Browser, shareUrl: string, request: string) {
  25. const customer = await browser.newContext({ storageState: { cookies: [], origins: [] } })
  26. const customerPage = await customer.newPage()
  27. await customerPage.goto(shareUrl)
  28. await expect(async () => {
  29. await customerPage.getByRole('button', { name: 'Request Changes' }).click()
  30. await expect(customerPage.getByRole('textbox')).toBeVisible({ timeout: 2_000 })
  31. }).toPass({ timeout: 30_000 })
  32. await customerPage.getByRole('textbox').fill(request)
  33. await customerPage.getByRole('button', { name: 'Submit Request' }).click()
  34. await expect(customerPage.getByText('Changes Requested').first()).toBeVisible()
  35. await customer.close()
  36. }
  37. /** Opens the bell and clicks the newest notification with this title. */
  38. async function clickNotification(page: Page, title: string) {
  39. const panel = page.getByRole('dialog', { name: 'Notifications' })
  40. await expect(async () => {
  41. await page.getByRole('button', { name: 'Open notifications' }).click()
  42. await expect(panel).toBeVisible({ timeout: 2_000 })
  43. }).toPass({ timeout: 30_000 })
  44. await panel.getByRole('button').filter({ hasText: title }).first().click()
  45. }
  46. test('opened from the bell, a change request lands on the quote showing the request', async ({
  47. page,
  48. browser,
  49. }) => {
  50. const request = `Please use a genuine filter ${stamp}`
  51. const title = `E2E notified quote ${stamp}`
  52. const { quoteUrl, shareUrl } = await sharedQuote(page, title)
  53. await requestChanges(browser, shareUrl, request)
  54. await page.goto('/')
  55. await settle(page)
  56. await clickNotification(page, 'Quote Changes Requested')
  57. await page.waitForURL(quoteUrl, { timeout: 15_000 })
  58. await expect(page.getByText(request)).toBeVisible()
  59. // And on the list, under "Needs attention", highlighted as a change request.
  60. await page.goto(`/quotes?status=attention&search=${encodeURIComponent(title)}`)
  61. await settle(page)
  62. const row = page.getByRole('row').filter({ hasText: title })
  63. await expect(row).toHaveAttribute('data-attention', 'changes_requested')
  64. await expect(page.getByRole('button', { name: /Needs attention/ })).toBeVisible()
  65. await page.goto(quoteUrl)
  66. // At the top of the quote, seen without scrolling past the lines first.
  67. await expect(page.getByText(request)).toBeInViewport()
  68. })
  69. test('arriving while the quote is open, clicking it shows the request without a reload', async ({
  70. page,
  71. browser,
  72. }) => {
  73. const request = `Could you add wiper blades ${stamp}`
  74. const { quoteUrl, shareUrl } = await sharedQuote(page, `E2E live notified quote ${stamp}`)
  75. await page.goto(quoteUrl)
  76. await settle(page)
  77. await requestChanges(browser, shareUrl, request)
  78. await clickNotification(page, 'Quote Changes Requested')
  79. // Still this quote: the newest notification is the one that just arrived.
  80. await expect(page).toHaveURL(quoteUrl)
  81. await expect(page.getByText(request)).toBeVisible({ timeout: 15_000 })
  82. await expect(page.getByText(request)).toBeInViewport()
  83. await expect(page.getByText('Changes Requested', { exact: true }).first()).toBeVisible()
  84. })