Novi Go testovi: - config_test.go: 9 testova (defaults, override, DSN, .env loading) - helpers_test.go: 13 testova (writeJSON, writeError, clientIP) Prosireni E2E testovi za svaku stranicu: - login: 15 testova (forma, auth, redirect, sesije) - dashboard: 18 testova (statistike, navbar, navigacija, odjava) - licenses: 20 testova (tabela, filteri, pretraga, kombinacije) - license-crud: 22 testa (forma, validacija, svi proizvodi/tipovi) - license-detail: 26 testova (info, aktivacije, audit, revoke, release) - audit: 14 testova (tabela, API zapisi, formati) - api-client: 18 testova (activate flow, auth, revoke flow) Azuriran TESTING.md sa kompletnom checklistom Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
191 lines
6.4 KiB
TypeScript
191 lines
6.4 KiB
TypeScript
import { test, expect, Page } from '@playwright/test';
|
|
|
|
const BASE = 'http://localhost:8090';
|
|
const API_KEY = 'dev-api-key-minimum-32-characters-long';
|
|
|
|
async function login(page: Page) {
|
|
await page.goto('/login');
|
|
await page.fill('input[name="password"]', 'admin123');
|
|
await page.click('button[type="submit"]');
|
|
await expect(page).toHaveURL(/\/dashboard/);
|
|
}
|
|
|
|
test.describe('Audit Log stranica', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await login(page);
|
|
});
|
|
|
|
test('prikazuje naslov Audit Log', async ({ page }) => {
|
|
await page.goto('/audit');
|
|
await expect(page.locator('h1')).toHaveText('Audit Log');
|
|
});
|
|
|
|
test('ima ispravan title', async ({ page }) => {
|
|
await page.goto('/audit');
|
|
await expect(page).toHaveTitle('Audit Log - DAL License Server');
|
|
});
|
|
|
|
test('prikazuje tabelu', async ({ page }) => {
|
|
await page.goto('/audit');
|
|
await expect(page.locator('table')).toBeVisible();
|
|
});
|
|
|
|
test('tabela ima 5 kolona', async ({ page }) => {
|
|
await page.goto('/audit');
|
|
const headers = page.locator('thead th');
|
|
await expect(headers).toHaveCount(5);
|
|
await expect(headers.nth(0)).toHaveText('Vreme');
|
|
await expect(headers.nth(1)).toHaveText('Akcija');
|
|
await expect(headers.nth(2)).toHaveText('Licenca');
|
|
await expect(headers.nth(3)).toHaveText('IP');
|
|
await expect(headers.nth(4)).toHaveText('Detalji');
|
|
});
|
|
|
|
test('navbar audit link je aktivan', async ({ page }) => {
|
|
await page.goto('/audit');
|
|
const link = page.locator('a[href="/audit"]');
|
|
await expect(link).toHaveClass(/active/);
|
|
});
|
|
|
|
test('navigacija iz navbara radi', async ({ page }) => {
|
|
await page.click('a[href="/audit"]');
|
|
await expect(page).toHaveURL(/\/audit/);
|
|
});
|
|
|
|
test('kreiranje licence generise CREATE zapis u audit-u', async ({ page }) => {
|
|
// Kreiraj licencu
|
|
await page.goto('/licenses/new');
|
|
const productSelect = page.locator('select[name="product_id"]');
|
|
const options = productSelect.locator('option');
|
|
const count = await options.count();
|
|
for (let i = 0; i < count; i++) {
|
|
const text = await options.nth(i).textContent();
|
|
if (text && text.includes('LIGHT_TICKET')) {
|
|
await productSelect.selectOption({ index: i });
|
|
break;
|
|
}
|
|
}
|
|
await page.selectOption('select[name="license_type"]', 'MONTHLY');
|
|
await page.fill('input[name="customer_name"]', `Audit Create ${Date.now()}`);
|
|
await page.click('button:has-text("Kreiraj licencu")');
|
|
await expect(page).toHaveURL(/\/licenses\/\d+/);
|
|
|
|
// Proveri audit
|
|
await page.goto('/audit');
|
|
await expect(page.locator('.badge', { hasText: 'CREATE' }).first()).toBeVisible();
|
|
});
|
|
|
|
test('audit prikazuje licencni kljuc', async ({ page }) => {
|
|
await page.goto('/audit');
|
|
// Audit zapisi koji imaju licencu prikazuju code element
|
|
const codeElements = page.locator('tbody code');
|
|
const count = await codeElements.count();
|
|
if (count > 0) {
|
|
const firstKey = await codeElements.first().textContent();
|
|
expect(firstKey).toMatch(/^(LT|ARV|ESIR)-/);
|
|
}
|
|
});
|
|
|
|
test('audit prikazuje IP adresu', async ({ page }) => {
|
|
await page.goto('/audit');
|
|
// Mora biti bar jedan zapis sa IP adresom
|
|
const rows = page.locator('tbody tr');
|
|
const count = await rows.count();
|
|
expect(count).toBeGreaterThan(0);
|
|
});
|
|
|
|
test('audit prikazuje vreme u ispravnom formatu', async ({ page }) => {
|
|
await page.goto('/audit');
|
|
const firstTimeCell = page.locator('tbody td').first();
|
|
const text = await firstTimeCell.textContent();
|
|
// Format: DD.MM.YYYY HH:MM
|
|
if (text && text.trim() !== 'Nema podataka') {
|
|
expect(text).toMatch(/\d{2}\.\d{2}\.\d{4}/);
|
|
}
|
|
});
|
|
|
|
test('audit prikazuje detalje kao JSON', async ({ page }) => {
|
|
await page.goto('/audit');
|
|
const details = page.locator('.audit-details');
|
|
const count = await details.count();
|
|
if (count > 0) {
|
|
await expect(details.first()).toBeVisible();
|
|
}
|
|
});
|
|
});
|
|
|
|
test.describe('Audit Log — API zapisi', () => {
|
|
test('aktivacija generise ACTIVATE zapis', async ({ request, page }) => {
|
|
// Kreiraj licencu
|
|
const createRes = await request.post(`${BASE}/api/v1/admin/licenses`, {
|
|
headers: { 'X-API-Key': API_KEY, 'Content-Type': 'application/json' },
|
|
data: {
|
|
product_id: 3,
|
|
license_type: 'MONTHLY',
|
|
customer_name: 'Audit Activate Test',
|
|
},
|
|
});
|
|
const created = await createRes.json();
|
|
|
|
// Aktiviraj
|
|
await request.post(`${BASE}/api/v1/activate`, {
|
|
data: {
|
|
license_key: created.license_key,
|
|
machine_fingerprint: 'sha256:audit-activate-test',
|
|
app_version: '1.0.0',
|
|
os: 'linux',
|
|
hostname: 'AUDIT-PC',
|
|
},
|
|
});
|
|
|
|
// Proveri audit na UI
|
|
await login(page);
|
|
await page.goto('/audit');
|
|
await expect(page.locator('.badge', { hasText: 'ACTIVATE' }).first()).toBeVisible();
|
|
});
|
|
|
|
test('deaktivacija generise DEACTIVATE zapis', async ({ request, page }) => {
|
|
const createRes = await request.post(`${BASE}/api/v1/admin/licenses`, {
|
|
headers: { 'X-API-Key': API_KEY, 'Content-Type': 'application/json' },
|
|
data: {
|
|
product_id: 3,
|
|
license_type: 'MONTHLY',
|
|
customer_name: 'Audit Deactivate Test',
|
|
},
|
|
});
|
|
const created = await createRes.json();
|
|
const fp = 'sha256:audit-deactivate-test';
|
|
|
|
await request.post(`${BASE}/api/v1/activate`, {
|
|
data: { license_key: created.license_key, machine_fingerprint: fp, app_version: '1.0.0', os: 'linux', hostname: 'PC' },
|
|
});
|
|
await request.post(`${BASE}/api/v1/deactivate`, {
|
|
data: { license_key: created.license_key, machine_fingerprint: fp },
|
|
});
|
|
|
|
await login(page);
|
|
await page.goto('/audit');
|
|
await expect(page.locator('.badge', { hasText: 'DEACTIVATE' }).first()).toBeVisible();
|
|
});
|
|
|
|
test('validacija generise VALIDATE zapis', async ({ request, page }) => {
|
|
const createRes = await request.post(`${BASE}/api/v1/admin/licenses`, {
|
|
headers: { 'X-API-Key': API_KEY, 'Content-Type': 'application/json' },
|
|
data: {
|
|
product_id: 3,
|
|
license_type: 'MONTHLY',
|
|
customer_name: 'Audit Validate Test',
|
|
},
|
|
});
|
|
const created = await createRes.json();
|
|
|
|
await request.post(`${BASE}/api/v1/validate`, {
|
|
data: { license_key: created.license_key, machine_fingerprint: 'sha256:validate-test' },
|
|
});
|
|
|
|
await login(page);
|
|
await page.goto('/audit');
|
|
await expect(page.locator('.badge', { hasText: 'VALIDATE' }).first()).toBeVisible();
|
|
});
|
|
});
|