package core import ( "context" "time" "github.com/navidrome/navidrome/log" "github.com/navidrome/navidrome/model" "github.com/navidrome/navidrome/model/request" "github.com/navidrome/navidrome/tests" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) var _ = Describe("Players", func() { var players Players var repo *mockPlayerRepository ctx := log.NewContext(context.TODO()) ctx = request.WithUser(ctx, model.User{ID: "userid", UserName: "johndoe"}) ctx = request.WithUsername(ctx, "johndoe") var beforeRegister time.Time BeforeEach(func() { repo = &mockPlayerRepository{} ds := &tests.MockDataStore{MockedPlayer: repo, MockedTranscoding: &tests.MockTranscodingRepo{}} players = NewPlayers(ds) beforeRegister = time.Now() }) Describe("Register", func() { It("creates a new player when no ID is specified", func() { p, trc, err := players.Register(ctx, "", "client", "chrome", "1.2.3.4") Expect(err).ToNot(HaveOccurred()) Expect(p.ID).ToNot(BeEmpty()) Expect(p.LastSeen).To(BeTemporally(">=", beforeRegister)) Expect(p.Client).To(Equal("client")) Expect(p.UserName).To(Equal("johndoe")) Expect(p.UserAgent).To(Equal("chrome")) Expect(repo.lastSaved).To(Equal(p)) Expect(trc).To(BeNil()) }) It("creates a new player if it cannot find any matching player", func() { p, trc, err := players.Register(ctx, "123", "client", "chrome", "1.2.3.4") Expect(err).ToNot(HaveOccurred()) Expect(p.ID).ToNot(BeEmpty()) Expect(p.LastSeen).To(BeTemporally(">=", beforeRegister)) Expect(repo.lastSaved).To(Equal(p)) Expect(trc).To(BeNil()) }) It("creates a new player if client does not match the one in DB", func() { plr := &model.Player{ID: "123", Name: "A Player", Client: "client1111", LastSeen: time.Time{}} repo.add(plr) p, trc, err := players.Register(ctx, "123", "client2222", "chrome", "1.2.3.4") Expect(err).ToNot(HaveOccurred()) Expect(p.ID).ToNot(BeEmpty()) Expect(p.ID).ToNot(Equal("123")) Expect(p.LastSeen).To(BeTemporally(">=", beforeRegister)) Expect(p.Client).To(Equal("client2222")) Expect(trc).To(BeNil()) }) It("finds players by ID", func() { plr := &model.Player{ID: "123", Name: "A Player", Client: "client", LastSeen: time.Time{}} repo.add(plr) p, trc, err := players.Register(ctx, "123", "client", "chrome", "1.2.3.4") Expect(err).ToNot(HaveOccurred()) Expect(p.ID).To(Equal("123")) Expect(p.LastSeen).To(BeTemporally(">=", beforeRegister)) Expect(repo.lastSaved).To(Equal(p)) Expect(trc).To(BeNil()) }) It("finds player by client and user names when ID is not found", func() { plr := &model.Player{ID: "123", Name: "A Player", Client: "client", UserName: "johndoe", LastSeen: time.Time{}} repo.add(plr) p, _, err := players.Register(ctx, "999", "client", "chrome", "1.2.3.4") Expect(err).ToNot(HaveOccurred()) Expect(p.ID).To(Equal("123")) Expect(p.LastSeen).To(BeTemporally(">=", beforeRegister)) Expect(repo.lastSaved).To(Equal(p)) }) It("finds player by client and user names when not ID is provided", func() { plr := &model.Player{ID: "123", Name: "A Player", Client: "client", UserName: "johndoe", LastSeen: time.Time{}} repo.add(plr) p, _, err := players.Register(ctx, "", "client", "chrome", "1.2.3.4") Expect(err).ToNot(HaveOccurred()) Expect(p.ID).To(Equal("123")) Expect(p.LastSeen).To(BeTemporally(">=", beforeRegister)) Expect(repo.lastSaved).To(Equal(p)) }) It("finds player by ID and return its transcoding", func() { plr := &model.Player{ID: "123", Name: "A Player", Client: "client", LastSeen: time.Time{}, TranscodingId: "1"} repo.add(plr) p, trc, err := players.Register(ctx, "123", "client", "chrome", "1.2.3.4") Expect(err).ToNot(HaveOccurred()) Expect(p.ID).To(Equal("123")) Expect(p.LastSeen).To(BeTemporally(">=", beforeRegister)) Expect(repo.lastSaved).To(Equal(p)) Expect(trc.ID).To(Equal("1")) }) }) }) type mockPlayerRepository struct { model.PlayerRepository lastSaved *model.Player data map[string]model.Player } func (m *mockPlayerRepository) add(p *model.Player) { if m.data == nil { m.data = make(map[string]model.Player) } m.data[p.ID] = *p } func (m *mockPlayerRepository) Get(id string) (*model.Player, error) { if p, ok := m.data[id]; ok { return &p, nil } return nil, model.ErrNotFound } func (m *mockPlayerRepository) FindMatch(userName, client, typ string) (*model.Player, error) { for _, p := range m.data { if p.Client == client && p.UserName == userName { return &p, nil } } return nil, model.ErrNotFound } func (m *mockPlayerRepository) Put(p *model.Player) error { m.lastSaved = p return nil }