You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

74 lines
2.8 KiB

package handlers
import (
"net/http"
"net/http/httptest"
"path/filepath"
"strings"
"testing"
"teraclone/internal/service"
)
func TestLogExplorerPagesPreserveFiltersAndRoleRestrictions(t *testing.T) {
app, err := service.NewAppService(filepath.Join(t.TempDir(), "frontend.db"))
if err != nil {
t.Fatal(err)
}
defer app.Close()
handler, err := NewDeviceHandler(app, "http://127.0.0.1:1")
if err != nil {
t.Fatal(err)
}
mux := http.NewServeMux()
handler.RegisterRoutes(mux)
for _, role := range []string{"administrator", "port_operator"} {
handler.sessions[role] = browserSession{Username: "test", BackendToken: "private-token", Role: role}
for _, path := range []string{"/logs/system", "/logs/ports", "/logs/links"} {
t.Run(role+path, func(t *testing.T) {
request := httptest.NewRequest(http.MethodGet, path, nil)
request.AddCookie(&http.Cookie{Name: sessionCookieName, Value: role})
response := httptest.NewRecorder()
mux.ServeHTTP(response, request)
if role == "port_operator" {
if response.Code != http.StatusForbidden {
t.Fatalf("operator log access = %d, want 403", response.Code)
}
return
}
if response.Code != http.StatusOK {
t.Fatalf("log page status = %d", response.Code)
}
body := response.Body.String()
for _, required := range []string{
`log-view.js?v=20260914-fixed-port-positions-2`, `port-log-clear.js?v=20260914-fixed-port-positions-2`, `integration.js?v=20260914-fixed-port-positions-2`,
`name="keyword"`, `name="from"`, `name="to"`, `name="limit"`, `name="auto_refresh"`,
`data-ui-action="primary-action"`, `data-ui-action="secondary-action"`, "로그 다운로드", "검색 초기화",
} {
if !strings.Contains(body, required) {
t.Errorf("missing log UI element: %s", required)
}
}
if strings.Contains(body, "private-token") {
t.Fatal("backend credential leaked")
}
if strings.Index(body, "log-view.js?") > strings.Index(body, "integration.js?") {
t.Fatal("log view must load before integration")
}
if strings.Index(body, "port-log-clear.js?") > strings.Index(body, "integration.js?") {
t.Fatal("port log clear must load before integration")
}
if path == "/logs/ports" {
for _, required := range []string{`value="CH01"`, `value="CH48"`, "RX/TX 데이터", "UP/DOWN 변경은 포트 상태 이벤트", "내보내기는 현재 검색 조건과 최대 다운로드 건수"} {
if !strings.Contains(body, required) {
t.Errorf("missing port log requirement: %s", required)
}
}
}
if path == "/logs/links" && (!strings.Contains(body, `value="transition"`) || !strings.Contains(body, "상태 변경 기록만 조회·내보내기")) {
t.Fatal("state event view is not changes-only")
}
})
}
}
}