3fefc550fe
- Django backend with DRF (clubs, wrestlers, trainers, exercises, templates, trainings, homework, locations, leistungstest) - Next.js 16 frontend with React, Shadcn UI, Tailwind - JWT authentication - Full CRUD for all entities - Calendar view for trainings - Homework management system - Leistungstest tracking
138 lines
4.6 KiB
TypeScript
138 lines
4.6 KiB
TypeScript
import { test, expect, Page } from '@playwright/test'
|
|
|
|
const adminCredentials = { username: 'admin', password: 'admin123' }
|
|
|
|
// Helper: ensure user is logged in; if not, perform login flow
|
|
async function ensureLoggedIn(page: Page) {
|
|
await page.goto('/dashboard', { waitUntil: 'domcontentloaded' })
|
|
const url = page.url()
|
|
if (url.includes('/login')) {
|
|
await page.goto('/login')
|
|
// Try multiple selectors for username field
|
|
const userSelectors = [
|
|
'input[name="username"]',
|
|
'input[name="email"]',
|
|
'input#username',
|
|
'input#email',
|
|
'input[placeholder="Username"]',
|
|
'input[placeholder="Email"]',
|
|
]
|
|
let filledUser = false
|
|
for (const sel of userSelectors) {
|
|
const el = page.locator(sel)
|
|
if (await el.count() > 0) {
|
|
await el.fill(adminCredentials.username)
|
|
filledUser = true
|
|
break
|
|
}
|
|
}
|
|
if (!filledUser) {
|
|
const label = page.locator('label', { hasText: /username|email/i })
|
|
if (await label.count() > 0) {
|
|
const input = label.locator('xpath=following-sibling::input[1]')
|
|
if (await input.count() > 0) await input.fill(adminCredentials.username)
|
|
}
|
|
}
|
|
// Password
|
|
const passSelectors = [
|
|
'input[name="password"]',
|
|
'input#password',
|
|
'input[placeholder="Password"]',
|
|
'input[aria-label="Password"]',
|
|
]
|
|
for (const sp of passSelectors) {
|
|
const el = page.locator(sp)
|
|
if (await el.count() > 0) {
|
|
await el.fill(adminCredentials.password)
|
|
break
|
|
}
|
|
}
|
|
const loginBtn = page.locator('button', { hasText: /log|sign in|anmelden|einloggen/i })
|
|
if (await loginBtn.count() > 0) {
|
|
await loginBtn.first().click()
|
|
} else {
|
|
await page.keyboard.press('Enter')
|
|
}
|
|
await page.waitForURL('**/dashboard', { timeout: 10000 })
|
|
}
|
|
}
|
|
|
|
test.describe('WrestleDesk End-to-End (Partial) - Auth and Core Views', () => {
|
|
|
|
test('Login page - valid credentials', async ({ page }) => {
|
|
await page.goto('/login')
|
|
const userSelectors = [
|
|
'input[name="username"]',
|
|
'input[name="email"]',
|
|
'input#username',
|
|
'input#email',
|
|
'input[placeholder="Username"]',
|
|
'input[placeholder="Email"]',
|
|
]
|
|
let filled = false
|
|
for (const sel of userSelectors) {
|
|
const el = page.locator(sel)
|
|
if (await el.count() > 0) {
|
|
await el.fill(adminCredentials.username)
|
|
filled = true
|
|
break
|
|
}
|
|
}
|
|
if (!filled) {
|
|
const label = page.locator('label', { hasText: /username|email/i })
|
|
if (await label.count() > 0) {
|
|
const input = label.locator('xpath=following-sibling::input[1]')
|
|
if (await input.count() > 0) await input.fill(adminCredentials.username)
|
|
}
|
|
}
|
|
const passSelectors = [
|
|
'input[name="password"]',
|
|
'input#password',
|
|
'input[placeholder="Password"]',
|
|
'input[aria-label="Password"]',
|
|
]
|
|
filled = false
|
|
for (const sp of passSelectors) {
|
|
const el = page.locator(sp)
|
|
if (await el.count() > 0) {
|
|
await el.fill(adminCredentials.password)
|
|
filled = true
|
|
break
|
|
}
|
|
}
|
|
if (!filled) {
|
|
const pwd = page.locator('input[type="password"]')
|
|
if (await pwd.count() > 0) await pwd.fill(adminCredentials.password)
|
|
}
|
|
const loginBtn = page.locator('button', { hasText: /log|sign in|anmelden|einloggen/i })
|
|
if (await loginBtn.count() > 0) {
|
|
await loginBtn.first().click()
|
|
} else {
|
|
await page.keyboard.press('Enter')
|
|
}
|
|
await page.waitForURL('**/dashboard', { timeout: 10000 })
|
|
await page.screenshot({ path: '/tmp/test-results/login.png', fullPage: true })
|
|
expect(page.url()).toContain('/dashboard')
|
|
})
|
|
|
|
test('Dashboard loads and navigates to Wrestlers', async ({ page }) => {
|
|
await ensureLoggedIn(page)
|
|
await expect(page).toHaveURL(/.*dashboard/)
|
|
const hasWrestlersCard = await page.locator('text=/Wrestlers|Wrestler(s)?/i').first().count()
|
|
await page.screenshot({ path: '/tmp/test-results/dashboard.png', fullPage: true })
|
|
expect(hasWrestlersCard).toBeGreaterThan(0)
|
|
const wrestlersLink = page.locator('a', { hasText: /Wrestler|Wrestlers/i })
|
|
if (await wrestlersLink.count() > 0) {
|
|
await wrestlersLink.first().click()
|
|
await page.waitForURL(/.*wrestlers/i)
|
|
await page.screenshot({ path: '/tmp/test-results/dashboard-to-wrestlers.png', fullPage: true })
|
|
} else {
|
|
await page.goto('/wrestlers')
|
|
await page.waitForURL(/.*wrestlers/i)
|
|
await page.screenshot({ path: '/tmp/test-results/navigate-wrestlers.png', fullPage: true })
|
|
}
|
|
})
|
|
|
|
// Additional blocks would be added here for Wrestlers CRUD, Trainers CRUD, etc.
|
|
})
|