diff --git a/cypress/e2e/tools.cy.ts b/cypress/e2e/tools.cy.ts new file mode 100644 index 000000000..4068f2dd0 --- /dev/null +++ b/cypress/e2e/tools.cy.ts @@ -0,0 +1,98 @@ +// eslint-disable-next-line @typescript-eslint/triple-slash-reference +/// + +// These tests run through the chat flow. +describe('Settings', () => { + // Wait for 2 seconds after all tests to fix an issue with Cypress's video recording missing the last few frames + after(() => { + // eslint-disable-next-line cypress/no-unnecessary-waiting + cy.wait(2000); + }); + + beforeEach(() => { + // Login as the admin user + cy.loginAdmin(); + // Visit the home page + cy.visit('/'); + }); + + context('Ollama', () => { + it('user can select a model', () => { + // Click on the model selector + cy.get('button[aria-label="Select a model"]').click(); + // Select the first model + cy.get('button[aria-label="model-item"]').first().click(); + }); + + it('user can add tool', () => { + // Click on the add tool button + cy.visit("/workspace/tools/create") + + // TODO: better way to get these! + cy.get('input[placeholder="Toolkit Name (e.g. My ToolKit)"]') + .type('My Custom Toolkit Name'); + + cy.get('input[placeholder="Toolkit ID (e.g. my_toolkit)"]') + .type('my_custom_toolkit'); + + cy.get('input[placeholder="Toolkit Description (e.g. A toolkit for performing various operations)"]') + .type('This is a custom toolkit for various operations.'); + + cy.contains('button', 'Save').click(); + cy.contains('button', 'Confirm').click(); + }); + + it('user can chat using tool', () => { + cy.visit("/"); + + // Open the tools menu + cy.get('div[aria-label="More"]') + .find('button') + .click({ force: true }); + + // TODO: better way to get this! + cy.get('div.max-h-28.overflow-y-auto.scrollbar-hidden') // Select the container div + .find('div.flex').first().find('button').click(); // Enable first tool + + // Click on the model selector + cy.get('button[aria-label="Select a model"]').click(); + // Select the first model + cy.get('button[aria-label="model-item"]').first().click(); + // Type a message + cy.get('#chat-textarea').type('What\'s 12786/9487+897/900? Make sure you answer with at least 5 digits after the decimal.', { + force: true + }); + // Send the message + cy.get('button[type="submit"]').click(); + // User's message should be visible + cy.get('.chat-user').should('exist'); + // Wait for the response + // .chat-assistant is created after the first token is received + cy.get('.chat-assistant', { timeout: 10_000 }).should('exist'); + // Generation should contain the answer from calculator tool + cy.get('.chat-assistant', { timeout: 10_000 }).should('contain.text', '2.3444'); + // Generation Info is created after the stop token is received + cy.get('div[aria-label="Generation Info"]', { timeout: 120_000 }).should('exist'); + }); + + it('user can perform text chat', () => { + // Click on the model selector + cy.get('button[aria-label="Select a model"]').click(); + // Select the first model + cy.get('button[aria-label="model-item"]').first().click(); + // Type a message + cy.get('#chat-textarea').type('Hi, what can you do? A single sentence only please.', { + force: true + }); + // Send the message + cy.get('button[type="submit"]').click(); + // User's message should be visible + cy.get('.chat-user').should('exist'); + // Wait for the response + // .chat-assistant is created after the first token is received + cy.get('.chat-assistant', { timeout: 10_000 }).should('exist'); + // Generation Info is created after the stop token is received + cy.get('div[aria-label="Generation Info"]', { timeout: 120_000 }).should('exist'); + }); + }); +}); diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index bfd5b3001..663339687 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -567,7 +567,7 @@ {/if} -
+