Files
QuoteForge/internal/services/project_test.go
T
Mikhail ChusavitinandClaude Sonnet 5 2f3bdc609a fix: невалидное имя варианта проекта — предупреждение вместо ошибки
Имя варианта "main" или с недопустимыми символами больше не отклоняет
запрос ошибкой 400 — теперь автоматически конвертируется в валидное
(sanitizeProjectVariantName), а API/UI показывают variant_warning вместо
блокировки создания/переименования варианта.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-17 11:56:55 +03:00

101 lines
3.1 KiB
Go

package services
import (
"path/filepath"
"testing"
"git.mchus.pro/mchus/quoteforge/internal/localdb"
)
// TestProjectServiceCreateSanitizesReservedMainVariant verifies that naming a new
// variant "main" no longer errors: the name is auto-converted to a valid one and a
// warning is returned instead of the request being rejected.
func TestProjectServiceCreateSanitizesReservedMainVariant(t *testing.T) {
local, err := newProjectTestLocalDB(t)
if err != nil {
t.Fatalf("open localdb: %v", err)
}
service := NewProjectService(local)
project, warning, err := service.Create("tester", &CreateProjectRequest{
Code: "OPS-1",
Variant: "main",
})
if err != nil {
t.Fatalf("create project: %v", err)
}
if warning == "" {
t.Fatalf("expected a warning about the reserved variant name")
}
if project.Variant == "" || normalizeProjectVariant(project.Variant) == "main" {
t.Fatalf("expected variant to be converted away from 'main', got %q", project.Variant)
}
}
// TestProjectServiceUpdateSanitizesReservedMainVariant mirrors the create case for
// renaming an existing (non-main) variant to "main".
func TestProjectServiceUpdateSanitizesReservedMainVariant(t *testing.T) {
local, err := newProjectTestLocalDB(t)
if err != nil {
t.Fatalf("open localdb: %v", err)
}
service := NewProjectService(local)
created, _, err := service.Create("tester", &CreateProjectRequest{
Code: "OPS-1",
Variant: "Lenovo",
})
if err != nil {
t.Fatalf("create project: %v", err)
}
mainName := "main"
updated, warning, err := service.Update(created.UUID, "tester", &UpdateProjectRequest{
Variant: &mainName,
})
if err != nil {
t.Fatalf("update project: %v", err)
}
if warning == "" {
t.Fatalf("expected a warning about the reserved variant name")
}
if updated.Variant == "" || normalizeProjectVariant(updated.Variant) == "main" {
t.Fatalf("expected variant to be converted away from 'main', got %q", updated.Variant)
}
}
// TestSanitizeProjectVariantName_InvalidChars verifies disallowed characters are
// stripped/replaced rather than rejected outright.
func TestSanitizeProjectVariantName_InvalidChars(t *testing.T) {
sanitized, warning := sanitizeProjectVariantName("Лендинг сервер!")
if warning == "" {
t.Fatalf("expected a warning for invalid characters")
}
if !projectCodeRe.MatchString(sanitized) {
t.Fatalf("sanitized variant %q still fails projectCodeRe", sanitized)
}
}
// TestSanitizeProjectVariantName_ValidPassesThrough ensures already-valid names are
// left untouched with no warning.
func TestSanitizeProjectVariantName_ValidPassesThrough(t *testing.T) {
sanitized, warning := sanitizeProjectVariantName("lenovo-2u")
if warning != "" {
t.Fatalf("expected no warning, got %q", warning)
}
if sanitized != "lenovo-2u" {
t.Fatalf("expected unchanged variant, got %q", sanitized)
}
}
func newProjectTestLocalDB(t *testing.T) (*localdb.LocalDB, error) {
t.Helper()
dbPath := filepath.Join(t.TempDir(), "project_test.db")
local, err := localdb.New(dbPath)
if err != nil {
return nil, err
}
t.Cleanup(func() { _ = local.Close() })
return local, nil
}