Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
143 lines
4.1 KiB
TypeScript
143 lines
4.1 KiB
TypeScript
import { BasePage } from './BasePage';
|
|
|
|
export class AIAssistantPage extends BasePage {
|
|
// #region Getters
|
|
|
|
getAskAssistantFloatingButton() {
|
|
return this.page.getByTestId('ask-assistant-floating-button');
|
|
}
|
|
|
|
getAskAssistantCanvasActionButton() {
|
|
return this.page.getByTestId('ask-assistant-canvas-action-button');
|
|
}
|
|
|
|
getAskAssistantChat() {
|
|
return this.page.getByTestId('ask-assistant-chat');
|
|
}
|
|
|
|
getAskAssistantSidebar() {
|
|
return this.page.getByTestId('ask-assistant-sidebar');
|
|
}
|
|
|
|
getPlaceholderMessage() {
|
|
return this.page.getByTestId('placeholder-message');
|
|
}
|
|
|
|
getChatInput() {
|
|
// Try suggestions input first (shown when suggestions are visible),
|
|
// fall back to regular input (shown when there are messages),
|
|
// or the mention input (shown when focused nodes feature is enabled)
|
|
const suggestionsInput = this.page.getByTestId('chat-suggestions-input').locator('textarea');
|
|
const regularInput = this.page.getByTestId('chat-input').locator('textarea');
|
|
const mentionInput = this.page.getByTestId('chat-input-with-mention').locator('textarea');
|
|
|
|
// Return the first one that's visible
|
|
return suggestionsInput.or(regularInput).or(mentionInput);
|
|
}
|
|
|
|
getSendMessageButton() {
|
|
return this.page.getByTestId('send-message-button');
|
|
}
|
|
|
|
getCloseChatButton() {
|
|
return this.page.getByTestId('close-chat-button');
|
|
}
|
|
|
|
getAskAssistantSidebarResizer() {
|
|
return this.getAskAssistantSidebar().locator('[class*="_resizer"][data-dir="left"]').first();
|
|
}
|
|
|
|
getNodeErrorViewAssistantButton() {
|
|
return this.page.getByTestId('node-error-view-ask-assistant-button').locator('button').first();
|
|
}
|
|
|
|
getChatMessagesAll() {
|
|
return this.page.locator('[data-test-id^="chat-message"]');
|
|
}
|
|
|
|
getChatMessagesAssistant() {
|
|
return this.page.getByTestId('chat-message-assistant');
|
|
}
|
|
|
|
getChatMessagesUser() {
|
|
return this.page.getByTestId('chat-message-user');
|
|
}
|
|
|
|
getChatMessagesSystem() {
|
|
return this.page.getByTestId('chat-message-system');
|
|
}
|
|
|
|
getQuickReplyButtons() {
|
|
return this.page.getByTestId('quick-replies').locator('button');
|
|
}
|
|
|
|
getNewAssistantSessionModal() {
|
|
return this.page.getByTestId('new-assistant-session-modal');
|
|
}
|
|
|
|
getCodeDiffs() {
|
|
return this.page.getByTestId('code-diff-suggestion');
|
|
}
|
|
|
|
getApplyCodeDiffButtons() {
|
|
return this.page.getByTestId('replace-code-button');
|
|
}
|
|
|
|
getUndoReplaceCodeButtons() {
|
|
return this.page.getByTestId('undo-replace-button');
|
|
}
|
|
|
|
getCodeReplacedMessage() {
|
|
return this.page.getByTestId('code-replaced-message');
|
|
}
|
|
|
|
getCredentialEditAssistantButton() {
|
|
return this.page.getByTestId('credential-edit-ask-assistant-button');
|
|
}
|
|
|
|
getCodeSnippet() {
|
|
return this.page.getByTestId('assistant-code-snippet-content');
|
|
}
|
|
|
|
// #endregion
|
|
|
|
// #region Actions
|
|
|
|
async sendMessage(
|
|
message: string,
|
|
method: 'send-message-button' | 'enter-key' = 'send-message-button',
|
|
) {
|
|
// Only type if there's a message to type (e.g., skip for pre-populated suggestion pills)
|
|
if (message) {
|
|
await this.getChatInput().pressSequentially(message, { delay: 20 });
|
|
}
|
|
if (method === 'enter-key') {
|
|
await this.getChatInput().press('Enter');
|
|
} else {
|
|
await this.getSendMessageButton().click();
|
|
}
|
|
}
|
|
|
|
async waitForStreamingComplete(options?: { timeout?: number }) {
|
|
const timeout = options?.timeout ?? 60000;
|
|
// Wait for at least one assistant message to appear (indicating streaming has produced output)
|
|
await this.getChatMessagesAssistant().first().waitFor({ state: 'visible', timeout });
|
|
// Wait for streaming to end by checking for the send button's arrow-up icon
|
|
// During streaming, a stop button with filled-square icon is shown instead
|
|
// After streaming, the send button with arrow-up icon appears
|
|
await this.page.waitForFunction(
|
|
() => {
|
|
const sendButton = document.querySelector('[data-test-id="send-message-button"]');
|
|
if (!sendButton) return false;
|
|
// The arrow-up icon indicates the send button (not streaming)
|
|
// The filled-square icon indicates the stop button (streaming)
|
|
const sendIcon = sendButton.querySelector('[data-icon="arrow-up"]');
|
|
return sendIcon !== null;
|
|
},
|
|
{ timeout },
|
|
);
|
|
}
|
|
|
|
// #endregion
|
|
}
|