workshop-setup.spec.ts 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import { expect, test } from '@playwright/test'
  2. import { signUpWithPassword } from '../../support/cloud'
  3. import { foreignServiceRecordId, organizationIdFor, workshopSetting } from '../../support/db'
  4. import { fillSettled, settle } from '../../support/hydration'
  5. import { pdfContent } from '../../support/pdf'
  6. /**
  7. * The guided setup of a new workshop, through the case that asked for it: an
  8. * owner in France whose browser speaks English. The language customers get
  9. * used to follow the owner's screens, so their invoices came out in English.
  10. * Here the country comes from the clock, French is suggested for the
  11. * documents, the owner's screens stay English, and the first invoice they
  12. * download is French.
  13. */
  14. test.describe.configure({ mode: 'serial', timeout: 180_000 })
  15. // Signed out: these specs sign up as strangers do.
  16. test.use({
  17. storageState: { cookies: [], origins: [] },
  18. timezoneId: 'Europe/Paris',
  19. locale: 'en-US',
  20. })
  21. const stamp = Date.now()
  22. const EMAIL = `e2e-setup-${stamp}@example.com`
  23. const WORKSHOP = `Garage Martin ${stamp}`
  24. test('a workshop in France gets French documents from an English browser', async ({ page }) => {
  25. await signUpWithPassword(page, { name: 'E2E Setup', email: EMAIL, password: `E2e-pass-${stamp}` })
  26. await settle(page)
  27. // Step 1: the country comes from the clock, and with it French for the
  28. // customers, opened under the owner's English by itself.
  29. await expect(page.getByRole('heading', { name: 'Set up your workshop' })).toBeVisible()
  30. await fillSettled(page.locator('#workshopName'), WORKSHOP)
  31. await expect(page.locator('#country')).toContainText('France')
  32. await expect(page.locator('#language')).toContainText('English')
  33. await expect(page.locator('#docLanguage')).toContainText('Français')
  34. await page.getByRole('button', { name: 'Continue' }).click()
  35. // Step 2: the region.
  36. await expect(page.getByRole('heading', { name: 'Language and region' })).toBeVisible()
  37. await expect(page.getByText(/Euro \(EUR\)/)).toBeVisible()
  38. await page.getByRole('button', { name: 'Continue' }).click()
  39. // Step 3: a rate the owner types, under the name used in France.
  40. await expect(page.getByRole('heading', { name: 'Taxes on your invoices' })).toBeVisible()
  41. await expect(page.locator('#taxName')).toHaveValue('TVA')
  42. await expect(page.getByRole('button', { name: 'Continue' })).toBeDisabled()
  43. await fillSettled(page.locator('#taxRate'), '20')
  44. await page.getByRole('button', { name: 'Continue' }).click()
  45. // Step 4: the last look, then the workshop.
  46. await expect(page.getByRole('heading', { name: `Ready to open ${WORKSHOP}` })).toBeVisible()
  47. await expect(page.getByText('Your screens: English')).toBeVisible()
  48. await page.getByRole('button', { name: 'Create workshop' }).click()
  49. await page.waitForURL((url) => !/^\/(auth|onboarding)/.test(url.pathname), { timeout: 60_000 })
  50. const organizationId = await organizationIdFor(EMAIL)
  51. expect(await workshopSetting(organizationId, 'workshop.locale')).toBe('fr')
  52. expect(await workshopSetting(organizationId, 'workshop.currencyCode')).toBe('EUR')
  53. expect(await workshopSetting(organizationId, 'workshop.taxLabel')).toBe('TVA')
  54. expect(await workshopSetting(organizationId, 'workshop.defaultTaxRate')).toBe('20')
  55. // The owner's screens are English, and the invoice they download is French.
  56. const jobId = await foreignServiceRecordId(organizationId)
  57. const response = await page.request.get(`/api/protected/services/${jobId}/pdf`)
  58. expect(response.ok()).toBe(true)
  59. const pdf = await pdfContent(await response.body())
  60. expect(pdf.flat).toContain('FACTURE')
  61. // The design prints the box headings in capitals: "FACTURER À".
  62. expect(pdf.flat.toLowerCase()).toContain('facturer à')
  63. expect(pdf.flat.toLowerCase()).not.toContain('bill to')
  64. })
  65. /**
  66. * Someone on a Norwegian computer whose workshop is in the United Kingdom.
  67. * Picking the country turns the page and the documents English, keeping what
  68. * was typed; picking a language afterwards is theirs, and the country no
  69. * longer moves it.
  70. */
  71. test.describe('the language follows the country until the owner picks one', () => {
  72. // The config pins every request to English; a Norwegian browser sends its own header.
  73. test.use({
  74. timezoneId: 'Europe/Oslo',
  75. locale: 'nb-NO',
  76. extraHTTPHeaders: { 'accept-language': 'nb-NO,nb;q=0.9' },
  77. })
  78. const email = `e2e-setup-uk-${stamp}@example.com`
  79. const workshop = `Riverside Motors ${stamp}`
  80. test('a British workshop set up from a Norwegian computer', async ({ page }) => {
  81. await signUpWithPassword(page, { name: 'E2E UK', email, password: `E2e-pass-${stamp}` })
  82. await settle(page)
  83. await expect(page.locator('html')).toHaveAttribute('lang', 'nb')
  84. await fillSettled(page.locator('#workshopName'), workshop)
  85. // The country: "UK" finds it, and the page turns English with the name kept.
  86. await page.locator('#country').click()
  87. await page.keyboard.type('UK')
  88. await page.keyboard.press('Enter')
  89. await expect(page.locator('html')).toHaveAttribute('lang', 'en', { timeout: 15_000 })
  90. await expect(page.getByRole('heading', { name: 'Set up your workshop' })).toBeVisible()
  91. await expect(page.locator('#workshopName')).toHaveValue(workshop)
  92. await expect(page.locator('#language')).toContainText('English')
  93. // The owner picks Norwegian: their screens and their customers get it.
  94. await page.locator('#language').click()
  95. await page.keyboard.type('Norsk')
  96. await page.keyboard.press('Enter')
  97. await expect(page.locator('html')).toHaveAttribute('lang', 'nb', { timeout: 15_000 })
  98. await expect(page.locator('#workshopName')).toHaveValue(workshop)
  99. await expect(page.locator('#country')).toContainText('Storbritannia')
  100. // A picked language stays when the country changes.
  101. await page.locator('#country').click()
  102. await page.keyboard.type('Irland')
  103. await page.keyboard.press('Enter')
  104. await expect(page.locator('#country')).toContainText('Irland')
  105. await settle(page)
  106. await expect(page.locator('html')).toHaveAttribute('lang', 'nb')
  107. // One language for everything: no customer language of its own.
  108. await expect(page.locator('#docLanguage')).toHaveCount(0)
  109. await page.locator('form button[type="submit"]').click()
  110. await page.locator('form button[type="submit"]').click()
  111. await fillSettled(page.locator('#taxRate'), '23')
  112. await page.locator('form button[type="submit"]').click()
  113. await page.locator('form button[type="submit"]').click()
  114. await page.waitForURL((url) => !/^\/(auth|onboarding)/.test(url.pathname), { timeout: 60_000 })
  115. const organizationId = await organizationIdFor(email)
  116. expect(await workshopSetting(organizationId, 'workshop.locale')).toBe('nb')
  117. expect(await workshopSetting(organizationId, 'workshop.currencyCode')).toBe('EUR')
  118. expect(await workshopSetting(organizationId, 'workshop.defaultTaxRate')).toBe('23')
  119. })
  120. })