diff --git a/apps/web/.env.example b/apps/web/.env.example index 582bdcb4d..633e85a88 100644 --- a/apps/web/.env.example +++ b/apps/web/.env.example @@ -1,11 +1,16 @@ # [[E2E Tests]] -E2E_TEST_USERNAME="Test" -E2E_TEST_USER_EMAIL="mytestuser@mail.com" -E2E_TEST_USER_PASSWORD="test_password" E2E_TEST_SIGNER_NAME="Test Signer" E2E_TEST_SIGNER_EMAIL="testsigner@mail.com" E2E_TEST_SIGNING_SUBJECT="Test subject" E2E_TEST_SIGNING_MESSAGE="Test message" +# User for the "auth.setup.ts" file and the authenticated tests +E2E_TEST_AUTHENTICATE_USERNAME="New user" +E2E_TEST_AUTHENTICATE_USER_EMAIL="mytestnewuser@mail.com" +E2E_TEST_AUTHENTICATE_USER_PASSWORD="new_test_password" +# User for the *.unauthenticated.ts files +E2E_TEST_USERNAME="Test" +E2E_TEST_USER_EMAIL="mytestuser@mail.com" +E2E_TEST_USER_PASSWORD="test_password" # [[SMTP]] # OPTIONAL: Defines the transport to use for sending emails. Available options: smtp-auth (default) | smtp-api | mailchannels diff --git a/apps/web/global.teardown.ts b/apps/web/global.teardown.ts index db45728f9..815f7abb3 100644 --- a/apps/web/global.teardown.ts +++ b/apps/web/global.teardown.ts @@ -1,12 +1,13 @@ -import { deleteUser } from '@documenso/lib/server-only/user/delete-user'; +import { deleteUserAndItsData } from '@documenso/lib/server-only/user/delete-user-and-data'; async function teardown() { - if (!process.env.E2E_TEST_USERNAME) { + if (!process.env.E2E_TEST_USERNAME || !process.env.E2E_TEST_AUTHENTICATE_USERNAME) { return; } try { - await deleteUser(process.env.E2E_TEST_USERNAME); + await deleteUserAndItsData(process.env.E2E_TEST_USERNAME); + await deleteUserAndItsData(process.env.E2E_TEST_AUTHENTICATE_USERNAME); } catch (e) { throw new Error(`Error deleting user: ${e}`); } diff --git a/apps/web/playwright.config.ts b/apps/web/playwright.config.ts index 9ad0407b2..2244fc785 100644 --- a/apps/web/playwright.config.ts +++ b/apps/web/playwright.config.ts @@ -32,7 +32,7 @@ export default defineConfig({ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: 'on-first-retry', - video: 'retain-on-failure', + navigationTimeout: 60 * 1000, }, /* Configure projects for major browsers */ @@ -41,7 +41,7 @@ export default defineConfig({ { name: 'Authenticated User Tests', testMatch: '*.authenticated.spec.ts', - dependencies: ['setup'], + dependencies: ['setup', 'cleanup db'], use: { ...devices['Desktop Chrome'], storageState: STORAGE_STATE, @@ -49,6 +49,7 @@ export default defineConfig({ }, { name: 'Unauthenticated User Tests', + dependencies: ['cleanup db'], use: { ...devices['Desktop Chrome'], }, diff --git a/apps/web/src/tests/e2e/auth.setup.ts b/apps/web/src/tests/e2e/auth.setup.ts index bc223a54c..1a3d3b1c8 100644 --- a/apps/web/src/tests/e2e/auth.setup.ts +++ b/apps/web/src/tests/e2e/auth.setup.ts @@ -2,9 +2,9 @@ import { type Page, expect, test as setup } from '@playwright/test'; import { STORAGE_STATE } from '../../../playwright.config'; -const username = process.env.E2E_TEST_USERNAME || ''; -const email = process.env.E2E_TEST_USER_EMAIL || ''; -const password = process.env.E2E_TEST_USER_PASSWORD || ''; +const username = process.env.E2E_TEST_AUTHENTICATE_USERNAME || ''; +const email = process.env.E2E_TEST_AUTHENTICATE_USER_EMAIL || ''; +const password = process.env.E2E_TEST_AUTHENTICATE_USER_PASSWORD || ''; setup('authenticate', async ({ page }: { page: Page }) => { await page.goto('/signup'); @@ -16,9 +16,9 @@ setup('authenticate', async ({ page }: { page: Page }) => { const box = await canvas.boundingBox(); if (box) { - await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2); + await page.mouse.move(box.x + box.width / 8, box.y + box.height / 6); await page.mouse.down(); - await page.mouse.move(box.x + box.width / 4, box.y + box.height / 4); + await page.mouse.move(box.x + box.width / 8, box.y + box.height / 6); await page.mouse.up(); } @@ -28,7 +28,7 @@ setup('authenticate', async ({ page }: { page: Page }) => { await page.getByLabel('Email').fill(email); await page.getByLabel('Password').fill(password); await page.getByRole('button', { name: 'Sign In' }).click(); - await page.waitForURL('/documents'); + await expect(page).toHaveURL('/documents'); await page.context().storageState({ path: STORAGE_STATE }); }); diff --git a/apps/web/src/tests/e2e/test-auth-flow.unauthenticated.spec.ts b/apps/web/src/tests/e2e/test-auth-flow.unauthenticated.spec.ts index cdceda253..5c22e595f 100644 --- a/apps/web/src/tests/e2e/test-auth-flow.unauthenticated.spec.ts +++ b/apps/web/src/tests/e2e/test-auth-flow.unauthenticated.spec.ts @@ -29,6 +29,9 @@ test('user can sign up with email and password', async ({ page }: { page: Page } } await page.getByRole('button', { name: 'Sign Up' }).click(); + await page.waitForURL('/documents'); + + await expect(page).toHaveURL('/documents'); }); test('user can login with user and password', async ({ page }: { page: Page }) => { @@ -37,5 +40,6 @@ test('user can login with user and password', async ({ page }: { page: Page }) = await page.getByLabel('Password').fill(password); await page.getByRole('button', { name: 'Sign In' }).click(); + await page.waitForURL('/documents'); await expect(page).toHaveURL('/documents'); }); diff --git a/package.json b/package.json index a11d66bf6..31c55004b 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "build": "turbo run build", "dev": "turbo run dev --filter=@documenso/web --filter=@documenso/marketing", "start": "cd apps && cd web && next start", - "test": "turbo run e2e:test", + "test": "cd apps && cd web && npm run test", "lint": "turbo run lint", "format": "prettier --write \"**/*.{js,jsx,cjs,mjs,ts,tsx,cts,mts,mdx}\"", "prepare": "husky install", diff --git a/packages/lib/server-only/user/delete-user-and-data.ts b/packages/lib/server-only/user/delete-user-and-data.ts new file mode 100644 index 000000000..b4868800e --- /dev/null +++ b/packages/lib/server-only/user/delete-user-and-data.ts @@ -0,0 +1,41 @@ +import { prisma } from '@documenso/prisma'; + +export const deleteUserAndItsData = async (name: string) => { + const user = await prisma.user.findFirst({ + where: { + name: { + contains: name, + }, + }, + }); + + if (!user) { + throw new Error(`User with name ${name} not found`); + } + + const document = await prisma.document.findMany({ + where: { + userId: user.id, + }, + select: { + documentData: { + select: { + data: true, + }, + }, + }, + }); + + return Promise.all([ + await prisma.user.delete({ + where: { + id: user.id, + }, + }), + await prisma.documentData.deleteMany({ + where: { + data: document[0]?.documentData.data, + }, + }), + ]); +}; diff --git a/packages/lib/server-only/user/delete-user.ts b/packages/lib/server-only/user/delete-user.ts deleted file mode 100644 index 901a8a3d7..000000000 --- a/packages/lib/server-only/user/delete-user.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { prisma } from '@documenso/prisma'; - -export const deleteUser = async (name: string) => { - const user = await prisma.user.findFirst({ - where: { - name: { - contains: name, - }, - }, - }); - - if (!user) { - throw new Error(`User with name ${name} not found`); - } - - return await prisma.user.delete({ - where: { - id: user.id, - }, - }); -}; diff --git a/turbo.json b/turbo.json index e37abd84d..7dd30c3c8 100644 --- a/turbo.json +++ b/turbo.json @@ -17,6 +17,7 @@ "globalDependencies": ["**/.env.*local"], "globalEnv": [ "APP_VERSION", + "E2E_TEST_USERNAME", "E2E_TEST_USER_EMAIL", "E2E_TEST_USER_PASSWORD", @@ -24,6 +25,10 @@ "E2E_TEST_SIGNER_EMAIL", "E2E_TEST_SIGNING_SUBJECT", "E2E_TEST_SIGNING_MESSAGE", + "E2E_TEST_AUTHENTICATE_USERNAME", + "E2E_TEST_AUTHENTICATE_USER_EMAIL", + "E2E_TEST_AUTHENTICATE_USER_PASSWORD", + "NEXTAUTH_URL", "NEXTAUTH_SECRET", "NEXT_PUBLIC_WEBAPP_URL",