style(boc): Landvex design system — no emojis, light theme, professional

- Replaced all emojis with SVG icons (Lucide-style)
- Changed color scheme to Landvex blue (#0066FF)
- Light theme background (#f5f5f7)
- Professional typography (Inter, JetBrains Mono)
- Clean, minimal design following Design Constitution
- No decorative elements — information first
- Consistent with Landvex Enterprise platform
This commit is contained in:
Bernt (LandveX AI)
2026-07-12 17:17:26 +00:00
parent 67a69ab073
commit 37a1af4a1f
7 changed files with 1468 additions and 698 deletions
BIN
View File
Binary file not shown.
+274
View File
@@ -0,0 +1,274 @@
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"sync"
"testing"
"time"
)
const (
baseURL = "http://localhost:9096"
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiMjIyMjIyMjItMjIyMi0yMjIyLTIyMjItMjIyMjIyMjIyMjIyIiwiZW1haWwiOiJlcmlrQGxhbmR2ZXguY29tIiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNzgyMzQ0MDAwfQ.demo"
)
// BenchmarkHealthCheck - simple health endpoint
func BenchmarkHealthCheck(b *testing.B) {
for i := 0; i < b.N; i++ {
resp, err := http.Get(baseURL + "/health")
if err != nil {
b.Fatal(err)
}
resp.Body.Close()
}
}
// BenchmarkLogin - auth endpoint
func BenchmarkLogin(b *testing.B) {
payload := map[string]string{
"email": "erik@landvex.com",
"password": "password123",
}
body, _ := json.Marshal(payload)
for i := 0; i < b.N; i++ {
resp, err := http.Post(baseURL+"/api/v1/auth/login", "application/json", bytes.NewReader(body))
if err != nil {
b.Fatal(err)
}
resp.Body.Close()
}
}
// BenchmarkDashboard - protected endpoint with analytics
func BenchmarkDashboard(b *testing.B) {
req, _ := http.NewRequest("GET", baseURL+"/api/v1/analytics/dashboard", nil)
req.Header.Set("Authorization", "Bearer "+token)
client := &http.Client{Timeout: 5 * time.Second}
for i := 0; i < b.N; i++ {
resp, err := client.Do(req)
if err != nil {
b.Fatal(err)
}
resp.Body.Close()
}
}
// BenchmarkQuotesList - database query
func BenchmarkQuotesList(b *testing.B) {
req, _ := http.NewRequest("GET", baseURL+"/api/v1/sales/quotes", nil)
req.Header.Set("Authorization", "Bearer "+token)
client := &http.Client{Timeout: 5 * time.Second}
for i := 0; i < b.N; i++ {
resp, err := client.Do(req)
if err != nil {
b.Fatal(err)
}
resp.Body.Close()
}
}
// Concurrent load test
func TestConcurrentLoad(t *testing.T) {
concurrency := 50
requests := 100
var wg sync.WaitGroup
errors := make(chan error, concurrency*requests)
start := time.Now()
for i := 0; i < concurrency; i++ {
wg.Add(1)
go func(worker int) {
defer wg.Done()
client := &http.Client{Timeout: 5 * time.Second}
for j := 0; j < requests; j++ {
req, _ := http.NewRequest("GET", baseURL+"/health", nil)
resp, err := client.Do(req)
if err != nil {
errors <- fmt.Errorf("worker %d req %d: %v", worker, j, err)
continue
}
if resp.StatusCode != 200 {
errors <- fmt.Errorf("worker %d req %d: status %d", worker, j, resp.StatusCode)
}
resp.Body.Close()
}
}(i)
}
wg.Wait()
close(errors)
duration := time.Since(start)
totalRequests := concurrency * requests
rps := float64(totalRequests) / duration.Seconds()
errCount := 0
for err := range errors {
if errCount < 5 {
t.Logf("Error: %v", err)
}
errCount++
}
t.Logf("Total: %d requests in %v (%.0f req/sec)", totalRequests, duration, rps)
t.Logf("Errors: %d (%.2f%%)", errCount, float64(errCount)/float64(totalRequests)*100)
if errCount > totalRequests/10 {
t.Fatalf("Too many errors: %d", errCount)
}
}
// TestFullWorkflow - complete business flow
func TestFullWorkflow(t *testing.T) {
client := &http.Client{Timeout: 10 * time.Second}
// 1. Login
loginPayload := map[string]string{
"email": "erik@landvex.com",
"password": "password123",
}
body, _ := json.Marshal(loginPayload)
resp, err := client.Post(baseURL+"/api/v1/auth/login", "application/json", bytes.NewReader(body))
if err != nil {
t.Fatalf("Login failed: %v", err)
}
var loginResp map[string]interface{}
json.NewDecoder(resp.Body).Decode(&loginResp)
resp.Body.Close()
authToken, ok := loginResp["token"].(string)
if !ok {
t.Fatal("No token in response")
}
t.Logf("✓ Login successful")
// 2. Create customer
customerPayload := map[string]interface{}{
"name": "Stress Test AB",
"email": "stress@test.com",
"phone": "+46701234567",
"address": "Testgatan 1, Stockholm",
}
body, _ = json.Marshal(customerPayload)
req, _ := http.NewRequest("POST", baseURL+"/api/v1/crm/customers", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+authToken)
req.Header.Set("Content-Type", "application/json")
resp, err = client.Do(req)
if err != nil {
t.Fatalf("Create customer failed: %v", err)
}
var customerResp map[string]interface{}
json.NewDecoder(resp.Body).Decode(&customerResp)
resp.Body.Close()
customerID := customerResp["id"].(string)
t.Logf("✓ Customer created: %s", customerID)
// 3. Create quote
quotePayload := map[string]interface{}{
"customer_id": customerID,
"title": "Stress Test Quote",
"items": []map[string]interface{}{
{
"description": "Test Product",
"quantity": 10,
"unit_price": 1000.00,
"tax_rate": 25.0,
},
},
}
body, _ = json.Marshal(quotePayload)
req, _ = http.NewRequest("POST", baseURL+"/api/v1/sales/quotes", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+authToken)
req.Header.Set("Content-Type", "application/json")
resp, err = client.Do(req)
if err != nil {
t.Fatalf("Create quote failed: %v", err)
}
var quoteResp map[string]interface{}
json.NewDecoder(resp.Body).Decode(&quoteResp)
resp.Body.Close()
quoteID := quoteResp["id"].(string)
t.Logf("✓ Quote created: %s", quoteID)
// 4. Accept quote
req, _ = http.NewRequest("POST", baseURL+"/api/v1/sales/quotes/"+quoteID+"/accept", nil)
req.Header.Set("Authorization", "Bearer "+authToken)
resp, err = client.Do(req)
if err != nil {
t.Fatalf("Accept quote failed: %v", err)
}
resp.Body.Close()
t.Logf("✓ Quote accepted")
// 5. Convert to order
req, _ = http.NewRequest("POST", baseURL+"/api/v1/sales/quotes/"+quoteID+"/convert", nil)
req.Header.Set("Authorization", "Bearer "+authToken)
resp, err = client.Do(req)
if err != nil {
t.Fatalf("Convert quote failed: %v", err)
}
var orderResp map[string]interface{}
json.NewDecoder(resp.Body).Decode(&orderResp)
resp.Body.Close()
t.Logf("✓ Quote converted to order: %s", orderResp["order_id"])
// 6. Get dashboard
req, _ = http.NewRequest("GET", baseURL+"/api/v1/analytics/dashboard", nil)
req.Header.Set("Authorization", "Bearer "+authToken)
resp, err = client.Do(req)
if err != nil {
t.Fatalf("Dashboard failed: %v", err)
}
resp.Body.Close()
t.Logf("✓ Dashboard loaded")
t.Logf("\n=== WORKFLOW COMPLETE ===")
}
// TestPDFGeneration - stress PDF generation
func TestPDFGeneration(t *testing.T) {
client := &http.Client{Timeout: 10 * time.Second}
// Get existing quote
req, _ := http.NewRequest("GET", baseURL+"/api/v1/sales/quotes", nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, err := client.Do(req)
if err != nil {
t.Fatalf("List quotes failed: %v", err)
}
var quotesResp map[string]interface{}
json.NewDecoder(resp.Body).Decode(&quotesResp)
resp.Body.Close()
quotes := quotesResp["quotes"].([]interface{})
if len(quotes) == 0 {
t.Skip("No quotes to test")
}
quoteID := quotes[0].(map[string]interface{})["id"].(string)
// Generate PDF
start := time.Now()
req, _ = http.NewRequest("GET", baseURL+"/api/v1/sales/quotes/"+quoteID+"/pdf", nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, err = client.Do(req)
if err != nil {
t.Fatalf("PDF generation failed: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
t.Fatalf("PDF generation returned %d", resp.StatusCode)
}
duration := time.Since(start)
t.Logf("✓ PDF generated in %v (status: %d, content-type: %s)", duration, resp.StatusCode, resp.Header.Get("Content-Type"))
}