E2E tests working again (#4103)

This commit is contained in:
Zane
2025-08-15 07:08:51 -07:00
committed by GitHub
parent a98ef2550a
commit f2e81a3d1c
4 changed files with 93 additions and 136 deletions
@@ -143,6 +143,7 @@ const AppSidebar: React.FC<SidebarProps> = ({ currentPath }) => {
<div className="sidebar-item"> <div className="sidebar-item">
<SidebarMenuItem> <SidebarMenuItem>
<SidebarMenuButton <SidebarMenuButton
data-testid={`sidebar-${entry.label.toLowerCase()}-button`}
onClick={() => navigate(entry.path)} onClick={() => navigate(entry.path)}
isActive={isActivePath(entry.path)} isActive={isActivePath(entry.path)}
tooltip={entry.tooltip} tooltip={entry.tooltip}
@@ -81,19 +81,27 @@ export default function SettingsView({
<Tabs value={activeTab} onValueChange={setActiveTab} className="h-full flex flex-col"> <Tabs value={activeTab} onValueChange={setActiveTab} className="h-full flex flex-col">
<div className="px-1"> <div className="px-1">
<TabsList className="w-full mb-2 justify-start"> <TabsList className="w-full mb-2 justify-start">
<TabsTrigger value="models" className="flex gap-2"> <TabsTrigger
value="models"
className="flex gap-2"
data-testid="settings-models-tab"
>
<Bot className="h-4 w-4" /> <Bot className="h-4 w-4" />
Models Models
</TabsTrigger> </TabsTrigger>
<TabsTrigger value="chat" className="flex gap-2"> <TabsTrigger value="chat" className="flex gap-2" data-testid="settings-chat-tab">
<MessageSquare className="h-4 w-4" /> <MessageSquare className="h-4 w-4" />
Chat Chat
</TabsTrigger> </TabsTrigger>
<TabsTrigger value="sharing" className="flex gap-2"> <TabsTrigger
value="sharing"
className="flex gap-2"
data-testid="settings-sharing-tab"
>
<Share2 className="h-4 w-4" /> <Share2 className="h-4 w-4" />
Session Session
</TabsTrigger> </TabsTrigger>
<TabsTrigger value="app" className="flex gap-2"> <TabsTrigger value="app" className="flex gap-2" data-testid="settings-app-tab">
<Monitor className="h-4 w-4" /> <Monitor className="h-4 w-4" />
App App
</TabsTrigger> </TabsTrigger>
@@ -406,7 +406,11 @@ export default function ExtensionModal({
<Button variant="outline" onClick={handleClose}> <Button variant="outline" onClick={handleClose}>
Cancel Cancel
</Button> </Button>
<Button onClick={handleSubmit} disabled={!isFormValid()}> <Button
data-testid="extension-submit-btn"
onClick={handleSubmit}
disabled={!isFormValid()}
>
{submitLabel} {submitLabel}
</Button> </Button>
</> </>
+75 -131
View File
@@ -20,8 +20,7 @@ type TestFixtures = {
// Define available providers, keeping as a list of objects for easy expansion // Define available providers, keeping as a list of objects for easy expansion
const providers: Provider[] = [ const providers: Provider[] = [
{ name: 'Databricks' }, { name: 'Databricks' }
{ name: 'Google' }
]; ];
// Create test with fixtures // Create test with fixtures
@@ -64,24 +63,36 @@ async function selectProvider(mainWindow: any, provider: Provider) {
}).catch(() => null); }).catch(() => null);
if (chatTextarea) { if (chatTextarea) {
// Click menu button to reset providers // Navigate to Settings via sidebar to reset providers
console.log('Opening menu to reset providers...'); console.log('Opening settings to reset providers...');
const menuButton = await mainWindow.waitForSelector('[data-testid="more-options-button"]', { const settingsButton = await mainWindow.waitForSelector('[data-testid="sidebar-settings-button"]', {
timeout: 5000, timeout: 5000,
state: 'visible' state: 'visible'
}); });
await menuButton.click(); await settingsButton.click();
// Wait for menu to appear and be interactive // Wait for settings page to load and navigate to Models tab
await mainWindow.waitForSelector('[data-testid="settings-models-tab"]', {
timeout: 5000,
state: 'visible'
});
const modelsTab = await mainWindow.waitForSelector('[data-testid="settings-models-tab"]');
await modelsTab.click();
// Wait for models section to load
await mainWindow.waitForTimeout(1000); await mainWindow.waitForTimeout(1000);
// Click Reset Provider and Model // Click Reset Provider and Model button
console.log('Clicking Reset provider and model...'); console.log('Clicking Reset provider and model...');
const resetButton = await mainWindow.waitForSelector('button:has-text("Reset provider and model")', { const resetButton = await mainWindow.waitForSelector('button:has-text("Reset provider and model")', {
timeout: 5000, timeout: 5000,
state: 'visible' state: 'visible'
}); });
await resetButton.click(); await resetButton.click();
// Wait for the reset to complete
await mainWindow.waitForTimeout(1000);
} }
// Wait for React app to be ready and animations to complete // Wait for React app to be ready and animations to complete
@@ -94,6 +105,29 @@ async function selectProvider(mainWindow: any, provider: Provider) {
// Take a screenshot before proceeding // Take a screenshot before proceeding
await mainWindow.screenshot({ path: `test-results/before-provider-${provider.name.toLowerCase()}-check.png` }); await mainWindow.screenshot({ path: `test-results/before-provider-${provider.name.toLowerCase()}-check.png` });
// Check if we're already at the chat interface (provider already configured)
const chatInputAfterReset = await mainWindow.waitForSelector('[data-testid="chat-input"]', {
timeout: 2000,
state: 'visible'
}).catch(() => null);
if (chatInputAfterReset) {
console.log('Provider already configured, chat interface is available');
return; // Provider is already selected, no need to do anything
}
// Check if we need to click "configure other providers (advanced)" button
const configureAdvancedButton = await mainWindow.waitForSelector('button:has-text("configure other providers (advanced)")', {
timeout: 3000,
state: 'visible'
}).catch(() => null);
if (configureAdvancedButton) {
console.log('Found "configure other providers (advanced)" button, clicking it...');
await configureAdvancedButton.click();
await mainWindow.waitForTimeout(1500);
}
// We should now be at provider selection // We should now be at provider selection
await mainWindow.waitForSelector('[data-testid="provider-selection-heading"]'); await mainWindow.waitForSelector('[data-testid="provider-selection-heading"]');
@@ -261,11 +295,24 @@ test.describe('Goose App', () => {
await selectProvider(mainWindow, providers[0]); await selectProvider(mainWindow, providers[0]);
} }
const menuButton = await mainWindow.waitForSelector('[data-testid="more-options-button"]', { // Navigate to Settings via sidebar
const settingsButton = await mainWindow.waitForSelector('[data-testid="sidebar-settings-button"]', {
timeout: 5000, timeout: 5000,
state: 'visible' state: 'visible'
}); });
await menuButton.click(); await settingsButton.click();
// Wait for settings page to load and navigate to App tab
await mainWindow.waitForSelector('[data-testid="settings-app-tab"]', {
timeout: 5000,
state: 'visible'
});
const appTab = await mainWindow.waitForSelector('[data-testid="settings-app-tab"]');
await appTab.click();
// Wait for the theme selector to be visible
await mainWindow.waitForTimeout(1000);
// Find and click the dark mode toggle button // Find and click the dark mode toggle button
const darkModeButton = await mainWindow.waitForSelector('[data-testid="dark-mode-button"]'); const darkModeButton = await mainWindow.waitForSelector('[data-testid="dark-mode-button"]');
@@ -301,8 +348,9 @@ test.describe('Goose App', () => {
// Pause to show return to original state // Pause to show return to original state
await mainWindow.waitForTimeout(2000); await mainWindow.waitForTimeout(2000);
// Close menu with ESC key // Navigate back to home
await mainWindow.keyboard.press('Escape'); const homeButton = await mainWindow.waitForSelector('[data-testid="sidebar-home-button"]');
await homeButton.click();
}); });
}); });
@@ -327,9 +375,6 @@ test.describe('Goose App', () => {
// Take screenshot before sending // Take screenshot before sending
await mainWindow.screenshot({ path: `test-results/${provider.name.toLowerCase()}-before-send.png` }); await mainWindow.screenshot({ path: `test-results/${provider.name.toLowerCase()}-before-send.png` });
// Get initial message count
const initialMessages = await mainWindow.locator('[data-testid="message-container"]').count();
// Send message // Send message
await chatInput.press('Enter'); await chatInput.press('Enter');
@@ -347,12 +392,6 @@ test.describe('Goose App', () => {
await mainWindow.waitForSelector('[data-testid="loading-indicator"]', await mainWindow.waitForSelector('[data-testid="loading-indicator"]',
{ state: 'hidden', timeout: 30000 }); { state: 'hidden', timeout: 30000 });
// Wait for new message to appear
await mainWindow.waitForFunction((count) => {
const messages = document.querySelectorAll('[data-testid="message-container"]');
return messages.length > count;
}, initialMessages, { timeout: 30000 });
// Get the latest response // Get the latest response
const response = await mainWindow.locator('[data-testid="message-container"]').last(); const response = await mainWindow.locator('[data-testid="message-container"]').last();
expect(await response.isVisible()).toBe(true); expect(await response.isVisible()).toBe(true);
@@ -375,9 +414,6 @@ test.describe('Goose App', () => {
// Test message sending with a specific question // Test message sending with a specific question
await chatInput.fill('What is 2+2?'); await chatInput.fill('What is 2+2?');
// Get initial message count
const initialMessages = await mainWindow.locator('[data-testid="message-container"]').count();
// Send message // Send message
await chatInput.press('Enter'); await chatInput.press('Enter');
@@ -385,12 +421,6 @@ test.describe('Goose App', () => {
await mainWindow.waitForSelector('[data-testid="loading-indicator"]', await mainWindow.waitForSelector('[data-testid="loading-indicator"]',
{ state: 'hidden', timeout: 30000 }); { state: 'hidden', timeout: 30000 });
// Wait for new message
await mainWindow.waitForFunction((count) => {
const messages = document.querySelectorAll('[data-testid="message-container"]');
return messages.length > count;
}, initialMessages, { timeout: 30000 });
// Get the latest response // Get the latest response
const response = await mainWindow.locator('[data-testid="message-container"]').last(); const response = await mainWindow.locator('[data-testid="message-container"]').last();
const responseText = await response.textContent(); const responseText = await response.textContent();
@@ -440,27 +470,15 @@ test.describe('Goose App', () => {
// Take screenshot of initial state // Take screenshot of initial state
await mainWindow.screenshot({ path: `test-results/${provider.name.toLowerCase()}-initial-state.png` }); await mainWindow.screenshot({ path: `test-results/${provider.name.toLowerCase()}-initial-state.png` });
// First navigate to Advanced Settings to check for existing Running Quotes extension // Navigate to Extensions via sidebar
console.log('Checking for existing Running Quotes extension...'); console.log('Navigating to Extensions...');
const extensionsButton = await mainWindow.waitForSelector('[data-testid="sidebar-extensions-button"]', {
// Click the menu button (3 dots) timeout: 5000,
const menuButton = await mainWindow.waitForSelector('[data-testid="more-options-button"]', {
timeout: 2000,
state: 'visible' state: 'visible'
}); });
await menuButton.click(); await extensionsButton.click();
// Wait for menu to appear // Wait for extensions page to load
await mainWindow.waitForTimeout(1000);
// Click Advanced settings
const advancedSettingsButton = await mainWindow.waitForSelector('button:has-text("Advanced settings")', {
timeout: 2000,
state: 'visible'
});
await advancedSettingsButton.click();
// Wait for settings page to load
await mainWindow.waitForTimeout(1000); await mainWindow.waitForTimeout(1000);
// Look for Running Quotes extension card // Look for Running Quotes extension card
@@ -500,44 +518,9 @@ test.describe('Goose App', () => {
} }
} }
// Click Back to return to main menu
let backButton = await mainWindow.waitForSelector('button:has-text("Back")', {
timeout: 2000,
state: 'visible'
});
await backButton.click();
// Wait for menu transition
await mainWindow.waitForTimeout(1000);
// Now proceed with adding the extension // Now proceed with adding the extension
console.log('Proceeding with adding Running Quotes extension...'); console.log('Proceeding with adding Running Quotes extension...');
// Find and click the menu button (3 dots) again
console.log('Finding menu button again...');
const menuButtonAgain = await mainWindow.waitForSelector('[data-testid="more-options-button"]', {
timeout: 2000,
state: 'visible'
});
await menuButtonAgain.click();
// Wait for menu to appear and take screenshot
await mainWindow.waitForTimeout(1000);
await mainWindow.screenshot({ path: `test-results/${provider.name.toLowerCase()}-after-menu.png` });
// Click Advanced settings again
console.log('Looking for Advanced settings button again...');
const advancedSettingsButtonAgain = await mainWindow.waitForSelector('button:has-text("Advanced settings")', {
timeout: 2000,
state: 'visible'
});
await advancedSettingsButtonAgain.click();
console.log('Clicked Advanced settings');
// Wait for navigation and take screenshot
await mainWindow.waitForTimeout(1000);
await mainWindow.screenshot({ path: `test-results/${provider.name.toLowerCase()}-settings-page.png` });
// Click "Add custom extension" button // Click "Add custom extension" button
console.log('Looking for Add custom extension button...'); console.log('Looking for Add custom extension button...');
const addExtensionButton = await mainWindow.waitForSelector('button:has-text("Add custom extension")', { const addExtensionButton = await mainWindow.waitForSelector('button:has-text("Add custom extension")', {
@@ -589,7 +572,7 @@ test.describe('Goose App', () => {
// Click Add Extension button in modal footer // Click Add Extension button in modal footer
console.log('Looking for Add Extension button in modal...'); console.log('Looking for Add Extension button in modal...');
const modalAddButton = await mainWindow.waitForSelector('button.text-textProminent', { const modalAddButton = await mainWindow.waitForSelector('[data-testid="extension-submit-btn"]', {
timeout: 2000, timeout: 2000,
state: 'visible' state: 'visible'
}); });
@@ -615,6 +598,7 @@ test.describe('Goose App', () => {
); );
// Verify the extension is enabled // Verify the extension is enabled
await mainWindow.waitForTimeout(1000);
const toggleButton = await extensionCard.$('button[role="switch"][data-state="checked"]'); const toggleButton = await extensionCard.$('button[role="switch"][data-state="checked"]');
const isEnabled = !!toggleButton; const isEnabled = !!toggleButton;
console.log('Extension enabled:', isEnabled); console.log('Extension enabled:', isEnabled);
@@ -639,13 +623,10 @@ test.describe('Goose App', () => {
throw error; throw error;
} }
// Click Back button // Navigate back to home
backButton = await mainWindow.waitForSelector('button:has-text("Back")', { const homeButton = await mainWindow.waitForSelector('[data-testid="sidebar-home-button"]');
timeout: 2000, await homeButton.click();
state: 'visible' console.log('Navigated back to home');
});
await backButton.click();
console.log('Clicked Back button');
} catch (error) { } catch (error) {
// Take error screenshot and log details // Take error screenshot and log details
@@ -668,58 +649,21 @@ test.describe('Goose App', () => {
expect(await chatInput.isVisible()).toBe(true); expect(await chatInput.isVisible()).toBe(true);
// Type a message requesting a running quote // Type a message requesting a running quote
await chatInput.fill('Can you give me an inspirational running quote using the runningQuote tool?'); await chatInput.fill('Can you give me an inspirational running quote using the runningQuotes tool?');
// Take screenshot before sending // Take screenshot before sending
await mainWindow.screenshot({ path: `test-results/${provider.name.toLowerCase()}-before-quote-request.png` }); await mainWindow.screenshot({ path: `test-results/${provider.name.toLowerCase()}-before-quote-request.png` });
// Get initial message count
const initialMessages = await mainWindow.locator('[data-testid="message-container"]').count();
// Send message // Send message
await chatInput.press('Enter'); await chatInput.press('Enter');
// Wait for loading indicator
const loadingIndicator = await mainWindow.waitForSelector('[data-testid="loading-indicator"]',
{ timeout: 30000 });
expect(await loadingIndicator.isVisible()).toBe(true);
// Take screenshot of loading state
await mainWindow.screenshot({ path: `test-results/${provider.name.toLowerCase()}-quote-loading.png` });
// Wait for loading indicator to disappear
await mainWindow.waitForSelector('[data-testid="loading-indicator"]',
{ state: 'hidden', timeout: 30000 });
// Wait for new message to appear
await mainWindow.waitForFunction((count) => {
const messages = document.querySelectorAll('[data-testid="message-container"]');
return messages.length > count;
}, initialMessages, { timeout: 30000 });
// Get the latest response // Get the latest response
const response = await mainWindow.waitForSelector('.goose-message-tool', { timeout: 5000 }); const response = await mainWindow.waitForSelector('.goose-message-tool', { timeout: 5000 });
expect(await response.isVisible()).toBe(true); expect(await response.isVisible()).toBe(true);
// Click the Output dropdown to reveal the actual quote // Click the Output dropdown to reveal the actual quote
await mainWindow.screenshot({ path: `test-results/${provider.name.toLowerCase()}-quote-response-debug.png` });
const element = await mainWindow.$('.goose-message-tool');
const html = await element.innerHTML();
console.log('HTML content:', html);
// Click the Runningquote dropdown to reveal the actual quote
const runningQuoteButton = await mainWindow.waitForSelector('div.goose-message-tool svg.rotate-90', { timeout: 5000 });
await runningQuoteButton.click();
// Click the Output dropdown to reveal the actual quote
const outputButton = await mainWindow.waitForSelector('button:has-text("Output")', { timeout: 5000 });
await outputButton.click();
// Wait a bit and dump HTML to see structure
await mainWindow.waitForTimeout(1000);
// Take screenshot before trying to find content
await mainWindow.screenshot({ path: `test-results/${provider.name.toLowerCase()}-quote-response-debug.png` }); await mainWindow.screenshot({ path: `test-results/${provider.name.toLowerCase()}-quote-response-debug.png` });
// Now try to get the output content // Now try to get the output content
const outputContent = await mainWindow.waitForSelector('.whitespace-pre-wrap', { timeout: 5000 }); const outputContent = await mainWindow.waitForSelector('.whitespace-pre-wrap', { timeout: 5000 });
const outputText = await outputContent.textContent(); const outputText = await outputContent.textContent();