Files
Bose-SoundTouch/pkg/client/token_integration_test.go
T
Tobias Gesellchen 6a815219f6 Implement /requestToken API and fix clock time display
Major Features:
• Implement complete /requestToken API endpoint for bearer token generation
• Fix clock time parsing and display with comprehensive time information
• Add comprehensive API documentation for 103 discovered endpoints

/requestToken Implementation:
• Add BearerToken model with full XML marshaling support
• Add RequestToken() client method with proper error handling
• Add 'soundtouch-cli token request' CLI command with security features
• Token validation, formatting, and secure display (truncated for security)
• Comprehensive unit tests and integration tests
• Support for Authorization header formatting and raw token extraction

Clock Time Fixes:
• Fix ClockTime model to match actual device XML response structure
• Add LocalTime component for nested time details
• Support for utcTime, timeFormat, brightness, clockError attributes
• Enhanced CLI display with comprehensive time information
• Fixed month conversion (device uses 0-11, Go uses 1-12)

Documentation Enhancements:
• Add comprehensive /supportedURLs endpoint analysis (103 endpoints discovered)
• Create detailed unimplemented endpoints documentation with examples
• Update API coverage from 34% implemented to full endpoint catalog
• Add SoundTouch End of Life notice with May 6, 2026 details
• Enhanced endpoint descriptions with real device response examples

Security:
• All tests use generic token examples (no real tokens exposed)
• Integration tests validate token properties without exposing values
• Secure token display with truncation in CLI and string representations
• Environment variable based testing for real devices

Testing:
• 15+ new test functions with comprehensive coverage
• Real device validation on 192.168.178.28 and 192.168.178.35
• Mock server tests and XML marshaling validation
• Integration tests with SOUNDTOUCH_TEST_HOST environment variable

CLI Enhancements:
• Enhanced clock time display with local time details and device settings
• New token management commands with usage instructions
• Improved error handling and user-friendly output formatting
2026-01-11 23:09:29 +01:00

96 lines
2.8 KiB
Go

package client
import (
"os"
"strings"
"testing"
)
// TestRequestToken_Integration tests the RequestToken method against a real device
// This test only runs when SOUNDTOUCH_TEST_HOST environment variable is set
func TestRequestToken_Integration(t *testing.T) {
host := os.Getenv("SOUNDTOUCH_TEST_HOST")
if host == "" {
t.Skip("Skipping integration test: SOUNDTOUCH_TEST_HOST not set")
}
// Create client for real device
config := &Config{
Host: host,
Port: 8090,
}
client := NewClient(config)
// Test RequestToken with real device
token, err := client.RequestToken()
if err != nil {
t.Fatalf("RequestToken() failed with real device: %v", err)
}
if token == nil {
t.Fatal("RequestToken() returned nil token from real device")
}
// Validate token properties without exposing actual values
tokenValue := token.GetToken()
// Token should have Bearer prefix
if !strings.HasPrefix(tokenValue, "Bearer ") {
t.Error("Real device token should have 'Bearer ' prefix")
}
// Token should be valid according to our validation
if !token.IsValid() {
t.Error("Real device token should be valid")
}
// Raw token should not include Bearer prefix
rawToken := token.GetTokenWithoutPrefix()
if strings.HasPrefix(rawToken, "Bearer ") {
t.Error("Raw token should not include Bearer prefix")
}
// Token should be reasonably long (real bearer tokens are substantial)
if len(rawToken) < 80 {
t.Errorf("Real device token seems too short: %d characters", len(rawToken))
}
// Token should only contain base64-like characters plus common token chars
validChars := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
for _, char := range rawToken {
if !strings.ContainsRune(validChars, char) {
t.Errorf("Token contains unexpected character: %c", char)
}
}
// Auth header should match full token value
if token.GetAuthHeader() != tokenValue {
t.Error("Auth header should match full token value")
}
// String representation should be truncated for security
stringRepr := token.String()
if len(stringRepr) >= len(tokenValue) {
t.Error("String representation should be shorter than full token for security")
}
// String representation should contain "..." for long tokens
if !strings.Contains(stringRepr, "...") {
t.Error("String representation should contain '...' for long tokens")
}
// Multiple calls should generate different tokens (if the device supports it)
token2, err := client.RequestToken()
if err != nil {
t.Fatalf("Second RequestToken() call failed: %v", err)
}
// Note: Some devices may return the same token, so we don't enforce uniqueness
// but we do verify the second token is also valid
if !token2.IsValid() {
t.Error("Second token should also be valid")
}
t.Logf("Successfully validated real device token properties (length: %d chars)", len(rawToken))
}