From 69e5851278dc6ab9aa8c48972c5c7e1eb47c32e5 Mon Sep 17 00:00:00 2001 From: gubin-dev Date: Wed, 29 Jul 2026 00:10:00 +0300 Subject: [PATCH 1/6] feat(webview): add OpenAI Codex speed selector --- .../settings/providers/OpenAICodex.tsx | 47 ++++++++- .../providers/__tests__/OpenAICodex.spec.tsx | 97 +++++++++++++++++++ webview-ui/src/i18n/locales/ca/settings.json | 6 ++ webview-ui/src/i18n/locales/de/settings.json | 6 ++ webview-ui/src/i18n/locales/en/settings.json | 6 ++ webview-ui/src/i18n/locales/es/settings.json | 6 ++ webview-ui/src/i18n/locales/fr/settings.json | 6 ++ webview-ui/src/i18n/locales/hi/settings.json | 6 ++ webview-ui/src/i18n/locales/id/settings.json | 6 ++ webview-ui/src/i18n/locales/it/settings.json | 6 ++ webview-ui/src/i18n/locales/ja/settings.json | 6 ++ webview-ui/src/i18n/locales/ko/settings.json | 6 ++ webview-ui/src/i18n/locales/nl/settings.json | 6 ++ webview-ui/src/i18n/locales/pl/settings.json | 6 ++ .../src/i18n/locales/pt-BR/settings.json | 6 ++ webview-ui/src/i18n/locales/ru/settings.json | 6 ++ webview-ui/src/i18n/locales/tr/settings.json | 6 ++ webview-ui/src/i18n/locales/vi/settings.json | 6 ++ .../src/i18n/locales/zh-CN/settings.json | 6 ++ .../src/i18n/locales/zh-TW/settings.json | 6 ++ 20 files changed, 250 insertions(+), 2 deletions(-) create mode 100644 webview-ui/src/components/settings/providers/__tests__/OpenAICodex.spec.tsx diff --git a/webview-ui/src/components/settings/providers/OpenAICodex.tsx b/webview-ui/src/components/settings/providers/OpenAICodex.tsx index 755b272702..443335a79c 100644 --- a/webview-ui/src/components/settings/providers/OpenAICodex.tsx +++ b/webview-ui/src/components/settings/providers/OpenAICodex.tsx @@ -1,9 +1,23 @@ import React from "react" -import { type ProviderSettings, openAiCodexDefaultModelId, openAiCodexModels } from "@roo-code/types" +import { + OPEN_AI_CODEX_SERVICE_TIER_KEY, + OpenAiCodexServiceTier, + type ProviderSettings, + openAiCodexDefaultModelId, + openAiCodexModels, +} from "@roo-code/types" import { useAppTranslation } from "@src/i18n/TranslationContext" -import { Button } from "@src/components/ui" +import { + Button, + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, + StandardTooltip, +} from "@src/components/ui" import { vscode } from "@src/utils/vscode" import { ModelPicker } from "../ModelPicker" @@ -66,6 +80,35 @@ export const OpenAICodex: React.FC = ({ simplifySettings={simplifySettings} hidePricing /> + +
+
+ + + + +
+ +
) } diff --git a/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.spec.tsx b/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.spec.tsx new file mode 100644 index 0000000000..d73120ada3 --- /dev/null +++ b/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.spec.tsx @@ -0,0 +1,97 @@ +import React from "react" + +import { + OPEN_AI_CODEX_SERVICE_TIER_KEY, + OpenAiCodexServiceTier, + providerIdentifiers, + type ProviderSettings, +} from "@roo-code/types" + +import { fireEvent, render, screen } from "@/utils/test-utils" +import { vscode } from "@src/utils/vscode" + +import { OpenAICodex } from "../OpenAICodex" + +vi.mock("@src/i18n/TranslationContext", () => ({ + useAppTranslation: () => ({ + t: (key: string) => + ({ + "settings:openAiCodexSpeed.label": "Speed", + "settings:openAiCodexSpeed.tooltip": + "Fast uses Codex priority processing for about 1.5x speed and consumes more subscription quota.", + "settings:openAiCodexSpeed.standard": "Standard", + "settings:openAiCodexSpeed.fast": "Fast (1.5x speed, increased usage)", + })[key] ?? key, + }), +})) + +vi.mock("@src/components/ui", () => ({ + Button: ({ children, ...props }: React.ButtonHTMLAttributes) => ( + + ), + Select: ({ children, value, onValueChange }: any) => ( + + ), + SelectContent: ({ children }: any) => <>{children}, + SelectItem: ({ children, value }: any) => , + SelectTrigger: ({ children }: any) => <>{children}, + SelectValue: () => null, + StandardTooltip: ({ children, content }: any) => {children}, +})) + +vi.mock("../../ModelPicker", () => ({ + ModelPicker: () =>
, +})) + +vi.mock("../OpenAICodexRateLimitDashboard", () => ({ + OpenAICodexRateLimitDashboard: () => null, +})) + +vi.mock("@src/utils/vscode", () => ({ + vscode: { postMessage: vi.fn() }, +})) + +describe("OpenAICodex speed selector", () => { + const renderSelector = (apiConfiguration: ProviderSettings, setApiConfigurationField = vi.fn()) => { + render() + return { setApiConfigurationField, selector: screen.getByRole("combobox", { name: "Speed" }) } + } + + it("defaults to Standard and clearly explains the Fast quota trade-off", () => { + const { selector } = renderSelector({ apiProvider: providerIdentifiers.openaiCodex }) + + expect(selector).toHaveValue(OpenAiCodexServiceTier.Default) + expect(screen.getByRole("option", { name: "Standard" })).toBeInTheDocument() + expect(screen.getByRole("option", { name: "Fast (1.5x speed, increased usage)" })).toBeInTheDocument() + expect( + screen.getByTitle( + "Fast uses Codex priority processing for about 1.5x speed and consumes more subscription quota.", + ), + ).toBeInTheDocument() + }) + + it("selects Fast from a saved preference and persists changes through the settings callback", () => { + const { selector, setApiConfigurationField } = renderSelector({ + apiProvider: providerIdentifiers.openaiCodex, + [OPEN_AI_CODEX_SERVICE_TIER_KEY]: OpenAiCodexServiceTier.Priority, + }) + const postMessage = vi.mocked(vscode.postMessage) + + expect(selector).toHaveValue(OpenAiCodexServiceTier.Priority) + + fireEvent.change(selector, { target: { value: OpenAiCodexServiceTier.Default } }) + expect(setApiConfigurationField).toHaveBeenLastCalledWith( + OPEN_AI_CODEX_SERVICE_TIER_KEY, + OpenAiCodexServiceTier.Default, + ) + + fireEvent.change(selector, { target: { value: OpenAiCodexServiceTier.Priority } }) + expect(setApiConfigurationField).toHaveBeenLastCalledWith( + OPEN_AI_CODEX_SERVICE_TIER_KEY, + OpenAiCodexServiceTier.Priority, + ) + expect(postMessage).not.toHaveBeenCalled() + }) +}) diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index b9644e0d12..7c0454f55c 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -1046,6 +1046,12 @@ "limitMaxTokensDescription": "Limitar el nombre màxim de tokens en la resposta", "maxOutputTokensLabel": "Tokens màxims de sortida", "maxTokensGenerateDescription": "Tokens màxims a generar en la resposta", + "openAiCodexSpeed": { + "label": "Velocitat", + "tooltip": "El mode ràpid utilitza el processament prioritari de Codex per oferir aproximadament 1,5 vegades més velocitat i consumeix més quota de subscripció.", + "standard": "Estàndard", + "fast": "Ràpid (1,5 vegades més velocitat, més consum)" + }, "serviceTier": { "label": "Nivell de servei", "tooltip": "Per a un processament més ràpid de les sol·licituds de l'API, proveu el nivell de servei de processament prioritari. Per a preus més baixos amb una latència més alta, proveu el nivell de processament flexible.", diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index 46a8bd28e4..504bb56cba 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -1046,6 +1046,12 @@ "limitMaxTokensDescription": "Begrenze die maximale Anzahl von Tokens in der Antwort", "maxOutputTokensLabel": "Maximale Ausgabe-Tokens", "maxTokensGenerateDescription": "Maximale Tokens, die in der Antwort generiert werden", + "openAiCodexSpeed": { + "label": "Geschwindigkeit", + "tooltip": "Der schnelle Modus nutzt die priorisierte Codex-Verarbeitung für etwa 1,5-fache Geschwindigkeit und verbraucht mehr von deinem Abonnementkontingent.", + "standard": "Standard", + "fast": "Schnell (1,5-fache Geschwindigkeit, höherer Verbrauch)" + }, "serviceTier": { "label": "Service-Stufe", "tooltip": "Für eine schnellere Verarbeitung von API-Anfragen, probiere die Prioritäts-Verarbeitungsstufe. Für niedrigere Preise bei höherer Latenz, probiere die Flex-Verarbeitungsstufe.", diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index 37d33f8172..3d84065849 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -1126,6 +1126,12 @@ "limitMaxTokensDescription": "Limit the maximum number of tokens in the response", "maxOutputTokensLabel": "Max output tokens", "maxTokensGenerateDescription": "Maximum tokens to generate in response", + "openAiCodexSpeed": { + "label": "Speed", + "tooltip": "Fast uses Codex priority processing for about 1.5x speed and consumes more subscription quota.", + "standard": "Standard", + "fast": "Fast (1.5x speed, increased usage)" + }, "serviceTier": { "label": "Service tier", "tooltip": "For faster processing of API requests, try the priority processing service tier. For lower prices with higher latency, try the flex processing tier.", diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index f9c1be76f4..eba338005f 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -1046,6 +1046,12 @@ "limitMaxTokensDescription": "Limitar el número máximo de tokens en la respuesta", "maxOutputTokensLabel": "Tokens máximos de salida", "maxTokensGenerateDescription": "Tokens máximos a generar en la respuesta", + "openAiCodexSpeed": { + "label": "Velocidad", + "tooltip": "El modo rápido usa el procesamiento prioritario de Codex para ofrecer aproximadamente 1,5 veces más velocidad y consume más cuota de suscripción.", + "standard": "Estándar", + "fast": "Rápido (1,5 veces más velocidad, mayor uso)" + }, "serviceTier": { "label": "Nivel de servicio", "tooltip": "Para un procesamiento más rápido de las solicitudes de API, prueba el nivel de servicio de procesamiento prioritario. Para precios más bajos con mayor latencia, prueba el nivel de procesamiento flexible.", diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 6da211144b..d6e6e0e64e 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -1046,6 +1046,12 @@ "limitMaxTokensDescription": "Limiter le nombre maximum de tokens dans la réponse", "maxOutputTokensLabel": "Tokens de sortie maximum", "maxTokensGenerateDescription": "Tokens maximum à générer dans la réponse", + "openAiCodexSpeed": { + "label": "Vitesse", + "tooltip": "Le mode rapide utilise le traitement prioritaire de Codex pour une vitesse environ 1,5 fois supérieure et consomme davantage de quota d'abonnement.", + "standard": "Standard", + "fast": "Rapide (vitesse 1,5 fois supérieure, utilisation accrue)" + }, "serviceTier": { "label": "Niveau de service", "tooltip": "Pour un traitement plus rapide des demandes d'API, essayez le niveau de service de traitement prioritaire. Pour des prix plus bas avec une latence plus élevée, essayez le niveau de traitement flexible.", diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index 522c68a586..3ff02125c5 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -1046,6 +1046,12 @@ "limitMaxTokensDescription": "प्रतिक्रिया में टोकन की अधिकतम संख्या सीमित करें", "maxOutputTokensLabel": "अधिकतम आउटपुट टोकन", "maxTokensGenerateDescription": "प्रतिक्रिया में उत्पन्न करने के लिए अधिकतम टोकन", + "openAiCodexSpeed": { + "label": "गति", + "tooltip": "तेज़ मोड लगभग 1.5 गुना गति के लिए Codex की प्राथमिकता प्रोसेसिंग का उपयोग करता है और अधिक सदस्यता कोटा खर्च करता है।", + "standard": "मानक", + "fast": "तेज़ (1.5 गुना गति, अधिक उपयोग)" + }, "serviceTier": { "label": "सेवा स्तर", "tooltip": "API अनुरोधों के तेज़ प्रसंस्करण के लिए, प्राथमिकता प्रसंस्करण सेवा स्तर का प्रयास करें। उच्च विलंबता के साथ कम कीमतों के लिए, फ्लेक्स प्रसंस्करण स्तर का प्रयास करें।", diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index b2943e63bc..6c4b91243f 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -1046,6 +1046,12 @@ "limitMaxTokensDescription": "Batasi jumlah maksimum token dalam respons", "maxOutputTokensLabel": "Token output maksimum", "maxTokensGenerateDescription": "Token maksimum untuk dihasilkan dalam respons", + "openAiCodexSpeed": { + "label": "Kecepatan", + "tooltip": "Mode Cepat menggunakan pemrosesan prioritas Codex untuk kecepatan sekitar 1,5x dan memakai lebih banyak kuota langganan.", + "standard": "Standar", + "fast": "Cepat (kecepatan 1,5x, penggunaan meningkat)" + }, "serviceTier": { "label": "Tingkat layanan", "tooltip": "Untuk pemrosesan permintaan API yang lebih cepat, coba tingkat layanan pemrosesan prioritas. Untuk harga lebih rendah dengan latensi lebih tinggi, coba tingkat pemrosesan fleksibel.", diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index 6bd638c796..8f7fd7e917 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -1046,6 +1046,12 @@ "limitMaxTokensDescription": "Limita il numero massimo di token nella risposta", "maxOutputTokensLabel": "Token di output massimi", "maxTokensGenerateDescription": "Token massimi da generare nella risposta", + "openAiCodexSpeed": { + "label": "Velocità", + "tooltip": "La modalità veloce usa l'elaborazione prioritaria di Codex per una velocità circa 1,5 volte superiore e consuma più quota dell'abbonamento.", + "standard": "Standard", + "fast": "Veloce (velocità 1,5 volte superiore, utilizzo maggiore)" + }, "serviceTier": { "label": "Livello di servizio", "tooltip": "Per un'elaborazione più rapida delle richieste API, prova il livello di servizio di elaborazione prioritaria. Per prezzi più bassi con una latenza maggiore, prova il livello di elaborazione flessibile.", diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index 96fba3521a..ab692a49f8 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -1046,6 +1046,12 @@ "limitMaxTokensDescription": "レスポンスの最大トークン数を制限する", "maxOutputTokensLabel": "最大出力トークン", "maxTokensGenerateDescription": "レスポンスで生成する最大トークン数", + "openAiCodexSpeed": { + "label": "速度", + "tooltip": "高速モードは Codex の優先処理を使用して約1.5倍の速度を実現し、サブスクリプションの利用枠をより多く消費します。", + "standard": "標準", + "fast": "高速(約1.5倍、使用量増加)" + }, "serviceTier": { "label": "サービスティア", "tooltip": "APIリクエストをより速く処理するには、優先処理サービスティアをお試しください。低価格でレイテンシが高い場合は、フレックス処理ティアをお試しください。", diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index 40313a32f5..4e44f8170d 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -1046,6 +1046,12 @@ "limitMaxTokensDescription": "응답에서 최대 토큰 수 제한", "maxOutputTokensLabel": "최대 출력 토큰", "maxTokensGenerateDescription": "응답에서 생성할 최대 토큰 수", + "openAiCodexSpeed": { + "label": "속도", + "tooltip": "빠른 모드는 Codex 우선 처리를 사용하여 약 1.5배 빠른 속도를 제공하며 구독 할당량을 더 많이 사용합니다.", + "standard": "표준", + "fast": "빠름(1.5배 속도, 사용량 증가)" + }, "serviceTier": { "label": "서비스 등급", "tooltip": "API 요청을 더 빠르게 처리하려면 우선 처리 서비스 등급을 사용해 보세요. 더 낮은 가격에 더 높은 지연 시간을 원하시면 플렉스 처리 등급을 사용해 보세요.", diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index 6664eb3d74..d517df4bd0 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -1046,6 +1046,12 @@ "limitMaxTokensDescription": "Beperk het maximale aantal tokens in het antwoord", "maxOutputTokensLabel": "Maximale output tokens", "maxTokensGenerateDescription": "Maximale tokens om te genereren in het antwoord", + "openAiCodexSpeed": { + "label": "Snelheid", + "tooltip": "De snelle modus gebruikt prioriteitsverwerking van Codex voor ongeveer 1,5 keer hogere snelheid en verbruikt meer abonnementquotum.", + "standard": "Standaard", + "fast": "Snel (1,5 keer hogere snelheid, meer verbruik)" + }, "serviceTier": { "label": "Serviceniveau", "tooltip": "Voor snellere verwerking van API-verzoeken, probeer het prioriteitsverwerkingsniveau. Voor lagere prijzen met hogere latentie, probeer het flexverwerkingsniveau.", diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index 7a7ab3dcb0..3ef8e06c32 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -1046,6 +1046,12 @@ "limitMaxTokensDescription": "Ogranicz maksymalną liczbę tokenów w odpowiedzi", "maxOutputTokensLabel": "Maksymalne tokeny wyjściowe", "maxTokensGenerateDescription": "Maksymalne tokeny do wygenerowania w odpowiedzi", + "openAiCodexSpeed": { + "label": "Szybkość", + "tooltip": "Tryb szybki korzysta z priorytetowego przetwarzania Codex, zapewniając około 1,5 raza większą szybkość i zużywając więcej limitu subskrypcji.", + "standard": "Standardowy", + "fast": "Szybki (1,5 raza szybciej, większe użycie)" + }, "serviceTier": { "label": "Poziom usług", "tooltip": "Aby szybciej przetwarzać żądania API, wypróbuj priorytetowy poziom usług. Aby uzyskać niższe ceny przy wyższej latencji, wypróbuj elastyczny poziom usług.", diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index bb44c1bcaa..9c67418d16 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -1046,6 +1046,12 @@ "limitMaxTokensDescription": "Limitar o número máximo de tokens na resposta", "maxOutputTokensLabel": "Tokens máximos de saída", "maxTokensGenerateDescription": "Tokens máximos para gerar na resposta", + "openAiCodexSpeed": { + "label": "Velocidade", + "tooltip": "O modo rápido usa o processamento prioritário do Codex para oferecer cerca de 1,5 vez mais velocidade e consome mais cota da assinatura.", + "standard": "Padrão", + "fast": "Rápido (1,5 vez mais velocidade, maior uso)" + }, "serviceTier": { "label": "Nível de serviço", "tooltip": "Para um processamento mais rápido das solicitações de API, experimente o nível de serviço de processamento prioritário. Para preços mais baixos com maior latência, experimente o nível de processamento flexível.", diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index ee02578534..6d81073dbe 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -1046,6 +1046,12 @@ "limitMaxTokensDescription": "Ограничить максимальное количество токенов в ответе", "maxOutputTokensLabel": "Максимальные выходные токены", "maxTokensGenerateDescription": "Максимальные токены для генерации в ответе", + "openAiCodexSpeed": { + "label": "Скорость", + "tooltip": "Быстрый режим использует приоритетную обработку Codex, обеспечивая примерно 1,5-кратную скорость и расходуя больше квоты подписки.", + "standard": "Стандартный", + "fast": "Быстрый (скорость 1,5×, повышенный расход)" + }, "serviceTier": { "label": "Уровень обслуживания", "tooltip": "Для более быстрой обработки запросов API попробуйте уровень обслуживания с приоритетной обработкой. Для более низких цен с более высокой задержкой попробуйте уровень гибкой обработки.", diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index e37c154ead..0456367efc 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -1046,6 +1046,12 @@ "limitMaxTokensDescription": "Yanıttaki maksimum token sayısını sınırla", "maxOutputTokensLabel": "Maksimum çıktı tokenları", "maxTokensGenerateDescription": "Yanıtta oluşturulacak maksimum token sayısı", + "openAiCodexSpeed": { + "label": "Hız", + "tooltip": "Hızlı mod, yaklaşık 1,5 kat hız için Codex öncelikli işlemeyi kullanır ve daha fazla abonelik kotası tüketir.", + "standard": "Standart", + "fast": "Hızlı (1,5 kat hız, daha fazla kullanım)" + }, "serviceTier": { "label": "Hizmet seviyesi", "tooltip": "Daha hızlı API isteği işleme için öncelikli işleme hizmeti seviyesini deneyin. Daha düşük gecikme süresiyle daha düşük fiyatlar için esnek işleme seviyesini deneyin.", diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index c3b40a004a..4beb3f7171 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -1046,6 +1046,12 @@ "limitMaxTokensDescription": "Giới hạn số lượng token tối đa trong phản hồi", "maxOutputTokensLabel": "Token đầu ra tối đa", "maxTokensGenerateDescription": "Token tối đa để tạo trong phản hồi", + "openAiCodexSpeed": { + "label": "Tốc độ", + "tooltip": "Chế độ Nhanh sử dụng xử lý ưu tiên của Codex để đạt tốc độ nhanh hơn khoảng 1,5 lần và tiêu tốn nhiều hạn mức đăng ký hơn.", + "standard": "Tiêu chuẩn", + "fast": "Nhanh (tốc độ 1,5 lần, mức sử dụng cao hơn)" + }, "serviceTier": { "label": "Cấp độ dịch vụ", "tooltip": "Để xử lý các yêu cầu API nhanh hơn, hãy thử cấp độ dịch vụ xử lý ưu tiên. Để có giá thấp hơn với độ trễ cao hơn, hãy thử cấp độ xử lý linh hoạt.", diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index 2e8abf435e..8624c1899b 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -1046,6 +1046,12 @@ "limitMaxTokensDescription": "限制响应中的最大 Token 数量", "maxOutputTokensLabel": "最大输出 Token 数", "maxTokensGenerateDescription": "响应中生成的最大 Token 数", + "openAiCodexSpeed": { + "label": "速度", + "tooltip": "快速模式使用 Codex 优先处理,速度约为 1.5 倍,但会消耗更多订阅配额。", + "standard": "标准", + "fast": "快速(1.5 倍速度,用量增加)" + }, "serviceTier": { "label": "服务等级", "tooltip": "为加快API请求处理速度,请尝试优先处理服务等级。为获得更低价格但延迟较高,请尝试灵活处理等级。", diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index 481bab5301..8556e8b2f4 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -1073,6 +1073,12 @@ "limitMaxTokensDescription": "限制回應中的最大 Token 數量", "maxOutputTokensLabel": "最大輸出 Token 數", "maxTokensGenerateDescription": "回應中產生的最大 Token 數", + "openAiCodexSpeed": { + "label": "速度", + "tooltip": "快速模式使用 Codex 優先處理,速度約為 1.5 倍,但會消耗更多訂閱配額。", + "standard": "標準", + "fast": "快速(1.5 倍速度,用量增加)" + }, "serviceTier": { "label": "服務層級", "tooltip": "若需更快的 API 請求處理,請嘗試優先處理服務層級。若需較低價格但延遲較高,請嘗試彈性處理層級。", From 1977341f3f051a682fb7c2d4b65f410862116c26 Mon Sep 17 00:00:00 2001 From: gubin-dev Date: Fri, 31 Jul 2026 11:11:45 +0300 Subject: [PATCH 2/6] test(webview): add Codex speed selector visual coverage --- .../settings/providers/OpenAICodex.tsx | 44 +++--------------- .../providers/OpenAICodexSpeedSelector.tsx | 42 +++++++++++++++++ .../__tests__/OpenAICodex.visual.fixture.tsx | 28 +++++++++++ .../__tests__/OpenAICodex.visual.tsx | 16 +++++++ .../openai-codex-speed-selector-dark.png | Bin 0 -> 3065 bytes 5 files changed, 92 insertions(+), 38 deletions(-) create mode 100644 webview-ui/src/components/settings/providers/OpenAICodexSpeedSelector.tsx create mode 100644 webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.fixture.tsx create mode 100644 webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.tsx create mode 100644 webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-dark.png diff --git a/webview-ui/src/components/settings/providers/OpenAICodex.tsx b/webview-ui/src/components/settings/providers/OpenAICodex.tsx index 443335a79c..ee2abf0e2b 100644 --- a/webview-ui/src/components/settings/providers/OpenAICodex.tsx +++ b/webview-ui/src/components/settings/providers/OpenAICodex.tsx @@ -2,26 +2,18 @@ import React from "react" import { OPEN_AI_CODEX_SERVICE_TIER_KEY, - OpenAiCodexServiceTier, type ProviderSettings, openAiCodexDefaultModelId, openAiCodexModels, } from "@roo-code/types" import { useAppTranslation } from "@src/i18n/TranslationContext" -import { - Button, - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, - StandardTooltip, -} from "@src/components/ui" +import { Button } from "@src/components/ui" import { vscode } from "@src/utils/vscode" import { ModelPicker } from "../ModelPicker" import { OpenAICodexRateLimitDashboard } from "./OpenAICodexRateLimitDashboard" +import { OpenAICodexSpeedSelector } from "./OpenAICodexSpeedSelector" interface OpenAICodexProps { apiConfiguration: ProviderSettings @@ -81,34 +73,10 @@ export const OpenAICodex: React.FC = ({ hidePricing /> -
-
- - - - -
- -
+ setApiConfigurationField(OPEN_AI_CODEX_SERVICE_TIER_KEY, value)} + />
) } diff --git a/webview-ui/src/components/settings/providers/OpenAICodexSpeedSelector.tsx b/webview-ui/src/components/settings/providers/OpenAICodexSpeedSelector.tsx new file mode 100644 index 0000000000..adb62a0099 --- /dev/null +++ b/webview-ui/src/components/settings/providers/OpenAICodexSpeedSelector.tsx @@ -0,0 +1,42 @@ +import React from "react" + +import { + OpenAiCodexServiceTier, + type OpenAiCodexServiceTier as OpenAiCodexServiceTierValue, +} from "@roo-code/types/model" + +import { useAppTranslation } from "@src/i18n/TranslationContext" +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, StandardTooltip } from "@src/components/ui" + +interface OpenAICodexSpeedSelectorProps { + value?: OpenAiCodexServiceTierValue + onValueChange: (value: OpenAiCodexServiceTierValue) => void +} + +export const OpenAICodexSpeedSelector: React.FC = ({ value, onValueChange }) => { + const { t } = useAppTranslation() + + return ( +
+
+ + + + +
+ +
+ ) +} diff --git a/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.fixture.tsx b/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.fixture.tsx new file mode 100644 index 0000000000..8c8bbd8eed --- /dev/null +++ b/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.fixture.tsx @@ -0,0 +1,28 @@ +import React from "react" + +import { TranslationContext } from "@src/i18n/TranslationContext" +import { TooltipProvider } from "@src/components/ui/tooltip" +import { OpenAICodexSpeedSelector } from "../OpenAICodexSpeedSelector" + +const translations: Record = { + "settings:common.select": "Select", + "settings:openAiCodexSpeed.label": "Speed", + "settings:openAiCodexSpeed.tooltip": + "Fast uses Codex priority processing for about 1.5x speed and consumes more subscription quota.", + "settings:openAiCodexSpeed.standard": "Standard", + "settings:openAiCodexSpeed.fast": "Fast (1.5x speed, increased usage)", +} + +export const OpenAICodexFixture = () => ( + translations[key] ?? key, + i18n: null as unknown as typeof import("../../../../i18n/setup").default, + }}> + +
+ {}} /> +
+
+
+) diff --git a/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.tsx b/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.tsx new file mode 100644 index 0000000000..eedaec811e --- /dev/null +++ b/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.tsx @@ -0,0 +1,16 @@ +import React from "react" + +import { expect, test } from "../../../../../playwright/coverage-fixture" +import { OpenAICodexFixture } from "./OpenAICodex.visual.fixture" + +test("renders the OpenAI Codex speed selector in the VS Code dark theme", async ({ mount }) => { + const component = await mount() + const selector = component.getByTestId("openai-codex-service-tier") + + await selector.evaluate(async () => { + await document.fonts.ready + await new Promise((resolve) => requestAnimationFrame(() => resolve())) + }) + + await expect(selector).toHaveScreenshot("openai-codex-speed-selector-dark.png") +}) diff --git a/webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-dark.png b/webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..da01a5a142b93f09c92dac0f1362777dc61e0346 GIT binary patch literal 3065 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 Date: Fri, 31 Jul 2026 11:20:25 +0300 Subject: [PATCH 3/6] test(webview): exclude visual fixture from unit coverage --- .../settings/providers/__tests__/OpenAICodex.visual.fixture.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.fixture.tsx b/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.fixture.tsx index 8c8bbd8eed..0f158544a1 100644 --- a/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.fixture.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.fixture.tsx @@ -1,3 +1,4 @@ +/* v8 ignore file -- Playwright component fixture is covered by the visual test. */ import React from "react" import { TranslationContext } from "@src/i18n/TranslationContext" From 0c7b0f9321fa3cdf97ecedf9d6e547c75d356861 Mon Sep 17 00:00:00 2001 From: gubin-dev Date: Fri, 31 Jul 2026 12:50:08 +0300 Subject: [PATCH 4/6] test(webview): cover codex speed themes --- webview-ui/playwright/index.tsx | 1 + webview-ui/playwright/vscode-theme-light.css | 35 ++++++++ .../__tests__/OpenAICodex.visual.fixture.tsx | 13 ++- .../__tests__/OpenAICodex.visual.tsx | 79 ++++++++++++++++-- ...nai-codex-speed-selector-priority-dark.png | Bin 0 -> 4866 bytes ...ai-codex-speed-selector-priority-light.png | Bin 0 -> 4644 bytes ...ai-codex-speed-selector-standard-dark.png} | Bin ...ai-codex-speed-selector-standard-light.png | Bin 0 -> 2949 bytes 8 files changed, 117 insertions(+), 11 deletions(-) create mode 100644 webview-ui/playwright/vscode-theme-light.css create mode 100644 webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-priority-dark.png create mode 100644 webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-priority-light.png rename webview-ui/src/components/settings/providers/__tests__/__screenshots__/{openai-codex-speed-selector-dark.png => openai-codex-speed-selector-standard-dark.png} (100%) create mode 100644 webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-standard-light.png diff --git a/webview-ui/playwright/index.tsx b/webview-ui/playwright/index.tsx index 67af70105d..3710fe1502 100644 --- a/webview-ui/playwright/index.tsx +++ b/webview-ui/playwright/index.tsx @@ -1,6 +1,7 @@ import "./vscode-theme-dark.css" import "@vscode/codicons/dist/codicon.css" import "../src/index.css" +import "./vscode-theme-light.css" // Components read `window.IMAGES_BASE_URI` at mount time to resolve extension // image assets. Under Playwright CT the extension host isn't present, so seed diff --git a/webview-ui/playwright/vscode-theme-light.css b/webview-ui/playwright/vscode-theme-light.css new file mode 100644 index 0000000000..c877cea470 --- /dev/null +++ b/webview-ui/playwright/vscode-theme-light.css @@ -0,0 +1,35 @@ +.vscode-light { + color-scheme: light; + --vscode-foreground: #3b3b3b; + --vscode-disabledForeground: #61616180; + --vscode-descriptionForeground: #717171; + --vscode-errorForeground: #a1260d; + --vscode-focusBorder: #0090f1; + --vscode-editor-foreground: #333333; + --vscode-editor-background: #ffffff; + --vscode-button-foreground: #ffffff; + --vscode-button-background: #007acc; + --vscode-button-hoverBackground: #0062a3; + --vscode-dropdown-foreground: #3b3b3b; + --vscode-dropdown-background: #ffffff; + --vscode-dropdown-border: #cecece; + --vscode-input-foreground: #3b3b3b; + --vscode-input-background: #ffffff; + --vscode-input-border: #cecece; + --vscode-list-hoverForeground: #3b3b3b; + --vscode-list-hoverBackground: #e8e8e8; + --vscode-list-focusBackground: #d6ebff; + --vscode-list-activeSelectionBackground: #0060c0; + --vscode-list-activeSelectionForeground: #ffffff; + --vscode-toolbar-hoverBackground: #e8e8e8; + --vscode-widget-border: #d4d4d4; + --vscode-widget-shadow: #00000029; + --vscode-menu-foreground: #3b3b3b; + --vscode-menu-background: #ffffff; + --vscode-editorHoverWidget-foreground: #3b3b3b; + --vscode-editorHoverWidget-background: #f8f8f8; + --vscode-editorHoverWidget-border: #c8c8c8; + --vscode-scrollbarSlider-background: #64646466; + --vscode-scrollbarSlider-hoverBackground: #64646499; + --vscode-scrollbarSlider-activeBackground: #00000099; +} diff --git a/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.fixture.tsx b/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.fixture.tsx index 0f158544a1..8d10ac902f 100644 --- a/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.fixture.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.fixture.tsx @@ -1,6 +1,11 @@ /* v8 ignore file -- Playwright component fixture is covered by the visual test. */ import React from "react" +import { + OpenAiCodexServiceTier, + type OpenAiCodexServiceTier as OpenAiCodexServiceTierValue, +} from "@roo-code/types/model" + import { TranslationContext } from "@src/i18n/TranslationContext" import { TooltipProvider } from "@src/components/ui/tooltip" import { OpenAICodexSpeedSelector } from "../OpenAICodexSpeedSelector" @@ -14,7 +19,11 @@ const translations: Record = { "settings:openAiCodexSpeed.fast": "Fast (1.5x speed, increased usage)", } -export const OpenAICodexFixture = () => ( +interface OpenAICodexFixtureProps { + value?: OpenAiCodexServiceTierValue +} + +export const OpenAICodexFixture = ({ value = OpenAiCodexServiceTier.Default }: OpenAICodexFixtureProps) => ( translations[key] ?? key, @@ -22,7 +31,7 @@ export const OpenAICodexFixture = () => ( }}>
- {}} /> + {}} />
diff --git a/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.tsx b/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.tsx index eedaec811e..90bd470011 100644 --- a/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.tsx @@ -1,16 +1,77 @@ import React from "react" +import { OpenAiCodexServiceTier } from "@roo-code/types/model" + import { expect, test } from "../../../../../playwright/coverage-fixture" import { OpenAICodexFixture } from "./OpenAICodex.visual.fixture" -test("renders the OpenAI Codex speed selector in the VS Code dark theme", async ({ mount }) => { - const component = await mount() - const selector = component.getByTestId("openai-codex-service-tier") +const themes = [ + { + name: "dark", + bodyClass: "vscode-dark", + themeId: "Default Dark Modern", + editorBackground: "#1e1e1e", + dropdownBackground: "#3c3c3c", + triggerBackground: "rgb(60, 60, 60)", + }, + { + name: "light", + bodyClass: "vscode-light", + themeId: "Default Light Modern", + editorBackground: "#ffffff", + dropdownBackground: "#ffffff", + triggerBackground: "rgb(255, 255, 255)", + }, +] as const + +const tiers = [ + { name: "standard", value: OpenAiCodexServiceTier.Default }, + { name: "priority", value: OpenAiCodexServiceTier.Priority }, +] as const + +for (const theme of themes) { + for (const tier of tiers) { + test(`renders the ${tier.name} OpenAI Codex speed in the VS Code ${theme.name} theme`, async ({ mount }) => { + const component = await mount() + const selector = component.getByTestId("openai-codex-service-tier") + + await selector.evaluate((element, { bodyClass, themeId }) => { + const { document } = element.ownerDocument.defaultView! + + document.documentElement.className = bodyClass + document.body.className = bodyClass + document.body.dataset.vscodeThemeId = themeId + }, theme) + await expect + .poll(() => + selector.evaluate((element) => { + const body = element.ownerDocument.body + const styles = getComputedStyle(body) + const trigger = element.querySelector("button")! + + return { + documentClass: element.ownerDocument.documentElement.className, + bodyClass: body.className, + editorBackground: styles.getPropertyValue("--vscode-editor-background").trim(), + dropdownBackground: styles.getPropertyValue("--vscode-dropdown-background").trim(), + triggerBackground: getComputedStyle(trigger).backgroundColor, + } + }), + ) + .toEqual({ + documentClass: theme.bodyClass, + bodyClass: theme.bodyClass, + editorBackground: theme.editorBackground, + dropdownBackground: theme.dropdownBackground, + triggerBackground: theme.triggerBackground, + }) - await selector.evaluate(async () => { - await document.fonts.ready - await new Promise((resolve) => requestAnimationFrame(() => resolve())) - }) + await selector.evaluate(async () => { + await document.fonts.ready + await new Promise((resolve) => requestAnimationFrame(() => resolve())) + }) - await expect(selector).toHaveScreenshot("openai-codex-speed-selector-dark.png") -}) + await expect(selector).toHaveScreenshot(`openai-codex-speed-selector-${tier.name}-${theme.name}.png`) + }) + } +} diff --git a/webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-priority-dark.png b/webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-priority-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..bb315cca44aae9224882c83c4014c2747ac94e25 GIT binary patch literal 4866 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 literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-priority-light.png b/webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-priority-light.png new file mode 100644 index 0000000000000000000000000000000000000000..c161d5d2aef67ed2bfab5db06f9157974a0c297a GIT binary patch literal 4644 zcmV+<65H*GP)!BMcVeXtF@ z*ayW2+XqVrOF$$0pcbgy0#!Ek7rh>M*rgj(O0ZPgP<9}uFu93I1?>(c z$8i)nb=-eS_xC|U&_i-&I0V1^&2N61Y5VTG?=S!W0O09q!&-%^Qv5ud{p^}_>&_O2 zJ$Lvhd;Fx^{kENI#{d8TT9Mzhf(2ULEUtd?$?BaWZ~gblw~wC-;aPQh*(|@PlJ^xTWtDBpf)%tEb#h*Fr5#IXTue z4N1;3Jj)|Xl)-c*T^Ig#t^H)+?Ux?dp7;Lwm-pwc9q$|T zzE-n2+h2P7-IJex^fzJs*vXfmBM$&T3vmdua&9M)k4|1$UKPYbMaL{8!;qHRQ9~;g zDF5W#hl?K!bA`loN>njF?e$xs^i$L1I3V?inx4re6Y zv~3e|_tgByA4Uc^MJyYS6|dg9c8B`yTSp!$W5;Xn_6_#E``W`Ed;5{M-adS%cuU0q z003HvLl|c58i_^xR52Z&=s$nj{rhv5uB=LRwZd_l@3fI<&&qk6v{IBbS| ziM8@xFQ=@m6xFhjm1vLOg{)2sEcYG(6wr%_i*9@G%>&7f@MHy+$s?eZ| z_wOl+a_>F{007Y9wCS>#6AjMAGc}y zfCm%+fR^GAW)zm9q41J`yq_kjluzdr+U_tdPs1qZmjxLesff#Yh2k9)!?`&vm&{A% z>1ttlW;!jZ7Mgdnaypf-Wul6y>6v8-qa6-hTFDhv^Tb?6XyOAUj~=Hs1>x&mR%lxX zNs=AA0{p8R|M-04u>B~B0RRBB616x`p%w>PD3%n1pzXZN=l8qOaC>bOo^m_N`GTxG zG77&OolXiGh8r5@@Q;o9II=bhADu}T3}m&UbAw~U9weX3ll_xfjiPAQ<)MXTBN%Ip z1Kqr~@cx3*)fd=fjJ>-4*++Aqk!SyO_Bcd>0szobJmHr}wJ@e-XC&s^)i3`Eco0Z` z{tVx!q1AO^@q_f&$KU%C1kwWl&~miEZ{c6C|4-k0*Q~bu`g5Y_jdi1 z^S!<MLZBBFpm7p@&094+XTYo=1-!B?tlo0000UMO9TE8;J|)-kHonR7G39u?6G$-Xm9Z>B|1g_%E| z39VMJUjSWN4)qPCTHql9z*B)7o=7=$U2j7J^ZSkW#A)~BY~zv~`$jM2=2KFyvy*u= zs$ZA0(RjIQe1Ny=^73RTOK_a6&@>A}({O&^gRsx>lTMNUV`6dm=NA1K&xE0 zr07IKC>rvR78o1#JX|D1EvD0w!#`YGZyuXhC*xI zQ>Ln_Vsa?7%8x(tI#z^KJeiYJ9kYqMo|pQs0K#u**b+}|0Tg2i?}tklXp0Yk|@gxD%3wR z;6;V%m8*%#=u*Cf(Y!k_5cJrz<6D-t7|u8Y!vo!B+v(Cu zJf6(viyDC%-5(5^^?&?MQB~DKlgm+J7(EVyqOB~88`z^`hp0*WLnVJ~s+%!Sy)tyE z$fTFGG;2x5>2swf zQhD#VSr`EPUZz_?$o(Z(sT%roPW@*r%iKJ-erIkd(Jw87> z$ZIR%OG(W$KEJp)J945BomeR7=$n;^Msv6?vXEJr^5OY-A}2S$Q@PpY=sPo=kh`Z) z^&@R!@XIPH+ z4#pNTOEDx7smW*-y>~SURgW#>#dDBeRiu^>K>#ppS|LlaaLGPM_QKSy*|mms3_&in@jIMm}8} z_c*Mi)$VjM7&2+~W_Q~3az*?Uaw+f0G$%ArNP(y2|lYAwWTiZ4s?I)Vv z>1m?b<%%IAR|v7)=C~D=r0t{f&7P?hNopdR$mUB*?Hs~oV7jKM^;~NyR+hpQ^G=&I zFZ$G?j}UqkxM3S|8!|J9tuYj92dZTD0-z(R4BW{`cQ7`Zz*!Fr3*HmE~HWdKgc&IJjr(X z$GZHc(uYIQnI%5r#0*1KwpGJWH3Ny@VS=^Nye|^=?(#68e&^$fsE@izU}dfT#v{E@ z3}e4GXah(nNles``G}d0O}S7sDElrow&0YNKG8cBx#-yaVUSls(`h^q%XBjqT~3c) zNbhl{V|0_t^+K7zi<(g{)Tn5U(p9U#PNJqgkk`kaDeJj95ifR)&qqwRw=jKSLaBXG zNZhEHL2?$;>r(5HpgV2Sya4b^v0FnArk-`@=b^eGiX9MLE0@qX24|~{Ok|e?#e6Z% zQHcJTt7d47g>`TYVVY|-GtIyreOqe^f)waU(NMZ9tgM=27e*mHF?1dIQBmU%`rSl)cS-K?BW z<;_77(~mbjvn*lF5_J-FIx#VuH+^`OwdLhP-TXogu#!qQ4b<8ToOZex)U94q&D@7`OvQ`}WmKo?nu}>==0DdHpX#Q7?gV~;S=cj3be)G*Y*a5N7&a!b9_w3hFU3-Vx;5!zJFKO%C@KdZ%I+`E82`y{mR2DWZ{CWSHnu zs=qh7RzEU%_MJ)0c6N4lkQP(XI59fQb#?|ve3wJRr{_`Ekmg;1v0yh-S)GUqY#`!d zNDCDVL=+PijB* z^yqLUJbm^Z0WK0X)i?@dz_>FD;J z=AugzVaHS;z&G3}8jXMaa*RCT^Yi_a7fz=rnss@cHn~AT(HOfcIof|ZYv*{Ui?yprmW#}TSJ$71)3rl9yvG*(P%iyjP?Y5Vl;I2>iKqe0005aNkl|h8QPgj?wzi7JBFAyqFM}C|G*R}& z#=8#~U;6aygcf;z29RB@(1qy+X3AKrfc5eQ=fo-IUCG^b^< z)c66t_#X&q_j=jFQnv6EJ>M2Z*Dwy*bN}(`i8=-6&P}YCJ#@9ST62)>8D$~oQ#s7# zbAoyT&l2@%>XCAqzlBGG_YF}|KPMK(GZ3_`L=(a<@^iu;5ewVd%`;$qTAhBsQ%hay zJ#*&5bcqiR^z1Qkq)W^3l;(LX^b7!6oa@)G*JGZxCsf|p*f0zOCS(Et0C+MtZ{9@a z=Zi1Ci0#Y=dgRCvG^nJi5X}q#0I(;Uo140>*VPl-JtO_GW5;A!1`P!O0B8zQ&vLoE zJM5`(Q90DNudm^W0RR9152&y7j?}aHqH;UjzI}UreI1?mgC-dP008(^fX3XBWl7WY zPS1UZCIX7p7WqJOyS25|(b0iqw7xy?&piPE0G=VL)hZHAG%Qr#qE0y)b8jku%>}d$ zvR8MqK-;I9>j?k=;2EW@t!>9}L|cnx&)~!-2`B&n0PqC<4FCZD|1Rd)a{vGU21!Ig aR09BVu%dAZIbx^)0000DxE|_3ixr=J(!fw(o-! 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 literal 0 HcmV?d00001 From 4ca5f3e7be02b7021e23635be03d7eaa1f180787 Mon Sep 17 00:00:00 2001 From: gubin-dev Date: Fri, 31 Jul 2026 13:05:58 +0300 Subject: [PATCH 5/6] test(webview): combine codex speed snapshots --- .../__tests__/OpenAICodex.visual.fixture.tsx | 16 ++-- .../__tests__/OpenAICodex.visual.tsx | 83 ++++++++---------- ...nai-codex-speed-selector-priority-dark.png | Bin 4866 -> 0 bytes ...ai-codex-speed-selector-priority-light.png | Bin 4644 -> 0 bytes ...nai-codex-speed-selector-standard-dark.png | Bin 3065 -> 0 bytes ...ai-codex-speed-selector-standard-light.png | Bin 2949 -> 0 bytes ...penai-codex-speed-selector-states-dark.png | Bin 0 -> 8208 bytes ...enai-codex-speed-selector-states-light.png | Bin 0 -> 7853 bytes 8 files changed, 43 insertions(+), 56 deletions(-) delete mode 100644 webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-priority-dark.png delete mode 100644 webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-priority-light.png delete mode 100644 webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-standard-dark.png delete mode 100644 webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-standard-light.png create mode 100644 webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-states-dark.png create mode 100644 webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-states-light.png diff --git a/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.fixture.tsx b/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.fixture.tsx index 8d10ac902f..2061f00614 100644 --- a/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.fixture.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.fixture.tsx @@ -1,10 +1,7 @@ /* v8 ignore file -- Playwright component fixture is covered by the visual test. */ import React from "react" -import { - OpenAiCodexServiceTier, - type OpenAiCodexServiceTier as OpenAiCodexServiceTierValue, -} from "@roo-code/types/model" +import { OpenAiCodexServiceTier } from "@roo-code/types/model" import { TranslationContext } from "@src/i18n/TranslationContext" import { TooltipProvider } from "@src/components/ui/tooltip" @@ -19,19 +16,16 @@ const translations: Record = { "settings:openAiCodexSpeed.fast": "Fast (1.5x speed, increased usage)", } -interface OpenAICodexFixtureProps { - value?: OpenAiCodexServiceTierValue -} - -export const OpenAICodexFixture = ({ value = OpenAiCodexServiceTier.Default }: OpenAICodexFixtureProps) => ( +export const OpenAICodexFixture = () => ( translations[key] ?? key, i18n: null as unknown as typeof import("../../../../i18n/setup").default, }}> -
- {}} /> +
+ {}} /> + {}} />
diff --git a/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.tsx b/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.tsx index 90bd470011..e8902cd87c 100644 --- a/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/OpenAICodex.visual.tsx @@ -1,7 +1,5 @@ import React from "react" -import { OpenAiCodexServiceTier } from "@roo-code/types/model" - import { expect, test } from "../../../../../playwright/coverage-fixture" import { OpenAICodexFixture } from "./OpenAICodex.visual.fixture" @@ -24,54 +22,49 @@ const themes = [ }, ] as const -const tiers = [ - { name: "standard", value: OpenAiCodexServiceTier.Default }, - { name: "priority", value: OpenAiCodexServiceTier.Priority }, -] as const - for (const theme of themes) { - for (const tier of tiers) { - test(`renders the ${tier.name} OpenAI Codex speed in the VS Code ${theme.name} theme`, async ({ mount }) => { - const component = await mount() - const selector = component.getByTestId("openai-codex-service-tier") + test(`renders both OpenAI Codex speeds in the VS Code ${theme.name} theme`, async ({ mount }) => { + const component = await mount() + const selectors = component.getByTestId("openai-codex-service-tier") + const selector = selectors.first() - await selector.evaluate((element, { bodyClass, themeId }) => { - const { document } = element.ownerDocument.defaultView! + await expect(selectors).toHaveCount(2) + await selector.evaluate((element, { bodyClass, themeId }) => { + const { document } = element.ownerDocument.defaultView! - document.documentElement.className = bodyClass - document.body.className = bodyClass - document.body.dataset.vscodeThemeId = themeId - }, theme) - await expect - .poll(() => - selector.evaluate((element) => { - const body = element.ownerDocument.body - const styles = getComputedStyle(body) - const trigger = element.querySelector("button")! + document.documentElement.className = bodyClass + document.body.className = bodyClass + document.body.dataset.vscodeThemeId = themeId + }, theme) + await expect + .poll(() => + selector.evaluate((element) => { + const body = element.ownerDocument.body + const styles = getComputedStyle(body) + const trigger = element.querySelector("button")! - return { - documentClass: element.ownerDocument.documentElement.className, - bodyClass: body.className, - editorBackground: styles.getPropertyValue("--vscode-editor-background").trim(), - dropdownBackground: styles.getPropertyValue("--vscode-dropdown-background").trim(), - triggerBackground: getComputedStyle(trigger).backgroundColor, - } - }), - ) - .toEqual({ - documentClass: theme.bodyClass, - bodyClass: theme.bodyClass, - editorBackground: theme.editorBackground, - dropdownBackground: theme.dropdownBackground, - triggerBackground: theme.triggerBackground, - }) - - await selector.evaluate(async () => { - await document.fonts.ready - await new Promise((resolve) => requestAnimationFrame(() => resolve())) + return { + documentClass: element.ownerDocument.documentElement.className, + bodyClass: body.className, + editorBackground: styles.getPropertyValue("--vscode-editor-background").trim(), + dropdownBackground: styles.getPropertyValue("--vscode-dropdown-background").trim(), + triggerBackground: getComputedStyle(trigger).backgroundColor, + } + }), + ) + .toEqual({ + documentClass: theme.bodyClass, + bodyClass: theme.bodyClass, + editorBackground: theme.editorBackground, + dropdownBackground: theme.dropdownBackground, + triggerBackground: theme.triggerBackground, }) - await expect(selector).toHaveScreenshot(`openai-codex-speed-selector-${tier.name}-${theme.name}.png`) + await component.evaluate(async () => { + await document.fonts.ready + await new Promise((resolve) => requestAnimationFrame(() => resolve())) }) - } + + await expect(component).toHaveScreenshot(`openai-codex-speed-selector-states-${theme.name}.png`) + }) } diff --git a/webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-priority-dark.png b/webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-priority-dark.png deleted file mode 100644 index bb315cca44aae9224882c83c4014c2747ac94e25..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4866 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 diff --git a/webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-priority-light.png b/webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-priority-light.png deleted file mode 100644 index c161d5d2aef67ed2bfab5db06f9157974a0c297a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4644 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 diff --git a/webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-states-dark.png b/webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-codex-speed-selector-states-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..87f8a1e06120099239fdc8151587379194c07fab GIT binary patch literal 8208 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 i@vS%o?*9w%_ki|deR6KTgID~-# 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 YkgBlz$xs+{h`$1;DrzcJ%UQhtZ$?vHrT_o{ literal 0 HcmV?d00001 From bcb5e4b07fcdd05c0a71d61963acd912442c9843 Mon Sep 17 00:00:00 2001 From: gubin-dev Date: Fri, 31 Jul 2026 14:21:41 +0300 Subject: [PATCH 6/6] fix(webview): label codex speed selector --- .../settings/providers/OpenAICodexSpeedSelector.tsx | 7 +++++-- .../settings/providers/__tests__/OpenAICodex.visual.tsx | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/webview-ui/src/components/settings/providers/OpenAICodexSpeedSelector.tsx b/webview-ui/src/components/settings/providers/OpenAICodexSpeedSelector.tsx index adb62a0099..09faf5cd8d 100644 --- a/webview-ui/src/components/settings/providers/OpenAICodexSpeedSelector.tsx +++ b/webview-ui/src/components/settings/providers/OpenAICodexSpeedSelector.tsx @@ -15,17 +15,20 @@ interface OpenAICodexSpeedSelectorProps { export const OpenAICodexSpeedSelector: React.FC = ({ value, onValueChange }) => { const { t } = useAppTranslation() + const selectId = React.useId() return (
- +