single-workshop.spec.ts 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import { expect, test } from '@playwright/test'
  2. import { deletePersonWithEmail, organizationCount, personWithEmail } from '../../support/db'
  3. import { settle } from '../../support/hydration'
  4. /**
  5. * A self-hosted install runs one workshop.
  6. *
  7. * The seeded workshop is that one. A stranger who signs up afterwards is not
  8. * opening a second workshop: they are told to ask its owner for an
  9. * invitation, and the owner's own "Add New Company" is refused with the
  10. * pointer to the licence. Both are proved on the count of workshops in the
  11. * database, not only on what the screen says. Lifting the limit with a
  12. * licence is a signed token from torqvoice.com, which this harness cannot
  13. * mint, so that half lives in src/__tests__/lib/features.test.ts.
  14. */
  15. test.describe.configure({ mode: 'serial' })
  16. const stamp = Date.now()
  17. const STRANGER = `e2e-stranger-${stamp}@example.com`
  18. const PASSWORD = `E2e-pass-${stamp}`
  19. let workshops = 0
  20. test.beforeAll(async () => {
  21. workshops = await organizationCount()
  22. expect(workshops, 'the install already has its workshop').toBeGreaterThanOrEqual(1)
  23. })
  24. test.afterAll(async () => {
  25. await deletePersonWithEmail(STRANGER)
  26. })
  27. test.describe('a stranger signing up', () => {
  28. test.use({ storageState: { cookies: [], origins: [] } })
  29. test('is told to ask for an invitation instead of opening a workshop', async ({ page }) => {
  30. await page.goto('/auth/sign-up')
  31. await settle(page)
  32. await page.locator('#name').fill('E2E Stranger')
  33. await page.locator('#email').fill(STRANGER)
  34. await page.locator('#password').fill(PASSWORD)
  35. await page.locator('#terms').click()
  36. await page.locator('form button[type="submit"]').click()
  37. await page.waitForURL(/\/onboarding/, { timeout: 30_000 })
  38. await expect(
  39. page.getByRole('heading', { name: 'This installation already has its workshop' })
  40. ).toBeVisible()
  41. await expect(page.getByText(STRANGER)).toBeVisible()
  42. await expect(page.locator('#workshopName')).toHaveCount(0)
  43. // The account exists, so an invitation can reach it; the workshop count did not move.
  44. expect((await personWithEmail(STRANGER)).users).toBe(1)
  45. expect(await organizationCount()).toBe(workshops)
  46. await page.getByRole('button', { name: 'Sign out' }).click()
  47. await page.waitForURL(/\/auth\/sign-in/, { timeout: 15_000 })
  48. })
  49. test('is sent back to the notice on every visit until invited', async ({ page }) => {
  50. await page.goto('/auth/sign-in')
  51. await settle(page)
  52. await page.locator('#email').fill(STRANGER)
  53. await page.locator('#password').fill(PASSWORD)
  54. await page.getByRole('button', { name: 'Sign In', exact: true }).click()
  55. await page.waitForURL(/\/onboarding/, { timeout: 30_000 })
  56. await expect(
  57. page.getByRole('heading', { name: 'This installation already has its workshop' })
  58. ).toBeVisible()
  59. })
  60. })
  61. test.describe('the owner', () => {
  62. test('cannot add a second company without a licence', async ({ page }) => {
  63. await page.goto('/settings/company')
  64. await settle(page)
  65. const dialog = page.getByRole('dialog', { name: 'Add New Company' })
  66. await expect(async () => {
  67. await page.getByRole('button', { name: 'Add New Company' }).click()
  68. await expect(dialog).toBeVisible({ timeout: 2_000 })
  69. }).toPass({ timeout: 30_000 })
  70. await dialog.locator('#settings-org-name').fill(`E2E Second Garage ${stamp}`)
  71. await dialog.getByRole('button', { name: 'Create Company' }).click()
  72. await expect(page.getByText('This installation runs one workshop')).toBeVisible()
  73. expect(await organizationCount()).toBe(workshops)
  74. })
  75. })