Some checks failed
Pipeline: Test, Lint, Build / Get version info (push) Has been cancelled
Pipeline: Test, Lint, Build / Lint Go code (push) Has been cancelled
Pipeline: Test, Lint, Build / Test Go code (push) Has been cancelled
Pipeline: Test, Lint, Build / Test JS code (push) Has been cancelled
Pipeline: Test, Lint, Build / Lint i18n files (push) Has been cancelled
Pipeline: Test, Lint, Build / Check Docker configuration (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (darwin/amd64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (darwin/arm64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/386) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/amd64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/arm/v5) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/arm/v6) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/arm/v7) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/arm64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (windows/386) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (windows/amd64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Push to GHCR (push) Has been cancelled
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Has been cancelled
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Has been cancelled
Pipeline: Test, Lint, Build / Build Windows installers (push) Has been cancelled
Pipeline: Test, Lint, Build / Package/Release (push) Has been cancelled
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled
POEditor import / update-translations (push) Has been cancelled
90 lines
2.5 KiB
Go
90 lines
2.5 KiB
Go
package scrobbler
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/navidrome/navidrome/model"
|
|
"github.com/navidrome/navidrome/tests"
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
)
|
|
|
|
var _ = Describe("BufferedScrobbler", func() {
|
|
var ds model.DataStore
|
|
var scr *fakeScrobbler
|
|
var bs *bufferedScrobbler
|
|
var ctx context.Context
|
|
var buffer *tests.MockedScrobbleBufferRepo
|
|
|
|
BeforeEach(func() {
|
|
ctx = context.Background()
|
|
buffer = tests.CreateMockedScrobbleBufferRepo()
|
|
ds = &tests.MockDataStore{
|
|
MockedScrobbleBuffer: buffer,
|
|
}
|
|
scr = &fakeScrobbler{Authorized: true}
|
|
bs = newBufferedScrobbler(ds, scr, "test")
|
|
})
|
|
|
|
It("forwards IsAuthorized calls", func() {
|
|
scr.Authorized = true
|
|
Expect(bs.IsAuthorized(ctx, "user1")).To(BeTrue())
|
|
|
|
scr.Authorized = false
|
|
Expect(bs.IsAuthorized(ctx, "user1")).To(BeFalse())
|
|
})
|
|
|
|
It("forwards NowPlaying calls", func() {
|
|
track := &model.MediaFile{ID: "123", Title: "Test Track"}
|
|
Expect(bs.NowPlaying(ctx, "user1", track, 0)).To(Succeed())
|
|
Expect(scr.GetNowPlayingCalled()).To(BeTrue())
|
|
Expect(scr.GetUserID()).To(Equal("user1"))
|
|
Expect(scr.GetTrack()).To(Equal(track))
|
|
})
|
|
|
|
It("enqueues scrobbles to buffer", func() {
|
|
track := model.MediaFile{ID: "123", Title: "Test Track"}
|
|
now := time.Now()
|
|
scrobble := Scrobble{MediaFile: track, TimeStamp: now}
|
|
Expect(buffer.Length()).To(Equal(int64(0)))
|
|
Expect(scr.ScrobbleCalled.Load()).To(BeFalse())
|
|
|
|
Expect(bs.Scrobble(ctx, "user1", scrobble)).To(Succeed())
|
|
|
|
// Wait for the background goroutine to process the scrobble.
|
|
// We don't check buffer.Length() here because the background goroutine
|
|
// may dequeue the entry before we can observe it.
|
|
Eventually(scr.ScrobbleCalled.Load).Should(BeTrue())
|
|
|
|
lastScrobble := scr.LastScrobble.Load()
|
|
Expect(lastScrobble.MediaFile.ID).To(Equal("123"))
|
|
Expect(lastScrobble.TimeStamp).To(BeTemporally("==", now))
|
|
})
|
|
|
|
It("stops the background goroutine when Stop is called", func() {
|
|
// Replace the real run method with one that signals when it exits
|
|
done := make(chan struct{})
|
|
|
|
// Start our instrumented run function that will signal when it exits
|
|
go func() {
|
|
defer close(done)
|
|
bs.run(bs.ctx)
|
|
}()
|
|
|
|
// Wait a bit to ensure the goroutine is running
|
|
time.Sleep(10 * time.Millisecond)
|
|
|
|
// Call the real Stop method
|
|
bs.Stop()
|
|
|
|
// Wait for the goroutine to exit or timeout
|
|
select {
|
|
case <-done:
|
|
// Success, goroutine exited
|
|
case <-time.After(100 * time.Millisecond):
|
|
Fail("Goroutine did not exit in time after Stop was called")
|
|
}
|
|
})
|
|
})
|