diff --git a/.gitignore b/.gitignore index a0e84f5..2f0291d 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,9 @@ Thumbs.db !.env.example !.env.test +# Tests +test-results + # Vite vite.config.js.timestamp-* vite.config.ts.timestamp-* diff --git a/bun.lockb b/bun.lockb index 8370767..a78075d 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 2d4216c..dfc67e2 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,9 @@ "minio": "minio server minio-storage", "preview": "vite preview", "prepare": "svelte-kit sync || echo ''", - "production": "tsm ./prodServer.ts" + "production": "tsm ./prodServer.ts", + "test": "playwright test", + "test:head": "playwright test --headed" }, "devDependencies": { "@eslint/compat": "^1.2.5", @@ -37,6 +39,7 @@ "typescript-eslint": "^8.20.0" }, "dependencies": { + "@playwright/test": "^1.50.1", "@sveltejs/adapter-node": "^5.2.12", "@tailwindcss/typography": "^0.5.16", "@types/better-sqlite3": "^7.6.12", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..a96f63d --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from '@playwright/test'; + +export default defineConfig({ + testDir: 'tests', + reporter: 'list', + testMatch: /(.+\.)?(test|spec)\.[jt]s/, + webServer: { + command: 'npm run dev', + port: 5174, + reuseExistingServer: true, + }, +}); diff --git a/src/lib/components/user.svelte b/src/lib/components/user.svelte index 650e1b9..ecee8d6 100644 --- a/src/lib/components/user.svelte +++ b/src/lib/components/user.svelte @@ -16,7 +16,7 @@
-

{data.user.username}

+

{data.user.username}

diff --git a/tests/updateUsername.spec.ts b/tests/updateUsername.spec.ts new file mode 100644 index 0000000..9171e30 --- /dev/null +++ b/tests/updateUsername.spec.ts @@ -0,0 +1,50 @@ +import { test, expect, type Page, type Locator } from '@playwright/test'; +import { login } from './utils'; + +test.describe.configure({ mode: 'parallel' }); +test.describe('Username Update Form', () => { + let page: Page; + let usernameInput: Locator; + let submitButton: Locator; + let currentUsernameElement: Locator; + const newUsername: string = 'testuser' + Math.floor(Math.random() * 10000); + + test.beforeEach(async ({ browser }) => { + page = await browser.newPage(); + // Initialize locators + usernameInput = page.locator('input#username'); + submitButton = page.getByRole('button', { name: 'Update Username' }); + currentUsernameElement = page.locator('#currentuser-username'); + + await login(page); + page.goto('http://localhost:5173/account'); + }); + + // Test that the username will change + test('should successfully update the username', async () => { + await usernameInput.fill(newUsername); + await submitButton.click(); + + // Check for success message + const successMessageLocator = page.locator('p.text-sm.text-green-500:has-text("Username updated.")'); + await expect(successMessageLocator).toBeVisible(); + + // Verify the username displayed in the UI has been updated + const updatedUsername: string = (await currentUsernameElement.textContent()) || ''; + expect(updatedUsername).toBe(newUsername); + }); + + // Test invalidator + test('should show validation error for invalid username', async () => { + await usernameInput.fill('a'); + await submitButton.click(); + + // Check for error message + const errorMessageLocator = page.locator('span.text-sm.text-red-500:has-text("Username must be at least 3 characters.")'); + await expect(errorMessageLocator).toBeVisible(); + + // Ensure the username wasn't updated + const currentUsername: string = (await currentUsernameElement.textContent()) || ''; + expect(currentUsername).not.toBe('a'); + }); +}); diff --git a/tests/utils.ts b/tests/utils.ts new file mode 100644 index 0000000..00192ec --- /dev/null +++ b/tests/utils.ts @@ -0,0 +1,10 @@ +import type { Page } from '@playwright/test'; + +export async function login(page: Page): Promise { + await page.goto('http://localhost:5174/login'); + await page.waitForLoadState('domcontentloaded'); + console.log('loaded'); + await page.fill('#email', 'playwright@playwright.com'); + await page.fill('#password', 'Password1234!'); + await page.click('button[type="submit"]'); +}