|
| 1 | +import { test, expect, request } from '@playwright/test'; |
| 2 | + |
| 3 | +/** |
| 4 | + * Shared driver-acceptance suite for the CRM example. |
| 5 | + * Each driver-specific spec calls `runDriverAcceptance({ label, baseURL })`. |
| 6 | + * The CRM dev server is expected to be reachable at `baseURL`, |
| 7 | + * already booted with the appropriate `OS_DATABASE_URL` for the driver |
| 8 | + * under test (this is wired by the Playwright `webServer` config or by |
| 9 | + * a wrapper script that boots the server out-of-band). |
| 10 | + */ |
| 11 | +export function runDriverAcceptance(opts: { label: string; baseURL?: string }) { |
| 12 | + const BASE_URL = opts.baseURL ?? process.env.CRM_BASE_URL ?? 'http://localhost:3001'; |
| 13 | + |
| 14 | + test.describe(`CRM running on ${opts.label} driver`, () => { |
| 15 | + test('Studio responds', async () => { |
| 16 | + const ctx = await request.newContext({ baseURL: BASE_URL }); |
| 17 | + const studio = await ctx.get('/_studio/'); |
| 18 | + expect(studio.status()).toBeGreaterThanOrEqual(200); |
| 19 | + expect(studio.status()).toBeLessThan(500); |
| 20 | + await ctx.dispose(); |
| 21 | + }); |
| 22 | + |
| 23 | + test('seed data is queryable', async () => { |
| 24 | + const ctx = await request.newContext({ baseURL: BASE_URL }); |
| 25 | + const res = await ctx.get('/api/v1/data/account?limit=10'); |
| 26 | + expect(res.ok()).toBe(true); |
| 27 | + const body = await res.json(); |
| 28 | + expect(body.object).toBe('account'); |
| 29 | + expect(Array.isArray(body.records)).toBe(true); |
| 30 | + expect(body.records.length).toBeGreaterThan(0); |
| 31 | + await ctx.dispose(); |
| 32 | + }); |
| 33 | + |
| 34 | + test('CRUD round-trip on account', async () => { |
| 35 | + const ctx = await request.newContext({ baseURL: BASE_URL }); |
| 36 | + const unique = `Playwright ${opts.label} ${Date.now()}`; |
| 37 | + |
| 38 | + const created = await ctx.post('/api/v1/data/account', { |
| 39 | + data: { name: unique, industry: 'technology', type: 'prospect' }, |
| 40 | + }); |
| 41 | + expect(created.ok()).toBe(true); |
| 42 | + const createdBody = await created.json(); |
| 43 | + const id = createdBody.id ?? createdBody.record?.id; |
| 44 | + expect(id).toBeTruthy(); |
| 45 | + expect(createdBody.record?.name).toBe(unique); |
| 46 | + |
| 47 | + const fetched = await ctx.get(`/api/v1/data/account/${id}`); |
| 48 | + expect(fetched.ok()).toBe(true); |
| 49 | + const fetchedBody = await fetched.json(); |
| 50 | + expect(fetchedBody.record?.name).toBe(unique); |
| 51 | + |
| 52 | + const updated = await ctx.patch(`/api/v1/data/account/${id}`, { |
| 53 | + data: { industry: 'finance' }, |
| 54 | + }); |
| 55 | + expect(updated.ok()).toBe(true); |
| 56 | + |
| 57 | + const reread = await ctx.get(`/api/v1/data/account/${id}`); |
| 58 | + const rereadBody = await reread.json(); |
| 59 | + expect(rereadBody.record?.industry).toBe('finance'); |
| 60 | + |
| 61 | + const deleted = await ctx.delete(`/api/v1/data/account/${id}`); |
| 62 | + expect(deleted.ok()).toBe(true); |
| 63 | + |
| 64 | + await ctx.dispose(); |
| 65 | + }); |
| 66 | + }); |
| 67 | +} |
0 commit comments