main
py 227 lines 12.9 KB
Raw
1 from pathlib import Path
2
3
4 PROJECT_ROOT = Path(__file__).resolve().parents[1]
5
6
7 def test_oauth_settings_exposes_provider_cards_and_model_slots():
8 config_html = (PROJECT_ROOT / "plugins/_oauth/webui/config.html").read_text(encoding="utf-8")
9 store_js = (PROJECT_ROOT / "plugins/_oauth/webui/oauth-config-store.js").read_text(encoding="utf-8")
10
11 assert "providerCards" in config_html + store_js
12 assert "OAuth Connections" in config_html + store_js
13 assert "OAUTH_PROVIDERS" not in store_js
14 assert "PROVIDER_FALLBACKS" not in store_js
15 assert "Connected accounts" not in config_html
16 assert "Choose your models" in config_html
17 assert "Main model" in store_js
18 assert "Utility model" in store_js
19 assert "provider_map" in store_js
20 assert "<h3>Accounts</h3>" not in config_html
21 assert "oauth-plan-catalog" not in config_html
22 assert "oauth-model-provider-field" in config_html
23 assert "slotProviderChoices(slot.key)" in config_html
24 assert "<span>Provider</span>" not in config_html
25 assert ':aria-label="`${slot.title} provider`"' in config_html
26 assert "connectedProviderCards().length" in config_html
27 assert "useProviderForSlot(slot.key, $event.target.value)" in config_html
28 assert ":value=\"$store.oauthConfig.slotCanUseModels(slot.key) ? $store.oauthConfig.modelSlot(slot.key).provider : ''\"" in config_html
29 assert "slotCanUseModels(slot.key)" in config_html
30 assert "<span>Account</span>" not in config_html
31 assert "oauth-connected-panel" not in config_html
32 assert "oauth-provider-usage" in config_html
33 assert "usageWindows(card.provider_id)" in config_html
34 assert "connectedUsageWindows()" not in config_html
35 assert "Agent Zero models" not in config_html
36 assert "Usage plans" not in config_html
37 assert "usagePlanEntries" in store_js
38 assert "usage_plan_catalog" in (PROJECT_ROOT / "plugins/_oauth/helpers/summary.py").read_text(encoding="utf-8")
39 assert "copyMainToUtility" in config_html + store_js
40 assert "connectedSummaryLabel()" not in config_html
41
42
43 def test_oauth_settings_exposes_provider_specific_controls_and_generic_copy():
44 config_html = (PROJECT_ROOT / "plugins/_oauth/webui/config.html").read_text(encoding="utf-8")
45 store_js = (PROJECT_ROOT / "plugins/_oauth/webui/oauth-config-store.js").read_text(encoding="utf-8")
46
47 assert "Check models" not in config_html
48 assert "card.connected ? 'Connected' : 'Available'" not in config_html
49 assert '<span class="oauth-account-state connected" x-show="card.connected">Connected</span>' in config_html
50 assert "Select account-backed models used by the Main model and Utility model slots." not in config_html
51 assert "Primary model for chat, reasoning, and browser tasks." not in config_html + store_js
52 assert "Background model for summaries, memory, and prompt preparation." not in config_html + store_js
53 assert '@click="$store.oauthConfig.openModelDropdown(slot.key, $el)"' in config_html
54 assert "top: calc(100% + 4px);" in config_html
55 assert "enterprise_domain" in config_html + store_js
56 assert "manualCallback" in config_html + store_js
57 assert "Paste callback URL, query string, or code" in config_html + store_js
58 assert "supports_enterprise_domain" in config_html + store_js
59 assert "supports_manual_callback" in config_html + store_js
60 assert "supports_oauth_client_config" in config_html + store_js
61 assert "supports_quota_project" in config_html + store_js
62 assert "OAuth client ID" in config_html
63 assert "quota_project_id" in config_html + store_js
64 assert "Codex response defaults" in config_html
65 assert "$store.oauthConfig.codex().reasoning_effort" in config_html
66 assert "$store.oauthConfig.codex().reasoning_summary" in config_html
67 assert "$store.oauthConfig.codex().text_verbosity" in config_html
68 assert "providerDetailOpen(card.provider_id)" in config_html + store_js
69 assert "providerDevice(card.provider_id)?.user_code" in config_html
70 assert "submitManualCallback(card.provider_id)" in config_html
71 assert "cancelConnect(card.provider_id)" in config_html
72 assert "selectedProvider()" not in config_html
73 assert "oauth-auth-attempt" in config_html
74 assert "oauth-provider-row-detail" in config_html
75 assert "oauth-provider-detail" not in config_html
76 assert "oauth-detail-metrics" not in config_html
77 assert "Codex/ChatGPT Account" not in config_html + store_js
78 assert "activeModelsDescription()" in config_html + store_js
79 assert "activeProviderModels()" in config_html + store_js
80 assert "Available models from Codex account" not in config_html
81 assert "disconnectProvider(card.provider_id)" in config_html
82 assert "disconnectProvider($store.oauthConfig.selectedProviderId)" not in config_html
83 assert "color: #35d07f;" not in config_html
84 assert ".oauth .oauth-provider-row.connected .oauth-provider-row-copy span" in config_html
85 assert ".oauth .oauth-provider-row.connected .oauth-usage-head strong" in config_html
86 assert ".oauth .oauth-provider-row.connected .oauth-usage-window p" in config_html
87 assert "var(--color-text-secondary, rgba(255, 255, 255, .72))" in config_html
88
89
90 def test_oauth_connect_buttons_disable_during_any_provider_connection():
91 config_html = (PROJECT_ROOT / "plugins/_oauth/webui/config.html").read_text(encoding="utf-8")
92 store_js = (PROJECT_ROOT / "plugins/_oauth/webui/oauth-config-store.js").read_text(encoding="utf-8")
93
94 assert "providerPrimaryDisabled" in config_html + store_js
95 assert "this.connectingProvider || this.disconnectingProvider" in store_js
96 assert ':disabled="Boolean($store.oauthConfig.connectingProvider) || $store.oauthConfig.disconnectingProvider"' not in config_html
97 assert "cancelConnect(providerId = \"\")" in store_js
98 assert "if (this.connectingProvider === providerId) this.connectingProvider = \"\";" in store_js
99
100
101 def test_oauth_available_models_list_sits_above_advanced_without_borders():
102 config_html = (PROJECT_ROOT / "plugins/_oauth/webui/config.html").read_text(encoding="utf-8")
103
104 assert "activeModelsDescription()" in config_html
105 assert config_html.index("<h3>Providers</h3>") < config_html.index("Choose your models")
106 assert config_html.index("<h3>Providers</h3>") < config_html.index("<summary>Advanced</summary>")
107 assert config_html.index("Available models") < config_html.index("<summary>Advanced</summary>")
108 assert ".oauth-models-panel {\n display: grid;\n gap: 10px;\n padding: 0;\n border: 0;\n }" in config_html
109 assert ".oauth-provider-list {\n display: grid;\n gap: 12px;\n padding: 0;\n border: 0;" in config_html
110 assert ".oauth-provider-row-detail {\n display: grid;\n grid-column: 1 / -1;" in config_html
111 assert ".oauth-advanced {\n border: 0;\n border-radius: 0;\n padding: 0;\n }" in config_html
112 model_chip_rule = config_html.split(".oauth-models span {", 1)[1].split("}", 1)[0]
113 assert "border:" not in model_chip_rule
114
115
116 def test_oauth_model_slots_reuse_model_config_api():
117 store_js = (PROJECT_ROOT / "plugins/_oauth/webui/oauth-config-store.js").read_text(encoding="utf-8")
118
119 assert 'import { store as modelConfigStore } from "/plugins/_model_config/webui/model-config-store.js";' in store_js
120 assert 'const MODEL_CONFIG_API = "/plugins/_model_config";' in store_js
121 assert "model_config_get" in store_js
122 assert "model_config_set" in store_js
123 assert "isOauthProvider" in store_js
124 assert "providerCards()" in store_js
125 assert "saveModelConfigIfDirty" in store_js
126 assert "slotProviderChoices()" in store_js
127 assert "modelProviderOptionLabel(provider)" in store_js
128 assert "return this.connectedProviderCards();" in store_js
129 assert "if (!this.providerConnected(providerId)) return;" in store_js
130 assert "const providerId = slot.provider;" in store_js
131 assert "const providerId = this.isOauthProvider(this.activeModelProvider)" not in store_js
132 assert "applySoleConnectedProviderDefaults" in store_js
133 assert "this.applySoleConnectedProviderDefaults();" in store_js
134 assert "if (providers.length !== 1 || !this.modelConfig) return;" in store_js
135 assert "if (model.provider && model.provider !== providerId) continue;" in store_js
136 assert "model.name = \"\";" in store_js
137 assert "this.modelSlotCurrentProviders[key] ?? slot.provider" in store_js
138 assert "currentChatModelConfigured" not in store_js
139 assert "providerDefaultModel" not in store_js
140 assert 'new CustomEvent("model-setup-changed"' in store_js
141 assert 'detail: { source: "_oauth", providerId }' in store_js
142 assert "await this.handleProviderConnected(providerId)" in store_js
143
144
145 def test_browser_callback_completion_is_observed_from_modal():
146 store_js = (PROJECT_ROOT / "plugins/_oauth/webui/oauth-config-store.js").read_text(encoding="utf-8")
147
148 assert "startCallbackPolling(providerId)" in store_js
149 assert "stopCallbackPolling(providerId)" in store_js
150 assert "this.providerConnected(providerId)" in store_js
151 assert "await this.handleProviderConnected(providerId, { statusLoaded: true })" in store_js
152
153
154 def test_device_polling_honors_provider_interval_updates():
155 store_js = (PROJECT_ROOT / "plugins/_oauth/webui/oauth-config-store.js").read_text(encoding="utf-8")
156
157 start_polling = store_js.split("startPolling(providerId = CODEX_PROVIDER)", 1)[1].split(
158 "pollProvider(providerId = CODEX_PROVIDER)",
159 1,
160 )[0]
161 assert "window.setTimeout(tick, delayMs)" in start_polling
162 assert "window.setInterval(tick" not in start_polling
163 assert "void tick();" not in start_polling
164 assert "interval: response.interval || device.interval" in start_polling
165 assert "expires_at: response.expires_at || device.expires_at" in start_polling
166 assert "Date.now() / 1000 > expiresAt" in start_polling
167
168
169 def test_usage_plan_catalog_stays_backend_only_on_oauth_settings_page():
170 config_html = (PROJECT_ROOT / "plugins/_oauth/webui/config.html").read_text(encoding="utf-8")
171 store_js = (PROJECT_ROOT / "plugins/_oauth/webui/oauth-config-store.js").read_text(encoding="utf-8")
172 plans_py = (PROJECT_ROOT / "plugins/_oauth/helpers/usage_plans.py").read_text(encoding="utf-8")
173
174 assert "oauth-plan-catalog" not in config_html
175 assert "usagePlanEntries" in store_js
176 assert "Google Cloud Gemini" in plans_py
177 assert "Google Cloud project" in plans_py
178 assert "GEMINI_API_PROVIDER_ID" in plans_py
179 assert "Google Gemini / Antigravity" not in plans_py
180 assert "Claude Code" not in plans_py
181 assert "antigravity_subscription_oauth" not in plans_py
182 assert "claude_code_oauth" not in plans_py
183
184
185 def test_oauth_model_wrappers_do_not_add_box_borders_or_lateral_padding():
186 config_html = (PROJECT_ROOT / "plugins/_oauth/webui/config.html").read_text(encoding="utf-8")
187
188 assert ".oauth-model-config {\n display: grid;\n gap: 12px;\n padding: 0;\n border: 0;\n }" in config_html
189 assert ".oauth-model-card {\n display: grid;" in config_html
190 assert " padding: 0;\n border: 0;\n background: transparent;" in config_html
191 assert "oauth-model-card.is-codex" not in config_html
192 assert "'is-codex'" not in config_html
193
194
195 def test_oauth_discovery_card_renders_in_welcome_account_panel():
196 discovery_cards = (
197 PROJECT_ROOT
198 / "plugins/_discovery/extensions/python/banners/10_discovery_cards.py"
199 ).read_text(encoding="utf-8")
200 welcome_cards = (
201 PROJECT_ROOT
202 / "plugins/_discovery/extensions/webui/welcome-actions-end/discovery-cards.html"
203 ).read_text(encoding="utf-8")
204 discovery_store = (PROJECT_ROOT / "plugins/_discovery/webui/discovery-store.js").read_text(encoding="utf-8")
205
206 assert "discovery-oauth-accounts" in discovery_cards
207 assert "Your AI accounts" in discovery_cards
208 assert "Use your subscription-backed logins for model access." in discovery_cards
209 assert "Link account-backed providers such as" not in discovery_cards
210 assert "Connected OAuth accounts" not in discovery_cards
211 assert "discovery-codex-oauth" not in discovery_cards
212 assert "5h and weekly limits are ready." not in discovery_cards
213 assert "account providers connected and ready for model selection" not in discovery_cards
214 assert '"icon": "account_circle"' not in discovery_cards
215 assert "usage_windows" in discovery_cards
216 assert "account_chips" in discovery_cards
217 assert "discovery-account-card" in welcome_cards
218 assert "discovery-account-chip" in welcome_cards
219 assert "discovery-account-icon" not in welcome_cards
220 assert ".discovery-account-chip {\n display: inline-grid;" in welcome_cards
221 assert " border-radius: 8px;" in welcome_cards
222 assert "discovery-account-usage" in welcome_cards
223 assert "formatRemainingPercent(window)" in welcome_cards
224 assert "formatRemainingPercent(window)" in discovery_store
225 assert "usageWidth(window)" in discovery_store
226 assert "oauthAccountCards" in discovery_store
227 assert 'card.id === "discovery-oauth-accounts"' in discovery_store