dal-license-server/internal/handler/helpers_test.go
djuka 1b8db5e4a7 Obimni testovi: 179 ukupno (46 Go + 133 Playwright)
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>
2026-03-04 07:58:24 +00:00

179 lines
4.7 KiB
Go

package handler
import (
"dal-license-server/internal/model"
"dal-license-server/internal/service"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
)
func TestWriteJSON(t *testing.T) {
w := httptest.NewRecorder()
data := map[string]string{"key": "value"}
writeJSON(w, http.StatusOK, data)
if w.Code != http.StatusOK {
t.Errorf("status: ocekivano 200, dobijeno %d", w.Code)
}
if ct := w.Header().Get("Content-Type"); ct != "application/json" {
t.Errorf("Content-Type: ocekivano 'application/json', dobijeno %q", ct)
}
var result map[string]string
json.Unmarshal(w.Body.Bytes(), &result)
if result["key"] != "value" {
t.Errorf("body: ocekivano 'value', dobijeno %q", result["key"])
}
}
func TestWriteJSON_StatusCreated(t *testing.T) {
w := httptest.NewRecorder()
writeJSON(w, http.StatusCreated, map[string]int{"id": 1})
if w.Code != http.StatusCreated {
t.Errorf("status: ocekivano 201, dobijeno %d", w.Code)
}
}
func TestWriteJSON_NilData(t *testing.T) {
w := httptest.NewRecorder()
writeJSON(w, http.StatusOK, nil)
if w.Code != http.StatusOK {
t.Errorf("status: ocekivano 200, dobijeno %d", w.Code)
}
}
func TestWriteJSON_EmptySlice(t *testing.T) {
w := httptest.NewRecorder()
writeJSON(w, http.StatusOK, []string{})
body := w.Body.String()
if body != "[]\n" {
t.Errorf("body: ocekivano '[]\\n', dobijeno %q", body)
}
}
func TestWriteError(t *testing.T) {
w := httptest.NewRecorder()
writeError(w, http.StatusBadRequest, "INVALID_KEY", "Kljuc nije pronadjen")
if w.Code != http.StatusBadRequest {
t.Errorf("status: ocekivano 400, dobijeno %d", w.Code)
}
var resp model.ErrorResponse
json.Unmarshal(w.Body.Bytes(), &resp)
if resp.Error.Code != "INVALID_KEY" {
t.Errorf("error code: ocekivano 'INVALID_KEY', dobijeno %q", resp.Error.Code)
}
if resp.Error.Message != "Kljuc nije pronadjen" {
t.Errorf("error message: ocekivano 'Kljuc nije pronadjen', dobijeno %q", resp.Error.Message)
}
}
func TestWriteError_Unauthorized(t *testing.T) {
w := httptest.NewRecorder()
writeError(w, http.StatusUnauthorized, "UNAUTHORIZED", "Neautorizovan pristup")
if w.Code != http.StatusUnauthorized {
t.Errorf("status: ocekivano 401, dobijeno %d", w.Code)
}
}
func TestWriteError_InternalServerError(t *testing.T) {
w := httptest.NewRecorder()
writeError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "Nesto je poslo naopako")
if w.Code != http.StatusInternalServerError {
t.Errorf("status: ocekivano 500, dobijeno %d", w.Code)
}
}
func TestWriteLicenseError(t *testing.T) {
w := httptest.NewRecorder()
err := &service.LicenseError{
Code: "ALREADY_ACTIVATED",
Message: "Licenca je vec aktivirana",
Details: map[string]interface{}{"activated_on": "PC-1"},
}
writeLicenseError(w, err)
if w.Code != http.StatusBadRequest {
t.Errorf("status: ocekivano 400, dobijeno %d", w.Code)
}
var resp model.ErrorResponse
json.Unmarshal(w.Body.Bytes(), &resp)
if resp.Error.Code != "ALREADY_ACTIVATED" {
t.Errorf("error code: ocekivano 'ALREADY_ACTIVATED', dobijeno %q", resp.Error.Code)
}
}
func TestWriteLicenseError_GenericError(t *testing.T) {
w := httptest.NewRecorder()
writeLicenseError(w, &genericError{"some error"})
if w.Code != http.StatusInternalServerError {
t.Errorf("status: ocekivano 500, dobijeno %d", w.Code)
}
var resp model.ErrorResponse
json.Unmarshal(w.Body.Bytes(), &resp)
if resp.Error.Code != "INTERNAL_ERROR" {
t.Errorf("generic error mora vratiti INTERNAL_ERROR, dobijeno %q", resp.Error.Code)
}
}
type genericError struct{ msg string }
func (e *genericError) Error() string { return e.msg }
func TestClientIP_RemoteAddr(t *testing.T) {
req := httptest.NewRequest("GET", "/", nil)
req.RemoteAddr = "1.2.3.4:5678"
ip := clientIP(req)
if ip != "1.2.3.4:5678" {
t.Errorf("ocekivano '1.2.3.4:5678', dobijeno %q", ip)
}
}
func TestClientIP_XForwardedFor(t *testing.T) {
req := httptest.NewRequest("GET", "/", nil)
req.RemoteAddr = "10.0.0.1:1234"
req.Header.Set("X-Forwarded-For", "5.5.5.5")
ip := clientIP(req)
if ip != "5.5.5.5" {
t.Errorf("ocekivano '5.5.5.5', dobijeno %q", ip)
}
}
func TestClientIP_XRealIP(t *testing.T) {
req := httptest.NewRequest("GET", "/", nil)
req.RemoteAddr = "10.0.0.1:1234"
req.Header.Set("X-Real-IP", "8.8.8.8")
ip := clientIP(req)
if ip != "8.8.8.8" {
t.Errorf("ocekivano '8.8.8.8', dobijeno %q", ip)
}
}
func TestClientIP_XForwardedFor_Priority(t *testing.T) {
req := httptest.NewRequest("GET", "/", nil)
req.RemoteAddr = "10.0.0.1:1234"
req.Header.Set("X-Forwarded-For", "1.1.1.1")
req.Header.Set("X-Real-IP", "2.2.2.2")
ip := clientIP(req)
if ip != "1.1.1.1" {
t.Errorf("X-Forwarded-For mora imati prioritet, ocekivano '1.1.1.1', dobijeno %q", ip)
}
}