ranking_test.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. package query_test
  2. import (
  3. "testing"
  4. "github.com/pocketbase/pocketbase/core"
  5. "code.osinet.fr/fgm/jamtrack/internal/query"
  6. _ "code.osinet.fr/fgm/jamtrack/migrations"
  7. _ "github.com/pocketbase/pocketbase/migrations"
  8. )
  9. // newTestApp creates a bootstrapped PocketBase app in a temp directory with
  10. // all jamtrack migrations applied. The caller is responsible for calling
  11. // app.ResetBootstrapState() via t.Cleanup.
  12. func newTestApp(t *testing.T) core.App {
  13. t.Helper()
  14. app := core.NewBaseApp(core.BaseAppConfig{DataDir: t.TempDir()})
  15. if err := app.Bootstrap(); err != nil {
  16. t.Fatalf("Bootstrap: %v", err)
  17. }
  18. if err := app.RunAppMigrations(); err != nil {
  19. t.Fatalf("RunAppMigrations: %v", err)
  20. }
  21. t.Cleanup(func() { app.ResetBootstrapState() })
  22. return app
  23. }
  24. func mustSave(t *testing.T, app core.App, record *core.Record) {
  25. t.Helper()
  26. if err := app.Save(record); err != nil {
  27. t.Fatalf("Save %s: %v", record.Collection().Name, err)
  28. }
  29. }
  30. func newRecord(t *testing.T, app core.App, collection string) *core.Record {
  31. t.Helper()
  32. col, err := app.FindCollectionByNameOrId(collection)
  33. if err != nil {
  34. t.Fatalf("FindCollection %q: %v", collection, err)
  35. }
  36. return core.NewRecord(col)
  37. }
  38. func TestFetchRanking(t *testing.T) {
  39. app := newTestApp(t)
  40. // Seed: one location
  41. loc := newRecord(t, app, "locations")
  42. loc.Set("name", "The Rusty String")
  43. mustSave(t, app, loc)
  44. // Seed: three songs
  45. songs := []struct{ artist, title string }{
  46. {"Tom Petty", "Learning to Fly"},
  47. {"Pink Floyd", "Learning to Fly"},
  48. {"Eagles", "Hotel California"},
  49. }
  50. songRecords := make([]*core.Record, len(songs))
  51. for i, s := range songs {
  52. r := newRecord(t, app, "songs")
  53. r.Set("artist", s.artist)
  54. r.Set("title", s.title)
  55. mustSave(t, app, r)
  56. songRecords[i] = r
  57. }
  58. // Seed: two jams
  59. newJam := func(date string) *core.Record {
  60. j := newRecord(t, app, "jams")
  61. j.Set("date", date)
  62. j.Set("location", loc.Id)
  63. mustSave(t, app, j)
  64. return j
  65. }
  66. jam1 := newJam("2024-01-10")
  67. jam2 := newJam("2024-02-14")
  68. // Seed setlist entries.
  69. // jam1: Tom Petty played, Pink Floyd proposed, Eagles played
  70. // jam2: Tom Petty played, Eagles proposed
  71. entries := []struct {
  72. jam *core.Record
  73. song *core.Record
  74. played bool
  75. }{
  76. {jam1, songRecords[0], true}, // Tom Petty — played
  77. {jam1, songRecords[1], false}, // Pink Floyd — proposed only
  78. {jam1, songRecords[2], true}, // Eagles — played
  79. {jam2, songRecords[0], true}, // Tom Petty — played again
  80. {jam2, songRecords[2], false}, // Eagles — proposed only
  81. }
  82. for _, en := range entries {
  83. sl := newRecord(t, app, "setlist")
  84. sl.Set("jam", en.jam.Id)
  85. sl.Set("song", en.song.Id)
  86. sl.Set("played", en.played)
  87. mustSave(t, app, sl)
  88. }
  89. t.Run("global ranking", func(t *testing.T) {
  90. ranks, err := query.FetchRanking(app, "")
  91. if err != nil {
  92. t.Fatalf("FetchRanking: %v", err)
  93. }
  94. if len(ranks) != 3 {
  95. t.Fatalf("want 3 rows, got %d", len(ranks))
  96. }
  97. // Tom Petty: played=2, proposed=2 → first
  98. if ranks[0].Artist != "Tom Petty" || ranks[0].PlayedCount != 2 || ranks[0].ProposedCount != 2 {
  99. t.Errorf("rank[0] = %+v, want Tom Petty played=2 proposed=2", ranks[0])
  100. }
  101. // Eagles: played=1, proposed=2 → second
  102. if ranks[1].Artist != "Eagles" || ranks[1].PlayedCount != 1 || ranks[1].ProposedCount != 2 {
  103. t.Errorf("rank[1] = %+v, want Eagles played=1 proposed=2", ranks[1])
  104. }
  105. // Pink Floyd: played=0, proposed=1 → last
  106. if ranks[2].Artist != "Pink Floyd" || ranks[2].PlayedCount != 0 || ranks[2].ProposedCount != 1 {
  107. t.Errorf("rank[2] = %+v, want Pink Floyd played=0 proposed=1", ranks[2])
  108. }
  109. })
  110. t.Run("location filter", func(t *testing.T) {
  111. // With location filter the results should be the same (all entries
  112. // are at the same location), so just check the count and top entry.
  113. ranks, err := query.FetchRanking(app, loc.Id)
  114. if err != nil {
  115. t.Fatalf("FetchRanking with location: %v", err)
  116. }
  117. if len(ranks) != 3 {
  118. t.Fatalf("want 3 rows, got %d", len(ranks))
  119. }
  120. if ranks[0].Artist != "Tom Petty" {
  121. t.Errorf("rank[0].Artist = %q, want Tom Petty", ranks[0].Artist)
  122. }
  123. })
  124. t.Run("unknown location returns empty", func(t *testing.T) {
  125. ranks, err := query.FetchRanking(app, "nonexistentid000")
  126. if err != nil {
  127. t.Fatalf("FetchRanking: %v", err)
  128. }
  129. if len(ranks) != 0 {
  130. t.Errorf("want 0 rows for unknown location, got %d", len(ranks))
  131. }
  132. })
  133. }
