Initial commit
This commit is contained in:
commit
02a6dabcfb
62 files changed
+15751
No files matched your search
@@ -0,0 +1,383 @@
|
||||
package ynison
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/client"
|
||||
"gitea.mrixs.me/Mrixs/yandex-music-api-go/internal/ynison/proto"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
// TestYnisonClient_Connect tests the Connect method with a mock WebSocket server
|
||||
func TestYnisonClient_Connect(t *testing.T) {
|
||||
// Create a mock WebSocket server
|
||||
var receivedMessages [][]byte
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
upgrader := websocket.Upgrader{
|
||||
CheckOrigin: func(r *http.Request) bool { return true },
|
||||
}
|
||||
conn, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
t.Logf("Upgrade error: %v", err)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// Read messages from client
|
||||
for {
|
||||
_, message, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
|
||||
t.Logf("Read error: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
receivedMessages = append(receivedMessages, message)
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
// Convert HTTP URL to WS URL
|
||||
wsURL := "ws" + server.URL[4:] // Replace http with ws
|
||||
|
||||
// Create a client with test token
|
||||
c := client.NewClient(client.ClientConfig{
|
||||
Token: "test-token",
|
||||
})
|
||||
|
||||
config := DeviceConfig{
|
||||
DeviceID: "test-device-123",
|
||||
Title: "Test Device",
|
||||
DeviceType: proto.DeviceType_DEVICE_TYPE_WEB_DESKTOP,
|
||||
AppName: "TestApp",
|
||||
AppVersion: "1.0.0",
|
||||
CanBePlayer: true,
|
||||
CanBeRemote: true,
|
||||
VolumeGran: 100,
|
||||
}
|
||||
|
||||
ynisonClient := NewYnisonClient(c, config)
|
||||
|
||||
// Override the wsURL for testing
|
||||
ynisonClient.overrideWSURL(wsURL)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
err := ynisonClient.Connect(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Connect failed: %v", err)
|
||||
}
|
||||
|
||||
if !ynisonClient.IsConnected() {
|
||||
t.Error("Expected client to be connected after Connect")
|
||||
}
|
||||
|
||||
// Wait a bit for the initial message to be sent
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
// Verify that an UpdateFullState message was sent
|
||||
if len(receivedMessages) == 0 {
|
||||
t.Error("Expected at least one message to be sent")
|
||||
} else {
|
||||
var req proto.PutYnisonStateRequest
|
||||
if err := json.Unmarshal(receivedMessages[0], &req); err != nil {
|
||||
t.Fatalf("Failed to unmarshal sent message: %v", err)
|
||||
}
|
||||
if req.UpdateFullState == nil {
|
||||
t.Error("Expected UpdateFullState in first message")
|
||||
}
|
||||
if req.UpdateFullState.Device == nil {
|
||||
t.Error("Expected Device in UpdateFullState")
|
||||
}
|
||||
if req.UpdateFullState.Device.Info.DeviceId != "test-device-123" {
|
||||
t.Errorf("Expected DeviceId 'test-device-123', got '%s'", req.UpdateFullState.Device.Info.DeviceId)
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
err = ynisonClient.Disconnect()
|
||||
if err != nil {
|
||||
t.Errorf("Disconnect failed: %v", err)
|
||||
}
|
||||
|
||||
if ynisonClient.IsConnected() {
|
||||
t.Error("Expected client to be disconnected after Disconnect")
|
||||
}
|
||||
}
|
||||
|
||||
// TestYnisonClient_Disconnect tests the Disconnect method
|
||||
func TestYnisonClient_Disconnect(t *testing.T) {
|
||||
// Create a mock WebSocket server
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
upgrader := websocket.Upgrader{
|
||||
CheckOrigin: func(r *http.Request) bool { return true },
|
||||
}
|
||||
conn, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// Keep connection open until client closes it
|
||||
for {
|
||||
_, _, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
wsURL := "ws" + server.URL[4:]
|
||||
|
||||
c := client.NewClient(client.ClientConfig{
|
||||
Token: "test-token",
|
||||
})
|
||||
|
||||
config := DeviceConfig{
|
||||
DeviceID: "test-device-disconnect",
|
||||
}
|
||||
|
||||
ynisonClient := NewYnisonClient(c, config)
|
||||
ynisonClient.overrideWSURL(wsURL)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
err := ynisonClient.Connect(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Connect failed: %v", err)
|
||||
}
|
||||
|
||||
if !ynisonClient.IsConnected() {
|
||||
t.Error("Expected client to be connected")
|
||||
}
|
||||
|
||||
err = ynisonClient.Disconnect()
|
||||
if err != nil {
|
||||
t.Errorf("Disconnect failed: %v", err)
|
||||
}
|
||||
|
||||
if ynisonClient.IsConnected() {
|
||||
t.Error("Expected client to be disconnected after Disconnect")
|
||||
}
|
||||
|
||||
// Calling Disconnect again should not error
|
||||
err = ynisonClient.Disconnect()
|
||||
if err != nil {
|
||||
t.Errorf("Second Disconnect should not error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestYnisonClient_UpdatePlayingStatus tests the UpdatePlayingStatus method
|
||||
func TestYnisonClient_UpdatePlayingStatus(t *testing.T) {
|
||||
var receivedMessages [][]byte
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
upgrader := websocket.Upgrader{
|
||||
CheckOrigin: func(r *http.Request) bool { return true },
|
||||
}
|
||||
conn, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
for {
|
||||
_, message, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
receivedMessages = append(receivedMessages, message)
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
wsURL := "ws" + server.URL[4:]
|
||||
|
||||
c := client.NewClient(client.ClientConfig{
|
||||
Token: "test-token",
|
||||
})
|
||||
|
||||
config := DeviceConfig{
|
||||
DeviceID: "test-device-status",
|
||||
}
|
||||
|
||||
ynisonClient := NewYnisonClient(c, config)
|
||||
ynisonClient.overrideWSURL(wsURL)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
err := ynisonClient.Connect(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("Connect failed: %v", err)
|
||||
}
|
||||
|
||||
// Wait for initial connection message
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
initialMsgCount := len(receivedMessages)
|
||||
|
||||
// Create a playing status
|
||||
status := CreatePlayingStatus(50000, 200000, false, 1.0, "test-device-status")
|
||||
|
||||
// Update playing status
|
||||
err = ynisonClient.UpdatePlayingStatus(ctx, status)
|
||||
if err != nil {
|
||||
t.Fatalf("UpdatePlayingStatus failed: %v", err)
|
||||
}
|
||||
|
||||
// Wait for message to be sent
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
// Verify the UpdatePlayingStatus message was sent
|
||||
if len(receivedMessages) <= initialMsgCount {
|
||||
t.Error("Expected UpdatePlayingStatus message to be sent")
|
||||
} else {
|
||||
var req proto.PutYnisonStateRequest
|
||||
if err := json.Unmarshal(receivedMessages[initialMsgCount], &req); err != nil {
|
||||
t.Fatalf("Failed to unmarshal sent message: %v", err)
|
||||
}
|
||||
if req.UpdatePlayingStatus == nil {
|
||||
t.Error("Expected UpdatePlayingStatus in message")
|
||||
}
|
||||
if req.UpdatePlayingStatus.PlayingStatus == nil {
|
||||
t.Error("Expected PlayingStatus in UpdatePlayingStatus")
|
||||
}
|
||||
if req.UpdatePlayingStatus.PlayingStatus.ProgressMs != 50000 {
|
||||
t.Errorf("Expected ProgressMs 50000, got %d", req.UpdatePlayingStatus.PlayingStatus.ProgressMs)
|
||||
}
|
||||
if req.UpdatePlayingStatus.PlayingStatus.DurationMs != 200000 {
|
||||
t.Errorf("Expected DurationMs 200000, got %d", req.UpdatePlayingStatus.PlayingStatus.DurationMs)
|
||||
}
|
||||
if req.UpdatePlayingStatus.PlayingStatus.Paused != false {
|
||||
t.Errorf("Expected Paused false, got %v", req.UpdatePlayingStatus.PlayingStatus.Paused)
|
||||
}
|
||||
if req.UpdatePlayingStatus.PlayingStatus.PlaybackSpeed != 1.0 {
|
||||
t.Errorf("Expected PlaybackSpeed 1.0, got %f", req.UpdatePlayingStatus.PlayingStatus.PlaybackSpeed)
|
||||
}
|
||||
if req.UpdatePlayingStatus.PlayingStatus.Version.DeviceId != "test-device-status" {
|
||||
t.Errorf("Expected DeviceId 'test-device-status', got '%s'", req.UpdatePlayingStatus.PlayingStatus.Version.DeviceId)
|
||||
}
|
||||
if req.Rid == "" {
|
||||
t.Error("Expected non-empty Rid")
|
||||
}
|
||||
}
|
||||
|
||||
err = ynisonClient.Disconnect()
|
||||
if err != nil {
|
||||
t.Errorf("Disconnect failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestYnisonClient_UpdatePlayingStatus_NotConnected tests UpdatePlayingStatus when not connected
|
||||
func TestYnisonClient_UpdatePlayingStatus_NotConnected(t *testing.T) {
|
||||
c := client.NewClient(client.ClientConfig{
|
||||
Token: "test-token",
|
||||
})
|
||||
|
||||
config := DeviceConfig{
|
||||
DeviceID: "test-device-not-connected",
|
||||
}
|
||||
|
||||
ynisonClient := NewYnisonClient(c, config)
|
||||
|
||||
status := CreatePlayingStatus(50000, 200000, false, 1.0, "test-device-not-connected")
|
||||
|
||||
err := ynisonClient.UpdatePlayingStatus(context.Background(), status)
|
||||
if err == nil {
|
||||
t.Error("Expected error when not connected")
|
||||
}
|
||||
if err != nil && err.Error() != "not connected" {
|
||||
t.Errorf("Expected 'not connected' error, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestYnisonClient_Connect_NoToken tests Connect without a token
|
||||
func TestYnisonClient_Connect_NoToken(t *testing.T) {
|
||||
c := client.NewClient(client.ClientConfig{
|
||||
Token: "",
|
||||
})
|
||||
|
||||
config := DeviceConfig{
|
||||
DeviceID: "test-device-no-token",
|
||||
}
|
||||
|
||||
ynisonClient := NewYnisonClient(c, config)
|
||||
|
||||
err := ynisonClient.Connect(context.Background())
|
||||
if err == nil {
|
||||
t.Error("Expected error when no token")
|
||||
}
|
||||
if err != nil && err.Error() != "no auth token available" {
|
||||
t.Errorf("Expected 'no auth token available' error, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestYnisonClient_IsConnected tests the IsConnected method
|
||||
func TestYnisonClient_IsConnected(t *testing.T) {
|
||||
c := client.NewClient(client.ClientConfig{
|
||||
Token: "test-token",
|
||||
})
|
||||
|
||||
config := DeviceConfig{
|
||||
DeviceID: "test-device-isconnected",
|
||||
}
|
||||
|
||||
ynisonClient := NewYnisonClient(c, config)
|
||||
|
||||
if ynisonClient.IsConnected() {
|
||||
t.Error("Expected client to not be connected initially")
|
||||
}
|
||||
|
||||
// We can't easily test connected state without a real server,
|
||||
// but we verified this in the Connect/Disconnect tests
|
||||
}
|
||||
|
||||
// TestYnisonClient_RegisterHandler tests handler registration
|
||||
func TestYnisonClient_RegisterHandler(t *testing.T) {
|
||||
c := client.NewClient(client.ClientConfig{
|
||||
Token: "test-token",
|
||||
})
|
||||
|
||||
config := DeviceConfig{
|
||||
DeviceID: "test-device-handler",
|
||||
}
|
||||
|
||||
ynisonClient := NewYnisonClient(c, config)
|
||||
|
||||
ynisonClient.RegisterHandler("test", func(resp *proto.PutYnisonStateResponse) {})
|
||||
|
||||
// We can't easily test handler invocation without a real server,
|
||||
// but we can verify the handler is registered
|
||||
ynisonClient.UnregisterHandler("test")
|
||||
|
||||
// Re-register and verify it doesn't panic
|
||||
ynisonClient.RegisterHandler("test2", func(resp *proto.PutYnisonStateResponse) {})
|
||||
ynisonClient.UnregisterHandler("test2")
|
||||
ynisonClient.UnregisterHandler("nonexistent") // Should not panic
|
||||
}
|
||||
|
||||
// TestYnisonClient_DisconnectWithoutConnect tests Disconnect without prior Connect
|
||||
func TestYnisonClient_DisconnectWithoutConnect(t *testing.T) {
|
||||
c := client.NewClient(client.ClientConfig{
|
||||
Token: "test-token",
|
||||
})
|
||||
|
||||
config := DeviceConfig{
|
||||
DeviceID: "test-device-disconnect-no-connect",
|
||||
}
|
||||
|
||||
ynisonClient := NewYnisonClient(c, config)
|
||||
|
||||
// Should not panic or error
|
||||
err := ynisonClient.Disconnect()
|
||||
if err != nil {
|
||||
t.Errorf("Disconnect without connect should not error: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user