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>
210 lines
8.8 KiB
TypeScript
210 lines
8.8 KiB
TypeScript
import { test, expect, Page } from '@playwright/test';
|
|
|
|
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/);
|
|
}
|
|
|
|
async function selectProduct(page: Page, productCode: string) {
|
|
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(productCode)) {
|
|
await productSelect.selectOption({ index: i });
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
test.describe('Forma za novu licencu', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await login(page);
|
|
await page.goto('/licenses/new');
|
|
});
|
|
|
|
test('prikazuje naslov Nova licenca', async ({ page }) => {
|
|
await expect(page.locator('h1')).toHaveText('Nova licenca');
|
|
});
|
|
|
|
test('ima ispravan title', async ({ page }) => {
|
|
await expect(page).toHaveTitle('Nova licenca - DAL License Server');
|
|
});
|
|
|
|
test('prikazuje sva polja forme', async ({ page }) => {
|
|
await expect(page.locator('select[name="product_id"]')).toBeVisible();
|
|
await expect(page.locator('select[name="license_type"]')).toBeVisible();
|
|
await expect(page.locator('input[name="customer_name"]')).toBeVisible();
|
|
await expect(page.locator('input[name="customer_pib"]')).toBeVisible();
|
|
await expect(page.locator('input[name="customer_email"]')).toBeVisible();
|
|
await expect(page.locator('input[name="limits"]')).toBeVisible();
|
|
await expect(page.locator('input[name="grace_days"]')).toBeVisible();
|
|
await expect(page.locator('textarea[name="notes"]')).toBeVisible();
|
|
});
|
|
|
|
test('customer_name je obavezan', async ({ page }) => {
|
|
await expect(page.locator('input[name="customer_name"]')).toHaveAttribute('required', '');
|
|
});
|
|
|
|
test('product_id je obavezan', async ({ page }) => {
|
|
await expect(page.locator('select[name="product_id"]')).toHaveAttribute('required', '');
|
|
});
|
|
|
|
test('license_type je obavezan', async ({ page }) => {
|
|
await expect(page.locator('select[name="license_type"]')).toHaveAttribute('required', '');
|
|
});
|
|
|
|
test('dropdown ima sve proizvode (min 3)', async ({ page }) => {
|
|
const options = page.locator('select[name="product_id"] option');
|
|
const count = await options.count();
|
|
expect(count).toBeGreaterThanOrEqual(3);
|
|
const texts = await options.allTextContents();
|
|
expect(texts.some(t => t.includes('ESIR'))).toBe(true);
|
|
expect(texts.some(t => t.includes('ARV'))).toBe(true);
|
|
expect(texts.some(t => t.includes('LIGHT_TICKET'))).toBe(true);
|
|
});
|
|
|
|
test('dropdown ima sve tipove licenci', async ({ page }) => {
|
|
const options = page.locator('select[name="license_type"] option');
|
|
const texts = await options.allTextContents();
|
|
expect(texts.join(' ')).toContain('Mesecna');
|
|
expect(texts.join(' ')).toContain('Godisnja');
|
|
expect(texts.join(' ')).toContain('Trajna');
|
|
expect(texts.join(' ')).toContain('Trial');
|
|
});
|
|
|
|
test('grace_days ima default 30', async ({ page }) => {
|
|
const val = await page.locator('input[name="grace_days"]').inputValue();
|
|
expect(val).toBe('30');
|
|
});
|
|
|
|
test('limits polje ima placeholder', async ({ page }) => {
|
|
await expect(page.locator('input[name="limits"]')).toHaveAttribute('placeholder', '{"max_operators": 3}');
|
|
});
|
|
|
|
test('email polje ima type email', async ({ page }) => {
|
|
await expect(page.locator('input[name="customer_email"]')).toHaveAttribute('type', 'email');
|
|
});
|
|
|
|
test('otkazi dugme vodi na listu licenci', async ({ page }) => {
|
|
await page.click('a:has-text("Otkazi")');
|
|
await expect(page).toHaveURL(/\/licenses$/);
|
|
});
|
|
|
|
test('forma ima POST method i ispravnu action', async ({ page }) => {
|
|
const form = page.locator('form.form-card');
|
|
await expect(form).toHaveAttribute('method', 'POST');
|
|
await expect(form).toHaveAttribute('action', '/licenses');
|
|
});
|
|
|
|
test('ima Kreiraj licencu dugme', async ({ page }) => {
|
|
await expect(page.locator('button:has-text("Kreiraj licencu")')).toBeVisible();
|
|
await expect(page.locator('button:has-text("Kreiraj licencu")')).toHaveClass(/btn-primary/);
|
|
});
|
|
});
|
|
|
|
test.describe('Kreiranje licence — svi proizvodi', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await login(page);
|
|
});
|
|
|
|
test('kreiranje LIGHT_TICKET MONTHLY licence sa svim poljima', async ({ page }) => {
|
|
await page.goto('/licenses/new');
|
|
await selectProduct(page, 'LIGHT_TICKET');
|
|
await page.selectOption('select[name="license_type"]', 'MONTHLY');
|
|
await page.fill('input[name="customer_name"]', 'E2E Komplet Test DOO');
|
|
await page.fill('input[name="customer_pib"]', '111222333');
|
|
await page.fill('input[name="customer_email"]', 'komplet@test.rs');
|
|
await page.fill('input[name="limits"]', '{"max_operators": 5}');
|
|
await page.fill('input[name="grace_days"]', '15');
|
|
await page.fill('textarea[name="notes"]', 'Komplet E2E test sa svim poljima');
|
|
|
|
await page.click('button:has-text("Kreiraj licencu")');
|
|
|
|
await expect(page).toHaveURL(/\/licenses\/\d+/);
|
|
const key = await page.locator('h1 code').textContent();
|
|
expect(key).toMatch(/^LT-/);
|
|
expect(key).toMatch(/^LT-[A-HJ-NP-Y2-9]{4}-[A-HJ-NP-Y2-9]{4}-[A-HJ-NP-Y2-9]{4}-[A-HJ-NP-Y2-9]{4}$/);
|
|
});
|
|
|
|
test('kreiranje LIGHT_TICKET PERPETUAL licence', async ({ page }) => {
|
|
await page.goto('/licenses/new');
|
|
await selectProduct(page, 'LIGHT_TICKET');
|
|
await page.selectOption('select[name="license_type"]', 'PERPETUAL');
|
|
await page.fill('input[name="customer_name"]', 'E2E Perpetual LT');
|
|
await page.click('button:has-text("Kreiraj licencu")');
|
|
await expect(page).toHaveURL(/\/licenses\/\d+/);
|
|
// Perpetual treba da prikaze Neograniceno za istek
|
|
await expect(page.locator('td', { hasText: 'Neograniceno' })).toBeVisible();
|
|
});
|
|
|
|
test('kreiranje ARV ANNUAL licence', async ({ page }) => {
|
|
await page.goto('/licenses/new');
|
|
await selectProduct(page, 'ARV');
|
|
await page.selectOption('select[name="license_type"]', 'ANNUAL');
|
|
await page.fill('input[name="customer_name"]', 'E2E ARV Godisnja');
|
|
await page.fill('input[name="customer_email"]', 'arv@test.rs');
|
|
await page.click('button:has-text("Kreiraj licencu")');
|
|
await expect(page).toHaveURL(/\/licenses\/\d+/);
|
|
const key = await page.locator('h1 code').textContent();
|
|
expect(key).toMatch(/^ARV-/);
|
|
});
|
|
|
|
test('kreiranje ARV TRIAL licence', async ({ page }) => {
|
|
await page.goto('/licenses/new');
|
|
await selectProduct(page, 'ARV');
|
|
await page.selectOption('select[name="license_type"]', 'TRIAL');
|
|
await page.fill('input[name="customer_name"]', 'E2E ARV Trial');
|
|
await page.click('button:has-text("Kreiraj licencu")');
|
|
await expect(page).toHaveURL(/\/licenses\/\d+/);
|
|
});
|
|
|
|
test('kreiranje ESIR PERPETUAL licence', async ({ page }) => {
|
|
await page.goto('/licenses/new');
|
|
await selectProduct(page, 'ESIR');
|
|
await page.selectOption('select[name="license_type"]', 'PERPETUAL');
|
|
await page.fill('input[name="customer_name"]', 'E2E ESIR Prodavnica');
|
|
await page.fill('input[name="customer_pib"]', '555666777');
|
|
await page.click('button:has-text("Kreiraj licencu")');
|
|
await expect(page).toHaveURL(/\/licenses\/\d+/);
|
|
const key = await page.locator('h1 code').textContent();
|
|
expect(key).toMatch(/^ESIR-/);
|
|
});
|
|
|
|
test('kreiranje ESIR MONTHLY licence', async ({ page }) => {
|
|
await page.goto('/licenses/new');
|
|
await selectProduct(page, 'ESIR');
|
|
await page.selectOption('select[name="license_type"]', 'MONTHLY');
|
|
await page.fill('input[name="customer_name"]', 'E2E ESIR Mesecna');
|
|
await page.click('button:has-text("Kreiraj licencu")');
|
|
await expect(page).toHaveURL(/\/licenses\/\d+/);
|
|
});
|
|
|
|
test('kreirana licenca se pojavljuje u listi', async ({ page }) => {
|
|
const uniqueName = `E2E Lista Test ${Date.now()}`;
|
|
await page.goto('/licenses/new');
|
|
await selectProduct(page, 'LIGHT_TICKET');
|
|
await page.selectOption('select[name="license_type"]', 'MONTHLY');
|
|
await page.fill('input[name="customer_name"]', uniqueName);
|
|
await page.click('button:has-text("Kreiraj licencu")');
|
|
await expect(page).toHaveURL(/\/licenses\/\d+/);
|
|
|
|
// Proveri da je u listi
|
|
await page.goto('/licenses');
|
|
await expect(page.locator('td', { hasText: uniqueName })).toBeVisible();
|
|
});
|
|
|
|
test('kreirana licenca ima status Aktivna', async ({ page }) => {
|
|
await page.goto('/licenses/new');
|
|
await selectProduct(page, 'LIGHT_TICKET');
|
|
await page.selectOption('select[name="license_type"]', 'MONTHLY');
|
|
await page.fill('input[name="customer_name"]', 'E2E Status Check');
|
|
await page.click('button:has-text("Kreiraj licencu")');
|
|
await expect(page).toHaveURL(/\/licenses\/\d+/);
|
|
await expect(page.locator('.badge.status-active')).toBeVisible();
|
|
});
|
|
});
|