Merge pull request 'chore: clean up docker-compose files and enhance SQL migration for skills' (#7) from develop into main
Reviewed-on: #7
This commit is contained in:
commit
390b0ecb73
|
|
@ -2,6 +2,18 @@
|
|||
-- One-time import of skills with categories from karatetrainer.net
|
||||
-- Source: https://karatetrainer.net/index.php?title=Fähigkeitsmatrix
|
||||
|
||||
-- ON CONFLICT (name) erfordert einen UNIQUE-Constraint auf skills.name (003/007 legten keinen an)
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint c
|
||||
JOIN pg_class t ON c.conrelid = t.oid
|
||||
WHERE t.relname = 'skills' AND c.contype = 'u' AND c.conname = 'skills_name_unique'
|
||||
) THEN
|
||||
ALTER TABLE skills ADD CONSTRAINT skills_name_unique UNIQUE (name);
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Create skill categories first
|
||||
INSERT INTO skill_categories (name, description, sort_order) VALUES
|
||||
('Kihon', 'Grundtechniken', 1),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
version: '3.8'
|
||||
|
||||
# Keine festen container_name — Compose-Namen haben Projektprefix (<projekt>-postgres-1).
|
||||
# Gleiche Variablennamen wie docker-compose.yml; andere Werte in einer eigenen .env neben dieser Datei.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
version: '3.8'
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
|
|
|
|||
|
|
@ -43,8 +43,10 @@ test('2. Dashboard lädt ohne Fehler', async ({ page }) => {
|
|||
// Warte bis Spinner verschwunden
|
||||
await expect(page.locator('.spinner')).toHaveCount(0, { timeout: 10000 });
|
||||
|
||||
// Prüfe ob Dashboard-Inhalt da ist
|
||||
await expect(page.locator('text=Willkommen')).toBeVisible({ timeout: 5000 });
|
||||
// Zwei verschiedene "Willkommen"-Texte im Dashboard → kein ambiguity locator('text=Willkommen')
|
||||
await expect(
|
||||
page.getByRole('heading', { name: /Willkommen bei Shinkan/i }),
|
||||
).toBeVisible({ timeout: 5000 });
|
||||
|
||||
await page.screenshot({ path: 'screenshots/02-dashboard.png' });
|
||||
console.log('✓ Dashboard OK');
|
||||
|
|
@ -53,8 +55,11 @@ test('2. Dashboard lädt ohne Fehler', async ({ page }) => {
|
|||
test('3. Navigation zu Übungen', async ({ page }) => {
|
||||
await login(page);
|
||||
|
||||
// Bottom-Nav: Übungen klicken
|
||||
await page.click('text=Übungen');
|
||||
// Bei Viewport ≥1024px ist .bottom-nav versteckt — Mobile garantieren wie in playwright.config.js
|
||||
await page.setViewportSize({ width: 390, height: 844 });
|
||||
|
||||
// Desktop-Sidebar enthält ebenfalls Übungen – nur Mobile-Bottom-Nav klicken (sichtbarer Link)
|
||||
await page.locator('.bottom-nav a[href="/exercises"]').click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// Prüfe ob Übungen-Seite geladen
|
||||
|
|
@ -66,9 +71,9 @@ test('3. Navigation zu Übungen', async ({ page }) => {
|
|||
|
||||
test('4. Navigation zu Vereine', async ({ page }) => {
|
||||
await login(page);
|
||||
await page.setViewportSize({ width: 390, height: 844 });
|
||||
|
||||
// Bottom-Nav: Vereine klicken
|
||||
await page.click('text=Vereine');
|
||||
await page.locator('.bottom-nav a[href="/clubs"]').click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// Prüfe ob Vereine-Seite geladen
|
||||
|
|
@ -109,16 +114,17 @@ test('6. Bottom-Nav sichtbar (Mobile)', async ({ page }) => {
|
|||
test('7. Session-Persistenz nach Reload', async ({ page }) => {
|
||||
await login(page);
|
||||
|
||||
// Warte auf Dashboard
|
||||
await expect(page.locator('.spinner')).toHaveCount(0, { timeout: 10000 });
|
||||
|
||||
// Reload
|
||||
await page.reload();
|
||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// Sollte NICHT zur Login-Seite redirecten
|
||||
const loginButton = page.locator('button:has-text("Login")');
|
||||
await expect(loginButton).toHaveCount(0, { timeout: 5000 });
|
||||
// Auth lädt erst nach Spinner – nicht auf /login stranden (stabiler als Button „Login“-Tab auf Login-Screen)
|
||||
await expect(page.locator('.spinner')).toHaveCount(0, { timeout: 20000 });
|
||||
await expect(page).not.toHaveURL('**/login', { timeout: 20000 });
|
||||
await expect(page.locator('h1').filter({ hasText: /^Dashboard$/ })).toBeVisible({
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
await page.screenshot({ path: 'screenshots/07-nach-reload.png' });
|
||||
console.log('✓ Session bleibt nach Reload erhalten');
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user