mirror of
https://github.com/AppFlowy-IO/AppFlowy-Web.git
synced 2025-11-30 11:27:55 +08:00
270 lines
8.5 KiB
TypeScript
270 lines
8.5 KiB
TypeScript
import { AuthTestUtils } from '../../support/auth-utils';
|
|
import { TestTool } from '../../support/page-utils';
|
|
import { AddPageSelectors, ModelSelectorSelectors, PageSelectors, SidebarSelectors, ChatSelectors } from '../../support/selectors';
|
|
import { generateRandomEmail, logAppFlowyEnvironment } from '../../support/test-config';
|
|
|
|
describe('Chat Input Tests', () => {
|
|
let testEmail: string;
|
|
|
|
before(() => {
|
|
logAppFlowyEnvironment();
|
|
});
|
|
|
|
beforeEach(() => {
|
|
testEmail = generateRandomEmail();
|
|
});
|
|
|
|
it('tests chat input UI controls', () => {
|
|
cy.on('uncaught:exception', (err: Error) => {
|
|
if (err.message.includes('No workspace or service found') ||
|
|
err.message.includes('View not found') ||
|
|
err.message.includes('WebSocket') ||
|
|
err.message.includes('connection') ||
|
|
err.message.includes('Failed to load models') ||
|
|
err.message.includes('Minified React error')) {
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
|
|
cy.visit('/login', { failOnStatusCode: false });
|
|
cy.wait(2000);
|
|
|
|
const authUtils = new AuthTestUtils();
|
|
authUtils.signInWithTestUrl(testEmail).then(() => {
|
|
cy.url().should('include', '/app');
|
|
|
|
SidebarSelectors.pageHeader().should('be.visible', { timeout: 30000 });
|
|
PageSelectors.items().should('exist', { timeout: 30000 });
|
|
cy.wait(2000);
|
|
|
|
TestTool.expandSpace();
|
|
cy.wait(1000);
|
|
|
|
PageSelectors.items()
|
|
.first()
|
|
.trigger('mouseenter', { force: true })
|
|
.trigger('mouseover', { force: true });
|
|
|
|
cy.wait(1000);
|
|
|
|
AddPageSelectors.inlineAddButton().first().click({ force: true });
|
|
AddPageSelectors.addAIChatButton().should('be.visible').click();
|
|
|
|
cy.wait(2000);
|
|
|
|
// Test 1: Format toggle
|
|
cy.log('Testing format toggle');
|
|
ChatSelectors.formatGroup().then($group => {
|
|
if ($group.length > 0) {
|
|
ChatSelectors.formatToggle().click();
|
|
ChatSelectors.formatGroup().should('not.exist');
|
|
}
|
|
});
|
|
|
|
ChatSelectors.formatToggle().should('be.visible').click();
|
|
ChatSelectors.formatGroup().should('exist');
|
|
ChatSelectors.formatGroup().find('button').should('have.length.at.least', 4);
|
|
ChatSelectors.formatToggle().click();
|
|
ChatSelectors.formatGroup().should('not.exist');
|
|
|
|
// Test 2: Model selector
|
|
cy.log('Testing model selector');
|
|
ModelSelectorSelectors.button().should('be.visible').click();
|
|
ModelSelectorSelectors.options().should('exist');
|
|
cy.get('body').click(0, 0);
|
|
|
|
// Test 3: Browse prompts
|
|
cy.log('Testing browse prompts');
|
|
ChatSelectors.browsePromptsButton().click();
|
|
cy.get('[role="dialog"]').should('exist');
|
|
cy.get('[role="dialog"]').contains('Browse prompts').should('be.visible');
|
|
cy.get('body').type('{esc}');
|
|
cy.get('[role="dialog"]').should('not.exist');
|
|
|
|
// Test 4: Related views
|
|
cy.log('Testing related views');
|
|
ChatSelectors.relatedViewsButton().click();
|
|
ChatSelectors.relatedViewsPopover().should('be.visible');
|
|
cy.get('body').type('{esc}');
|
|
ChatSelectors.relatedViewsPopover().should('not.exist');
|
|
});
|
|
});
|
|
|
|
it('tests chat input message handling', () => {
|
|
cy.on('uncaught:exception', (err: Error) => {
|
|
if (err.message.includes('No workspace or service found') ||
|
|
err.message.includes('View not found') ||
|
|
err.message.includes('WebSocket') ||
|
|
err.message.includes('connection') ||
|
|
err.message.includes('Failed to load models') ||
|
|
err.message.includes('Minified React error')) {
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
|
|
cy.visit('/login', { failOnStatusCode: false });
|
|
cy.wait(2000);
|
|
|
|
const authUtils = new AuthTestUtils();
|
|
authUtils.signInWithTestUrl(testEmail).then(() => {
|
|
cy.url().should('include', '/app');
|
|
|
|
SidebarSelectors.pageHeader().should('be.visible', { timeout: 30000 });
|
|
PageSelectors.items().should('exist', { timeout: 30000 });
|
|
cy.wait(2000);
|
|
|
|
TestTool.expandSpace();
|
|
cy.wait(1000);
|
|
|
|
PageSelectors.items()
|
|
.first()
|
|
.trigger('mouseenter', { force: true })
|
|
.trigger('mouseover', { force: true });
|
|
|
|
cy.wait(1000);
|
|
|
|
AddPageSelectors.inlineAddButton().first().click({ force: true });
|
|
AddPageSelectors.addAIChatButton().should('be.visible').click();
|
|
|
|
cy.wait(3000); // Wait for chat to fully load
|
|
|
|
// Mock API endpoints with more realistic responses
|
|
cy.intercept('POST', '**/api/chat/**/message/question', (req) => {
|
|
req.reply({
|
|
statusCode: 200,
|
|
body: {
|
|
code: 0,
|
|
data: {
|
|
message_id: Date.now().toString(),
|
|
content: req.body.content || 'Test message',
|
|
chat_id: 'test-chat-id',
|
|
},
|
|
message: 'success',
|
|
},
|
|
});
|
|
}).as('submitQuestion');
|
|
|
|
cy.intercept('POST', '**/api/chat/**/answer/stream', (req) => {
|
|
req.reply({
|
|
statusCode: 200,
|
|
body: 'data: {"content":"Test response","type":"message"}\n\n',
|
|
headers: {
|
|
'content-type': 'text/event-stream',
|
|
},
|
|
});
|
|
}).as('streamAnswer');
|
|
|
|
// Get the textarea using a more flexible selector
|
|
const getTextarea = () => cy.get('textarea').first();
|
|
|
|
// Test 1: Check textarea exists and is ready
|
|
cy.log('Testing textarea availability');
|
|
getTextarea().should('exist').and('be.visible');
|
|
|
|
// Test 2: Keyboard interactions with better waits
|
|
cy.log('Testing keyboard interactions');
|
|
getTextarea()
|
|
.should('not.be.disabled')
|
|
.clear()
|
|
.type('First line')
|
|
.should((el) => {
|
|
expect(el.val()).to.include('First line');
|
|
});
|
|
|
|
cy.wait(500);
|
|
|
|
getTextarea()
|
|
.type('{shift+enter}Second line')
|
|
.should((el) => {
|
|
expect(el.val()).to.include('First line\nSecond line');
|
|
});
|
|
|
|
// Test 3: Textarea auto-resize
|
|
cy.log('Testing auto-resize');
|
|
getTextarea().then($textarea => {
|
|
const initialHeight = $textarea.height();
|
|
cy.wrap($textarea)
|
|
.clear()
|
|
.type('Line 1{shift+enter}Line 2{shift+enter}Line 3{shift+enter}Line 4');
|
|
|
|
cy.wait(500);
|
|
|
|
getTextarea().then($resized => {
|
|
const newHeight = $resized.height();
|
|
cy.log(`Initial height: ${initialHeight}, New height: ${newHeight}`);
|
|
expect(newHeight).to.be.at.least(initialHeight!);
|
|
});
|
|
});
|
|
|
|
// Test 4: Button states with better selectors
|
|
cy.log('Testing button states');
|
|
getTextarea().clear();
|
|
cy.wait(500);
|
|
|
|
// Check send button is disabled when empty
|
|
ChatSelectors.sendButton().should('exist');
|
|
ChatSelectors.sendButton().then($button => {
|
|
// Button might be disabled via attribute or opacity
|
|
const isDisabled = $button.prop('disabled') || $button.css('opacity') === '0.5';
|
|
expect(isDisabled).to.be.true;
|
|
});
|
|
|
|
// Type message and check button becomes enabled
|
|
getTextarea().type('Test message');
|
|
cy.wait(500);
|
|
|
|
ChatSelectors.sendButton().then($button => {
|
|
const isDisabled = $button.prop('disabled') || $button.css('opacity') === '0.5';
|
|
expect(isDisabled).to.be.false;
|
|
});
|
|
|
|
// Test 5: Message sending with proper waits
|
|
cy.log('Testing message sending');
|
|
getTextarea().clear().type('Hello world');
|
|
cy.wait(500);
|
|
|
|
ChatSelectors.sendButton().click();
|
|
cy.wait('@submitQuestion', { timeout: 10000 });
|
|
|
|
// Wait for textarea to be ready again
|
|
cy.wait(2000);
|
|
|
|
getTextarea()
|
|
.should('exist')
|
|
.and('be.visible')
|
|
.and('have.value', '');
|
|
|
|
// Test 6: Special characters with simpler approach
|
|
cy.log('Testing special characters');
|
|
cy.wait(1000);
|
|
|
|
const specialMessage = 'Test with special: @#$%';
|
|
getTextarea()
|
|
.should('not.be.disabled')
|
|
.clear()
|
|
.type(specialMessage);
|
|
|
|
cy.wait(500);
|
|
|
|
getTextarea().should((el) => {
|
|
expect(el.val()).to.equal(specialMessage);
|
|
});
|
|
|
|
// Test 7: Enter sends message with better handling
|
|
cy.log('Testing Enter key');
|
|
getTextarea().clear();
|
|
cy.wait(500);
|
|
|
|
getTextarea().type('Quick test{enter}');
|
|
cy.wait('@submitQuestion', { timeout: 10000 });
|
|
|
|
cy.wait(2000);
|
|
getTextarea()
|
|
.should('exist')
|
|
.and('have.value', '');
|
|
});
|
|
});
|
|
});
|