mirror of
https://github.com/gesellix/Bose-SoundTouch.git
synced 2026-08-18 00:26:29 +00:00
feat: add Amazon LWA mock server (testutils + integration mocks)
Mirror the Spotify equivalents: pkg/testutils/amazon/handlers.go provides HandleToken and HandleProfile for use in unit tests; tests/integration/mocks/amazon.go wraps them in an AmazonMock with TokenURL() and ProfileURL() accessors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
cb037df831
commit
70d05554a0
@@ -0,0 +1,93 @@
|
||||
// Package amazon provides shared handlers for mocking the Amazon LWA API.
|
||||
package amazon
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// NewAmazonHandler returns a new http.Handler configured with Amazon LWA mock endpoints.
|
||||
func NewAmazonHandler() http.Handler {
|
||||
mux := http.NewServeMux()
|
||||
|
||||
// LWA Token Endpoint (POST body credentials, not Basic Auth)
|
||||
mux.HandleFunc("/auth/o2/token", HandleToken)
|
||||
|
||||
// LWA User Profile Endpoint
|
||||
mux.HandleFunc("/user/profile", HandleProfile)
|
||||
|
||||
return mux
|
||||
}
|
||||
|
||||
// HandleToken simulates the Amazon LWA token endpoint.
|
||||
// Amazon requires client_id and client_secret as POST body fields, not HTTP Basic Auth.
|
||||
func HandleToken(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("[Amazon Mock] Token request: %s", r.Method)
|
||||
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
if err := r.ParseForm(); err != nil {
|
||||
http.Error(w, "Bad request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
grantType := r.FormValue("grant_type")
|
||||
log.Printf("[Amazon Mock] Grant type: %s", grantType)
|
||||
|
||||
resp := map[string]interface{}{
|
||||
"access_token": "Atza|amazon-access-token",
|
||||
"token_type": "bearer",
|
||||
"expires_in": 3600,
|
||||
"refresh_token": "Atzr|amazon-refresh-token",
|
||||
}
|
||||
|
||||
switch grantType {
|
||||
case "authorization_code":
|
||||
if r.FormValue("code") == "" {
|
||||
http.Error(w, `{"error":"invalid_grant"}`, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
case "refresh_token":
|
||||
if r.FormValue("refresh_token") == "" {
|
||||
http.Error(w, `{"error":"invalid_grant"}`, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
default:
|
||||
http.Error(w, `{"error":"unsupported_grant_type"}`, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(resp); err != nil {
|
||||
log.Printf("Error encoding token response: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// HandleProfile simulates the Amazon LWA user profile endpoint.
|
||||
// LWA returns "user_id" and "name" (not "id" / "display_name" like Spotify).
|
||||
func HandleProfile(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("[Amazon Mock] Profile request: %s", r.Method)
|
||||
|
||||
auth := r.Header.Get("Authorization")
|
||||
if auth != "Bearer Atza|amazon-access-token" {
|
||||
http.Error(w, `{"error":"unauthorized"}`, http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
resp := map[string]interface{}{
|
||||
"user_id": "amzn1.account.TESTUSER",
|
||||
"name": "Amazon Test User",
|
||||
"email": "amazon-test@example.com",
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(resp); err != nil {
|
||||
log.Printf("Error encoding profile response: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package mocks
|
||||
|
||||
import (
|
||||
"net/http/httptest"
|
||||
|
||||
"github.com/gesellix/bose-soundtouch/pkg/testutils/amazon"
|
||||
)
|
||||
|
||||
// AmazonMock simulates Amazon LWA API responses for OAuth and profile interactions.
|
||||
type AmazonMock struct {
|
||||
server *httptest.Server
|
||||
}
|
||||
|
||||
// NewAmazonMock creates and starts a new Amazon LWA mock server.
|
||||
func NewAmazonMock() *AmazonMock {
|
||||
return &AmazonMock{
|
||||
server: httptest.NewServer(amazon.NewAmazonHandler()),
|
||||
}
|
||||
}
|
||||
|
||||
// URL returns the base URL of the mock server.
|
||||
func (m *AmazonMock) URL() string {
|
||||
return m.server.URL
|
||||
}
|
||||
|
||||
// TokenURL returns the LWA token endpoint URL.
|
||||
func (m *AmazonMock) TokenURL() string {
|
||||
return m.server.URL + "/auth/o2/token"
|
||||
}
|
||||
|
||||
// ProfileURL returns the LWA user profile endpoint URL.
|
||||
func (m *AmazonMock) ProfileURL() string {
|
||||
return m.server.URL + "/user/profile"
|
||||
}
|
||||
|
||||
// Close stops the mock server.
|
||||
func (m *AmazonMock) Close() {
|
||||
m.server.Close()
|
||||
}
|
||||
Reference in New Issue
Block a user