package main import ( "fmt" "os" "path/filepath" "time" "kra/internal/service/dto" ) func setup() error { if f, err := readFixtures(); err == nil { fmt.Printf("Existing isolated fixtures retained: %s room=%d replay=%d\n", f.Database, f.RoomID, f.ReplayID) return nil } c := newClient() var status struct { NeedInit bool `json:"needInit"` } must(c.call("POST", "/init/checkdb", nil, &status)) databaseDir, err := filepath.Abs(outputDir) if err != nil { return err } if status.NeedInit { must(c.call("POST", "/init/initdb", dto.DatabaseInitRequest{ DBType: "sqlite", DBName: "acceptance.db", DBPath: databaseDir, AdminPassword: adminPassword, }, nil)) } db, err := openFixtureDB() if err != nil { return err } // This test-only fixture setting must be seeded before the first login. // Production configuration and security settings are never touched. must(db.Exec("UPDATE sys_security_config SET captcha_open = 1000 WHERE id = 1").Error) sqlDB, err := db.DB() if err != nil { return err } must(sqlDB.Close()) f := &fixtures{ BaseURL: baseURL, Database: filepath.Join(databaseDir, "acceptance.db"), CreatedAt: time.Now().Format(time.RFC3339), Admin: account{Username: "admin", Password: adminPassword, ID: 1}, } admin, err := login(f.Admin, true) if err != nil { return err } f.Checks = append(f.Checks, "isolated SQLite initialization API and administrator login") users := []*account{&f.Anchor, &f.Viewer, &f.Other} for index, username := range []string{"accept_anchor", "accept_viewer", "accept_other"} { var auth dto.LiveClientAuthResponse input := dto.LiveClientRegisterRequest{Username: username, Nickname: username, Password: userPassword, ConfirmPassword: userPassword} client := newClient() if err = client.call("POST", "/live/client/auth/register", input, &auth); err != nil { client, err = login(account{Username: username, Password: userPassword}, false) if err != nil { return fmt.Errorf("create fixture %s: %w", username, err) } var user dto.LiveClientAccountResponse must(client.call("GET", "/live/client/me", nil, &user)) auth.User = &user } check(auth.User != nil && auth.User.UserID != 0, "register %s returned no user", username) *users[index] = account{Username: username, Password: userPassword, ID: auth.User.UserID} } f.Checks = append(f.Checks, "PC anchor and two viewer registrations") var integration dto.IntegrationConfigResponse must(admin.call("GET", "/integration/configs/websocket/melody", nil, &integration)) must(admin.call("PUT", "/integration/configs/websocket/melody", dto.IntegrationConfigRequest{Enabled: true, Config: integration.Config}, nil)) f.Checks = append(f.Checks, "WebSocket integration enabled through administration API") var category dto.LiveCategoryResponse categoryInput := dto.LiveCategoryRequest{Name: "API Test", Icon: "video", Sort: 1, Enabled: true} must(admin.call("POST", "/live/admin/categories", categoryInput, &category)) f.CategoryID = category.ID categoryInput.Name = "API Live" must(admin.call("PUT", fmt.Sprintf("/live/admin/categories/%d", category.ID), categoryInput, &category)) f.Checks = append(f.Checks, "category creation and update through administration API") for _, room := range []struct { name string replay string enabled bool id *uint }{ {"Acceptance Live Room", "", true, &f.RoomID}, {"Acceptance Replay Room", "/uploads/acceptance-replay.webm", true, &f.ReplayID}, {"Acceptance Disabled Room", "", false, &f.DisabledID}, } { var value dto.LiveRoomResponse must(admin.call("POST", "/live/admin/rooms", makeRoom(room.name, f.CategoryID, f.Anchor.ID, room.replay, room.enabled), &value)) *room.id = value.ID } f.Checks = append(f.Checks, "live, recorded and disabled rooms created through administration API") var gift dto.GiftResponse must(admin.call("POST", "/live/admin/gifts", dto.GiftRequest{ Name: "API Star", Icon: "star", Description: "Local acceptance gift", Price: 7, Tiers: []int{1, 10}, Enabled: true, Sort: 1, }, &gift)) f.GiftID = gift.ID f.Checks = append(f.Checks, "configured gift created through administration API") must(admin.call("PUT", "/live/admin/recharge/plans", dto.RechargePlansRequest{Plans: []*dto.RechargePlan{ {ID: 1, Sort: 1, Diamonds: 60, AmountCents: 600, Enabled: true}, {ID: 2, Sort: 2, Diamonds: 300, AmountCents: 3000, Enabled: true}, {ID: 3, Sort: 3, Diamonds: 10, AmountCents: 100, Enabled: true}, }}, nil)) f.Checks = append(f.Checks, "recharge plans configured through administration API") must(os.MkdirAll(filepath.Join(outputDir, "uploads"), 0700)) cover, err := os.ReadFile("frontend/src/assets/images/tupian/cyber_streamer_1.jpg") if err != nil { return err } must(os.WriteFile(filepath.Join(outputDir, "uploads", "acceptance-cover.jpg"), cover, 0600)) must(saveJSON("fixtures.json", f)) fmt.Printf("API=%s database=%s\nanchor=%s viewer=%s other=%s password=%s\nroom=%d replay=%d disabled=%d category=%d gift=%d\n", baseURL, f.Database, f.Anchor.Username, f.Viewer.Username, f.Other.Username, userPassword, f.RoomID, f.ReplayID, f.DisabledID, f.CategoryID, f.GiftID) return nil } func setupBrowserRoom() error { f, err := readFixtures() if err != nil { return err } if f.BrowserID == 0 { admin, err := login(f.Admin, true) if err != nil { return err } var room dto.LiveRoomResponse must(admin.call("POST", "/live/admin/rooms", makeRoom("Acceptance Browser Room", f.CategoryID, f.Anchor.ID, "", true), &room)) f.BrowserID = room.ID must(saveJSON("fixtures.json", f)) } fmt.Printf("Dedicated browser publisher room=%d anchor=%s password=%s; API verification uses room=%d\n", f.BrowserID, f.Anchor.Username, f.Anchor.Password, f.RoomID) return nil }