Files
dsh/upstream/container/platform/test/platform-management.test.mjs

1144 lines
70 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import assert from 'node:assert/strict'
import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'
import { createServer } from 'node:http'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import test from 'node:test'
import { buildSystemPluginClient } from '../tools/build-system-plugin-client.mjs'
import { apply as applyPlatformManagement, inject, managedNetworkInternals } from '../../environment/resources/plugins/platform-management/package/lib/index.js'
import {
installProviderRouting, providerRoutingInternals,
} from '../../environment/resources/plugins/platform-management/package/lib/provider-routing.js'
const root = new URL('../../environment/resources/plugins/platform-management/package/', import.meta.url)
test('Platform Management classifies official DSH Shell subprocesses as Agent network traffic', () => {
assert.deepEqual(inject, ['subprocess'])
const environment = {
DSH_PLATFORM_AGENT_PROXY_URL: 'http://127.0.0.1:17895',
NO_PROXY: 'localhost,.example.com',
ALL_PROXY: 'http://127.0.0.1:17898',
}
const ordinary = { env: { FEATURE: 'ordinary' } }
assert.equal(managedNetworkInternals.managedSubprocessSpec(ordinary, environment), ordinary)
assert.equal(managedNetworkInternals.managedSubprocessSpec({ env: { DSH_SHELL: '1' } }, {}).env.DSH_SHELL, '1')
const managed = managedNetworkInternals.managedSubprocessSpec({
env: { DSH_SHELL: '1', FEATURE: 'kept', HTTP_PROXY: 'http://127.0.0.1:17898' },
}, environment)
assert.deepEqual(managed.env, {
DSH_SHELL: '1',
FEATURE: 'kept',
HTTP_PROXY: 'http://127.0.0.1:17895',
HTTPS_PROXY: 'http://127.0.0.1:17895',
http_proxy: 'http://127.0.0.1:17895',
https_proxy: 'http://127.0.0.1:17895',
NO_PROXY: 'localhost,.example.com',
no_proxy: 'localhost,.example.com',
ALL_PROXY: 'http://127.0.0.1:17895',
all_proxy: 'http://127.0.0.1:17895',
})
const observed = []
const subprocess = {
spawn(spec) { observed.push(['spawn', spec]); return 'spawned' },
spawnTerminal(spec) { observed.push(['terminal', spec]); return Promise.resolve('terminal') },
}
let cleanup
applyPlatformManagement({
subprocess,
on() { return () => {} },
effect(factory) { cleanup = factory() },
})
const previous = process.env.DSH_PLATFORM_AGENT_PROXY_URL
process.env.DSH_PLATFORM_AGENT_PROXY_URL = 'http://127.0.0.1:17895'
try {
assert.equal(subprocess.spawn({ env: { DSH_SHELL: '1' } }), 'spawned')
assert.equal(observed[0][1].env.HTTP_PROXY, 'http://127.0.0.1:17895')
cleanup()
subprocess.spawn({ env: { DSH_SHELL: '1' } })
assert.equal(observed[1][1].env.HTTP_PROXY, undefined)
} finally {
if (previous === undefined) delete process.env.DSH_PLATFORM_AGENT_PROXY_URL
else process.env.DSH_PLATFORM_AGENT_PROXY_URL = previous
}
})
test('Platform Management gives disabled Agent and Provider routes a real direct path', async () => {
const root = await mkdtemp(join(tmpdir(), 'dsh-direct-routing-'))
const routingStatePath = join(root, 'routing.json')
await writeFile(routingStatePath, JSON.stringify({
schema: 1,
revision: 'direct-revision',
enabled: true,
scopes: { dshCore: false, dshPlugins: false, agentNetwork: false },
modelApi: {
default: { proxyEnabled: false },
providers: {},
},
}))
try {
const spec = managedNetworkInternals.managedSubprocessSpec({
env: { DSH_SHELL: '1' },
}, {
HTTP_PROXY: 'http://127.0.0.1:17898',
HTTPS_PROXY: 'http://127.0.0.1:17898',
DSH_PLATFORM_AGENT_PROXY_URL: 'http://127.0.0.1:17895',
}, routingStatePath)
assert.equal(spec.env.HTTP_PROXY, undefined)
assert.equal(spec.env.HTTPS_PROXY, undefined)
assert.equal(spec.env.ALL_PROXY, undefined)
const listeners = new Map()
let directClosed = false
let agentClosed = false
let sharedClosed = false
const directDispatcher = { close: async () => { directClosed = true } }
const agentDispatcher = { close: async () => { agentClosed = true } }
const sharedDispatcher = { close: async () => { sharedClosed = true } }
const previousFetch = globalThis.fetch
const observed = []
globalThis.fetch = async () => { throw new Error('ambient proxy fetch must not be used') }
const remove = installProviderRouting({
on(event, callback) { listeners.set(event, callback); return () => { listeners.delete(event) } },
}, {
socketPath: join(root, 'missing.sock'),
routingStatePath,
createDirectDispatcher: () => directDispatcher,
createAgentDispatcher: () => agentDispatcher,
createSharedDispatcher: () => sharedDispatcher,
routedFetch: async (_input, init) => {
observed.push(init.dispatcher)
return { ok: true }
},
})
try {
await fetch('https://ordinary-dsh.invalid')
assert.deepEqual(observed, [directDispatcher])
const stream = listeners.get('llm/stream')({ provider: 'deepseek-official' }, () => (async function* () {
await fetch('https://provider.invalid')
yield 'direct'
})())
assert.deepEqual(await stream.next(), { value: 'direct', done: false })
assert.deepEqual(await stream.next(), { value: undefined, done: true })
assert.deepEqual(observed, [directDispatcher, directDispatcher])
await listeners.get('tools/execute')({ name: 'web_fetch' }, async () => {
await fetch('https://agent-direct.invalid')
})
assert.equal(observed.at(-1), directDispatcher)
await writeFile(routingStatePath, JSON.stringify({
schema: 1,
revision: 'proxy-revision',
enabled: true,
scopes: { dshCore: false, dshPlugins: false, agentNetwork: true },
modelApi: {
default: { proxyEnabled: true },
providers: {},
},
}))
await listeners.get('tools/execute')({ name: 'web_fetch' }, async () => {
await fetch('https://agent-proxied.invalid')
})
assert.equal(observed.at(-1), agentDispatcher)
const protectedStream = listeners.get('llm/stream')({ provider: 'deepseek-official' }, () => (async function* () {
yield 'must-not-run'
})())
await assert.rejects(protectedStream.next(), /ENOENT|ECONNREFUSED/)
const sharedDirect = listeners.get('llm/stream')({
provider: 'shared-provider', supportsIndependentRouting: false,
}, () => (async function* () {
await fetch('https://shared-direct.invalid')
yield 'shared-direct'
})())
assert.deepEqual(await sharedDirect.next(), { value: 'shared-direct', done: false })
assert.equal(observed.at(-1), directDispatcher)
await writeFile(routingStatePath, JSON.stringify({
schema: 1,
revision: 'shared-revision',
enabled: true,
scopes: { dshCore: false, dshPlugins: true, agentNetwork: false },
modelApi: {
default: { proxyEnabled: false },
providers: { 'shared-provider': { proxyEnabled: true } },
},
}))
const sharedProxied = listeners.get('llm/stream')({
provider: 'shared-provider', routingCapability: 'shared-dsh',
}, () => (async function* () {
await fetch('https://shared-proxied.invalid')
yield 'shared-proxied'
})())
assert.deepEqual(await sharedProxied.next(), { value: 'shared-proxied', done: false })
assert.equal(observed.at(-1), sharedDispatcher)
await writeFile(routingStatePath, JSON.stringify({
schema: 1,
revision: 'shared-direct-revision',
enabled: true,
scopes: { dshCore: true, dshPlugins: true, agentNetwork: false },
modelApi: {
default: { proxyEnabled: false },
providers: { 'shared-provider': { proxyEnabled: false } },
},
}))
const sharedDisabled = listeners.get('llm/stream')({
provider: 'shared-provider', supportsIndependentRouting: false,
}, () => (async function* () {
await fetch('https://shared-disabled.invalid')
yield 'shared-disabled'
})())
assert.deepEqual(await sharedDisabled.next(), { value: 'shared-disabled', done: false })
assert.equal(observed.at(-1), directDispatcher)
} finally {
remove()
globalThis.fetch = previousFetch
}
await new Promise(resolve => setImmediate(resolve))
assert.equal(directClosed, true)
assert.equal(agentClosed, true)
assert.equal(sharedClosed, true)
} finally {
await rm(root, { recursive: true, force: true })
}
})
test('Platform Management retries one Provider policy revision conflict and no more', async () => {
const root = await mkdtemp(join(tmpdir(), 'dsh-provider-revision-retry-'))
const socketPath = join(root, 'proxy.sock')
const requests = []
let revision = 'revision-one'
let conflicts = 0
const server = createServer(async (request, response) => {
const chunks = []
for await (const chunk of request) chunks.push(chunk)
const body = chunks.length === 0 ? undefined : JSON.parse(Buffer.concat(chunks).toString('utf8'))
requests.push([request.method, request.url, body])
response.setHeader('content-type', 'application/json')
if (request.method === 'GET') {
response.end(JSON.stringify({ revision }))
return
}
conflicts += 1
revision = `revision-${conflicts + 1}`
response.statusCode = 409
response.end(JSON.stringify({ error: { code: 'REVISION_CONFLICT', message: 'changed' } }))
})
await new Promise((resolve, reject) => {
server.once('error', reject)
server.listen(socketPath, resolve)
})
try {
await assert.rejects(
providerRoutingInternals.issueProviderHandle('deepseek-official', socketPath),
error => error.code === 'REVISION_CONFLICT',
)
assert.deepEqual(requests, [
['GET', '/v1/configuration', undefined],
['POST', '/v1/provider-handles', { providerId: 'deepseek-official', policyRevision: 'revision-one' }],
['GET', '/v1/configuration', undefined],
['POST', '/v1/provider-handles', { providerId: 'deepseek-official', policyRevision: 'revision-2' }],
])
} finally {
await new Promise(resolve => server.close(resolve))
await rm(root, { recursive: true, force: true })
}
})
test('Platform Management removes stale shared DSH proxy variables when routing becomes direct', () => {
const environment = {
HTTP_PROXY: 'http://127.0.0.1:17898',
HTTPS_PROXY: 'http://127.0.0.1:17898',
ALL_PROXY: 'http://127.0.0.1:17898',
NO_PROXY: 'stale.invalid',
}
managedNetworkInternals.synchronizeSharedDshEnvironment(environment, {
schema: 1,
enabled: false,
scopes: { dshCore: true, dshPlugins: true },
environment: { allProxy: 'scope-proxy' },
noProxy: { system: ['localhost', '127.0.0.1'], user: ['.example.com'] },
})
assert.equal(environment.HTTP_PROXY, undefined)
assert.equal(environment.HTTPS_PROXY, undefined)
assert.equal(environment.ALL_PROXY, undefined)
assert.equal(environment.NO_PROXY, 'localhost,127.0.0.1,.example.com')
assert.equal(environment.no_proxy, environment.NO_PROXY)
managedNetworkInternals.synchronizeSharedDshEnvironment(environment, {
schema: 1,
enabled: true,
scopes: { dshCore: false, dshPlugins: true },
environment: { allProxy: 'scope-proxy' },
noProxy: { system: ['localhost'], user: [] },
})
assert.equal(environment.HTTP_PROXY, 'http://127.0.0.1:17898')
assert.equal(environment.HTTPS_PROXY, 'http://127.0.0.1:17898')
assert.equal(environment.ALL_PROXY, 'http://127.0.0.1:17898')
})
test('Platform Management routes every valid llm/stream Provider through opaque handles', async () => {
const root = await mkdtemp(join(tmpdir(), 'dsh-provider-routing-'))
const socketPath = join(root, 'proxy.sock')
const requests = []
const server = createServer(async (request, response) => {
const chunks = []
for await (const chunk of request) chunks.push(chunk)
const body = chunks.length === 0 ? undefined : JSON.parse(Buffer.concat(chunks).toString('utf8'))
requests.push([request.method, request.url, body])
response.setHeader('content-type', 'application/json')
if (request.method === 'GET') response.end(JSON.stringify({ revision: 'revision-one' }))
else response.end(JSON.stringify({ handle: 'a'.repeat(43), policyRevision: 'revision-one' }))
})
await new Promise((resolve, reject) => {
server.once('error', reject)
server.listen(socketPath, resolve)
})
const previousFetch = globalThis.fetch
const observed = []
const dispatchers = []
globalThis.fetch = async (_input, init) => {
observed.push(init?.dispatcher ?? null)
return { ok: true }
}
const listeners = new Map()
const remove = installProviderRouting({
on(event, callback, options) {
assert.deepEqual(options, { global: true, prepend: true })
listeners.set(event, callback)
return () => { listeners.delete(event) }
},
}, {
socketPath,
routedFetch: async (_input, init) => {
observed.push(init?.dispatcher ?? null)
return { ok: true }
},
createDispatcher(options) {
const dispatcher = { options, closed: false, async close() { this.closed = true } }
dispatchers.push(dispatcher)
return dispatcher
},
})
try {
const routed = listeners.get('llm/stream')({ provider: 'deepseek-official' }, () => (async function* () {
await fetch('https://provider.invalid')
yield 'chunk'
})())
assert.deepEqual(await routed.next(), { value: 'chunk', done: false })
assert.deepEqual(await routed.next(), { value: undefined, done: true })
assert.equal(observed[0], dispatchers[0])
assert.deepEqual(dispatchers[0].options, {
uri: 'http://127.0.0.1:17897',
token: `DSH-Provider ${'a'.repeat(43)}`,
})
assert.equal(dispatchers[0].closed, true)
assert.deepEqual(requests, [
['GET', '/v1/configuration', undefined],
['POST', '/v1/provider-handles', { providerId: 'deepseek-official', policyRevision: 'revision-one' }],
])
const custom = listeners.get('llm/stream')({ provider: 'custom-provider' }, () => (async function* () {
await fetch('https://provider.invalid')
yield 'custom'
})())
assert.deepEqual(await custom.next(), { value: 'custom', done: false })
assert.equal(observed[1], dispatchers[1])
assert.deepEqual(requests.slice(-2), [
['GET', '/v1/configuration', undefined],
['POST', '/v1/provider-handles', { providerId: 'custom-provider', policyRevision: 'revision-one' }],
])
const invalid = listeners.get('llm/stream')({ provider: '../invalid' }, () => (async function* () {
await fetch('https://provider.invalid')
yield 'invalid'
})())
assert.deepEqual(await invalid.next(), { value: 'invalid', done: false })
assert.equal(observed[2], null)
} finally {
remove()
globalThis.fetch = previousFetch
await new Promise(resolve => server.close(resolve))
await rm(root, { recursive: true, force: true })
}
})
test('Platform Management keeps Provider fetch and dispatcher ownership aligned across scopes', async () => {
const root = await mkdtemp(join(tmpdir(), 'dsh-provider-scope-routing-'))
const socketPath = join(root, 'proxy.sock')
const server = createServer((request, response) => {
response.setHeader('content-type', 'application/json')
response.end(JSON.stringify(request.method === 'GET'
? { revision: 'scope-revision' }
: { handle: 'b'.repeat(43), policyRevision: 'scope-revision' }))
})
await new Promise((resolve, reject) => {
server.once('error', reject)
server.listen(socketPath, resolve)
})
const previousFetch = globalThis.fetch
globalThis.fetch = async () => ({ ok: true })
const listeners = []
const observed = []
const install = owner => installProviderRouting({
on(_event, listener) { listeners.push(listener); return () => {} },
}, {
socketPath,
createDispatcher: () => ({ owner, async close() {} }),
routedFetch: async (_input, init) => {
observed.push([owner, init.dispatcher.owner])
return { ok: true }
},
})
const removeFirst = install('first')
const removeSecond = install('second')
try {
const stream = listeners.at(-1)({ provider: 'deepseek-official' }, () => (async function* () {
await fetch('https://provider.invalid')
yield 'done'
})())
assert.deepEqual(await stream.next(), { value: 'done', done: false })
assert.deepEqual(observed, [['second', 'second']])
} finally {
removeSecond()
removeFirst()
globalThis.fetch = previousFetch
await new Promise(resolve => server.close(resolve))
await rm(root, { recursive: true, force: true })
}
})
test('Platform Management closes Provider dispatchers when a minimal stream is cancelled', async () => {
const root = await mkdtemp(join(tmpdir(), 'dsh-provider-cancel-'))
const socketPath = join(root, 'proxy.sock')
const server = createServer((request, response) => {
response.setHeader('content-type', 'application/json')
if (request.method === 'GET') response.end(JSON.stringify({ revision: 'revision-one' }))
else response.end(JSON.stringify({ handle: 'b'.repeat(43), policyRevision: 'revision-one' }))
})
await new Promise((resolve, reject) => {
server.once('error', reject)
server.listen(socketPath, resolve)
})
let listener
const dispatchers = []
const remove = installProviderRouting({
on(_event, callback) { listener = callback; return () => { listener = undefined } },
}, {
socketPath,
createDispatcher(options) {
const dispatcher = { options, closed: false, async close() { this.closed = true } }
dispatchers.push(dispatcher)
return dispatcher
},
})
try {
const stream = listener({ provider: 'deepseek-official' }, () => ({
[Symbol.asyncIterator]() {
return { next: async () => ({ value: 'unused', done: false }) }
},
}))
assert.deepEqual(await stream.return('cancelled'), { value: 'cancelled', done: true })
assert.equal(dispatchers[0].closed, true)
} finally {
remove()
await new Promise(resolve => server.close(resolve))
await rm(root, { recursive: true, force: true })
}
})
test('Platform Management declares a DSH web client and a platform-namespaced overlay row', async () => {
const packageJson = JSON.parse(await readFile(new URL('package.json', root)))
const patch = JSON.parse(await readFile(new URL('cordis.patch.json', root)))
assert.equal(packageJson.dsh.client.platform, 'web')
assert.ok(packageJson.dsh.client.inject.includes('@deepseek-ai/dsh-client-connection'))
assert.equal(packageJson.dsh.client.inject.includes('@deepseek-ai/dsh-client-runtime'), false)
assert.equal(packageJson.peerDependencies['@deepseek-ai/dsh-client-connection'], '*')
assert.equal(packageJson.peerDependencies['@deepseek-ai/dsh-client-runtime'], undefined)
assert.equal(packageJson.exports['./client'], './lib/client.bundle.js')
assert.equal(packageJson.exports['./package.json'], './package.json')
assert.equal(await readFile(new URL('lib/style.module.css', root), 'utf8').then(value => value.includes('@media (max-width: 640px)')), true)
assert.equal(packageJson.name, '@dsh-docker/platform-management')
assert.equal(packageJson.dshDocker.description.zh, '管理 DSH Docker 更新、运行维护、系统资源与登录会话。')
assert.equal(patch[0].insert[0].id, 'dsh-docker.platform-management.plugin')
})
test('Platform Management checked-in client bundle matches its source and DSH loader protocol', async () => {
const style = await readFile(new URL('lib/style.module.css', root), 'utf8')
const bundle = await readFile(new URL('lib/client.bundle.js', root), 'utf8')
const rebuilt = await buildSystemPluginClient({
pluginId: '@dsh-docker/platform-management',
sourcePath: new URL('lib/client.js', root),
stylePath: new URL('lib/style.module.css', root),
})
assert.equal(bundle, rebuilt)
assert.doesNotThrow(() => new Function(bundle))
assert.match(bundle, /^window\.__ModuleLoader__\.load\(/)
assert.doesNotMatch(bundle, /^import /m)
assert.doesNotMatch(style, /\[role=['"]dialog['"]\]/)
assert.doesNotMatch(style, /:has\(\.root\)/)
})
test('Platform Management is embedded in the official settings.section slot', async () => {
const source = await readFile(new URL('lib/client.js', root), 'utf8')
assert.match(source, /settings\.section/)
assert.match(source, /require\('@deepseek-ai\/dsh-client-ui-primitives'\)/)
assert.match(source, /function SelectMenu\(/)
assert.doesNotMatch(source, /h\('select'/)
assert.match(source, /settings\.dshPlatformManagement/)
assert.match(source, /id: 'dsh-platform-management'/)
assert.doesNotMatch(source, /dshPlatformUpdate|dsh-platform-update/)
const authentication = source.slice(source.indexOf('function AuthenticationSettings('), source.indexOf('\nfunction UpdateDashboard('))
assert.match(authentication, /`\$\{managementConsoleHref\}#auth-settings`/)
assert.doesNotMatch(source, /\/_dsh_platform\/auth\/management\/start/)
assert.match(source, /setManagementConsoleHref\(value\.managementConsoleHref/)
assert.match(source, /addEventListener\('focus', refreshManagementConsoleHref\)/)
assert.match(source, /fetch\(`/)
assert.match(source, /new EventSource/)
assert.match(source, /const value = await refresh\(\)[\s\S]*checkedOnOpen[\s\S]*void checkUpdates\('page-open'\)/)
const managementSource = source.slice(source.indexOf('function PlatformManagement('), source.indexOf('\nexport function apply('))
const refreshStatus = managementSource.slice(managementSource.indexOf('const refresh = useCallback'), managementSource.indexOf('const refreshInventory = useCallback'))
assert.match(refreshStatus, /const nextStatus = await request\('status'\)/)
assert.doesNotMatch(refreshStatus, /bundled-plugins|system-skills/)
const refreshInventory = managementSource.slice(managementSource.indexOf('const refreshInventory = useCallback'), managementSource.indexOf('const act = useCallback'))
assert.match(refreshInventory, /key === 'plugins'[\s\S]*path: 'bundled-plugins'[\s\S]*path: 'system-skills'/)
assert.match(refreshInventory, /loader\.apply\(await request\(loader\.path\)\)/)
assert.doesNotMatch(refreshInventory, /Promise\.all/)
assert.match(source, /activeTab === 'plugins' \|\| activeTab === 'skills'[\s\S]*refreshInventory\(activeTab\)/)
assert.doesNotMatch(source, /void refreshInventor(?:y|ies)\(\)[\s\S]*await refreshAndConnect\(\)/)
assert.match(source, /LIST_PAGE_SIZES = Object\.freeze\(\[5, 10, 20, 50\]\)/)
assert.match(source, /function usePaginatedItems\(key, items\)[\s\S]*items: items\.slice\(start, start \+ pageSize\)/)
assert.doesNotMatch(source, /function ListPagination[\s\S]*total <= LIST_PAGE_SIZES\[0\]/)
assert.match(source, /LIST_PAGE_SIZE_KEY_PREFIX = 'dsh-platform:plugin-page-size:'/)
assert.match(source, /h\(ListPagination, \{ pagination, total: filteredPlugins\.length, t \}\)/)
assert.match(source, /h\(ListPagination, \{ pagination, total: filteredSkills\.length, t \}\)/)
assert.match(source, /filteredPlugins = plugins\.filter\(plugin => matchesResourceSearch\(query, \[plugin\.id\]\)\)/)
assert.match(source, /filteredSkills = skills\.filter\(skill => matchesResourceSearch\(query, \[skill\.id\]\)\)/)
assert.doesNotMatch(source, /matchesResourceSearch\(query, \[(?:plugin|skill)\.id, (?:plugin|skill)\.description/)
assert.match(source, /function ListPagination[\s\S]*pagination\.lastPage[\s\S]*className: css\.pageJump/)
assert.match(source, /Math\.min\(pagination\.lastPage, Math\.max\(0, value - 1\)\)[\s\S]*setJumpValue\(String\(page \+ 1\)\)/)
assert.match(source, /function ExpandableDescription[\s\S]*scrollWidth > node\.clientWidth[\s\S]*aria-expanded/)
assert.match(source, /function scrollableAncestorPositions\(element\)[\s\S]*function restoreScrollableAncestors\(positions\)[\s\S]*current\.scrollTop = top[\s\S]*requestAnimationFrame/)
assert.match(source, /preserveScrollableAncestors\(event\.currentTarget, \(\) => setExpanded\(value => !value\)\)/)
assert.match(source, /h\('div', \{ className: css\.resourceHeading \}[\s\S]*h\('strong', null, `@dsh-docker\/\$\{plugin\.id\}`\)\),\s*h\(ExpandableDescription/)
assert.match(source, /h\('div', \{ className: css\.resourceHeading \}[\s\S]*h\('strong', null, skill\.id\)\),\s*h\(ExpandableDescription/)
assert.match(source, /function matchesResourceSearch/)
assert.match(source, /setConnection\('offline'\)/)
assert.doesNotMatch(source, /locked: '需要验证'|locked: 'Sign-in required'/)
assert.match(source, /className: css\.checkSpinner/)
assert.match(source, /function updateProgressModel\(update, t\)/)
assert.match(source, /ROLLBACK_PROGRESS_STAGE/)
assert.match(source, /const ROLLBACK_STAGE_ITEMS = Object\.freeze\([\s\S]*itemValidateRollback[\s\S]*itemRestoreSnapshot/)
assert.match(source, /stage\.key\.startsWith\('rollback'\) \? ROLLBACK_STAGE_ITEMS : UPDATE_STAGE_ITEMS/)
assert.match(source, /recoveryProgress \? progressModel\.title/)
assert.match(source, /function isRecoveryOperation\(operation\)[\s\S]*operation === 'return-stable'/)
assert.match(source, /returnStableProgress: '返回稳定通道'/)
assert.match(source, /const groupPrefix = isRecoveryOperation\(update\?\.operation\) \? 'rollback' : 'update'/)
assert.match(source, /function TransactionStageLogs\(\{ update, visible, t, onViewFullLog \}\)/)
assert.match(source, /'restoring-data': 3/)
assert.match(source, /const UPDATE_RECOVERY_STAGE_ITEMS = Object\.freeze\(\[[\s\S]*'itemSwitchPrevious'[\s\S]*'itemRestoreSnapshot'[\s\S]*'itemStartRuntime'[\s\S]*'itemCheckHealth'/)
assert.match(source, /phase === 'restoring-data'[\s\S]*'recovery:snapshot': 1[\s\S]*'recovery:health': 3/)
assert.match(source, /function transactionStageState\(index, currentIndex, status\)[\s\S]*status === 'success'[\s\S]*return 'completed'/)
assert.match(source, /setExpanded\(\{ \[currentStage\.key\]: update\.status !== 'success' \}\)/)
assert.match(source, /const toggleStage = key => \{[\s\S]*setExpanded\(value => \(\{ \.\.\.value, \[key\]: !\(value\[key\] \?\? key === currentStage\.key\) \}\)\)/)
assert.match(source, /aria-expanded': isExpanded[\s\S]*t\(isExpanded \? 'collapseStage' : 'expandStage'\)/)
assert.match(source, /'data-complete': progress === 100/)
assert.match(source, /progressLogGroupListPopulated/)
assert.match(source, /operation: String\(update\.operation \?\? 'update'\)[\s\S]*logs\/stream\?\$\{params\.toString\(\)\}/)
assert.match(source, /function LogViewer\(\{ active, focusTaskId, t \}\)/)
assert.match(source, /if \(focusTaskId\) setQuery\(String\(focusTaskId\)\)/)
assert.doesNotMatch(source, /progressVisible \? h\('div', \{ className: css\.statusLine \}/)
assert.match(source, /const failedDismissed = update\.status === 'failed'[\s\S]*dismissedProgressTaskId/)
assert.match(source, /!progressVisible && !failedDismissed && \(update\.error \|\| update\.outcome\)/)
assert.doesNotMatch(source, /onClick: \(\) => \{ void act\('rollback'/)
assert.doesNotMatch(source, /className: css\.progressSteps/)
assert.match(source, /className: `\$\{css\.progressStageMarker\} \$\{css\[`progressStageMarker/)
assert.match(source, /function stageItems\(stage, update, state, t\)/)
assert.match(source, /className: css\.progressStageItemMarker, 'aria-hidden': 'true'/)
assert.match(source, /className: css\.progressLogChevron, 'aria-hidden': 'true'/)
assert.match(source, /metricBytesCopied: '已复制 \{processed\} \/ \{total\}'/)
assert.match(source, /metricBytesRestored: '已恢复 \{processed\} \/ \{total\}'/)
assert.match(source, /metricProbationRemaining: '剩余观察 \{seconds\} 秒'/)
assert.match(source, /function probationRemainingSeconds\(update\)/)
assert.match(source, /setDismissedProgressTaskId\(String\(update\.taskId \?\? ''\)\)/)
assert.match(source, /t\(isExpanded \? 'collapseStage' : 'expandStage'\)\.replace\('\{count\}', String\(group\.entries\.length\)\)/)
assert.match(source, /progressDetailProbation: '候选 Runtime 正在持续接受健康检查,观察至 \{until\}。'/)
const style = await readFile(new URL('lib/style.module.css', root), 'utf8')
assert.match(style, /\.progress\[data-complete='true'\] span \{ width: 100% !important; transition: none; \}/)
assert.match(style, /\.progressStageMarker \{ --marker-size: 10px;/)
assert.match(style, /\.progressStageItemMarker \{ --marker-size: 10px;/)
assert.doesNotMatch(source, /[✓⟳✗○]/u)
assert.match(source, /changeChannel[\s\S]*void checkUpdates\('channel-change'\)/)
assert.match(source, /ctx\.locale\.getLocale\(\)/)
assert.match(source, /ctx\.on\('locale\/change'/)
assert.match(source, /dsh_locale/)
assert.match(source, /localizedError\(update\.error, t\)/)
assert.match(source, /localizedHoldReason\(hold, t\)/)
assert.match(source, /metadataUnavailable/)
assert.match(source, /remoteCheckError[\s\S]*remoteCheckSource === 'upstream'[\s\S]*upstreamCheckFailedNoResult[\s\S]*remoteCheckFailedNoResult/)
assert.match(source, /hasSupportedTarget/)
assert.match(source, /update\.updateAvailable !== true/)
assert.match(source, /className: css\.titleRow[\s\S]*className: css\.title[\s\S]*className: `\$\{css\.connection\}/)
assert.match(source, /ref: tabsRef, className: css\.tabs, role: 'tablist'/)
const tabs = source.slice(source.indexOf("h('div', { ref: tabsRef, className: css.tabs"), source.indexOf("\n\n h('div', {\n id: 'platform-tab-updates'"))
assert.doesNotMatch(tabs, /disabled:/)
assert.match(source, /function makeHorizontalTabStripScrollable\(tablist\)/)
assert.match(source, /addEventListener\('wheel', wheel, \{ passive: false \}\)/)
assert.match(source, /if \(event\.deltaX !== 0\) return/)
assert.match(source, /requestAnimationFrame\(animateWheel\)/)
assert.match(source, /addEventListener\('pointermove', pointerMove\)/)
assert.match(source, /if \(Math\.abs\(distance\) >= 4 && !dragged\) \{\s*dragged = true\s*tablist\.setPointerCapture\?\.\(pointerId\)/)
assert.doesNotMatch(source, /dragTarget = event\.target\s*tablist\.setPointerCapture/)
assert.match(source, /const displacedClickTarget = !dragged && event\.target !== dragTarget \? dragTarget : undefined[\s\S]*displacedClickTarget\?\.click\(\)/)
assert.match(source, /useEffect\(\(\) => makeHorizontalTabStripScrollable\(tabsRef\.current\), \[\]\)/)
assert.match(source, /role: 'tabpanel'/)
assert.match(source, /updatesTab: '更新管理', maintenanceTab: '运行维护', pluginsTab: '系统插件', skillsTab: '系统技能', authenticationTab: '认证设置', proxyTab: '代理设置'/)
assert.match(source, /updatesTab: 'Updates', maintenanceTab: 'Maintenance', pluginsTab: 'System plugins', skillsTab: 'System skills', authenticationTab: 'Authentication', proxyTab: 'Proxy'/)
assert.match(source, /\['maintenance', 'plugins', 'skills', 'proxy', 'updates', 'authentication'\]/)
assert.match(source, /authenticationRequest\('session-context'\)/)
assert.match(source, /authenticationRequest\('browser-logout', \{ method: 'POST', body: \{ scope \} \}\)/)
assert.match(authentication, /scope === 'all'[\s\S]*closePlatformStateEvents\(\)[\s\S]*authenticationRequest\('browser-logout'/)
assert.match(authentication, /catch \(nextError\) \{[\s\S]*openPlatformStateEvents\(\)/)
assert.match(authentication, /window\.setTimeout\(\(\) => setMessage\(''\), 3_000\)/)
assert.match(authentication, /window\.clearTimeout\(timer\)/)
assert.match(source, /dsh-platform access reset/)
assert.match(source, /const \[activeTab, setActiveTab\] = useState\('maintenance'\)/)
assert.match(source, /\['maintenance', 'plugins', 'skills', 'proxy', 'updates', 'authentication'\]\.map/)
assert.doesNotMatch(source, /platform-tab-(?:automatic|logs)(?:-button)?/)
assert.match(source, /h\(LogViewer, \{ active: activeTab === 'maintenance', focusTaskId: focusedLogTaskId, t \}\)/)
assert.match(source, /LOG_STREAM_LIMIT = 5_000/)
assert.match(source, /logs\/stream\?limit=\$\{String\(LOG_STREAM_LIMIT\)\}/)
assert.match(source, /const logIdentities = useRef\(new Set\(\)\)/)
assert.match(source, /const pendingEntries = useRef\(\[\]\)/)
assert.match(source, /requestAnimationFrame\(commitPendingEntries\)/)
assert.match(source, /logIdentities\.current\.has\(identity\)/)
assert.doesNotMatch(source, /previous\.some\(item => item\.identity === identity\)/)
assert.match(source, /function compactLogEntries\(entries\)/)
assert.match(source, /const \[expanded, setExpanded\] = useState/)
assert.match(source, /JSON\.stringify\(entry, null, 2\)/)
assert.match(source, /'aria-expanded': isExpanded/)
assert.match(source, /className: css\.logChevron/)
assert.match(source, /JSON\.parse\(lines\.join\('\\n'\)\)/)
assert.match(source, /message: JSON\.stringify\(value\)/)
assert.match(source, /if \(!isJsonFragment\(first\.value\.message \?\? ''\)\) compacted\.push\(first\)/)
assert.match(source, /const visibleEntries = limitProcessedLogEntries\(entries, displayLimit\)/)
assert.match(source, /replace\('\{total\}', String\(displayLimit\)\)/)
assert.match(source, /DEFAULT_LOG_DISPLAY_LIMIT = 500/)
assert.match(source, /LOG_DISPLAY_LIMITS = Object\.freeze\(\[100, 250, 500, 1_000\]\)/)
assert.match(source, /localStorage\.setItem\(LOG_DISPLAY_LIMIT_KEY, String\(value\)\)/)
assert.match(source, /logDisplayLimit: '显示条数'/)
assert.match(source, /searchLogs: '搜索日志'/)
assert.match(source, /allSources: '全部模块'/)
assert.match(source, /levelWarning: '警告'/)
assert.match(source, /autoScroll: '自动滚动'/)
assert.match(source, /clearLogView: '清空显示'/)
assert.match(source, /refreshLogs: '刷新日志'/)
assert.match(source, /refreshLogs: 'Refresh logs'/)
assert.match(source, /exportLogs: '导出日志'/)
assert.match(source, /exportLogs: 'Export logs'/)
assert.match(source, /application\/x-ndjson;charset=utf-8/)
assert.match(source, /downloadLogJsonl\(exportEntries\)/)
assert.match(source, /addEventListener\('heartbeat'/)
assert.match(source, /setStreamRevision\(value => value \+ 1\)/)
assert.match(source, /LOG_CLEAR_CUTOFF_KEY = 'dsh-platform:log-clear-cutoff'/)
assert.match(source, /sessionStorage\.setItem\(LOG_CLEAR_CUTOFF_KEY, clearCutoff\.current\)/)
assert.match(source, /isClearedLog\(entry, clearCutoff\.current\)/)
assert.match(source, /listRef\.current\.scrollTop = listRef\.current\.scrollHeight/)
assert.match(source, /requestAnimationFrame[\s\S]*requestAnimationFrame/)
assert.match(source, /\[active, autoScroll, displayLimit, entries, level, query, source\]/)
assert.match(source, /checked: autoScroll/)
const checkUpdates = source.slice(source.indexOf('const checkUpdates = useCallback'), source.indexOf('const changeChannel = useCallback'))
assert.match(checkUpdates, /await request\('check'/)
assert.doesNotMatch(checkUpdates, /await act\(/)
assert.doesNotMatch(source, /运行详情|平台日志/)
for (const route of ['status', 'check', 'update', 'channel', 'automatic-check', 'holds\\/retry', 'restart-dsh', 'bundled-plugins', 'bundled-plugins\\/action', 'bundled-plugins\\/recovery-action', 'bundled-plugins\\/discard', 'system-skills', 'system-skills\\/action', 'proxy', 'proxy\\/provider-inventory', 'proxy\\/test']) {
assert.match(source, new RegExp(`['"]${route}['"]`))
}
assert.match(source, /function ProxySettings\(\{ active, t \}\)/)
assert.match(source, /const saveConnection = async[\s\S]*candidate\(\)/)
assert.doesNotMatch(source, /const saveRules = async/)
assert.match(source, /const saveImmediate = async mutate[\s\S]*rules: 'saved'/)
assert.match(source, /schema: 1, enabled: source\.enabled === true/)
assert.match(source, /const candidate = \(\{[\s\S]*includeSecret = true[\s\S]*if \(includeSecret\)/)
assert.match(source, /saveImmediate[\s\S]*includeSecret: false/)
assert.match(source, /setPassword\(''\)[\s\S]*setClearPassword\(false\)/)
assert.match(source, /className: css\.proxyClearPassword[\s\S]*'aria-pressed': clearPassword/)
assert.match(source, /className: `\$\{css\.proxySettingRow\} \$\{css\.proxyAdvancedSetting\}`[\s\S]*className: css\.toggle[\s\S]*checked: connection\.allProxy/)
assert.match(source, /const \[providerQuery, setProviderQuery\] = useState\(''\)/)
assert.match(source, /className: `\$\{css\.section\} \$\{css\.proxyProviderSection\}`/)
assert.match(style, /\.proxyProviderSection \{ padding-bottom: 0; border-bottom: 0; \}/)
assert.match(style, /\.primaryButton,[\s\S]*?\.smallButton \{[^}]*border-radius: 18px;/)
assert.match(style, /\.smallButton \{[^}]*border-radius: 14px;/)
assert.match(style, /\.toggle > span \{[^}]*border-radius: 10px;/)
assert.match(style, /\.statusBadge \{[^}]*display: inline-flex;[^}]*min-height: 18px;[^}]*border-radius: 999px;/)
assert.match(style, /\.managedBadge \{[^}]*border-radius: 12px;/)
assert.match(style, /\.autoScrollButton,[\s\S]*?\.clearLogsButton \{[^}]*border-radius: 999px;/)
assert.match(style, /\.logAutoScroll > span \{[^}]*border-radius: 8px;/)
assert.match(source, /visibleProviders = providers\.filter[\s\S]*proxyProviderSearch/)
assert.match(source, /providerInfoDialog[\s\S]*event\.target === event\.currentTarget[\s\S]*\.close\(\)/)
assert.match(source, /function splitDirectRules\(value\)[\s\S]*noProxy:[\s\S]*bypass:/)
assert.match(source, /setDirectRulesText\(directRuleText\(next\)\)/)
assert.match(source, /proxySystemRulesTitle/)
assert.doesNotMatch(source, /const \[noProxyText|const \[bypassText/)
assert.match(source, /connectionSource\.port === '' \|\| connectionSource\.port == null \? null/)
assert.match(source, /function ExpandableProxyDescription\([\s\S]*preserveScrollableAncestors/)
assert.match(source, /const rememberToggleScroll = useCallback\([\s\S]*scrollableAncestorPositions\(event\.currentTarget\)/)
assert.match(source, /const preserveToggleScroll = useCallback\([\s\S]*toggleScrollPositions\.current \?\? scrollableAncestorPositions\(element\)[\s\S]*restoreScrollableAncestors\(positions\)/)
assert.match(source, /advanced \? h\('div', \{ className: css\.proxyAdvanced \}[\s\S]*checked: connection\.allProxy/)
assert.doesNotMatch(source, /next\.environment\.allProxy/)
assert.match(source, /visibleSaveState = formDirty \? 'unsaved' : saveState[\s\S]*3_000/)
assert.match(source, /const displayName =[\s\S]*return matchesResourceSearch\(providerQuery, \[displayName\]\)/)
assert.doesNotMatch(source, /matchesResourceSearch\(providerQuery, \[provider\.displayName, provider\.id, provider\.type\]\)/)
assert.match(source, /ref: testDialog, className: css\.proxyTestDialog/)
assert.match(source, /task\.status === 'failed' \? css\.error : css\.proxyHint/)
assert.match(source, /const toggleProxy = event =>/)
assert.match(source, /toggleProxy[\s\S]*saveImmediate\(next => \{ next\.enabled = event\.target\.checked \}\)/)
assert.ok(source.indexOf("'platform-proxy-master-title'") < source.indexOf("'platform-proxy-title'"))
assert.match(source, /h\('h3', \{ id: 'platform-proxy-master-title' \}[\s\S]*configuration\.componentReady === false[\s\S]*proxyComponentAlert/)
assert.match(source, /const componentUnavailable = configuration\.componentReady === false/)
assert.match(source, /checked: configuration\.enabled === true, disabled: busy \|\| componentUnavailable/)
assert.match(source, /disabled: busy \|\| taskRunning \|\| componentUnavailable/)
assert.match(source, /value: connection\.protocol,[\s\S]*disabled: componentUnavailable,[\s\S]*items: \[\{ id: 'http', label: 'HTTP' \}, \{ id: 'socks5', label: 'SOCKS5' \}\]/)
assert.match(source, /value: connection\.host, disabled: componentUnavailable/)
assert.match(source, /value: connection\.username, disabled: componentUnavailable/)
assert.match(source, /value: password, disabled: clearPassword \|\| componentUnavailable/)
assert.match(source, /value: directRulesText, disabled: componentUnavailable/)
assert.match(source, /value: providerQuery, disabled: componentUnavailable/)
assert.match(source, /checked: configuration\.scopes\[id\], disabled: busy \|\| componentUnavailable/)
assert.match(source, /disabled: provider\.routingCapability === 'forced-direct' \|\| componentUnavailable/)
assert.match(source, /M12 6\.5v7[\s\S]*M12 17\.5h\.01/)
assert.match(source, /ref: componentDialog[\s\S]*proxyComponentIssueTitle[\s\S]*proxyComponentIssueDetail/)
assert.doesNotMatch(source, /proxyReadyShort|proxyUnavailableShort|proxyComponentState/)
assert.match(style, /\.proxyComponentAlert circle \{[^}]*fill: var\(--dsw-alias-state-error-primary\)/)
assert.match(style, /\.proxyComponentAlert path \{ stroke: var\(--dsw-alias-label-primary-foreground\)/)
assert.match(style, /\.proxyMasterRow > div > small \{ font-size: 13px; line-height: 20px; \}/)
assert.match(style, /\.proxyAdvancedSetting > div > small \{ font-size: 13px; line-height: 20px; \}/)
assert.match(source, /h\('h4', null, t\('proxyRules'\)[\s\S]*h\('h4', null, t\('proxyAllProxy'\)/)
assert.doesNotMatch(source, /h\('span', null, t\('proxyDirectRules'\)\)/)
assert.match(source, /taskRunning[\s\S]*cancelTest\(\)[\s\S]*testDialog\.current\?\.close\(\)/)
assert.match(source, /task && !taskRunning[\s\S]*proxyTestSuccess[\s\S]*taskRunning/)
assert.doesNotMatch(source, /connection\.enabled/)
assert.match(source, /const policy = configuration\.modelApi\.providers\[provider\.id\][\s\S]*proxyEnabled:/)
assert.doesNotMatch(source, /followDsh/)
const proxySettings = source.slice(source.indexOf('function ProxySettings('), source.indexOf('\nfunction PlatformManagement('))
assert.match(proxySettings, /useEffect\(\(\) => \{\s*void load\(\)\s*\}, \[load\]\)/)
assert.match(proxySettings, /const next = await request\('proxy'\)[\s\S]*setConfiguration\(next\)[\s\S]*void refreshProviders\(\)/)
assert.doesNotMatch(proxySettings, /if \(active\) void load\(\)/)
assert.match(proxySettings, /advanced \? h\('div', \{ className: css\.proxyAdvanced \},[\s\S]*t\('proxyRules'\)[\s\S]*t\('proxyAllProxy'\)[\s\S]*connection\.protocol === 'socks5'[\s\S]*t\('proxyRemoteDns'\)/)
assert.match(source, /configuration\.scopeCatalog/)
assert.match(source, /proxyTransportWarning/)
assert.doesNotMatch(source, /setPassword\(next\.proxy|value: configuration\.proxy\.password/)
assert.doesNotMatch(source, /confirmDataLoss: true/)
assert.match(source, /status\?\.dshLifecycle/)
assert.match(source, /await request\('restart-dsh'[\s\S]*sessionStorage\.removeItem\(PLUGIN_DRAFT_KEY\)/)
assert.doesNotMatch(source, /if \(hadDraft\) sessionStorage\.removeItem\(PLUGIN_DRAFT_KEY\)/)
assert.doesNotMatch(source, /window\.location\.reload\(\)/)
assert.match(source, /const \[confirmRestart, setConfirmRestart\] = useState\(false\)/)
assert.match(source, /function transactionLogStage\(phase, update, t\)/)
assert.match(source, /taskId: String\(update\.taskId\), operation: String\(update\.operation \?\? 'update'\), limit: '1000'/)
assert.match(source, /setExpanded\(\{ \[currentStage\.key\]: update\.status !== 'success' \}\)/)
assert.match(source, /viewFullTransactionLog: '查看完整事务日志'/)
assert.match(source, /setConfirmRestart\(value => !value\)/)
assert.match(source, /'aria-controls': 'restart-dsh-confirmation'/)
assert.match(source, /'aria-expanded': confirmRestart/)
assert.match(source, /t\(confirmRestart \? 'cancelRestartDsh' : 'restartDsh'\)/)
assert.match(source, /const API = '\/_dsh_platform\/plugin-api\/v1'/)
assert.match(source, /function subscribePlatformStateEvents/)
assert.equal(source.match(/new EventSource\(`\$\{API\}\/events`\)/g)?.length, 1)
assert.doesNotMatch(source, /platformAuthRequired|platformSignIn|authRequired/)
assert.equal(source.match(/href: managementConsoleHref/g)?.length, 2)
assert.doesNotMatch(source, /href: '\/_dsh_platform\/auth\/management\/start/)
assert.match(source, /nav: '平台管理', title: '平台管理'/)
assert.match(source, /nav: 'Platform Management', title: 'Platform Management'/)
assert.match(source, /standaloneManagement: 'DSH 管理中心'/)
assert.match(source, /standaloneManagement: 'DSH Management Console'/)
assert.match(source, /restartDshSection: '重启 DSH'/)
assert.match(source, /restartDshSection: 'Restart DSH'/)
assert.match(source, /cancelRestartDsh: '取消重启 DSH'/)
assert.match(source, /cancelRestartDsh: 'Cancel DSH restart'/)
assert.match(source, /restartWarning: '当前 DSH 连接会暂时中断/)
assert.match(source, /restartWarning: 'The current DSH connection will be interrupted briefly/)
assert.match(source, /plugin\.protected/)
assert.match(source, /platformManaged: '平台核心组件,始终保持安装和启用。'/)
assert.match(source, /systemPluginsDetail: '管理 DSH Docker 提供的系统插件。'/)
assert.match(source, /plugins\.some\(plugin => plugin\.pendingRestart\)/)
assert.match(source, /visiblePlugins = pagination\.items/)
assert.match(source, /filteredPlugins = plugins\.filter[\s\S]*usePaginatedItems\('system-plugins', filteredPlugins\)/)
assert.match(source, /filteredSkills = skills\.filter[\s\S]*usePaginatedItems\('system-skills', filteredSkills\)/)
assert.match(source, /searchSystemPlugins: '搜索系统插件'/)
assert.match(source, /searchSystemSkills: '搜索系统技能'/)
assert.doesNotMatch(source, /pluginInstallHint|missingPluginsPrefix|platformManagementPage|missingPluginsSuffix/)
assert.doesNotMatch(source, /pluginPendingRestart/)
assert.match(source, /function ResourceStatusBadge/)
const systemPluginManager = source.slice(source.indexOf('function SystemPluginManager('), source.indexOf('function PlatformManagement('))
const systemSkillManager = source.slice(source.indexOf('function SystemSkillManager('), source.indexOf('function PlatformManagement('))
assert.match(systemPluginManager, /const restartRequired = draft\.size > 0 \|\| plugins\.some\(plugin => plugin\.pendingRestart\)[\s\S]*const applyingAction = restartRequired[\s\S]*applyingDraft\.get\(plugin\.id\)/)
assert.match(systemPluginManager, /h\(ResourceStatusBadge[\s\S]*enabled: applyingAction === undefined && action === undefined && plugin\.enabled, pending: applyingAction !== undefined \|\| action !== undefined/)
assert.doesNotMatch(systemPluginManager, /pluginPendingRestart/)
assert.match(systemPluginManager, /action !== undefined[\s\S]*pendingInstall[\s\S]*pendingUninstall[\s\S]*pendingEnable[\s\S]*pendingDisable/)
assert.match(source, /const applySystemPluginChanges = useCallback[\s\S]*setSystemPluginApplyingDraft\(new Map\(systemPluginDraft\)\)[\s\S]*waitForSystemPluginTask/)
assert.match(systemSkillManager, /h\(ResourceStatusBadge[\s\S]*pending: isActive/)
assert.doesNotMatch(systemPluginManager, /h\('b', null, projected\.enabled/)
assert.doesNotMatch(systemSkillManager, /h\('b', null, skill\.enabled/)
assert.doesNotMatch(systemPluginManager, /isActive \? h\('p', \{ className: css\.pluginOperation/)
assert.doesNotMatch(systemSkillManager, /isActive \? h\('p', \{ className: css\.pluginOperation/)
assert.equal(systemPluginManager.indexOf('className: css.emptyPlugins') < systemPluginManager.indexOf('h(ListPagination'), true)
assert.equal(systemSkillManager.indexOf('className: css.emptyPlugins') < systemSkillManager.indexOf('h(ListPagination'), true)
assert.match(source, /pluginChangesPending: '有待应用的修改'/)
assert.match(source, /pluginChangesPending: 'Changes pending'/)
assert.match(source, /pendingSystemPluginChanges: '有 \{count\} 项修改待应用'/)
assert.match(source, /setSystemPluginProgress\(\{ phase: 'restarting', total: changes\.length, taskId: restartTask\.taskId \}\)/)
assert.match(source, /lifecycle\?\.taskId !== systemPluginProgress\.taskId[\s\S]*\['running', 'failed', 'stopped'\]/)
assert.match(systemPluginManager, /systemPluginSummary\(progress, draft, t\)/)
assert.match(source, /setSystemPluginProgress\(\{ phase: 'applying', id, action, current: index \+ 1, total: changes\.length \}\)/)
assert.match(source, /plugin\.description\?\.\[t\('localeCode'\)\]/)
assert.match(source, /PLUGIN_DRAFT_KEY = 'dsh-platform:system-plugin-draft'/)
assert.match(source, /const \[systemPluginDraft, setSystemPluginDraft\] = useState\(\(\) => new Map\(\)\)/)
assert.match(source, /const manageSystemPlugin = useCallback\([\s\S]*setSystemPluginDraft[\s\S]*next\.set\(plugin\.id, action\)/)
assert.match(source, /const applySystemPluginChanges = useCallback\([\s\S]*for \(const \[index, \[id, action\]\] of changes\.entries\(\)\)[\s\S]*waitForSystemPluginTask\(task\.taskId\)[\s\S]*request\('restart-dsh'/)
assert.match(source, /waitForSystemPluginTask[\s\S]*request\(`bundled-plugins\/task\/\$\{taskId\}`\)/)
assert.match(source, /const cancelSystemPluginChanges = useCallback\([\s\S]*setSystemPluginDraft\(new Map\(\)\)/)
assert.match(source, /sessionStorage\.setItem\(PLUGIN_DRAFT_KEY, '1'\)/)
assert.match(source, /bundled-plugins\/discard[\s\S]*sessionStorage\.removeItem\(PLUGIN_DRAFT_KEY\)/)
assert.match(source, /\(acting && !checking\)/)
assert.match(source, /const checkingProgress = update\.operation === 'check'[\s\S]*checkingProgress[\s\S]*t\('statusChecking'\)[\s\S]*updateToTarget/)
assert.doesNotMatch(source, /插件设置并重启 DSH|settings and restarting DSH/)
for (const action of ['enable', 'disable']) assert.match(source, new RegExp(`'${action}'`))
assert.match(systemPluginManager, /!projected\.installed[\s\S]*onAction\(plugin, 'install'\)/)
assert.doesNotMatch(systemPluginManager, /onAction\([^\n]+, 'uninstall'\)|t\('uninstallPlugin'\)/)
assert.match(systemSkillManager, /!skill\.installed[\s\S]*onAction\(skill, 'install'\)/)
assert.match(systemSkillManager, /event\.target\.checked \? 'enable' : 'disable'/)
assert.doesNotMatch(systemSkillManager, /onAction\([^\n]+, 'uninstall'\)|t\('uninstallPlugin'\)/)
assert.doesNotMatch(source, /trust\/reset/)
assert.match(source, /status\?\.updateChannel === 'experimental'\s*\? h\(VersionCell, \{ label: t\('upstream'\)/)
assert.match(source, /`env-\$\{String\(value\)\}`/)
assert.equal((source.match(/detail: displayEnvironment/g) ?? []).length, 2)
assert.doesNotMatch(source, /display\(update\.status\)/)
assert.match(source, /stable: '稳定', experimental: '实验'/)
assert.match(source, /}, t\(channel\)\)\)\)\)/)
assert.doesNotMatch(source, /回滚 previous|正式 Environment|恢复 Stable|立即回 Stable/)
assert.match(source, /shell\.overlay/)
assert.match(source, /export const inject = \['slots', 'locale', 'connection'\]/)
assert.match(source, /id: 'dsh-platform-lifecycle-guard'/)
assert.match(source, /const generation = connection\.generation \?\? connection\.hostDescription/)
assert.match(source, /generation\.subscribe\(connectionChanged\)/)
assert.match(source, /CONNECTION_LOSS_GRACE_MS = 1_000/)
assert.match(source, /fetch\(LIFECYCLE_READINESS_PATH/)
assert.match(source, /response\.status === 503/)
assert.match(source, /window\.location\.replace\(lifecycleWaitUrl\(\)\)/)
assert.match(source, /encodeURIComponent\(lifecycleReturnPath\(locationValue\)\)/)
assert.match(source, /latestAutomatic/)
assert.match(source, /notificationsEnabled/)
assert.match(source, /updateNotifications: '更新提醒'/)
assert.match(source, /updateNotificationsDetail: '自动检查发现新版本时,弹窗提醒更新。'/)
assert.match(source, /updateNotifications: 'Update notifications'/)
assert.match(source, /status\?\.updateChannel === 'stable' && status\?\.latestAutomatic\?\.stable/)
assert.match(source, /status\?\.updateChannel === 'experimental' && upstream/)
assert.match(source, /stableNoticeBothTitle: '正式更新:DSH 与 Environment'/)
assert.match(source, /updateNoticeDshLine: 'DSH:\{version\}\{state\}'/)
assert.match(source, /updateNoticeEnvironmentLine: 'ENV:\{version\}\{state\}'/)
assert.match(source, /stableNoticeBothTitle: 'Supported update: DSH and Environment'/)
assert.match(source, /updateNoticeDshLine: 'DSH: \{version\}\{state\}'/)
assert.match(source, /updateNoticeEnvironmentLine: 'ENV: \{version\}\{state\}'/)
assert.doesNotMatch(source, /noticeUnchanged|保持不变|\(unchanged\)/)
assert.match(source, /不再提醒此版本/)
assert.match(source, /Do not remind for this version/)
assert.match(source, /closeReminder: '关闭更新提醒'/)
assert.match(source, /closeReminder: 'Close update reminder'/)
assert.match(source, /previousFocus\.current\?\.isConnected/)
assert.match(source, /'data-notice-action': 'snooze', 'aria-label': t\('closeReminder'\)/)
assert.match(source, /source = 'manual'/)
assert.doesNotMatch(source, /detail: t\(detailKey\)/)
})
test('update reminders identify DSH, Environment, or combined changes', async () => {
const source = await readFile(new URL('lib/client.js', root), 'utf8')
const candidatesSource = source.slice(
source.indexOf('function candidateIdentity('),
source.indexOf('\nfunction clearSatisfiedDismissals('),
)
const eligibleCandidates = new Function('storageValue', `${candidatesSource}; return eligibleCandidates`)(() => null)
const modelSource = source.slice(
source.indexOf('function updateNoticeModel('),
source.indexOf('\nfunction UpdateReminder('),
)
const updateNoticeModel = new Function(`${modelSource}; return updateNoticeModel`)()
const automatic = {
notificationsEnabled: true,
}
const latestAutomatic = {
stable: { dsh: '0.1.1-rc.2', environment: '1.0.6', targetSequence: 2 },
upstream: { version: '0.1.1-rc.3' },
}
assert.deepEqual(eligibleCandidates({ automaticCheck: automatic, latestAutomatic, updateChannel: 'stable' }).map(candidate => candidate.kind), ['stable'])
assert.deepEqual(eligibleCandidates({ automaticCheck: automatic, latestAutomatic, updateChannel: 'experimental', holds: [] }).map(candidate => candidate.kind), ['upstream'])
assert.deepEqual(updateNoticeModel({
kind: 'stable', dsh: '0.1.1-rc.2', environment: '1.0.6',
}, {
current: { dsh: '0.1.1-rc.1', environment: '1.0.5' },
}), {
kind: 'stable', scope: 'both', dsh: '0.1.1-rc.2', environment: '1.0.6',
dshChanged: true, environmentChanged: true,
})
assert.equal(updateNoticeModel({
kind: 'stable', dsh: '0.1.1-rc.1', environment: '1.0.6',
}, {
current: { dsh: '0.1.1-rc.1', environment: '1.0.5' },
}).scope, 'environment')
assert.deepEqual(updateNoticeModel({ kind: 'upstream', version: '0.1.1-rc.2' }, {
current: { dsh: '0.1.1-rc.1', environment: '1.0.6' },
supported: { environment: '1.0.6' },
}), {
kind: 'upstream', scope: 'dsh', dsh: '0.1.1-rc.2', dshChanged: true,
})
})
test('Platform Management compacts multiline JSON only in the log presentation', async () => {
const source = await readFile(new URL('lib/client.js', root), 'utf8')
const helpers = source.slice(source.indexOf('function logLevel('), source.indexOf('function LogViewer('))
const compactLogEntries = new Function(`${helpers}; return compactLogEntries`)()
const status = {
platformLayout: 1,
recoveryMode: null,
trust: { keyringGeneration: 1, targetSequence: null, officialDshVersion: null },
dshLifecycle: { state: 'running', taskId: null, error: null, updatedAt: null },
}
let index = 0
const entry = message => ({
identity: `entry-${String(index)}`,
value: {
timestamp: new Date(Date.UTC(2026, 7, 20, 0, 0, 0, index++)).toISOString(),
source: 'platform-management',
stream: 'stdout',
level: 'info',
message,
},
})
const visible = compactLogEntries([
entry('"orphanedAtBoundary": null,'),
...JSON.stringify(status, null, 2).split('\n').map(entry),
entry('ordinary output'),
entry('{"already":"compact"}'),
])
assert.deepEqual(visible.map(item => item.value.message), [
JSON.stringify(status),
'ordinary output',
'{"already":"compact"}',
])
})
test('Platform Management does not present ordinary DSH stderr as an error', async () => {
const source = await readFile(new URL('lib/client.js', root), 'utf8')
const helpers = source.slice(source.indexOf('function logLevel('), source.indexOf('function LogViewer('))
const logLevel = new Function(`${helpers}; return logLevel`)()
assert.equal(logLevel({
source: 'dsh-runtime', stream: 'stderr', level: 'error', message: '[net-proxy] 已启用代理 http://172.17.0.1:7890',
}), 'info')
assert.equal(logLevel({ source: 'dsh-runtime', stream: 'stderr', level: 'error', message: 'Error: startup failed' }), 'error')
assert.equal(logLevel({ source: 'dsh-runtime', stream: 'stderr', level: 'info', message: 'file:///app/index.js:2\nError: startup failed\n at boot' }), 'error')
assert.equal(logLevel({ source: 'dsh-runtime', stream: 'stderr', level: 'error', message: 'warning: retrying' }), 'warning')
})
test('Platform Management summarizes multiline errors until expanded', async () => {
const source = await readFile(new URL('lib/client.js', root), 'utf8')
const helpers = source.slice(source.indexOf('function logLevel('), source.indexOf('function LogViewer('))
const logMessageSummary = new Function(`${helpers}; return logMessageSummary`)()
assert.equal(logMessageSummary([
'file:///app/index.js:2',
' throw new Error("startup failed")',
'Error: startup failed',
' at boot (file:///app/index.js:2:9)',
].join('\n')), 'Error: startup failed')
assert.equal(logMessageSummary('ordinary output'), 'ordinary output')
})
test('Platform Management lifecycle guard recognizes only registered transition states', async () => {
const source = await readFile(new URL('lib/client.js', root), 'utf8')
const helpers = source.slice(
source.indexOf('function requiresLifecycleHoldingPage('),
source.indexOf('\n\nfunction display('),
)
const { requiresLifecycleHoldingPage, lifecycleWaitUrl } = new Function(
`const LIFECYCLE_WAIT_PATH = '/_dsh_gateway/wait'; ${helpers}; return { requiresLifecycleHoldingPage, lifecycleWaitUrl }`,
)()
for (const operation of ['restarting', 'switching', 'recovering', 'restart-failed']) {
assert.equal(requiresLifecycleHoldingPage({ operation }), true)
}
for (const state of ['starting', 'stopping', 'stopped', 'restarting', 'recovering', 'failed']) {
assert.equal(requiresLifecycleHoldingPage({ dshLifecycle: { state } }), true)
}
assert.equal(requiresLifecycleHoldingPage({ dshLifecycle: { state: 'running' }, update: { status: 'checking' } }), false)
assert.equal(
lifecycleWaitUrl({ pathname: '/sessions/current', search: '?view=chat', hash: '#latest' }),
'/_dsh_gateway/wait?return=%2Fsessions%2Fcurrent%3Fview%3Dchat%23latest',
)
})
test('Platform Management leaves lifecycle navigation to the global holding-page guard', async () => {
const source = await readFile(new URL('lib/client.js', root), 'utf8')
assert.match(source, /window\.location\.replace\(lifecycleWaitUrl\(\)\)/)
assert.doesNotMatch(source, /window\.location\.reload\(\)/)
assert.doesNotMatch(source, /requestedRestart/)
})
test('Platform Management limits the processed log entries instead of raw fragments', async () => {
const source = await readFile(new URL('lib/client.js', root), 'utf8')
const helpers = source.slice(source.indexOf('function logLevel('), source.indexOf('function LogViewer('))
const limitProcessedLogEntries = new Function(`${helpers}; return limitProcessedLogEntries`)()
let index = 0
const entry = message => ({
identity: `entry-${String(index)}`,
value: {
timestamp: new Date(Date.UTC(2026, 7, 20, 0, 0, 0, index++)).toISOString(),
source: 'platform-management', stream: 'stdout', level: 'info', message,
},
})
const raw = [
...JSON.stringify({ first: true }, null, 2).split('\n').map(entry),
...Array.from({ length: 1_000 }, (_, value) => entry(`line-${String(value)}`)),
]
const visible = limitProcessedLogEntries(raw, 1_000)
assert.equal(visible.length, 1_000)
assert.equal(visible[0].value.message, 'line-0')
assert.equal(visible.at(-1).value.message, 'line-999')
})
test('Platform Management keeps a browser-tab log clear cutoff across refreshes', async () => {
const source = await readFile(new URL('lib/client.js', root), 'utf8')
const helpers = source.slice(source.indexOf('function logLevel('), source.indexOf('function LogViewer('))
const values = new Function(`${helpers}; return { latestLogCutoff, isClearedLog }`)()
const now = Date.parse('2026-08-20T12:00:00.000Z')
const cutoff = values.latestLogCutoff([
{ value: { timestamp: '2026-08-20T11:59:59.000Z' } },
{ value: { timestamp: '2026-08-20T12:00:01.000Z' } },
], now)
assert.equal(cutoff, '2026-08-20T12:00:01.000Z')
assert.equal(values.isClearedLog({ timestamp: cutoff }, cutoff), true)
assert.equal(values.isClearedLog({ timestamp: '2026-08-20T12:00:01.001Z' }, cutoff), false)
assert.equal(values.isClearedLog({ timestamp: 'invalid' }, cutoff), false)
})
test('Platform Management follows DSH settings tokens and responsive layout', async () => {
const source = await readFile(new URL('lib/client.js', root), 'utf8')
const style = await readFile(new URL('lib/style.module.css', root), 'utf8')
assert.match(style, /--dsw-alias-label-primary/)
assert.match(style, /--dsw-alias-button-primary-fill/)
assert.match(style, /--dsw-alias-border-l2/)
assert.match(style, /\.progressLogGroupList \{[^}]*background: var\(--dsw-alias-bg-layer-2\);/)
assert.match(style, /\.progressLogEntry \{[^}]*background: var\(--dsw-alias-bg-layer-2\);/)
assert.doesNotMatch(style, /\.progressLogEntry:last-child \{[^}]*border-bottom: 0;/)
assert.match(style, /@media \(max-width: 640px\)/)
assert.match(style, /\.pluginRestartNotice \{[\s\S]*justify-content: space-between/)
assert.match(style, /\.pluginActions \.toggle \{ width: auto; \}/)
assert.match(style, /\.logEntry\[aria-expanded='false'\] \.logMessageRow > pre \{[^}]*white-space: nowrap;/)
assert.match(source, /className: css\.resourceHeadingDetail[\s\S]*className: css\.resourceSearch/)
assert.match(style, /\.resourceHeadingDetail \{[^}]*display: flex;[^}]*align-items: center;/)
assert.match(style, /\.resourceSearch \{[^}]*width: min\(320px, 45%\);[^}]*margin: 0 0 0 auto;/)
assert.match(style, /\.pluginIdentity > \.resourceDescription \{[^}]*display: block;[^}]*margin-top: 2px;/)
assert.match(style, /@media \(max-width: 640px\)[\s\S]*\.resourceHeadingDetail \{[^}]*flex-direction: column;[^}]*\}[\s\S]*\.resourceSearch \{[^}]*width: 100%;[^}]*margin-left: 0;/)
assert.match(source, /className: css\.platformHeader[\s\S]*className: css\.heading[\s\S]*className: css\.tabs/)
assert.match(source, /SystemPluginManager\(\{ plugins, draft, applyingDraft,[\s\S]*const applyingAction = restartRequired[\s\S]*applyingDraft\.get\(plugin\.id\)[\s\S]*statusEnabling[\s\S]*statusDisabling/)
assert.match(source, /function preserveResourceRowPosition\(element, update\)[\s\S]*current === panel\) break[\s\S]*querySelectorAll\('article'\)[\s\S]*current\.scrollTop \+= offset/)
assert.match(source, /onChange: event => preserveResourceRowPosition\(event\.currentTarget, \(\) => onAction\(plugin, event\.target\.checked \? 'enable' : 'disable'\)\)/)
assert.match(source, /onChange: event => preserveResourceRowPosition\(event\.currentTarget, \(\) => onAction\(skill, event\.target\.checked \? 'enable' : 'disable'\)\)/)
assert.match(style, /\.root \{[^}]*height: min\(720px, calc\(100dvh - 152px\)\);[^}]*overflow: hidden;/)
assert.match(style, /\.platformHeader \{[^}]*width: 100%;[^}]*min-width: 0;[^}]*max-width: 100%;[^}]*flex: none;[^}]*background: var\(--dsw-alias-bg-layer-2\);/)
assert.match(style, /\.tabPanel \{[^}]*min-height: 0;[^}]*flex: 1;[^}]*overflow-y: auto;[^}]*scrollbar-gutter: stable;/)
assert.match(style, /\.pluginSection \{[^}]*height: 100%;[^}]*min-height: 0;[^}]*overflow: visible;/)
assert.match(style, /\.pluginSection > \.resourceSectionHeading,[\s\S]*\.pluginSection > \.listPagination,[\s\S]*\.pluginSection > \.error \{ flex: none; \}/)
assert.match(style, /\.pluginList \{[^}]*min-height: 68px;[^}]*max-height:[^}]*flex: 0 1 auto;[^}]*overflow-y: auto;/)
assert.match(style, /\.pluginSection \.listPagination \{ position: static; \}/)
assert.match(style, /@media \(max-width: 640px\)[\s\S]*\.pluginList \{ min-height: 122px; \}/)
assert.match(style, /\.proxyProviderList \{[^}]*max-height: 320px;[^}]*overflow-y: auto;/)
assert.match(style, /\.proxyScopeDescription \{[^}]*-webkit-line-clamp: 1;/)
assert.match(source, /className: css\.proxyScopeCard[\s\S]*className: css\.toggle[\s\S]*checked: configuration\.scopes\[id\]/)
assert.match(source, /DSH Docker 系统插件等的非本地外部请求/)
assert.match(source, /DSH Docker System Plugins, and other platform components/)
assert.doesNotMatch(source, /第三方及 DSH Docker 系统插件的联网/)
assert.doesNotMatch(source, /third-party, and DSH Docker System Plugin traffic/)
assert.match(source, /className: css\.proxyProviderRoute[\s\S]*proxyProviderShared[\s\S]*className: css\.toggle[\s\S]*proxyEnabled/)
assert.doesNotMatch(source, /proxyProviderFollow|data-shared-route/)
assert.match(source, /function localizedProxyTestDetail\(stage, t, fallback\)/)
assert.match(source, /localizedProxyTestDetail\(stage, t, status\)/)
assert.match(source, /proxyStageDetailAddress: '已解析 \{count\} 个代理地址记录。'/)
assert.match(source, /proxyStageDetailAddress: 'Resolved \{count\} proxy address record\(s\)\.'/)
assert.match(source, /function pendingProxyTestStages\(proxy = \{\}\)[\s\S]*stage !== 'target-dns'[\s\S]*proxy\.protocol === 'socks5'[\s\S]*status: 'pending'/)
assert.match(source, /const startTest = async \(\) => \{[\s\S]*status: 'starting'[\s\S]*pendingProxyTestStages\(connection\)[\s\S]*showModal\(\)/)
assert.match(source, /className: css\.proxyTestStages[\s\S]*task\.stages\.map/)
assert.match(source, /const \[expandedTestStages, setExpandedTestStages\] = useState\(\(\) => new Set\(\)\)/)
assert.match(source, /role: 'button'[\s\S]*'aria-expanded': expanded[\s\S]*onClick: event => toggleDetails\(event\.currentTarget\)[\s\S]*h\('small', null, status\)/)
assert.match(style, /\.proxyProviderRoute \{[^}]*background: var\(--dsw-alias-bg-module-platform\)/)
assert.match(style, /proxyTestStages > li\[data-state='running'\][^{]*\{[^}]*animation: checkSpin/)
assert.match(style, /\.proxyTestStages > li > span:nth-child\(2\) \{[^}]*display: grid;[^}]*gap: 1px;/)
assert.match(style, /\.proxyTestDialog footer \{[^}]*display: grid;[^}]*grid-template-columns: minmax\(0, 1fr\) auto;/)
assert.match(style, /\.proxyTestDialog footer > \.proxyHint, \.proxyTestDialog footer > \.error \{[^}]*margin: 0;/)
assert.doesNotMatch(style, /@media \(max-width: 640px\)[\s\S]*\.proxyTestDialog \{[^}]*height: 100dvh;/)
assert.match(style, /\.proxyScopeDialog \{[^}]*height: min\(720px, calc\(100dvh - 40px\)\)/)
assert.match(style, /\.proxyScopeCatalog \{[^}]*min-height: 0;[^}]*overflow: auto;/)
assert.match(source, /h\(ExpandableProxyDescription, \{ text: localize\(entry\.detail\), identity: entry\.id \}\)/)
assert.match(style, /progressStageMarkerActive::before[^{]*\{[^}]*animation: checkSpin/)
assert.doesNotMatch(source, /className: css\.proxyProvider[\s\S]{0,800}h\('select'/)
assert.match(source, /className: css\.proxyProviderIdentity[\s\S]*className: css\.proxyProviderInfo/)
assert.match(source, /ref: providerInfoDialog[\s\S]*providerInfo\?\.detail/)
assert.doesNotMatch(style, /\.proxyProviderDescription/)
assert.match(style, /\.listPagination \{[^}]*position: sticky;[^}]*bottom: 0;[^}]*display: grid;[^}]*grid-template-columns: minmax\(0, 1fr\) auto auto auto;/)
assert.match(style, /\.listPagination \{[^}]*background: var\(--dsw-alias-bg-layer-2\);/)
assert.match(style, /\.pageArrow::before \{[^}]*border-top: 1\.5px solid currentColor;[^}]*border-right: 1\.5px solid currentColor;/)
assert.doesNotMatch(source, /className: `\$\{css\.smallButton\} \$\{css\.pageArrow\}`[^\n]*[‹›]/)
assert.match(style, /\.statusEnabled \{[^}]*color: var\(--dsw-alias-state-success-primary\);[^}]*color-mix/)
assert.match(style, /@media \(max-width: 640px\)[\s\S]*\.listPagination \{ grid-template-columns: minmax\(0, 1fr\) auto;/)
assert.match(style, /\.tabs \{[\s\S]*width: 100%;[\s\S]*overflow-x: auto/)
assert.match(style, /\.tabs \{[\s\S]*touch-action: pan-x;[\s\S]*white-space: nowrap/)
assert.match(style, /\.root \{[\s\S]*gap: 12px;[\s\S]*max-width: 760px/)
assert.match(style, /\.heading \{[\s\S]*gap: 12px/)
assert.match(style, /\.tabs \{[\s\S]*gap: 22px;[\s\S]*margin-top: 2px/)
assert.match(style, /padding: 7px 1px 9px/)
assert.match(style, /\.tabs button:focus-visible/)
assert.match(style, /\.tabs button \{[\s\S]*scroll-snap-align: start/)
assert.match(style, /@media \(hover: hover\) and \(pointer: fine\) \{\s*\.tabs \{ scroll-snap-type: none; \}/)
assert.match(style, /\.tabs button\[aria-selected='true'\]::after/)
assert.match(style, /\.tabPanel\[hidden\] \{ display: none; \}/)
assert.match(style, /\.versions \{[\s\S]*grid-template-columns: repeat\(2,/)
assert.match(style, /\.experimentalVersions \{ grid-template-columns: repeat\(3,/)
assert.match(style, /@media \(max-width: 640px\)[\s\S]*\.actionHeading \{ align-items: flex-start; \}/)
assert.match(style, /@media \(max-width: 640px\)[\s\S]*\.actions \{ width: 100%; justify-content: flex-start; \}/)
assert.match(style, /@media \(max-width: 640px\)[\s\S]*\.maintenanceButton \{ width: 100%; \}/)
assert.match(style, /\.updateReminder/)
assert.match(style, /body\[data-dsh-platform-select-menu='open'\] > \[role='menu'\][\s\S]*?max-height: min\(320px, 60dvh\);[\s\S]*?overflow: hidden;/)
assert.match(style, /body\[data-dsh-platform-select-menu='open'\] > \[role='menu'\] > \[role='presentation'\][\s\S]*?overflow-y: auto;/)
assert.match(source, /dataset\.dshPlatformSelectMenu = 'open'/)
assert.match(source, /proxyEndpointRequired/)
assert.match(source, /addEventListener\('sources'/)
assert.match(style, /\.proxyFormGrid input:focus-visible,[\s\S]*?border-color: var\(--dsw-alias-label-primary\);[\s\S]*?outline: none;/)
assert.match(style, /\.settingRows/)
assert.match(style, /\.logFilters/)
assert.match(style, /\.logAutoScroll \{[^}]*margin-left: auto;/)
assert.match(source, /className: css\.logSummaryRow[\s\S]*className: css\.logSummary[\s\S]*className: css\.logAutoScroll/)
assert.match(style, /\.logResizeFrame \{[\s\S]*height: 280px;[\s\S]*min-height: 140px;[\s\S]*max-height: min\(560px, 70dvh\);/)
assert.match(style, /@media \(max-width: 640px\)[\s\S]*\.logResizeFrame \{[\s\S]*height: min\(260px, 36dvh\);[\s\S]*max-height: min\(520px, 72dvh\);/)
assert.match(style, /\.logResizeHandle \{[\s\S]*right: 0;[\s\S]*bottom: 0;[\s\S]*left: 0;[\s\S]*height: 16px;/)
assert.match(source, /frame\.style\.height = `\$\{String\(height\)\}px`/)
assert.match(source, /scrollContainer\.scrollTop \+= Math\.min\(overflow, 24\)/)
assert.match(style, /\.logDetails \{/)
assert.match(style, /\.logEntry\[aria-expanded='true'\] \.logChevron/)
assert.match(style, /\.logChevron::before \{[\s\S]*?width: 8px[\s\S]*?height: 5px[\s\S]*?clip-path: polygon[\s\S]*?transform-origin: center/)
assert.match(style, /\.logChevron \{[^}]*top: 2px/)
assert.doesNotMatch(style, /\.logChevron(?:::before)? \{[^}]*transition:/)
assert.match(style, /\.logEntry\[aria-expanded='true'\] \.logChevron::before \{[^}]*transform: rotate\(180deg\)/)
assert.match(source, /className: css\.logMeta[\s\S]*className: css\.logMessageRow[\s\S]*className: css\.logChevron/)
assert.match(style, /\.logWarning/)
assert.match(style, /\.autoScrollButton/)
assert.match(style, /\.clearLogsButton/)
assert.doesNotMatch(style, /#[0-9a-f]{3,8}\b/i)
})