-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
fix(ui): Add tracing inline settings back and create UI tests #9027
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| --- | ||
| name: 'UI E2E Tests' | ||
|
|
||
| on: | ||
| pull_request: | ||
| paths: | ||
| - 'core/http/**' | ||
| - 'tests/e2e-ui/**' | ||
| - 'tests/e2e/mock-backend/**' | ||
| push: | ||
| branches: | ||
| - master | ||
|
|
||
| concurrency: | ||
| group: ci-tests-ui-e2e-${{ github.head_ref || github.ref }}-${{ github.repository }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| tests-ui-e2e: | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| matrix: | ||
| go-version: ['1.26.x'] | ||
| steps: | ||
| - name: Clone | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| submodules: true | ||
| - name: Setup Go ${{ matrix.go-version }} | ||
| uses: actions/setup-go@v5 | ||
| with: | ||
| go-version: ${{ matrix.go-version }} | ||
| cache: false | ||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v6 | ||
| with: | ||
| node-version: '22' | ||
| - name: Proto Dependencies | ||
| run: | | ||
| curl -L -s https://github.com/protocolbuffers/protobuf/releases/download/v26.1/protoc-26.1-linux-x86_64.zip -o protoc.zip && \ | ||
| unzip -j -d /usr/local/bin protoc.zip bin/protoc && \ | ||
| rm protoc.zip | ||
| go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.34.2 | ||
| go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@1958fcbe2ca8bd93af633f11e97d44e567e945af | ||
| - name: System Dependencies | ||
| run: | | ||
| sudo apt-get update | ||
| sudo apt-get install -y build-essential libopus-dev | ||
| - name: Build UI test server | ||
| run: PATH="$PATH:$HOME/go/bin" make build-ui-test-server | ||
| - name: Install Playwright | ||
| working-directory: core/http/react-ui | ||
| run: | | ||
| npm install | ||
| npx playwright install --with-deps chromium | ||
| - name: Run Playwright tests | ||
| working-directory: core/http/react-ui | ||
| run: npx playwright test | ||
| - name: Upload Playwright report | ||
| if: ${{ failure() }} | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: playwright-report | ||
| path: core/http/react-ui/playwright-report/ | ||
| retention-days: 7 | ||
| - name: Setup tmate session if tests fail | ||
| if: ${{ failure() }} | ||
| uses: mxschmitt/action-tmate@v3.23 | ||
| with: | ||
| detached: true | ||
| connect-timeout-seconds: 180 | ||
| limit-access-to-actor: true |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| import { test, expect } from '@playwright/test' | ||
|
|
||
| test.describe('Navigation', () => { | ||
| test('/ redirects to /app', async ({ page }) => { | ||
| await page.goto('/') | ||
| await expect(page).toHaveURL(/\/app/) | ||
| }) | ||
|
|
||
| test('/app shows home page with LocalAI title', async ({ page }) => { | ||
| await page.goto('/app') | ||
| await expect(page.locator('.sidebar')).toBeVisible() | ||
| await expect(page.getByRole('heading', { name: 'How can I help you today?' })).toBeVisible() | ||
| }) | ||
|
|
||
| test('sidebar traces link navigates to /app/traces', async ({ page }) => { | ||
| await page.goto('/app') | ||
| const tracesLink = page.locator('a.nav-item[href="/app/traces"]') | ||
| await expect(tracesLink).toBeVisible() | ||
| await tracesLink.click() | ||
| await expect(page).toHaveURL(/\/app\/traces/) | ||
| await expect(page.getByRole('heading', { name: 'Traces', exact: true })).toBeVisible() | ||
| }) | ||
| }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| import { test, expect } from '@playwright/test' | ||
|
|
||
| test.describe('Traces Settings', () => { | ||
| test.beforeEach(async ({ page }) => { | ||
| await page.goto('/app/traces') | ||
| // Wait for settings panel to load | ||
| await expect(page.locator('text=Tracing is')).toBeVisible({ timeout: 10_000 }) | ||
| }) | ||
|
|
||
| test('settings panel is visible on page load', async ({ page }) => { | ||
| await expect(page.locator('text=Tracing is')).toBeVisible() | ||
| }) | ||
|
|
||
| test('expand and collapse settings', async ({ page }) => { | ||
| // The test server starts with tracing enabled, so the panel starts collapsed | ||
| const settingsHeader = page.locator('button', { hasText: 'Tracing is' }) | ||
|
|
||
| // Click to expand | ||
| await settingsHeader.click() | ||
| await expect(page.locator('text=Enable Tracing')).toBeVisible() | ||
|
|
||
| // Click to collapse | ||
| await settingsHeader.click() | ||
| await expect(page.locator('text=Enable Tracing')).not.toBeVisible() | ||
| }) | ||
|
|
||
| test('toggle tracing on and off', async ({ page }) => { | ||
| // Expand settings | ||
| const settingsHeader = page.locator('button', { hasText: 'Tracing is' }) | ||
| await settingsHeader.click() | ||
| await expect(page.locator('text=Enable Tracing')).toBeVisible() | ||
|
|
||
| // The Toggle component is a <label> wrapping a hidden checkbox. | ||
| // Target the checkbox within the settings panel. | ||
| const checkbox = page.locator('input[type="checkbox"]') | ||
|
|
||
| // Initially enabled (server starts with tracing on) | ||
| await expect(checkbox).toBeChecked() | ||
|
|
||
| // Click the label (parent) to toggle off | ||
| await checkbox.locator('..').click() | ||
| await expect(checkbox).not.toBeChecked() | ||
|
|
||
| // Click again to re-enable | ||
| await checkbox.locator('..').click() | ||
| await expect(checkbox).toBeChecked() | ||
| }) | ||
|
|
||
| test('set max items value', async ({ page }) => { | ||
| // Expand settings | ||
| await page.locator('button', { hasText: 'Tracing is' }).click() | ||
| await expect(page.locator('text=Enable Tracing')).toBeVisible() | ||
|
|
||
| const maxItemsInput = page.locator('input[type="number"]') | ||
| await maxItemsInput.fill('500') | ||
| await expect(maxItemsInput).toHaveValue('500') | ||
| }) | ||
|
|
||
| test('save shows toast', async ({ page }) => { | ||
| // Expand settings | ||
| await page.locator('button', { hasText: 'Tracing is' }).click() | ||
|
|
||
| // Click save | ||
| await page.locator('button', { hasText: 'Save' }).click() | ||
|
|
||
| // Verify toast appears | ||
| await expect(page.locator('text=Tracing settings saved')).toBeVisible({ timeout: 5_000 }) | ||
| }) | ||
|
|
||
| test('panel collapses after save when tracing is enabled', async ({ page }) => { | ||
| // Expand settings | ||
| await page.locator('button', { hasText: 'Tracing is' }).click() | ||
| await expect(page.locator('text=Enable Tracing')).toBeVisible() | ||
|
|
||
| // Tracing is already enabled; save | ||
| await page.locator('button', { hasText: 'Save' }).click() | ||
|
|
||
| // Panel should collapse | ||
| await expect(page.locator('text=Enable Tracing')).not.toBeVisible() | ||
| }) | ||
|
|
||
| test('panel stays expanded after save when tracing is off', async ({ page }) => { | ||
| // Expand settings | ||
| await page.locator('button', { hasText: 'Tracing is' }).click() | ||
| await expect(page.locator('text=Enable Tracing')).toBeVisible() | ||
|
|
||
| // Toggle tracing off | ||
| await page.locator('input[type="checkbox"]').locator('..').click() | ||
|
|
||
| // Save | ||
| await page.locator('button', { hasText: 'Save' }).click() | ||
|
|
||
| // Panel should stay expanded since tracing is now disabled | ||
| await expect(page.locator('text=Enable Tracing')).toBeVisible() | ||
| }) | ||
| }) |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| import { defineConfig } from '@playwright/test' | ||
|
|
||
| export default defineConfig({ | ||
| testDir: './e2e', | ||
| timeout: 30_000, | ||
| retries: process.env.CI ? 2 : 0, | ||
| reporter: process.env.CI ? 'html' : 'list', | ||
| use: { | ||
| baseURL: 'http://127.0.0.1:8089', | ||
| trace: 'on-first-retry', | ||
| }, | ||
| projects: [ | ||
| { | ||
| name: 'chromium', | ||
| use: { browserName: 'chromium' }, | ||
| }, | ||
| ], | ||
| webServer: process.env.PLAYWRIGHT_EXTERNAL_SERVER ? undefined : { | ||
| command: '../../../tests/e2e-ui/ui-test-server --mock-backend=../../../tests/e2e/mock-backend/mock-backend --port=8089', | ||
| port: 8089, | ||
| timeout: 120_000, | ||
| reuseExistingServer: !process.env.CI, | ||
| }, | ||
| }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| export default function Modal({ onClose, children, maxWidth = '600px' }) { | ||
| return ( | ||
| <div style={{ | ||
| position: 'fixed', inset: 0, zIndex: 1000, | ||
| display: 'flex', alignItems: 'center', justifyContent: 'center', | ||
| background: 'var(--color-modal-backdrop)', backdropFilter: 'blur(4px)', | ||
| }} onClick={onClose}> | ||
| <div style={{ | ||
| background: 'var(--color-bg-secondary)', | ||
| border: '1px solid var(--color-border-subtle)', | ||
| borderRadius: 'var(--radius-lg)', | ||
| maxWidth, width: '90%', maxHeight: '80vh', | ||
| display: 'flex', flexDirection: 'column', | ||
| overflow: 'auto', | ||
| }} onClick={e => e.stopPropagation()}> | ||
| {children} | ||
| </div> | ||
| </div> | ||
| ) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| export default function SettingRow({ label, description, children }) { | ||
| return ( | ||
| <div style={{ | ||
| display: 'flex', alignItems: 'center', justifyContent: 'space-between', | ||
| padding: 'var(--spacing-sm) 0', | ||
| borderBottom: '1px solid var(--color-border-subtle)', | ||
| }}> | ||
| <div style={{ flex: 1, marginRight: 'var(--spacing-md)' }}> | ||
| <div style={{ fontSize: '0.875rem', fontWeight: 500 }}>{label}</div> | ||
| {description && <div style={{ fontSize: '0.75rem', color: 'var(--color-text-muted)', marginTop: 2 }}>{description}</div>} | ||
| </div> | ||
| <div style={{ flexShrink: 0 }}>{children}</div> | ||
| </div> | ||
| ) | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️