Initial sanitized code sync
This commit is contained in:
168
internal/service/export_test.go
Normal file
168
internal/service/export_test.go
Normal file
@@ -0,0 +1,168 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gpt-plus/internal/db"
|
||||
|
||||
"github.com/glebarez/sqlite"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
)
|
||||
|
||||
func setupExportTestDB(t *testing.T) *gorm.DB {
|
||||
t.Helper()
|
||||
d, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{
|
||||
Logger: logger.Default.LogMode(logger.Silent),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("open db: %v", err)
|
||||
}
|
||||
d.AutoMigrate(&db.Account{})
|
||||
return d
|
||||
}
|
||||
|
||||
func TestExportSinglePlusAccount(t *testing.T) {
|
||||
d := setupExportTestDB(t)
|
||||
d.Create(&db.Account{
|
||||
Email: "plus@test.com", Plan: "plus", Status: "active",
|
||||
AccessToken: "at-123", RefreshToken: "rt-456", IDToken: "id-789",
|
||||
AccountID: "acc-001",
|
||||
})
|
||||
|
||||
data, filename, err := ExportAccounts(d, []uint{1}, "")
|
||||
if err != nil {
|
||||
t.Fatalf("export: %v", err)
|
||||
}
|
||||
if !strings.HasSuffix(filename, ".auth.json") {
|
||||
t.Fatalf("filename = %q, want *.auth.json", filename)
|
||||
}
|
||||
|
||||
var auth authFile
|
||||
if err := json.Unmarshal(data, &auth); err != nil {
|
||||
t.Fatalf("unmarshal: %v", err)
|
||||
}
|
||||
if auth.AccessToken != "at-123" {
|
||||
t.Fatalf("access_token = %q", auth.AccessToken)
|
||||
}
|
||||
if auth.Tokens.AccountID != "acc-001" {
|
||||
t.Fatalf("tokens.account_id = %q", auth.Tokens.AccountID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExportTeamWithSubAccounts(t *testing.T) {
|
||||
d := setupExportTestDB(t)
|
||||
owner := db.Account{
|
||||
Email: "owner@test.com", Plan: "team_owner", Status: "active",
|
||||
AccessToken: "owner-at", RefreshToken: "owner-rt",
|
||||
AccountID: "team-acc", TeamWorkspaceID: "ws-123", WorkspaceToken: "ws-tok",
|
||||
}
|
||||
d.Create(&owner)
|
||||
d.Create(&db.Account{
|
||||
Email: "member@test.com", Plan: "team_member", Status: "active",
|
||||
ParentID: &owner.ID, AccessToken: "mem-at", RefreshToken: "mem-rt",
|
||||
})
|
||||
|
||||
data, filename, err := ExportAccounts(d, []uint{owner.ID}, "test")
|
||||
if err != nil {
|
||||
t.Fatalf("export: %v", err)
|
||||
}
|
||||
if !strings.HasSuffix(filename, ".zip") {
|
||||
t.Fatalf("filename = %q, want *.zip", filename)
|
||||
}
|
||||
|
||||
r, err := zip.NewReader(bytes.NewReader(data), int64(len(data)))
|
||||
if err != nil {
|
||||
t.Fatalf("open zip: %v", err)
|
||||
}
|
||||
if len(r.File) != 2 {
|
||||
t.Fatalf("zip has %d files, want 2", len(r.File))
|
||||
}
|
||||
|
||||
names := make(map[string]bool)
|
||||
for _, f := range r.File {
|
||||
names[f.Name] = true
|
||||
}
|
||||
if !names["owner@test.com.auth.json"] {
|
||||
t.Fatal("missing owner auth file")
|
||||
}
|
||||
if !names["member@test.com.auth.json"] {
|
||||
t.Fatal("missing member auth file")
|
||||
}
|
||||
}
|
||||
|
||||
func TestExportTeamOwnerUsesWorkspaceToken(t *testing.T) {
|
||||
d := setupExportTestDB(t)
|
||||
d.Create(&db.Account{
|
||||
Email: "team@test.com", Plan: "team_owner", Status: "active",
|
||||
AccessToken: "normal-at", WorkspaceToken: "ws-at",
|
||||
TeamWorkspaceID: "team-ws-id", AccountID: "personal-acc",
|
||||
})
|
||||
|
||||
data, _, err := ExportAccounts(d, []uint{1}, "")
|
||||
if err != nil {
|
||||
t.Fatalf("export: %v", err)
|
||||
}
|
||||
|
||||
var auth authFile
|
||||
json.Unmarshal(data, &auth)
|
||||
if auth.AccessToken != "ws-at" {
|
||||
t.Fatalf("should use workspace token, got %q", auth.AccessToken)
|
||||
}
|
||||
if auth.Tokens.AccountID != "team-ws-id" {
|
||||
t.Fatalf("should use team workspace ID, got %q", auth.Tokens.AccountID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExportMultiplePlusAccounts(t *testing.T) {
|
||||
d := setupExportTestDB(t)
|
||||
d.Create(&db.Account{Email: "a@test.com", Plan: "plus", AccessToken: "at-a"})
|
||||
d.Create(&db.Account{Email: "b@test.com", Plan: "plus", AccessToken: "at-b"})
|
||||
|
||||
data, filename, err := ExportAccounts(d, []uint{1, 2}, "batch")
|
||||
if err != nil {
|
||||
t.Fatalf("export: %v", err)
|
||||
}
|
||||
if !strings.HasSuffix(filename, ".zip") {
|
||||
t.Fatalf("filename = %q, want *.zip for multiple", filename)
|
||||
}
|
||||
if !strings.Contains(filename, "batch") {
|
||||
t.Fatalf("filename should contain note, got %q", filename)
|
||||
}
|
||||
|
||||
r, _ := zip.NewReader(bytes.NewReader(data), int64(len(data)))
|
||||
if len(r.File) != 2 {
|
||||
t.Fatalf("zip has %d files, want 2", len(r.File))
|
||||
}
|
||||
}
|
||||
|
||||
func TestExportNotFound(t *testing.T) {
|
||||
d := setupExportTestDB(t)
|
||||
|
||||
_, _, err := ExportAccounts(d, []uint{999}, "")
|
||||
if err == nil {
|
||||
t.Fatal("expected error for nonexistent account")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildAuthFileFallbacks(t *testing.T) {
|
||||
acct := &db.Account{
|
||||
Email: "basic@test.com", AccessToken: "at-1", RefreshToken: "rt-1",
|
||||
IDToken: "id-1", AccountID: "acc-1",
|
||||
}
|
||||
auth := buildAuthFile(acct)
|
||||
|
||||
if auth.AccessToken != "at-1" {
|
||||
t.Fatalf("access_token = %q", auth.AccessToken)
|
||||
}
|
||||
if auth.Tokens.AccountID != "acc-1" {
|
||||
t.Fatalf("tokens.account_id = %q", auth.Tokens.AccountID)
|
||||
}
|
||||
if auth.LastRefresh == "" {
|
||||
t.Fatal("last_refresh should be set")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user