//go:build unit package repository import ( "testing" "github.com/Wei-Shaw/sub2api/internal/service" "github.com/stretchr/testify/require" ) func TestBuildSchedulerMetadataAccount_KeepsOpenAIWSFlags(t *testing.T) { account := service.Account{ ID: 42, Platform: service.PlatformOpenAI, Type: service.AccountTypeOAuth, Extra: map[string]any{ "openai_oauth_responses_websockets_v2_enabled": true, "openai_oauth_responses_websockets_v2_mode": service.OpenAIWSIngressModePassthrough, "openai_ws_force_http": true, "openai_responses_mode": "force_chat_completions", "openai_responses_supported": false, "mixed_scheduling": true, "unused_large_field": "drop-me", }, } got := buildSchedulerMetadataAccount(account) require.Equal(t, true, got.Extra["openai_oauth_responses_websockets_v2_enabled"]) require.Equal(t, service.OpenAIWSIngressModePassthrough, got.Extra["openai_oauth_responses_websockets_v2_mode"]) require.Equal(t, true, got.Extra["openai_ws_force_http"]) require.Equal(t, "force_chat_completions", got.Extra["openai_responses_mode"]) require.Equal(t, false, got.Extra["openai_responses_supported"]) require.Equal(t, true, got.Extra["mixed_scheduling"]) require.Nil(t, got.Extra["unused_large_field"]) } func TestBuildSchedulerMetadataAccount_KeepsSlimGroupMembership(t *testing.T) { account := service.Account{ ID: 42, Platform: service.PlatformAnthropic, GroupIDs: []int64{7, 9, 7, 0}, AccountGroups: []service.AccountGroup{ { AccountID: 42, GroupID: 7, Priority: 2, Account: &service.Account{ID: 42, Name: "drop-from-metadata"}, Group: &service.Group{ID: 7, Name: "drop-from-metadata"}, }, { AccountID: 42, GroupID: 11, Priority: 3, Group: &service.Group{ID: 11, Name: "drop-from-metadata"}, }, { AccountID: 42, GroupID: 0, Priority: 4, }, }, } got := buildSchedulerMetadataAccount(account) require.Equal(t, []int64{7, 9, 11}, got.GroupIDs) require.Len(t, got.AccountGroups, 2) require.Equal(t, int64(42), got.AccountGroups[0].AccountID) require.Equal(t, int64(7), got.AccountGroups[0].GroupID) require.Equal(t, 2, got.AccountGroups[0].Priority) require.Nil(t, got.AccountGroups[0].Account) require.Nil(t, got.AccountGroups[0].Group) require.Equal(t, int64(11), got.AccountGroups[1].GroupID) require.Nil(t, got.Groups) } func TestBuildSchedulerMetadataAccount_KeepsQuotaAutoPauseFields(t *testing.T) { account := service.Account{ ID: 88, Extra: map[string]any{ "codex_5h_used_percent": 12.34, "codex_7d_used_percent": 56.78, "codex_5h_reset_at": "2026-05-29T10:00:00Z", "codex_7d_reset_at": "2026-06-01T10:00:00Z", "codex_5h_reset_after_seconds": 300, "codex_7d_reset_after_seconds": 600, "codex_usage_updated_at": "2026-05-29T09:00:00Z", "auto_pause_5h_threshold": 0.95, "auto_pause_7d_threshold": 0.96, "auto_pause_5h_disabled": true, "auto_pause_7d_disabled": false, }, } got := buildSchedulerMetadataAccount(account) require.Equal(t, 12.34, got.Extra["codex_5h_used_percent"]) require.Equal(t, 56.78, got.Extra["codex_7d_used_percent"]) require.Equal(t, "2026-05-29T10:00:00Z", got.Extra["codex_5h_reset_at"]) require.Equal(t, "2026-06-01T10:00:00Z", got.Extra["codex_7d_reset_at"]) require.Equal(t, 300, got.Extra["codex_5h_reset_after_seconds"]) require.Equal(t, 600, got.Extra["codex_7d_reset_after_seconds"]) require.Equal(t, "2026-05-29T09:00:00Z", got.Extra["codex_usage_updated_at"]) require.Equal(t, 0.95, got.Extra["auto_pause_5h_threshold"]) require.Equal(t, 0.96, got.Extra["auto_pause_7d_threshold"]) require.Equal(t, true, got.Extra["auto_pause_5h_disabled"]) require.Equal(t, false, got.Extra["auto_pause_7d_disabled"]) } func TestBuildSchedulerMetadataAccount_KeepsModelRateLimits(t *testing.T) { account := service.Account{ ID: 90, Platform: service.PlatformAntigravity, Extra: map[string]any{ "model_rate_limits": map[string]any{ "gemini-3-flash": map[string]any{ "rate_limit_reset_at": "2026-05-30T10:10:00Z", }, "antigravity:gemini": map[string]any{ "rate_limit_reset_at": "2026-05-30T10:10:00Z", }, }, "unused_large_field": "drop-me", }, } got := buildSchedulerMetadataAccount(account) limits, ok := got.Extra["model_rate_limits"].(map[string]any) require.True(t, ok) require.Contains(t, limits, "gemini-3-flash") require.Contains(t, limits, "antigravity:gemini") require.Nil(t, got.Extra["unused_large_field"]) } func TestBuildSchedulerMetadataAccount_KeepsSparkShadowRoutingIdentity(t *testing.T) { parentID := int64(100) account := service.Account{ ID: 200, Platform: service.PlatformOpenAI, Type: service.AccountTypeOAuth, ParentAccountID: &parentID, QuotaDimension: service.QuotaDimensionSpark, Credentials: map[string]any{ "model_mapping": map[string]any{ "gpt-5.3-codex-spark": "gpt-5.3-codex-spark", }, "compact_model_mapping": map[string]any{ "gpt-5.4": "gpt-5.4-openai-compact", }, "access_token": "drop-me", }, } got := buildSchedulerMetadataAccount(account) require.NotNil(t, got.ParentAccountID) require.Equal(t, parentID, *got.ParentAccountID) require.Equal(t, service.QuotaDimensionSpark, got.QuotaDimension) require.Equal(t, map[string]any{"gpt-5.3-codex-spark": "gpt-5.3-codex-spark"}, got.Credentials["model_mapping"]) require.Equal(t, map[string]any{"gpt-5.4": "gpt-5.4-openai-compact"}, got.Credentials["compact_model_mapping"]) require.Nil(t, got.Credentials["access_token"]) }