Files
IT-Nexus/playwright-tests/check.js

274 lines
14 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const { chromium } = require('playwright');
const path = require('path');
const fs = require('fs');
const BASE = 'https://it-nexus.cereda-systems.de';
const USER = 'superadmin';
const PASS = 'Admin123!';
const OUT = path.join(__dirname, 'screenshots');
if (!fs.existsSync(OUT)) fs.mkdirSync(OUT, { recursive: true });
const issues = [];
const checks = [];
function note(section, msg) { issues.push(`[${section}] ${msg}`); console.log(` ⚠️ ${msg}`); }
function ok(section, msg) { checks.push(`[${section}] ✓ ${msg}`); console.log(`${msg}`); }
function info(msg) { console.log(` ${msg}`); }
async function shot(page, name) {
const file = path.join(OUT, `${name}.png`);
await page.screenshot({ path: file, fullPage: true });
console.log(` 📷 ${name}.png gespeichert`);
}
async function waitNet(page) {
await page.waitForLoadState('networkidle').catch(() => {});
await page.waitForTimeout(1500);
}
(async () => {
const browser = await chromium.launch({ headless: true });
const ctx = await browser.newContext({ viewport: { width: 1440, height: 900 } });
const page = await ctx.newPage();
// 404-Fehler mit URL aufzeichnen
const notFound404 = [];
const consoleErrors = [];
page.on('response', r => { if (r.status() === 404) notFound404.push(r.url()); });
page.on('console', m => { if (m.type() === 'error') consoleErrors.push(m.text()); });
// ── 1. LOGIN ───────────────────────────────────────────────────────────────
console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('🔐 LOGIN');
await page.goto(`${BASE}/login`);
await waitNet(page);
await shot(page, '01-login');
const userInput = page.locator('input[type="text"], input[name="username"], input[placeholder*="user" i], input[placeholder*="name" i]').first();
const passInput = page.locator('input[type="password"]').first();
await userInput.fill(USER);
await passInput.fill(PASS);
await shot(page, '02-login-filled');
await passInput.press('Enter');
await waitNet(page);
await shot(page, '03-after-login');
if (page.url().includes('login')) {
note('Login', `Login fehlgeschlagen — URL: ${page.url()}`);
const errText = await page.locator('.error, [class*="error"], [class*="alert"]').first().innerText().catch(() => '');
if (errText) note('Login', `Fehlermeldung: ${errText}`);
await browser.close(); printSummary(); return;
}
ok('Login', `Eingeloggt als ${USER}${page.url()}`);
// ── 2. DASHBOARD ──────────────────────────────────────────────────────────
console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('📊 DASHBOARD');
await page.goto(`${BASE}/dashboard`);
await waitNet(page);
await shot(page, '04-dashboard');
const bodyText = await page.locator('body').innerText();
if (bodyText.includes('Dashboard') || bodyText.includes('Willkommen')) ok('Dashboard', 'Seite geladen');
else note('Dashboard', 'Dashboard-Inhalt nicht erkennbar');
// ── 3. MONITORING ─────────────────────────────────────────────────────────
console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('🖥️ MONITORING');
await page.goto(`${BASE}/monitoring`);
await waitNet(page);
await shot(page, '05-monitoring');
// Geräte
const agentRows = await page.locator('tr[data-id], tbody tr, [class*="agent-row"]').count();
info(`${agentRows} Tabellenzeilen sichtbar`);
// Warte bis Monitoring-Tabelle geladen ist
await page.waitForTimeout(4000);
await shot(page, '05b-monitoring-loaded');
// IT-NB-02 per API prüfen — mit Auth-Token aus localStorage
const apiData = await page.evaluate(async () => {
try {
const token = localStorage.getItem('token') || localStorage.getItem('authToken') ||
Object.keys(localStorage).map(k=>localStorage.getItem(k)).find(v=>v?.startsWith?.('eyJ'));
const headers = token ? { Authorization: `Bearer ${token}` } : {};
const r = await fetch('/api/monitoring', { headers });
if (!r.ok) return { error: r.status };
const j = await r.json();
return j.data?.find(a => a.hostname === 'IT-NB-02') || null;
} catch(e) { return { error: e.message }; }
});
if (apiData && !apiData.error) {
ok('Monitoring', `IT-NB-02 via API gefunden (v${apiData.agent_version})`);
info(`OS: ${apiData.os_name || '?'}`);
info(`BitLocker: ${apiData.bitlocker_status || '?'}`);
info(`Defender: enabled=${apiData.defender_enabled}, age=${apiData.defender_signatures_age}`);
info(`Serial: ${apiData.hardware_serial || '?'}`);
if ((apiData.os_name || '').includes('11')) ok('Monitoring-API', `OS = ${apiData.os_name}`);
else note('Monitoring-API', `OS = ${apiData.os_name || 'null'} — erwartet Windows 11`);
if (apiData.bitlocker_status === 'encrypted') ok('Monitoring-API', 'BitLocker = encrypted ✓');
else note('Monitoring-API', `BitLocker = ${apiData.bitlocker_status || 'null'}`);
if (apiData.defender_enabled) ok('Monitoring-API', `Defender aktiv ✓ (Signaturen ${apiData.defender_signatures_age}d alt)`);
else note('Monitoring-API', 'Defender nicht aktiv oder Daten fehlen');
if (apiData.hardware_serial) ok('Monitoring-API', `Seriennummer = ${apiData.hardware_serial}`);
else note('Monitoring-API', 'Seriennummer fehlt');
} else {
note('Monitoring-API', `Fehler: ${apiData?.error || 'IT-NB-02 nicht gefunden'}`);
}
// Detail-Modal über Lupen-Button öffnen
const itnb02Text = page.locator('text=IT-NB-02').first();
if (await itnb02Text.isVisible().catch(() => false)) {
ok('Monitoring', 'IT-NB-02 in Tabelle sichtbar');
await itnb02Text.scrollIntoViewIfNeeded();
await page.waitForTimeout(500);
// Selektoren in Reihenfolge versuchen bis einer funktioniert
let clicked = false;
const selectors = [
'tr:has-text("IT-NB-02") button:first-child',
'tr:has-text("IT-NB-02") button',
'[class*="row"]:has-text("IT-NB-02") button',
'button:near(:text("IT-NB-02"))',
];
for (const sel of selectors) {
try {
const btn = page.locator(sel).first();
if (await btn.isVisible({ timeout: 1000 }).catch(() => false)) {
await btn.click();
clicked = true;
info(`Modal via Selektor geöffnet: ${sel}`);
break;
}
} catch { }
}
if (!clicked) {
// Letzter Fallback: direkt auf IT-NB-02 Text klicken
await itnb02Text.click();
info('Modal via Text-Klick versucht');
}
await page.waitForTimeout(2500);
await shot(page, '06-monitoring-detail-IT-NB-02');
const detail = await page.locator('body').innerText();
// Prüfe ob Modal offen (suche nach Sicherheits-Sektion-Keywords)
const hasModal = detail.includes('Sicherheit') || detail.includes('BitLocker') || detail.includes('Seriennummer');
info(`Modal offen: ${hasModal} | Body-Länge: ${detail.length} Zeichen`);
if (hasModal) {
if (detail.includes('Verschlüsselt')) ok('Monitoring-Modal', 'BitLocker = Verschlüsselt ✓');
else note('Monitoring-Modal', 'BitLocker kein "Verschlüsselt" text');
if (detail.includes('Defender') && detail.includes('Aktiv')) ok('Monitoring-Modal', 'Defender = Aktiv ✓');
else note('Monitoring-Modal', 'Defender Status unklar');
if (detail.includes('5CD44318HR')) ok('Monitoring-Modal', 'Seriennummer 5CD44318HR ✓');
else note('Monitoring-Modal', 'Seriennummer fehlt');
if (detail.includes('Arctic Wolf') || detail.includes('Docker') || detail.includes('IT Nexus Agent'))
ok('Monitoring-Modal', 'Software-Liste befüllt ✓');
else note('Monitoring-Modal', 'Software fehlt');
} else {
note('Monitoring-Modal', 'Detail-Modal hat nicht geöffnet — Sicherheits-Sektion nicht sichtbar');
}
await page.keyboard.press('Escape');
await page.waitForTimeout(500);
} else {
note('Monitoring', 'IT-NB-02 nicht gefunden');
}
// Warnungen prüfen (BitLocker off, Defender inaktiv)
const monBody = await page.locator('body').innerText();
if (monBody.includes('BitLocker aus')) note('Monitoring', 'Andere Geräte: BitLocker nicht aktiv — Warnung sichtbar');
if (monBody.includes('Defender inaktiv')) note('Monitoring', 'Andere Geräte: Defender inaktiv — Warnung sichtbar');
// ── 4. PATCH MANAGEMENT ───────────────────────────────────────────────────
console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('🔄 PATCH MANAGEMENT');
await page.goto(`${BASE}/patch-management`);
await waitNet(page);
await shot(page, '07-patch-management');
const patchBody = await page.locator('body').innerText();
// Version
if (patchBody.includes('v2.0.0')) ok('Patch', 'v2.0.0 als aktuelle Version angezeigt ✓');
else note('Patch', 'v2.0.0 nicht sichtbar');
if (patchBody.includes('1/1 aktualisiert')) ok('Patch', 'Test-Gruppe: 1/1 aktualisiert ✓');
else note('Patch', 'Test-Gruppe nicht korrekt aktualisiert');
// IT-NB-02 OS im Patch-Management
const itnb02PatchRow = page.locator('tr').filter({ hasText: 'IT-NB-02' }).first();
if (await itnb02PatchRow.isVisible().catch(() => false)) {
const rowText = await itnb02PatchRow.innerText();
info(`IT-NB-02 Patch-Row: ${rowText.replace(/\s+/g, ' ').substring(0, 120)}`);
if (rowText.includes('Win 11') || rowText.includes('11 Pro')) ok('Patch', 'IT-NB-02 OS = Win 11 ✓');
else if (rowText.includes('Win 10')) note('Patch', 'IT-NB-02 noch Win 10 — Check-in ausstehend');
if (rowText.includes('🪟')) ok('Patch', 'Win11-Badge = 🪟 Win 11 ✓');
else if (rowText.includes('Fähig')) note('Patch', 'Win11-Badge zeigt noch "Fähig" statt "🪟 Win 11"');
}
// Gruppen-Tab
const gruppenTab = page.locator('text=Gruppen').first();
if (await gruppenTab.isVisible()) {
await gruppenTab.click();
await page.waitForTimeout(1000);
await shot(page, '08-patch-gruppen');
}
// ── 5. HELPDESK / TICKETS ─────────────────────────────────────────────────
console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('🎫 HELPDESK');
await page.goto(`${BASE}/helpdesk`).catch(() => page.goto(`${BASE}/tickets`));
await waitNet(page);
await shot(page, '09-helpdesk');
const hdBody = await page.locator('body').innerText();
if (hdBody.includes('Ticket') || hdBody.includes('Helpdesk')) ok('Helpdesk', 'Seite geladen ✓');
else note('Helpdesk', 'Inhalt nicht erkennbar');
// ── 6. KI-ASSISTENT ───────────────────────────────────────────────────────
console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('🤖 KI-ASSISTENT');
await page.goto(`${BASE}/ai`).catch(() => page.goto(`${BASE}/ai-assistant`)).catch(() => {});
await waitNet(page);
await shot(page, '10-ki');
const kiBody = await page.locator('body').innerText();
if (kiBody.includes('KI') || kiBody.includes('Assistent') || kiBody.includes('Claude')) ok('KI', 'KI-Assistent Seite geladen ✓');
else note('KI', 'KI-Seite nicht gefunden oder leer');
// ── 7. 404 / CONSOLE ERRORS ───────────────────────────────────────────────
if (notFound404.length > 0) {
console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('🔴 404-FEHLER:');
[...new Set(notFound404)].forEach(u => note('404', u.replace(BASE, '')));
}
if (consoleErrors.length > 0) {
console.log('\n🔴 KONSOLEN-FEHLER:');
[...new Set(consoleErrors)].slice(0, 5).forEach(e => info(`Console: ${e.substring(0, 100)}`));
}
await browser.close();
printSummary();
})();
function printSummary() {
console.log('\n' + '═'.repeat(60));
console.log(`📊 ZUSAMMENFASSUNG: ${checks.length} OK, ${issues.length} Probleme`);
if (issues.length > 0) {
console.log('\n⚠ ZU FIXEN:');
issues.forEach((i, n) => console.log(` ${n+1}. ${i}`));
} else {
console.log('✅ Alles in Ordnung!');
}
console.log('\n📁 Screenshots: playwright-tests/screenshots/');
console.log('═'.repeat(60) + '\n');
}