Initial commit: IT Nexus Web-App
This commit is contained in:
273
playwright-tests/check.js
Normal file
273
playwright-tests/check.js
Normal file
@@ -0,0 +1,273 @@
|
||||
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');
|
||||
}
|
||||
Reference in New Issue
Block a user