HH-789 / HH-793: align theme tokens and BrowserList contract (#16)
This commit is contained in:
@@ -30,8 +30,9 @@ const statusLabels = {
|
||||
}
|
||||
|
||||
function Status({ state }) {
|
||||
const label = statusLabels[state]
|
||||
const color = state === 'running' ? 'success.main' : state === 'exited' ? 'warning.main' : 'text.secondary'
|
||||
return <Box sx={{ display: 'inline-flex', alignItems: 'center', gap: 1, color, fontWeight: 650 }}><Box sx={{ width: 8, height: 8, borderRadius: '50%', bgcolor: 'currentColor' }} />{statusLabels[state] || state}</Box>
|
||||
return <Box sx={{ display: 'inline-flex', alignItems: 'center', gap: 1, color, fontWeight: 650 }}><Box sx={{ width: 8, height: 8, borderRadius: '50%', bgcolor: 'currentColor' }} /><Box><Typography component="span" fontWeight="inherit">{label || '未知状态'}</Typography>{label ? null : <Typography component="span" variant="caption" color="text.secondary" sx={{ display: 'block' }}>{state}</Typography>}</Box></Box>
|
||||
}
|
||||
|
||||
function RuntimeActions({ runtime, busy, onAction }) {
|
||||
@@ -67,7 +68,7 @@ function RuntimeTable({ runtimes, busy, onAction }) {
|
||||
}
|
||||
|
||||
function RuntimeCards({ runtimes, busy, onAction }) {
|
||||
return <Stack spacing={2} sx={{ display: { xs: 'flex', md: 'none' } }}>{runtimes.map(runtime => <Paper key={runtime.id} variant="outlined" sx={{ p: 2.5 }}><Stack spacing={1.5}><Box><Typography fontWeight={700}>{runtime.name}</Typography><Typography variant="caption" color="text.secondary">{runtime.status}</Typography></Box><Status state={runtime.state} /><Typography component="code" variant="body2" sx={{ overflowWrap: 'anywhere' }}>{runtime.profile}</Typography><RuntimeActions runtime={runtime} busy={busy === runtime.name} onAction={onAction} /></Stack></Paper>)}</Stack>
|
||||
return <Stack spacing={2} sx={{ display: { xs: 'flex', md: 'none' } }}>{runtimes.map(runtime => <Paper key={runtime.id} variant="outlined" sx={{ p: 2.5 }}><Stack spacing={1.5}><Box><Typography fontWeight={700}>{runtime.name}</Typography><Typography variant="caption" color="text.secondary">{runtime.status}</Typography></Box><Status state={runtime.state} /><Typography component="code" variant="body2" sx={{ overflowWrap: 'anywhere' }}>{runtime.profile}</Typography><Box><Typography variant="caption" color="text.secondary">CDP</Typography><Typography component="code" variant="body2" sx={{ display: 'block', overflowWrap: 'anywhere' }}>{runtime.endpoint}</Typography></Box><RuntimeActions runtime={runtime} busy={busy === runtime.name} onAction={onAction} /></Stack></Paper>)}</Stack>
|
||||
}
|
||||
|
||||
export function BrowserList() {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import { CoreAdminContext } from 'ra-core'
|
||||
import { BrowserList } from './BrowserList'
|
||||
import { theme } from './theme'
|
||||
|
||||
afterEach(cleanup)
|
||||
|
||||
@@ -21,6 +22,30 @@ function provider(overrides = {}) {
|
||||
}
|
||||
|
||||
describe('BrowserList', () => {
|
||||
it('uses the semantic design colors', () => {
|
||||
expect(theme.palette.text.secondary).toBe('#475467')
|
||||
expect(theme.palette.success.main).toBe('#067647')
|
||||
expect(theme.palette.warning.main).toBe('#B54708')
|
||||
expect(theme.palette.error.main).toBe('#B42318')
|
||||
})
|
||||
|
||||
it('keeps CDP data in desktop and mobile views', async () => {
|
||||
render(<CoreAdminContext dataProvider={provider()}><BrowserList /></CoreAdminContext>)
|
||||
|
||||
expect(await screen.findAllByText('http://account-a:9222')).toHaveLength(2)
|
||||
expect(screen.getAllByText('CDP')).toHaveLength(3)
|
||||
})
|
||||
|
||||
it('shows unknown states with their raw value as secondary evidence', async () => {
|
||||
const unknownRuntime = { ...runtimes[0], state: 'dead' }
|
||||
render(<CoreAdminContext dataProvider={provider({ getList: vi.fn().mockResolvedValue({ data: [unknownRuntime], total: 1 }) })}><BrowserList /></CoreAdminContext>)
|
||||
|
||||
expect(await screen.findAllByText('未知状态')).toHaveLength(2)
|
||||
const rawStates = screen.getAllByText('dead')
|
||||
expect(rawStates).toHaveLength(2)
|
||||
expect(rawStates[0].className).toContain('MuiTypography-caption')
|
||||
})
|
||||
|
||||
it('disables invalid lifecycle actions and sends explicit domain actions', async () => {
|
||||
const dataProvider = provider()
|
||||
render(<CoreAdminContext dataProvider={dataProvider}><BrowserList /></CoreAdminContext>)
|
||||
|
||||
+4
-4
@@ -6,11 +6,11 @@ export const theme = createTheme({
|
||||
primary: { main: '#0866ef', dark: '#0759d4' },
|
||||
secondary: { main: '#061a38' },
|
||||
background: { default: '#ffffff', paper: '#ffffff' },
|
||||
text: { primary: '#111827', secondary: '#667085' },
|
||||
text: { primary: '#111827', secondary: '#475467' },
|
||||
divider: '#d7dde7',
|
||||
success: { main: '#079455' },
|
||||
warning: { main: '#d97706' },
|
||||
error: { main: '#dc2626' },
|
||||
success: { main: '#067647' },
|
||||
warning: { main: '#B54708' },
|
||||
error: { main: '#B42318' },
|
||||
},
|
||||
shape: { borderRadius: 8 },
|
||||
typography: {
|
||||
|
||||
Reference in New Issue
Block a user