just testing the environment
Some checks failed
Tests / test (push) Has been cancelled

This commit is contained in:
tom.hempel
2026-05-20 07:10:08 +02:00
parent 2a11dfd0d1
commit 06fc134299
56 changed files with 1890 additions and 361 deletions

View File

@ -0,0 +1,77 @@
import { test, expect } from '@playwright/test';
const API = '/api';
const PASSWORD = 'testpass123';
async function login(request: import('@playwright/test').APIRequestContext, username: string) {
const res = await request.post(`${API}/auth/login`, {
data: { username, password: PASSWORD },
});
const json = await res.json();
expect(json.ok).toBe(true);
return json.data.token as string;
}
test.describe('Android API app_questionnaires (HTTP smoke)', () => {
test('list active questionnaires over HTTP', async ({ request }) => {
const token = await login(request, 'testcoach1');
const res = await request.get(`${API}/app_questionnaires`, {
headers: { Authorization: `Bearer ${token}` },
});
expect(res.ok()).toBeTruthy();
const json = await res.json();
expect(json.ok).toBe(true);
expect(json.data.some((q: { id: string }) => q.id === 'questionnaire_test_demo')).toBe(true);
});
test('missing bearer returns 401', async ({ request }) => {
const res = await request.get(`${API}/app_questionnaires`);
expect(res.status()).toBe(401);
});
test('password change flow', async ({ request }) => {
const loginRes = await request.post(`${API}/auth/login`, {
data: { username: 'testmustchange', password: PASSWORD },
});
const loginJson = await loginRes.json();
expect(loginJson.data.mustChangePassword).toBe(true);
const tempToken = loginJson.data.token as string;
let fullToken: string | undefined;

25
e2e/api/auth.spec.ts Normal file
View File

@ -0,0 +1,25 @@
import { test, expect } from '@playwright/test';
const API = '/api';
test.describe('Android API auth', () => {
test('login returns token', async ({ request }) => {
const res = await request.post(`${API}/auth/login`, {
data: { username: 'testadmin', password: 'testpass123' },
});
expect(res.ok()).toBeTruthy();
const json = await res.json();
expect(json.ok).toBe(true);
expect(json.data.token).toBeTruthy();
expect(json.data.role).toBe('admin');
});
test('bad password returns error', async ({ request }) => {
const res = await request.post(`${API}/auth/login`, {
data: { username: 'testadmin', password: 'wrong' },
});
expect(res.status()).toBe(401);
const json = await res.json();
expect(json.ok).toBe(false);
});
});

16
e2e/global-setup.js Normal file
View File

@ -0,0 +1,16 @@
import { execSync } from 'child_process';
import path from 'path';
import { fileURLToPath } from 'url';
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
export default async function globalSetup() {
execSync('php tests/bin/seed-test-db.php', {
cwd: root,
stdio: 'inherit',
env: {
...process.env,
QDB_MASTER_KEY: 'dGVzdC1tYXN0ZXIta2V5LXRoaXQtMzJieXRzIQ==',
},
});
}

16
e2e/website/helpers.ts Normal file
View File

@ -0,0 +1,16 @@
import { Page, expect } from '@playwright/test';
export const TEST_PASSWORD = 'testpass123';
export async function loginAs(page: Page, username: string, password = TEST_PASSWORD) {
await page.goto('/website/#/login');
await page.locator('#username').fill(username);
await page.locator('#password').fill(password);
await page.locator('#loginForm button[type="submit"]').click();
await expect(page.locator('h1')).toContainText('Questionnaires', { timeout: 15000 });
}
export async function logout(page: Page) {
await page.locator('#logoutBtn').click();
await expect(page.locator('#loginForm')).toBeVisible();
}

21
e2e/website/login.spec.ts Normal file
View File

@ -0,0 +1,21 @@
import { test, expect } from '@playwright/test';
test.describe('Website login', () => {
test('shows login form', async ({ page }) => {
await page.goto('/website/#/login');
await expect(page.locator('#loginForm')).toBeVisible();
});
test('bad password shows error', async ({ page }) => {
await page.goto('/website/#/login');
await page.locator('#username').fill('testadmin');
await page.locator('#password').fill('wrong-password');
await page.locator('#loginForm button[type="submit"]').click();
await expect(page.locator('#loginError')).toBeVisible();
});
test('protected route redirects to login', async ({ page }) => {
await page.goto('/website/#/users');
await expect(page.locator('#loginForm')).toBeVisible();
});
});

View File

@ -0,0 +1,64 @@
import { test, expect } from '@playwright/test';
import { loginAs, logout } from './helpers';
test.describe('Website routes (admin)', () => {
test.beforeEach(async ({ page }) => {
await loginAs(page, 'testadmin');
});
test('dashboard lists questionnaires', async ({ page }) => {
await expect(page.locator('h1')).toHaveText('Questionnaires');
await expect(page.locator('.q-card, .empty-state')).toBeVisible();
});
test('export page', async ({ page }) => {
await page.goto('/website/#/export');
await expect(page.locator('h1')).toContainText('Export');
});
test('users page for admin', async ({ page }) => {
await page.goto('/website/#/users');
await expect(page.locator('h1')).toContainText('Users');
});
test('clients page', async ({ page }) => {
await page.goto('/website/#/clients');
await expect(page.locator('h1')).toContainText('Clients');
});
test('assignments page', async ({ page }) => {
await page.goto('/website/#/assignments');
await expect(page.locator('h1')).toContainText('Assign');
});
test('editor for seeded questionnaire', async ({ page }) => {
await page.goto('/website/#/questionnaire/questionnaire_test_demo');
await expect(page.locator('#editorTitle')).not.toHaveText('Loading...');
await expect(page.locator('#editorContent')).toContainText('Questions');
});
test('results page', async ({ page }) => {
await page.goto('/website/#/questionnaire/questionnaire_test_demo/results');
await expect(page.locator('h1')).toContainText('Results');
});
test('logout clears session', async ({ page }) => {
await logout(page);
await page.goto('/website/#/');
await expect(page.locator('#loginForm')).toBeVisible();
});
});
test.describe('Website role nav', () => {
test('coach cannot see admin nav items', async ({ page }) => {
await loginAs(page, 'testcoach1');
const usersNav = page.locator('[data-nav-roles] a[href="#/users"]');
await expect(usersNav).toBeHidden();
});
test('supervisor sees users nav', async ({ page }) => {
await loginAs(page, 'testsuper1');
const usersNav = page.locator('[data-nav-roles] a[href="#/users"]');
await expect(usersNav).toBeVisible();
});
});