skyview/internal/squawk/squawk_test.go
Ole-Morten Duesund 62ace55fe1 Implement transponder code (squawk) lookup and textual descriptions
Resolves #30

- Add comprehensive squawk code lookup database with emergency, standard, military, and special codes
- Implement squawk.Database with 20+ common transponder codes including:
  * Emergency codes: 7700 (General Emergency), 7600 (Radio Failure), 7500 (Hijacking)
  * Standard codes: 1200/7000 (VFR), operational codes by region
  * Special codes: 1277 (SAR), 1255 (Fire Fighting), military codes
- Add SquawkDescription field to Aircraft struct and JSON marshaling
- Integrate squawk database into merger for automatic description population
- Update frontend with color-coded squawk display and tooltips:
  * Red for emergency codes with warning symbols
  * Orange for special operations
  * Gray for military codes
  * Green for standard operational codes
- Add comprehensive test coverage for squawk lookup functionality

Features:
- Visual emergency code identification for safety
- Educational descriptions for aviation enthusiasts
- Configurable lookup system for regional variations
- Hover tooltips with full code explanations
- Graceful fallback for unknown codes

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-31 12:02:02 +02:00

209 lines
No EOL
4.6 KiB
Go

package squawk
import (
"testing"
)
func TestNewDatabase(t *testing.T) {
db := NewDatabase()
if db == nil {
t.Fatal("NewDatabase() returned nil")
}
if len(db.codes) == 0 {
t.Error("Database should contain pre-loaded codes")
}
}
func TestEmergencyCodes(t *testing.T) {
db := NewDatabase()
emergencyCodes := []string{"7500", "7600", "7700"}
for _, code := range emergencyCodes {
info := db.Lookup(code)
if info == nil {
t.Errorf("Emergency code %s not found", code)
continue
}
if info.Type != Emergency {
t.Errorf("Code %s should be Emergency type, got %s", code, info.Type)
}
if !db.IsEmergencyCode(code) {
t.Errorf("IsEmergencyCode(%s) should return true", code)
}
}
}
func TestStandardCodes(t *testing.T) {
db := NewDatabase()
testCases := []struct {
code string
description string
}{
{"1200", "VFR - Visual Flight Rules"},
{"7000", "VFR - Visual Flight Rules"},
{"1000", "Mode A/C Not Assigned"},
}
for _, tc := range testCases {
info := db.Lookup(tc.code)
if info == nil {
t.Errorf("Standard code %s not found", tc.code)
continue
}
if info.Description != tc.description {
t.Errorf("Code %s: expected description %q, got %q",
tc.code, tc.description, info.Description)
}
}
}
func TestLookupInt(t *testing.T) {
db := NewDatabase()
// Test integer lookup
info := db.LookupInt(7700)
if info == nil {
t.Fatal("LookupInt(7700) returned nil")
}
if info.Code != "7700" {
t.Errorf("Expected code '7700', got '%s'", info.Code)
}
if info.Type != Emergency {
t.Errorf("Code 7700 should be Emergency type, got %s", info.Type)
}
}
func TestLookupHex(t *testing.T) {
db := NewDatabase()
// 7700 in octal is 3840 in decimal, which is F00 in hex
// However, squawk codes are transmitted differently in different formats
// For now, test with a simple hex conversion
// Test invalid hex
info := db.LookupHex("INVALID")
if info != nil {
t.Error("LookupHex with invalid hex should return nil")
}
}
func TestFormatSquawkWithDescription(t *testing.T) {
db := NewDatabase()
testCases := []struct {
code string
expected string
}{
{"7700", "7700 (⚠️ EMERGENCY - General Emergency)"},
{"1200", "1200 (VFR - Visual Flight Rules)"},
{"1277", "1277 (🔸 Search and Rescue)"},
{"0000", "0000 (🔰 No Transponder/Military)"},
{"9999", "9999"}, // Unknown code should return just the code
}
for _, tc := range testCases {
result := db.FormatSquawkWithDescription(tc.code)
if result != tc.expected {
t.Errorf("FormatSquawkWithDescription(%s): expected %q, got %q",
tc.code, tc.expected, result)
}
}
}
func TestGetEmergencyCodes(t *testing.T) {
db := NewDatabase()
emergencyCodes := db.GetEmergencyCodes()
if len(emergencyCodes) != 3 {
t.Errorf("Expected 3 emergency codes, got %d", len(emergencyCodes))
}
// Check that they're sorted by priority (highest first)
for i := 1; i < len(emergencyCodes); i++ {
if emergencyCodes[i-1].Priority < emergencyCodes[i].Priority {
t.Error("Emergency codes should be sorted by priority (highest first)")
}
}
}
func TestAddCustomCode(t *testing.T) {
db := NewDatabase()
customCode := &CodeInfo{
Code: "1234",
Description: "Test Custom Code",
Type: Special,
Region: "Test",
Priority: 50,
Notes: "This is a test custom code",
}
db.AddCustomCode(customCode)
info := db.Lookup("1234")
if info == nil {
t.Fatal("Custom code not found after adding")
}
if info.Description != "Test Custom Code" {
t.Errorf("Custom code description mismatch: expected %q, got %q",
"Test Custom Code", info.Description)
}
}
func TestCodeTypeString(t *testing.T) {
testCases := []struct {
codeType CodeType
expected string
}{
{Unknown, "Unknown"},
{Emergency, "Emergency"},
{Standard, "Standard"},
{Military, "Military"},
{Special, "Special"},
}
for _, tc := range testCases {
result := tc.codeType.String()
if result != tc.expected {
t.Errorf("CodeType.String(): expected %q, got %q", tc.expected, result)
}
}
}
func TestGetAllCodes(t *testing.T) {
db := NewDatabase()
allCodes := db.GetAllCodes()
if len(allCodes) == 0 {
t.Error("GetAllCodes() should return non-empty slice")
}
// Verify we can find known codes in the result
found7700 := false
found1200 := false
for _, code := range allCodes {
if code.Code == "7700" {
found7700 = true
}
if code.Code == "1200" {
found1200 = true
}
}
if !found7700 {
t.Error("Emergency code 7700 not found in GetAllCodes() result")
}
if !found1200 {
t.Error("Standard code 1200 not found in GetAllCodes() result")
}
}