PANIC: session(release): write data/sessions/8/6/86c7128f88e85b0f: no space left on device

PANIC

session(release): write data/sessions/8/6/86c7128f88e85b0f: no space left on device
/my/cache/.heroku/go/go-path/pkg/mod/github.com/go-macaron/session@v1.0.3/session.go:204 (0xb13e07)
/my/cache/.heroku/go/go-path/pkg/mod/gopkg.in/macaron.v1@v1.5.1/context.go:80 (0x967b75)
/my/cache/.heroku/go/go-path/pkg/mod/github.com/go-macaron/inject@v0.0.0-20200308113650-138e5925c53b/inject.go:157 (0x9512ee)
/my/cache/.heroku/go/go-path/pkg/mod/github.com/go-macaron/inject@v0.0.0-20200308113650-138e5925c53b/inject.go:135 (0x951205)
/my/cache/.heroku/go/go-path/pkg/mod/gopkg.in/macaron.v1@v1.5.1/context.go:124 (0x967cc4)
/my/cache/.heroku/go/go-path/pkg/mod/gopkg.in/macaron.v1@v1.5.1/context.go:114 (0x967bf6)
/my/cache/.heroku/go/go-path/pkg/mod/gopkg.in/macaron.v1@v1.5.1/recovery.go:161 (0x15baec4)
/my/cache/.heroku/go/go-path/pkg/mod/gopkg.in/macaron.v1@v1.5.1/logger.go:40 (0x96b257)
/my/cache/.heroku/go/go-path/pkg/mod/github.com/go-macaron/inject@v0.0.0-20200308113650-138e5925c53b/inject.go:157 (0x9512ee)
/my/cache/.heroku/go/go-path/pkg/mod/github.com/go-macaron/inject@v0.0.0-20200308113650-138e5925c53b/inject.go:135 (0x951205)
/my/cache/.heroku/go/go-path/pkg/mod/gopkg.in/macaron.v1@v1.5.1/context.go:124 (0x967cc4)
/my/cache/.heroku/go/go-path/pkg/mod/gopkg.in/macaron.v1@v1.5.1/router.go:187 (0x972959)
/my/cache/.heroku/go/go-path/pkg/mod/gopkg.in/macaron.v1@v1.5.1/router.go:304 (0x973a01)
/my/cache/.heroku/go/go-path/pkg/mod/gopkg.in/macaron.v1@v1.5.1/macaron.go:218 (0x96c572)
/my/cache/.heroku/go/go1.26.3/go/src/net/http/server.go:3311 (0x85a5cd)
/my/cache/.heroku/go/go1.26.3/go/src/net/http/server.go:2073 (0x837f6f)
/my/cache/.heroku/go/go1.26.3/go/src/runtime/asm_amd64.s:1771 (0x493380)