summaryrefslogtreecommitdiff
path: root/llama.cpp/tools/server/webui/tests/stories/ChatForm.stories.svelte
diff options
context:
space:
mode:
authorMitja Felicijan <mitja.felicijan@gmail.com>2026-02-12 20:57:17 +0100
committerMitja Felicijan <mitja.felicijan@gmail.com>2026-02-12 20:57:17 +0100
commitb333b06772c89d96aacb5490d6a219fba7c09cc6 (patch)
tree211df60083a5946baa2ed61d33d8121b7e251b06 /llama.cpp/tools/server/webui/tests/stories/ChatForm.stories.svelte
downloadllmnpc-b333b06772c89d96aacb5490d6a219fba7c09cc6.tar.gz
Engage!
Diffstat (limited to 'llama.cpp/tools/server/webui/tests/stories/ChatForm.stories.svelte')
-rw-r--r--llama.cpp/tools/server/webui/tests/stories/ChatForm.stories.svelte161
1 files changed, 161 insertions, 0 deletions
diff --git a/llama.cpp/tools/server/webui/tests/stories/ChatForm.stories.svelte b/llama.cpp/tools/server/webui/tests/stories/ChatForm.stories.svelte
new file mode 100644
index 0000000..18319e8
--- /dev/null
+++ b/llama.cpp/tools/server/webui/tests/stories/ChatForm.stories.svelte
@@ -0,0 +1,161 @@
+<script module lang="ts">
+ import { defineMeta } from '@storybook/addon-svelte-csf';
+ import ChatForm from '$lib/components/app/chat/ChatForm/ChatForm.svelte';
+ import { expect } from 'storybook/test';
+ import { mockServerProps, mockConfigs } from './fixtures/storybook-mocks';
+ import jpgAsset from './fixtures/assets/1.jpg?url';
+ import svgAsset from './fixtures/assets/hf-logo.svg?url';
+ import pdfAsset from './fixtures/assets/example.pdf?raw';
+
+ const { Story } = defineMeta({
+ title: 'Components/ChatScreen/ChatForm',
+ component: ChatForm,
+ parameters: {
+ layout: 'centered'
+ }
+ });
+
+ let fileAttachments = $state([
+ {
+ id: '1',
+ name: '1.jpg',
+ type: 'image/jpeg',
+ size: 44891,
+ preview: jpgAsset,
+ file: new File([''], '1.jpg', { type: 'image/jpeg' })
+ },
+ {
+ id: '2',
+ name: 'hf-logo.svg',
+ type: 'image/svg+xml',
+ size: 1234,
+ preview: svgAsset,
+ file: new File([''], 'hf-logo.svg', { type: 'image/svg+xml' })
+ },
+ {
+ id: '3',
+ name: 'example.pdf',
+ type: 'application/pdf',
+ size: 351048,
+ file: new File([pdfAsset], 'example.pdf', { type: 'application/pdf' })
+ }
+ ]);
+</script>
+
+<Story
+ name="Default"
+ args={{ class: 'max-w-[56rem] w-[calc(100vw-2rem)]' }}
+ play={async ({ canvas, userEvent }) => {
+ mockServerProps(mockConfigs.noModalities);
+
+ const textarea = await canvas.findByRole('textbox');
+ const submitButton = await canvas.findByRole('button', { name: 'Send' });
+
+ // Expect the input to be focused after the component is mounted
+ await expect(textarea).toHaveFocus();
+
+ // Expect the submit button to be disabled
+ await expect(submitButton).toBeDisabled();
+
+ const text = 'What is the meaning of life?';
+
+ await userEvent.clear(textarea);
+ await userEvent.type(textarea, text);
+
+ await expect(textarea).toHaveValue(text);
+
+ const fileInput = document.querySelector('input[type="file"]');
+ await expect(fileInput).not.toHaveAttribute('accept');
+
+ // Open file attachments dropdown
+ const fileUploadButton = canvas.getByText('Attach files');
+ await userEvent.click(fileUploadButton);
+
+ // Check dropdown menu items are disabled (no modalities)
+ const imagesButton = document.querySelector('.images-button');
+ const audioButton = document.querySelector('.audio-button');
+
+ await expect(imagesButton).toHaveAttribute('data-disabled');
+ await expect(audioButton).toHaveAttribute('data-disabled');
+
+ // Close dropdown by pressing Escape
+ await userEvent.keyboard('{Escape}');
+ }}
+/>
+
+<Story name="Loading" args={{ class: 'max-w-[56rem] w-[calc(100vw-2rem)]', isLoading: true }} />
+
+<Story
+ name="VisionModality"
+ args={{ class: 'max-w-[56rem] w-[calc(100vw-2rem)]' }}
+ play={async ({ canvas, userEvent }) => {
+ mockServerProps(mockConfigs.visionOnly);
+
+ // Open file attachments dropdown and verify it works
+ const fileUploadButton = canvas.getByText('Attach files');
+ await userEvent.click(fileUploadButton);
+
+ // Verify dropdown menu items exist
+ const imagesButton = document.querySelector('.images-button');
+ const audioButton = document.querySelector('.audio-button');
+
+ await expect(imagesButton).toBeInTheDocument();
+ await expect(audioButton).toBeInTheDocument();
+
+ // Close dropdown by pressing Escape
+ await userEvent.keyboard('{Escape}');
+
+ console.log('✅ Vision modality: Dropdown menu verified');
+ }}
+/>
+
+<Story
+ name="AudioModality"
+ args={{ class: 'max-w-[56rem] w-[calc(100vw-2rem)]' }}
+ play={async ({ canvas, userEvent }) => {
+ mockServerProps(mockConfigs.audioOnly);
+
+ // Open file attachments dropdown and verify it works
+ const fileUploadButton = canvas.getByText('Attach files');
+ await userEvent.click(fileUploadButton);
+
+ // Verify dropdown menu items exist
+ const imagesButton = document.querySelector('.images-button');
+ const audioButton = document.querySelector('.audio-button');
+
+ await expect(imagesButton).toBeInTheDocument();
+ await expect(audioButton).toBeInTheDocument();
+
+ // Close dropdown by pressing Escape
+ await userEvent.keyboard('{Escape}');
+
+ console.log('✅ Audio modality: Dropdown menu verified');
+ }}
+/>
+
+<Story
+ name="FileAttachments"
+ args={{
+ class: 'max-w-[56rem] w-[calc(100vw-2rem)]',
+ uploadedFiles: fileAttachments
+ }}
+ play={async ({ canvas }) => {
+ mockServerProps(mockConfigs.bothModalities);
+
+ const jpgAttachment = canvas.getByAltText('1.jpg');
+ const svgAttachment = canvas.getByAltText('hf-logo.svg');
+ const pdfFileExtension = canvas.getByText('PDF');
+ const pdfAttachment = canvas.getByText('example.pdf');
+ const pdfSize = canvas.getByText('342.82 KB');
+
+ await expect(jpgAttachment).toBeInTheDocument();
+ await expect(jpgAttachment).toHaveAttribute('src', jpgAsset);
+
+ await expect(svgAttachment).toBeInTheDocument();
+ await expect(svgAttachment).toHaveAttribute('src', svgAsset);
+
+ await expect(pdfFileExtension).toBeInTheDocument();
+ await expect(pdfAttachment).toBeInTheDocument();
+ await expect(pdfSize).toBeInTheDocument();
+ }}
+/>