diff --git a/web/src/BrowserList.jsx b/web/src/BrowserList.jsx
index 0ef4f2a..04024ea 100644
--- a/web/src/BrowserList.jsx
+++ b/web/src/BrowserList.jsx
@@ -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 {statusLabels[state] || state}
+ return {label || '未知状态'}{label ? null : {state}}
}
function RuntimeActions({ runtime, busy, onAction }) {
@@ -67,7 +68,7 @@ function RuntimeTable({ runtimes, busy, onAction }) {
}
function RuntimeCards({ runtimes, busy, onAction }) {
- return {runtimes.map(runtime => {runtime.name}{runtime.status}{runtime.profile})}
+ return {runtimes.map(runtime => {runtime.name}{runtime.status}{runtime.profile}CDP{runtime.endpoint})}
}
export function BrowserList() {
diff --git a/web/src/BrowserList.test.jsx b/web/src/BrowserList.test.jsx
index d5c43eb..abfafed 100644
--- a/web/src/BrowserList.test.jsx
+++ b/web/src/BrowserList.test.jsx
@@ -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()
+
+ 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()
+
+ 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()
diff --git a/web/src/theme.js b/web/src/theme.js
index 384867e..dd91f65 100644
--- a/web/src/theme.js
+++ b/web/src/theme.js
@@ -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: {