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"]');
+}