Activity and nutrition legacy CSV imports enforce tier limits with UsageBadge UI; Universal CSV gets mapping validation on copy/import, format-check parity, and structured error_details. version: 0.9u module: activity 1.2.1, nutrition 1.0.3, csv_import 0.4.0 Co-authored-by: Cursor <cursoragent@cursor.com>
68 lines
2.7 KiB
JavaScript
68 lines
2.7 KiB
JavaScript
/**
|
|
* Gitea Issue-Audit — UI-Verifikation gegen dev.mitai.jinkendo.de
|
|
* Einmaliger Audit-Lauf; keine dauerhafte CI-Pflicht.
|
|
*/
|
|
const { test, expect } = require('@playwright/test');
|
|
|
|
const TEST_EMAIL = process.env.TEST_EMAIL || 'lars@stommer.com';
|
|
const TEST_PASSWORD = process.env.TEST_PASSWORD || '5112';
|
|
|
|
async function login(page) {
|
|
await page.goto('/');
|
|
await page.waitForLoadState('networkidle');
|
|
await page.fill('input[type="email"]', TEST_EMAIL);
|
|
await page.fill('input[type="password"]', TEST_PASSWORD);
|
|
await page.click('button:has-text("Anmelden")');
|
|
await page.waitForLoadState('networkidle');
|
|
await expect(page.locator('button:has-text("Anmelden")')).toHaveCount(0, { timeout: 15000 });
|
|
}
|
|
|
|
test.describe('Issue-Audit UI', () => {
|
|
test('#40 Logout-Button im Mobile-Header sichtbar', async ({ page }) => {
|
|
await login(page);
|
|
const logoutBtn = page.locator('header.app-header--mobile button[title="Abmelden"]');
|
|
await expect(logoutBtn).toBeVisible();
|
|
});
|
|
|
|
test('#25 Goals-Seite erreichbar und rendert Inhalt', async ({ page }) => {
|
|
await login(page);
|
|
await page.goto('/goals');
|
|
await page.waitForLoadState('networkidle');
|
|
await expect(page.locator('body')).not.toContainText('404', { timeout: 5000 });
|
|
const hasGoalsUi =
|
|
(await page.getByText(/Ziel/i).count()) > 0 ||
|
|
(await page.locator('.card').count()) > 0;
|
|
expect(hasGoalsUi).toBeTruthy();
|
|
});
|
|
|
|
test('#65 Dashboard-Layout-Konfiguration erreichbar', async ({ page }) => {
|
|
await login(page);
|
|
await page.goto('/settings/dashboard-layout');
|
|
await page.waitForLoadState('networkidle');
|
|
const body = await page.locator('body').innerText();
|
|
expect(body).toMatch(/Widget|Übersicht|Layout|Dashboard/i);
|
|
});
|
|
|
|
test('#30 Desktop-Sidebar bei breitem Viewport', async ({ page }) => {
|
|
await page.setViewportSize({ width: 1280, height: 800 });
|
|
await login(page);
|
|
const sidebar = page.locator('.desktop-sidebar, [class*="desktop-sidebar"]');
|
|
await expect(sidebar.first()).toBeVisible({ timeout: 10000 });
|
|
});
|
|
|
|
test('#38 Nutrition CSV Import — FDDB-Panel mit Usage-Integration', async ({ page }) => {
|
|
await login(page);
|
|
await page.goto('/nutrition');
|
|
await page.waitForLoadState('networkidle');
|
|
await page.getByRole('button', { name: /Import/i }).click();
|
|
await page.waitForLoadState('networkidle');
|
|
const importCard = page.locator('.card').filter({ hasText: 'FDDB CSV Import' });
|
|
await expect(importCard).toBeVisible();
|
|
// Nach Deploy: badge-container-right am Titel; UsageBadge nur bei endlichem Limit (Premium = kein Badge)
|
|
const titleRow = importCard.locator('.card-title.badge-container-right');
|
|
if (await titleRow.count()) {
|
|
await expect(titleRow).toBeVisible();
|
|
}
|
|
});
|
|
});
|