Files
djk/internal/app/ui_account_browser_test.go
T

131 lines
4.3 KiB
Go

package app
import (
"bytes"
"encoding/json"
"errors"
"net/http"
"net/http/httptest"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"sync"
"testing"
"time"
)
func TestAccountBrowserFixture(t *testing.T) {
root := os.Getenv("JUKU_ACCOUNT_BROWSER_ROOT")
if root == "" {
t.Skip("browser fixture is opt-in")
}
media, err := os.ReadFile(os.Getenv("JUKU_ACCOUNT_BROWSER_MEDIA"))
if err != nil {
t.Fatal(err)
}
ffmpeg, err := exec.LookPath("ffmpeg")
if err != nil {
t.Fatal(err)
}
mediaServer := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
if request.URL.Path != "/synthetic.mp4" {
t.Error("fixture attempted an unrelated media request", request.URL.Path)
http.NotFound(writer, request)
return
}
http.ServeContent(writer, request, "synthetic.mp4", time.Time{}, bytes.NewReader(media))
}))
defer mediaServer.Close()
app := viewerTestApp(t)
t.Cleanup(app.embySyncer().stop)
app.loadedAt = time.Now()
app.tasks = map[string]*UITask{}
app.cond = sync.NewCond(&app.mu)
app.statePath = filepath.Join(app.cfg.dataDirectory(), "ui-state.json")
app.downloader.cfg.FFmpeg = ffmpeg
app.cfg.FFmpeg = ffmpeg
app.downloader.ffmpegInstaller = &ffmpegInstaller{state: ffmpegInstallState{Status: "ready", Path: ffmpeg}}
transport := mediaServer.Client().Transport
app.downloader.client = &http.Client{Transport: rankingTransport(func(request *http.Request) (*http.Response, error) {
if !strings.HasPrefix(request.URL.String(), mediaServer.URL+"/") {
t.Error("browser fixture attempted an external request", request.URL.Host)
return nil, errors.New("external requests forbidden")
}
return transport.RoundTrip(request)
})}
app.cfg.adminUsername, app.cfg.adminPassword, app.cfg.adminPasswordExplicit = "admin", accountFixturePassword, true
adminPassword := accountFixturePassword
if os.Getenv("JUKU_ACCOUNT_BROWSER_RANDOM_ADMIN") == "1" {
app.cfg.adminPassword, app.cfg.adminPasswordExplicit = "", false
bootstrap, err := app.browserViewers().ensureAdministrator(app.cfg)
if err != nil {
t.Fatal(err)
}
adminPassword = bootstrap.InitialPassword
}
if err := app.prepareBrowserViewers(); err != nil {
t.Fatal(err)
}
client := app.downloader.hongguoClient()
entry := client.details["7000000000000000001"]
if os.Getenv("JUKU_ACCOUNT_BROWSER_MOBILE") == "1" {
entry.Chapters = nil
for index := 1; index <= 65; index++ {
entry.Chapters = append(entry.Chapters, Chapter{ID: providerChapterID(sourceHongguo, "7000000000000000001", strconv.Itoa(index)), Source: sourceHongguo, CurrentEpisode: rawEpisode(index)})
}
app.dramas[0].TotalEpisode = 65
app.dramas[0].ReleaseStatus = "finished"
}
for index := range entry.Chapters {
entry.Chapters[index].VideoURL = mediaServer.URL + "/synthetic.mp4"
}
client.details["7000000000000000001"] = entry
routes := app.routes()
var requestsMu sync.Mutex
var nativeRequests []map[string]string
server := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
switch request.URL.Path {
case "/api/ui/cover/repair":
writeJSON(writer, http.StatusOK, map[string]any{"dramaId": historyFixtureDramaID, "retryAfter": 300})
return
case "/api/ui/image":
t.Error("browser fixture must never request images")
http.NotFound(writer, request)
return
}
if strings.HasPrefix(request.URL.Path, "/api/ui/playback/hls/") {
account, _, _, _ := app.browserViewers().requestAccount(request)
requestsMu.Lock()
nativeRequests = append(nativeRequests, map[string]string{"path": request.URL.Path, "account": account.Username})
requestsMu.Unlock()
}
routes.ServeHTTP(writer, request)
}))
defer func() {
server.Close()
requestsMu.Lock()
data, err := json.Marshal(nativeRequests)
requestsMu.Unlock()
if err == nil {
err = os.WriteFile(filepath.Join(root, "native-requests.json"), data, 0600)
}
if err != nil {
t.Error(err)
}
}()
ready, _ := json.Marshal(map[string]string{"url": server.URL, "adminPassword": adminPassword})
if err = os.WriteFile(filepath.Join(root, "ready.json"), ready, 0600); err != nil {
t.Fatal(err)
}
deadline := time.Now().Add(4 * time.Minute)
for time.Now().Before(deadline) {
if _, err := os.Stat(filepath.Join(root, "stop")); err == nil {
return
}
time.Sleep(100 * time.Millisecond)
}
t.Fatal("browser fixture timed out")
}