🎉 Initial commit: PiAgentUI — AI Agent Desktop & Web UI
Build & Push Frontend Docker Image / build-and-push (push) Canceled after 0s
Build Validation / validate (push) Canceled after 6s
Build & Push Backend Docker Image / build-and-push (push) Failing after 10m10s
Build & Push Gateway Docker Image / build-and-push (push) Failing after 10m9s
Build & Push Frontend Docker Image / build-and-push (push) Canceled after 0s
Build Validation / validate (push) Canceled after 6s
Build & Push Backend Docker Image / build-and-push (push) Failing after 10m10s
Build & Push Gateway Docker Image / build-and-push (push) Failing after 10m9s
A professional workspace for AI coding agents with: - Real-time streaming chat with SSE - Session management (fork, clone, tree navigation) - MCP tools browser & metadata panel - Skills browser (global, project, package sources) - Voice input & STT provider configuration - Integrated terminal & file explorer - Model selector with capability metadata - Keyboard-first UI with command palette - 8 languages (en, pt-BR, es, ja, zh-CN, ar, bn, hi) - Tauri 2 desktop app - React 19 + TypeScript + Vite 8 + Tailwind CSS 4 - Pi Agent extension runtime Originally forked from OpenCodeUI, now an independent project. License: GPL-3.0-only
This commit is contained in:
commit
b3489e1ede
983 files changed
+158475
No files matched your search
@@ -0,0 +1,86 @@
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { SttSettings } from './SttSettings'
|
||||
import { getSttSettings, updateSttSettings } from '../../../api/stt'
|
||||
|
||||
vi.mock('../../../api/stt', () => ({
|
||||
getSttSettings: vi.fn(),
|
||||
updateSttSettings: vi.fn(),
|
||||
}))
|
||||
|
||||
const SETTINGS = {
|
||||
enabled: true,
|
||||
providerKind: 'openai-compatible' as const,
|
||||
mode: 'file' as const,
|
||||
baseUrl: 'https://api.openai.com/v1',
|
||||
apiKeyConfigured: true,
|
||||
apiKeyRequired: true,
|
||||
transcriptionEndpoint: '/audio/transcriptions',
|
||||
transcriptionModel: 'gpt-4o-mini-transcribe',
|
||||
language: 'pt',
|
||||
insertMode: 'append' as const,
|
||||
}
|
||||
|
||||
describe('SttSettings', () => {
|
||||
beforeEach(() => {
|
||||
vi.mocked(getSttSettings).mockReset()
|
||||
vi.mocked(updateSttSettings).mockReset()
|
||||
vi.mocked(getSttSettings).mockResolvedValue(SETTINGS)
|
||||
vi.mocked(updateSttSettings).mockImplementation(async payload => ({
|
||||
...SETTINGS,
|
||||
...payload,
|
||||
apiKeyConfigured: true,
|
||||
language: payload.language ?? SETTINGS.language,
|
||||
}))
|
||||
})
|
||||
|
||||
it('uses the shared switch pattern for enabling voice transcription', async () => {
|
||||
render(<SttSettings />)
|
||||
|
||||
const enableSwitch = await screen.findByRole('switch', { name: 'Enable voice transcription' })
|
||||
|
||||
expect(enableSwitch).toHaveAttribute('aria-checked', 'true')
|
||||
expect(screen.queryByRole('checkbox')).not.toBeInTheDocument()
|
||||
|
||||
fireEvent.click(enableSwitch)
|
||||
expect(enableSwitch).toHaveAttribute('aria-checked', 'false')
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Save transcription settings' }))
|
||||
|
||||
await waitFor(() => expect(updateSttSettings).toHaveBeenCalledWith(expect.objectContaining({ enabled: false })))
|
||||
})
|
||||
|
||||
it('persists whether the STT provider requires an API key', async () => {
|
||||
render(<SttSettings />)
|
||||
|
||||
const requireKeySwitch = await screen.findByRole('switch', { name: 'Require voice transcription API key' })
|
||||
expect(requireKeySwitch).toHaveAttribute('aria-checked', 'true')
|
||||
|
||||
fireEvent.click(requireKeySwitch)
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Save transcription settings' }))
|
||||
|
||||
await waitFor(() =>
|
||||
expect(updateSttSettings).toHaveBeenCalledWith(expect.objectContaining({ apiKeyRequired: false })),
|
||||
)
|
||||
})
|
||||
|
||||
it('shows one complete transcription configuration instead of split transcription cards', async () => {
|
||||
render(<SttSettings />)
|
||||
|
||||
expect(await screen.findByText('Speech-to-text transcription')).toBeInTheDocument()
|
||||
expect(screen.queryByText('Transcription provider')).not.toBeInTheDocument()
|
||||
expect(screen.getByLabelText('Provider')).toHaveValue('openai-compatible')
|
||||
expect(screen.getByLabelText('Base URL')).toHaveValue('https://api.openai.com/v1')
|
||||
expect(screen.getByLabelText('Endpoint')).toHaveValue('/audio/transcriptions')
|
||||
expect(screen.getByLabelText('Model')).toHaveValue('gpt-4o-mini-transcribe')
|
||||
})
|
||||
|
||||
it('styles dropdown lists with the app select treatment', async () => {
|
||||
render(<SttSettings />)
|
||||
|
||||
const insertMode = await screen.findByLabelText('Insert mode')
|
||||
|
||||
expect(insertMode).toHaveClass('appearance-none')
|
||||
expect(insertMode.closest('[data-settings-select]')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user