merge: 收敛 HWPOD native L1
This commit is contained in:
@@ -197,7 +197,7 @@ lanes:
|
||||
bindHost: 0.0.0.0
|
||||
probeHost: 127.0.0.1
|
||||
port: 5174
|
||||
runtimeConfig:
|
||||
runtimeConfig: &hwlabV03NativeCloudWebRuntimeConfig
|
||||
displayTime:
|
||||
timeZone: Asia/Shanghai
|
||||
locale: zh-CN
|
||||
@@ -259,6 +259,12 @@ lanes:
|
||||
bindHost: 0.0.0.0
|
||||
probeHost: 127.0.0.1
|
||||
port: 5175
|
||||
runtimeConfig: *hwlabV03NativeCloudWebRuntimeConfig
|
||||
accessProfile:
|
||||
id: hwpod-native-l1
|
||||
allowedNavIds:
|
||||
- admin.hwpodGroups
|
||||
startPath: /hwpods/devices
|
||||
caserun:
|
||||
publicExposure:
|
||||
publicBaseUrl: https://lab-dev-caserun.hwpod.com
|
||||
@@ -980,26 +986,32 @@ templates:
|
||||
hwpod:
|
||||
application: hwpod
|
||||
authentication: none
|
||||
path: /
|
||||
path: /hwpods/devices
|
||||
navigationTimeoutMs: 30000
|
||||
settleMs: 700
|
||||
commandTimeoutSeconds: 120
|
||||
viewport:
|
||||
width: 1440
|
||||
height: 900
|
||||
width: 1920
|
||||
height: 1080
|
||||
readySelectors:
|
||||
- "[data-testid='hwpod-console']"
|
||||
- "[data-resources] .resource"
|
||||
- .platform-sidebar
|
||||
minBodyTextLength: 40
|
||||
interaction:
|
||||
selector: "[data-resources] .resource:first-child"
|
||||
observedSelector: "[data-resources] .resource:first-child"
|
||||
observedAttribute: aria-current
|
||||
selector: .desktop-sidebar-toggle
|
||||
observedSelector: .platform-sidebar
|
||||
observedAttribute: data-collapsed
|
||||
failedResponseStatus: 400
|
||||
criticalPathPrefixes:
|
||||
- /v1/hwpod
|
||||
- /health/ready
|
||||
screenshotName: native-hwpod-ready.png
|
||||
layout:
|
||||
requireNoDocumentOverflow: true
|
||||
requireNoMainContentOverflow: false
|
||||
mainContentSelector: .platform-content
|
||||
internalScrollSelectors:
|
||||
- .platform-content
|
||||
outputLimits:
|
||||
errors: 20
|
||||
failedResponses: 20
|
||||
|
||||
+15
-1
@@ -101,20 +101,34 @@ HWLAB v0.2/v0.3 仓库内 `docs/reference/spec-*`,以及已收编的 `cloud-wo
|
||||
- 当前 lane 入口:
|
||||
- development `NC01/v03` 前端/API 入口为 `https://lab-dev.hwpod.com`;
|
||||
- production release lane `NC01/production` 的正式入口为 `https://lab.hwpod.com`。
|
||||
- HWPOD L1 Native 是独立于 Cloud Web 的运行面:
|
||||
- HWPOD L1 Native 是进程独立、界面复用完整 Cloud Web Shell 的运行面:
|
||||
- API、Temporal worker、Web 和固定端口必须从 owning YAML 读取:
|
||||
- `config/hwlab-node-lanes.yaml#lanes.<lane>.targets.<node>.nativeDevelopment.hwpod`;
|
||||
- 启停和状态统一使用 `hwlab nodes native-development hwpod api|worker|web`;
|
||||
- 聚合状态统一使用
|
||||
`bun scripts/cli.ts hwlab nodes native-development hwpod status --node <node> --lane <lane>`;
|
||||
- L1 API、worker 和 Web 是 NC01 host 上的 native 进程:
|
||||
- 任何情况下都不依赖 CI/CD、GitOps、Argo、Kubernetes 或集群 rollout;
|
||||
- 正常启动、首次拉起、配置变更、合并后复测和故障处理均适用;
|
||||
- L1 Web 必须复用完整 Cloud Web 的 `AppShell`、Router、总根导航和
|
||||
`/hwpods/devices` 页面,禁止另建 standalone SPA 或复制一套 HWPOD 页面;
|
||||
- 可见根导航和首屏路径由
|
||||
`nativeDevelopment.hwpod.web.accessProfile` 声明,runtime config 从同一 owning YAML
|
||||
渲染并注入,禁止前端或启动脚本硬编码默认值;
|
||||
- topology 首屏由 native HWPOD API 从 YAML-first/PostgreSQL spec registry 构建,
|
||||
禁止代理 deployment Cloud API 作为 L1 首屏数据源;
|
||||
- CLI `--over-api` 直接调用 owning YAML 固定端口上的 native API:
|
||||
- 同 host 回归使用 YAML probe host;
|
||||
- 禁止改走 Cloud API 或 Kubernetes Service;
|
||||
- L1 只验收本机 API、worker、Web 小回环:
|
||||
- 公网入口与 public-edge 是独立可选检查;
|
||||
- 不得成为 L1 启动、执行或完成条件;
|
||||
- 浏览器验收统一使用
|
||||
`bun scripts/cli.ts web-probe native-readiness --node <node> --lane <lane> --profile hwpod`;
|
||||
- HWPOD Web 无业务登录页时,由 owning YAML profile 声明 `authentication: none`,不得改用临时 Playwright 脚本或弱化浏览器错误断言。
|
||||
- native API 已接受操作且 Temporal workflow 已创建时,后续公共
|
||||
`/v1/hwpod-node-ops` 失败必须分类为外部 Cloud API 或 node 运行面故障,
|
||||
不得误判为 L1 API、worker 或 Temporal 未启动。
|
||||
- HWPOD L0 与 L1 的 host 边界:
|
||||
- L0 `--local` 直接执行当前 host 的 function 和文件系统,不提供跨 host 路由;
|
||||
- 跨 host 的 Windows spec 在 API host 做 L0 时,只比较 compiler/plan 合同;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { expect, test } from "bun:test";
|
||||
|
||||
import { hwlabNativeDevelopmentEnvironment, hwlabNativeDevelopmentHelp } from "./hwlab-native-development";
|
||||
import { hwlabHwpodNativeDevelopmentEnvironment, hwlabNativeDevelopmentEnvironment, hwlabNativeDevelopmentHelp } from "./hwlab-native-development";
|
||||
import { hwlabRuntimeLaneSpecForNode } from "./hwlab-node-lanes";
|
||||
import { resolveConfigRef } from "./ops/config-refs";
|
||||
|
||||
@@ -67,6 +67,11 @@ test("L1 HWPOD spec registry resolves PostgreSQL authority and frozen built-ins
|
||||
connectionTimeoutMs: 5000,
|
||||
});
|
||||
expect(native!.healthTimeoutMs).toBe(6000);
|
||||
expect(native!.web.accessProfile).toEqual({ id: "hwpod-native-l1", allowedNavIds: ["admin.hwpodGroups"], startPath: "/hwpods/devices" });
|
||||
const env = hwlabHwpodNativeDevelopmentEnvironment(native!);
|
||||
expect(JSON.parse(env.HWPOD_WEB_RUNTIME_CONFIG!)).toEqual(native!.web.runtimeConfig);
|
||||
expect(native!.web.runtimeConfig).toEqual(hwlabRuntimeLaneSpecForNode("v03", "NC01").nativeDevelopment!.workbench.web.runtimeConfig);
|
||||
expect(JSON.parse(env.HWPOD_WEB_ACCESS_PROFILE_JSON!)).toEqual(native!.web.accessProfile);
|
||||
expect(native!.specRegistry.builtInConfigRefs).toHaveLength(1);
|
||||
const resolved = resolveConfigRef(native!.specRegistry.builtInConfigRefs[0], "HWPOD built-in spec");
|
||||
expect(resolved.value).toMatchObject({ kind: "Hwpod", metadata: { name: "constart-71freq-c" } });
|
||||
|
||||
@@ -17,6 +17,7 @@ export function hwlabNativeDevelopmentHelp(): Record<string, unknown> {
|
||||
"bun scripts/cli.ts hwlab nodes native-development workbench status --node <node> --lane <lane>",
|
||||
"bun scripts/cli.ts hwlab nodes native-development workbench api|worker|web start|stop|restart|status|logs --node <node> --lane <lane>",
|
||||
"bun scripts/cli.ts hwlab nodes native-development workbench cli <health|session|turn|events ...> --node <node> --lane <lane>",
|
||||
"bun scripts/cli.ts hwlab nodes native-development hwpod status --node <node> --lane <lane>",
|
||||
"bun scripts/cli.ts hwlab nodes native-development hwpod api|worker|web start|stop|restart|status|logs --node <node> --lane <lane>",
|
||||
"bun scripts/cli.ts hwlab nodes native-development caserun api|web start|stop|restart|status|logs --node <node> --lane <lane>",
|
||||
],
|
||||
@@ -96,6 +97,24 @@ export function runHwlabNativeDevelopmentCommand(args: string[]): Record<string,
|
||||
...(result.exitCode === 0 ? {} : { error: { code: "hwlab_native_cli_failed", exitCode: result.exitCode, stderr: result.stderr.trim().slice(-2000) } }),
|
||||
};
|
||||
}
|
||||
if (application === "hwpod" && serviceRaw === "status") {
|
||||
const remaining = withoutOptions(args.slice(2), ["--node", "--lane"]);
|
||||
if (remaining.length > 0) throw new Error(`native-development hwpod status does not accept positional arguments: ${remaining.join(" ")}`);
|
||||
const command = ["bun", "tools/hwlab-cli/bin/hwlab-cli.ts", "hwpod", "service", "status"];
|
||||
const result = runCommand(command, spec.workspace, { timeoutMs: 30_000, env: { ...process.env, ...env } });
|
||||
const payload = parsePayload(result.stdout);
|
||||
return {
|
||||
ok: result.exitCode === 0 && payload.ok !== false,
|
||||
command: "hwlab nodes native-development hwpod status",
|
||||
node,
|
||||
lane,
|
||||
action: "status",
|
||||
configSource: `${hwlabRuntimeLaneConfigPath()}#lanes.${lane}.targets.${node}.nativeDevelopment.hwpod`,
|
||||
userEndpoint: { url: `${native.publicExposure.publicBaseUrl}${(native as NonNullable<HwlabRuntimeNativeDevelopmentSpec["hwpod"]>).web.accessProfile.startPath}` },
|
||||
serviceResult: payload,
|
||||
...(result.exitCode === 0 ? {} : { error: { code: "hwlab_native_cli_failed", exitCode: result.exitCode, stderr: result.stderr.trim().slice(-2000) } }),
|
||||
};
|
||||
}
|
||||
const service = parseService(serviceRaw, application);
|
||||
const action = parseAction(actionRaw);
|
||||
const command = ["bun", "tools/hwlab-cli/bin/hwlab-cli.ts", application, "service", service, action];
|
||||
@@ -104,7 +123,7 @@ export function runHwlabNativeDevelopmentCommand(args: string[]): Record<string,
|
||||
const publicEndpoint = service === "api"
|
||||
? { url: native.publicExposure.publicBaseUrl }
|
||||
: service === "web"
|
||||
? { url: application === "hwpod" ? native.publicExposure.publicBaseUrl : `${native.publicExposure.publicBaseUrl}/${application === "workbench" ? "workbench" : "caserun"}` }
|
||||
? { url: application === "hwpod" ? `${native.publicExposure.publicBaseUrl}${(native as NonNullable<HwlabRuntimeNativeDevelopmentSpec["hwpod"]>).web.accessProfile.startPath}` : `${native.publicExposure.publicBaseUrl}/${application === "workbench" ? "workbench" : "caserun"}` }
|
||||
: null;
|
||||
return {
|
||||
ok: result.exitCode === 0 && payload.ok !== false,
|
||||
@@ -281,7 +300,7 @@ function hwlabCaseRunNativeDevelopmentEnvironment(native: NonNullable<HwlabRunti
|
||||
};
|
||||
}
|
||||
|
||||
function hwlabHwpodNativeDevelopmentEnvironment(native: NonNullable<HwlabRuntimeNativeDevelopmentSpec["hwpod"]>): NodeJS.ProcessEnv {
|
||||
export function hwlabHwpodNativeDevelopmentEnvironment(native: NonNullable<HwlabRuntimeNativeDevelopmentSpec["hwpod"]>): NodeJS.ProcessEnv {
|
||||
const authorizationSource = readEnvSourceFile({
|
||||
root: "/root/.unidesk/.state/secrets",
|
||||
sourceRef: native.runtimeApiAuth.sourceRef,
|
||||
@@ -323,6 +342,8 @@ function hwlabHwpodNativeDevelopmentEnvironment(native: NonNullable<HwlabRuntime
|
||||
HWPOD_WEB_BIND_HOST: native.web.bindHost,
|
||||
HWPOD_WEB_PROBE_HOST: native.web.probeHost,
|
||||
HWPOD_WEB_PORT: String(native.web.port),
|
||||
HWPOD_WEB_RUNTIME_CONFIG: JSON.stringify(native.web.runtimeConfig),
|
||||
HWPOD_WEB_ACCESS_PROFILE_JSON: JSON.stringify(native.web.accessProfile),
|
||||
HWPOD_NATIVE_API_URL: `http://${native.api.probeHost}:${native.api.port}`,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -687,6 +687,18 @@ export interface HwlabRuntimeSourceWorkspaceHostDependenciesSpec {
|
||||
};
|
||||
}
|
||||
|
||||
export interface HwlabRuntimeNativeCloudWebRuntimeConfigSpec {
|
||||
readonly displayTime: { readonly timeZone: string; readonly locale: string; readonly label: string };
|
||||
readonly workbench: {
|
||||
readonly realtimeFeatures: { readonly liveKafkaSse: boolean; readonly kafkaRefreshReplay: boolean; readonly projectionRealtime: boolean };
|
||||
readonly debugCapabilities: {
|
||||
readonly isolatedKafka: boolean;
|
||||
readonly rawHwlabEventWindow: { readonly enabled: boolean; readonly maxEntries: number; readonly maxRetainedBytes: number };
|
||||
};
|
||||
readonly traceTimeline: { readonly autoExpandRunning: boolean; readonly autoCollapseTerminal: boolean };
|
||||
};
|
||||
}
|
||||
|
||||
export interface HwlabRuntimeNativeDevelopmentSpec {
|
||||
readonly tasktree?: {
|
||||
readonly publicExposure: HwlabRuntimeNativePublicExposureSpec;
|
||||
@@ -745,17 +757,7 @@ export interface HwlabRuntimeNativeDevelopmentSpec {
|
||||
readonly bindHost: string;
|
||||
readonly probeHost: string;
|
||||
readonly port: number;
|
||||
readonly runtimeConfig: {
|
||||
readonly displayTime: { readonly timeZone: string; readonly locale: string; readonly label: string };
|
||||
readonly workbench: {
|
||||
readonly realtimeFeatures: { readonly liveKafkaSse: boolean; readonly kafkaRefreshReplay: boolean; readonly projectionRealtime: boolean };
|
||||
readonly debugCapabilities: {
|
||||
readonly isolatedKafka: boolean;
|
||||
readonly rawHwlabEventWindow: { readonly enabled: boolean; readonly maxEntries: number; readonly maxRetainedBytes: number };
|
||||
};
|
||||
readonly traceTimeline: { readonly autoExpandRunning: boolean; readonly autoCollapseTerminal: boolean };
|
||||
};
|
||||
};
|
||||
readonly runtimeConfig: HwlabRuntimeNativeCloudWebRuntimeConfigSpec;
|
||||
};
|
||||
};
|
||||
readonly hwpod?: {
|
||||
@@ -787,7 +789,13 @@ export interface HwlabRuntimeNativeDevelopmentSpec {
|
||||
};
|
||||
readonly api: { readonly bindHost: string; readonly probeHost: string; readonly port: number };
|
||||
readonly worker: { readonly bindHost: string; readonly probeHost: string; readonly healthPort: number };
|
||||
readonly web: { readonly bindHost: string; readonly probeHost: string; readonly port: number };
|
||||
readonly web: {
|
||||
readonly bindHost: string;
|
||||
readonly probeHost: string;
|
||||
readonly port: number;
|
||||
readonly runtimeConfig: HwlabRuntimeNativeCloudWebRuntimeConfigSpec;
|
||||
readonly accessProfile: { readonly id: string; readonly allowedNavIds: readonly string[]; readonly startPath: string };
|
||||
};
|
||||
};
|
||||
readonly caserun?: {
|
||||
readonly publicExposure: HwlabRuntimeNativePublicExposureSpec;
|
||||
@@ -1626,17 +1634,10 @@ function nativeDevelopmentConfig(value: unknown, path: string): HwlabRuntimeNati
|
||||
const api = asRecord(workbench.api, `${path}.workbench.api`);
|
||||
const worker = asRecord(workbench.worker, `${path}.workbench.worker`);
|
||||
const web = asRecord(workbench.web, `${path}.workbench.web`);
|
||||
const runtimeConfig = asRecord(web.runtimeConfig, `${path}.workbench.web.runtimeConfig`);
|
||||
const displayTime = asRecord(runtimeConfig.displayTime, `${path}.workbench.web.runtimeConfig.displayTime`);
|
||||
const workbenchRuntime = asRecord(runtimeConfig.workbench, `${path}.workbench.web.runtimeConfig.workbench`);
|
||||
const realtimeFeatures = asRecord(workbenchRuntime.realtimeFeatures, `${path}.workbench.web.runtimeConfig.workbench.realtimeFeatures`);
|
||||
const refreshReplay = asRecord(kafka.refreshReplay, `${path}.workbench.kafka.refreshReplay`);
|
||||
const sessionIndex = refreshReplay.sessionIndex === undefined
|
||||
? undefined
|
||||
: asRecord(refreshReplay.sessionIndex, `${path}.workbench.kafka.refreshReplay.sessionIndex`);
|
||||
const debugCapabilities = asRecord(workbenchRuntime.debugCapabilities, `${path}.workbench.web.runtimeConfig.workbench.debugCapabilities`);
|
||||
const rawHwlabEventWindow = asRecord(debugCapabilities.rawHwlabEventWindow, `${path}.workbench.web.runtimeConfig.workbench.debugCapabilities.rawHwlabEventWindow`);
|
||||
const traceTimeline = asRecord(workbenchRuntime.traceTimeline, `${path}.workbench.web.runtimeConfig.workbench.traceTimeline`);
|
||||
return {
|
||||
...(raw.tasktree === undefined ? {} : { tasktree: nativeTaskTreeConfig(raw.tasktree, `${path}.tasktree`) }),
|
||||
workbench: {
|
||||
@@ -1689,32 +1690,7 @@ function nativeDevelopmentConfig(value: unknown, path: string): HwlabRuntimeNati
|
||||
bindHost: stringField(web, "bindHost", `${path}.workbench.web`),
|
||||
probeHost: stringField(web, "probeHost", `${path}.workbench.web`),
|
||||
port: numberField(web, "port", `${path}.workbench.web`),
|
||||
runtimeConfig: {
|
||||
displayTime: {
|
||||
timeZone: stringField(displayTime, "timeZone", `${path}.workbench.web.runtimeConfig.displayTime`),
|
||||
locale: stringField(displayTime, "locale", `${path}.workbench.web.runtimeConfig.displayTime`),
|
||||
label: stringField(displayTime, "label", `${path}.workbench.web.runtimeConfig.displayTime`),
|
||||
},
|
||||
workbench: {
|
||||
realtimeFeatures: {
|
||||
liveKafkaSse: booleanField(realtimeFeatures, "liveKafkaSse", `${path}.workbench.web.runtimeConfig.workbench.realtimeFeatures`),
|
||||
kafkaRefreshReplay: booleanField(realtimeFeatures, "kafkaRefreshReplay", `${path}.workbench.web.runtimeConfig.workbench.realtimeFeatures`),
|
||||
projectionRealtime: booleanField(realtimeFeatures, "projectionRealtime", `${path}.workbench.web.runtimeConfig.workbench.realtimeFeatures`),
|
||||
},
|
||||
debugCapabilities: {
|
||||
isolatedKafka: booleanField(debugCapabilities, "isolatedKafka", `${path}.workbench.web.runtimeConfig.workbench.debugCapabilities`),
|
||||
rawHwlabEventWindow: {
|
||||
enabled: booleanField(rawHwlabEventWindow, "enabled", `${path}.workbench.web.runtimeConfig.workbench.debugCapabilities.rawHwlabEventWindow`),
|
||||
maxEntries: numberField(rawHwlabEventWindow, "maxEntries", `${path}.workbench.web.runtimeConfig.workbench.debugCapabilities.rawHwlabEventWindow`),
|
||||
maxRetainedBytes: numberField(rawHwlabEventWindow, "maxRetainedBytes", `${path}.workbench.web.runtimeConfig.workbench.debugCapabilities.rawHwlabEventWindow`),
|
||||
},
|
||||
},
|
||||
traceTimeline: {
|
||||
autoExpandRunning: booleanField(traceTimeline, "autoExpandRunning", `${path}.workbench.web.runtimeConfig.workbench.traceTimeline`),
|
||||
autoCollapseTerminal: booleanField(traceTimeline, "autoCollapseTerminal", `${path}.workbench.web.runtimeConfig.workbench.traceTimeline`),
|
||||
},
|
||||
},
|
||||
},
|
||||
runtimeConfig: nativeCloudWebRuntimeConfig(web.runtimeConfig, `${path}.workbench.web.runtimeConfig`),
|
||||
},
|
||||
},
|
||||
...(raw.hwpod === undefined ? {} : { hwpod: nativeHwpodConfig(raw.hwpod, `${path}.hwpod`) }),
|
||||
@@ -1732,6 +1708,11 @@ function nativeHwpodConfig(value: unknown, path: string): NonNullable<HwlabRunti
|
||||
const api = asRecord(raw.api, `${path}.api`);
|
||||
const worker = asRecord(raw.worker, `${path}.worker`);
|
||||
const web = asRecord(raw.web, `${path}.web`);
|
||||
const accessProfile = asRecord(web.accessProfile, `${path}.web.accessProfile`);
|
||||
const startPath = stringField(accessProfile, "startPath", `${path}.web.accessProfile`);
|
||||
if (!startPath.startsWith("/")) throw new Error(`${path}.web.accessProfile.startPath must be an absolute application path`);
|
||||
const allowedNavIds = stringArrayField(accessProfile, "allowedNavIds", `${path}.web.accessProfile`);
|
||||
if (allowedNavIds.length === 0) throw new Error(`${path}.web.accessProfile.allowedNavIds must not be empty`);
|
||||
return {
|
||||
publicExposure: nativePublicExposureConfig(raw.publicExposure, `${path}.publicExposure`),
|
||||
stateDir: relativeWorkspacePathField(stringField(raw, "stateDir", path), `${path}.stateDir`),
|
||||
@@ -1764,7 +1745,53 @@ function nativeHwpodConfig(value: unknown, path: string): NonNullable<HwlabRunti
|
||||
},
|
||||
api: { bindHost: stringField(api, "bindHost", `${path}.api`), probeHost: stringField(api, "probeHost", `${path}.api`), port: numberField(api, "port", `${path}.api`) },
|
||||
worker: { bindHost: stringField(worker, "bindHost", `${path}.worker`), probeHost: stringField(worker, "probeHost", `${path}.worker`), healthPort: numberField(worker, "healthPort", `${path}.worker`) },
|
||||
web: { bindHost: stringField(web, "bindHost", `${path}.web`), probeHost: stringField(web, "probeHost", `${path}.web`), port: numberField(web, "port", `${path}.web`) },
|
||||
web: {
|
||||
bindHost: stringField(web, "bindHost", `${path}.web`),
|
||||
probeHost: stringField(web, "probeHost", `${path}.web`),
|
||||
port: numberField(web, "port", `${path}.web`),
|
||||
runtimeConfig: nativeCloudWebRuntimeConfig(web.runtimeConfig, `${path}.web.runtimeConfig`),
|
||||
accessProfile: {
|
||||
id: stringField(accessProfile, "id", `${path}.web.accessProfile`),
|
||||
allowedNavIds,
|
||||
startPath,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function nativeCloudWebRuntimeConfig(value: unknown, path: string): HwlabRuntimeNativeCloudWebRuntimeConfigSpec {
|
||||
const runtimeConfig = asRecord(value, path);
|
||||
const displayTime = asRecord(runtimeConfig.displayTime, `${path}.displayTime`);
|
||||
const workbench = asRecord(runtimeConfig.workbench, `${path}.workbench`);
|
||||
const realtimeFeatures = asRecord(workbench.realtimeFeatures, `${path}.workbench.realtimeFeatures`);
|
||||
const debugCapabilities = asRecord(workbench.debugCapabilities, `${path}.workbench.debugCapabilities`);
|
||||
const rawHwlabEventWindow = asRecord(debugCapabilities.rawHwlabEventWindow, `${path}.workbench.debugCapabilities.rawHwlabEventWindow`);
|
||||
const traceTimeline = asRecord(workbench.traceTimeline, `${path}.workbench.traceTimeline`);
|
||||
return {
|
||||
displayTime: {
|
||||
timeZone: stringField(displayTime, "timeZone", `${path}.displayTime`),
|
||||
locale: stringField(displayTime, "locale", `${path}.displayTime`),
|
||||
label: stringField(displayTime, "label", `${path}.displayTime`),
|
||||
},
|
||||
workbench: {
|
||||
realtimeFeatures: {
|
||||
liveKafkaSse: booleanField(realtimeFeatures, "liveKafkaSse", `${path}.workbench.realtimeFeatures`),
|
||||
kafkaRefreshReplay: booleanField(realtimeFeatures, "kafkaRefreshReplay", `${path}.workbench.realtimeFeatures`),
|
||||
projectionRealtime: booleanField(realtimeFeatures, "projectionRealtime", `${path}.workbench.realtimeFeatures`),
|
||||
},
|
||||
debugCapabilities: {
|
||||
isolatedKafka: booleanField(debugCapabilities, "isolatedKafka", `${path}.workbench.debugCapabilities`),
|
||||
rawHwlabEventWindow: {
|
||||
enabled: booleanField(rawHwlabEventWindow, "enabled", `${path}.workbench.debugCapabilities.rawHwlabEventWindow`),
|
||||
maxEntries: numberField(rawHwlabEventWindow, "maxEntries", `${path}.workbench.debugCapabilities.rawHwlabEventWindow`),
|
||||
maxRetainedBytes: numberField(rawHwlabEventWindow, "maxRetainedBytes", `${path}.workbench.debugCapabilities.rawHwlabEventWindow`),
|
||||
},
|
||||
},
|
||||
traceTimeline: {
|
||||
autoExpandRunning: booleanField(traceTimeline, "autoExpandRunning", `${path}.workbench.traceTimeline`),
|
||||
autoCollapseTerminal: booleanField(traceTimeline, "autoCollapseTerminal", `${path}.workbench.traceTimeline`),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -103,8 +103,9 @@ test("HWPOD native-readiness resolves the independent L1 Web origin", () => {
|
||||
assert.equal(options.action, "script");
|
||||
if (options.action !== "script") return;
|
||||
assert.equal(options.url, "https://lab-dev-hwpod.hwpod.com");
|
||||
assert.equal(options.viewport, "1440x900");
|
||||
assert.equal(options.viewport, "1920x1080");
|
||||
assert.equal(options.authentication, "none");
|
||||
assert.equal(options.scriptSource.path, "builtin:native-readiness/hwpod");
|
||||
});
|
||||
|
||||
test("CaseRun native readiness resolves the CaseRun YAML HTTPS origin", () => {
|
||||
|
||||
Reference in New Issue
Block a user