diff --git a/playwright/app.spec.ts b/playwright/app.spec.ts index 2b6be42..6a3205c 100644 --- a/playwright/app.spec.ts +++ b/playwright/app.spec.ts @@ -1,5 +1,6 @@ import { expect, test } from '@playwright/test' import type { Page } from '@playwright/test' +import { defaultGitHubChatModel } from '../src/modules/github-api.js' const webServerMode = process.env.PLAYWRIGHT_WEB_SERVER_MODE ?? 'dev' const appEntryPath = webServerMode === 'preview' ? '/index.html' : '/src/index.html' @@ -12,6 +13,8 @@ type ChatRequestMessage = { type ChatRequestBody = { metadata?: unknown messages?: ChatRequestMessage[] + model?: string + stream?: boolean } const waitForAppReady = async (page: Page, path = appEntryPath) => { @@ -256,6 +259,7 @@ test('AI chat prefers streaming responses when available', async ({ page }) => { ) expect(streamRequestBody?.metadata).toBeUndefined() + expect(streamRequestBody?.model).toBe(defaultGitHubChatModel) const systemMessage = streamRequestBody?.messages?.find( (message: ChatRequestMessage) => message.role === 'system', ) @@ -335,9 +339,14 @@ test('AI chat falls back to non-streaming response when streaming fails', async }) => { let streamAttemptCount = 0 let fallbackAttemptCount = 0 + const attemptedModels: string[] = [] await page.route('https://models.github.ai/inference/chat/completions', async route => { - const body = route.request().postDataJSON() as { stream?: boolean } | null + const body = route.request().postDataJSON() as ChatRequestBody | null + if (typeof body?.model === 'string') { + attemptedModels.push(body.model) + } + if (body?.stream) { streamAttemptCount += 1 await route.fulfill({ @@ -373,6 +382,10 @@ test('AI chat falls back to non-streaming response when streaming fails', async await connectByotWithSingleRepo(page) await ensureAiChatDrawerOpen(page) + const selectedModel = 'openai/gpt-5-mini' + await page.locator('#ai-chat-model').selectOption(selectedModel) + await expect(page.locator('#ai-chat-model')).toHaveValue(selectedModel) + await page.locator('#ai-chat-prompt').fill('Use fallback path.') await page.locator('#ai-chat-send').click() @@ -383,6 +396,8 @@ test('AI chat falls back to non-streaming response when streaming fails', async ) expect(streamAttemptCount).toBeGreaterThan(0) expect(fallbackAttemptCount).toBeGreaterThan(0) + expect(attemptedModels.length).toBeGreaterThan(0) + expect(attemptedModels.every(model => model === selectedModel)).toBe(true) }) test('BYOT remembers selected repository across reloads', async ({ page }) => { @@ -433,7 +448,7 @@ test('BYOT remembers selected repository across reloads', async ({ page }) => { test('renders default playground preview', async ({ page }) => { await waitForInitialRender(page) - await page.getByLabel('ShadowRoot (open)').uncheck() + await page.getByLabel('ShadowRoot').uncheck() await expect(page.locator('#status')).toHaveText('Rendered') await expectPreviewHasRenderedContent(page) }) @@ -668,7 +683,7 @@ test('renders in react mode with css modules', async ({ page }) => { await ensurePanelToolsVisible(page, 'component') await ensurePanelToolsVisible(page, 'styles') - await page.getByLabel('ShadowRoot (open)').uncheck() + await page.getByLabel('ShadowRoot').uncheck() await page.locator('#render-mode').selectOption('react') await page.locator('#style-mode').selectOption('module') await expect(page.locator('#status')).toHaveText('Rendered') @@ -678,7 +693,7 @@ test('renders in react mode with css modules', async ({ page }) => { test('transpiles TypeScript annotations in component source', async ({ page }) => { await waitForInitialRender(page) - await page.getByLabel('ShadowRoot (open)').uncheck() + await page.getByLabel('ShadowRoot').uncheck() await setComponentEditorSource( page, [ @@ -762,7 +777,7 @@ test('react mode executes default React import without TDZ runtime failure', asy await ensurePanelToolsVisible(page, 'component') - await page.getByLabel('ShadowRoot (open)').uncheck() + await page.getByLabel('ShadowRoot').uncheck() await page.locator('#render-mode').selectOption('react') await setComponentEditorSource( page, @@ -854,7 +869,7 @@ test('renders with less style mode', async ({ page }) => { await ensurePanelToolsVisible(page, 'styles') - await page.getByLabel('ShadowRoot (open)').uncheck() + await page.getByLabel('ShadowRoot').uncheck() await page.locator('#style-mode').selectOption('less') await expect(page.locator('#status')).toHaveText('Rendered') await expectPreviewHasRenderedContent(page) @@ -865,7 +880,7 @@ test('renders with sass style mode', async ({ page }) => { await ensurePanelToolsVisible(page, 'styles') - await page.getByLabel('ShadowRoot (open)').uncheck() + await page.getByLabel('ShadowRoot').uncheck() await page.locator('#style-mode').selectOption('sass') await expect(page.locator('#status')).toHaveText('Rendered') await expectPreviewHasRenderedContent(page) diff --git a/src/app.js b/src/app.js index 18c3f5d..e65d091 100644 --- a/src/app.js +++ b/src/app.js @@ -30,6 +30,7 @@ const aiChatDrawer = document.getElementById('ai-chat-drawer') const aiChatClose = document.getElementById('ai-chat-close') const aiChatClear = document.getElementById('ai-chat-clear') const aiChatPrompt = document.getElementById('ai-chat-prompt') +const aiChatModel = document.getElementById('ai-chat-model') const aiChatIncludeEditors = document.getElementById('ai-chat-include-editors') const aiChatSend = document.getElementById('ai-chat-send') const aiChatStatus = document.getElementById('ai-chat-status') @@ -477,6 +478,7 @@ const githubAiContextState = { let chatDrawerController = { setOpen: () => {}, setSelectedRepository: () => {}, + setToken: () => {}, dispose: () => {}, } @@ -509,6 +511,7 @@ const byotControls = createGitHubByotControls({ onTokenChange: token => { githubAiContextState.token = token syncAiChatTokenVisibility(token) + chatDrawerController.setToken(token) }, setStatus, }) @@ -527,6 +530,7 @@ chatDrawerController = createGitHubChatDrawer({ drawer: aiChatDrawer, closeButton: aiChatClose, promptInput: aiChatPrompt, + modelSelect: aiChatModel, includeEditorsContextToggle: aiChatIncludeEditors, sendButton: aiChatSend, clearButton: aiChatClear, diff --git a/src/index.html b/src/index.html index 4bad76f..ddd28fc 100644 --- a/src/index.html +++ b/src/index.html @@ -37,7 +37,7 @@