Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions frontend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1433,6 +1433,9 @@ DatePicker 在基础组件中展示日期与日期时间选择;IndexLayout 在

### 智能构建首页与任务找回

从创建入口重新进入智能构建时,返回首页并清除上次部署页的导航状态;仍可从已保存项目
选择版本再次部署。

首页将新建构建与进行中的任务并列展示,已保存项目位于下方。窄窗口优先展示进行中的
任务。列表通过已有后台任务监控读取当前登录用户的任务,显示需求摘要、状态和开始
时间;刷新或重新打开网页后仍可找到尚在运行、重连中或等待回复的任务。
Expand Down
1 change: 1 addition & 0 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7445,6 +7445,7 @@ export default function App() {
title: t("addAgent.intelligent.title"),
desc: t("addAgent.intelligent.description"),
onClick: () => {
setIntelligentDeployment(null);
setAddMenu(false);
setImportedDraft(null);
setRuntimeUpdateTarget(null);
Expand Down
84 changes: 84 additions & 0 deletions frontend/tests/intelligentCreateNavigation.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import test from "node:test";
import { JSDOM } from "jsdom";
import ts from "typescript";

const source = ts.createSourceFile(
"App.tsx",
readFileSync(new URL("../src/App.tsx", import.meta.url), "utf8"),
ts.ScriptTarget.Latest,
true,
ts.ScriptKind.TSX,
);

function findNode(predicate, node = source) {
return predicate(node) ? node : ts.forEachChild(node, (child) => findNode(predicate, child));
}

function bindCallback(node, bindings) {
assert.ok(node, "App navigation callback must exist");
const { outputText } = ts.transpileModule(`return (${node.getText(source)});`, {
compilerOptions: { target: ts.ScriptTarget.ES2022 },
});
return Function(...Object.keys(bindings), outputText)(...Object.values(bindings));
}

const deploymentSetter = findNode((node) =>
ts.isVariableDeclaration(node) && node.name.getText(source) === "setIntelligentDeployment",
).initializer.arguments[0];
const intelligentCard = findNode((node) => ts.isObjectLiteralExpression(node)
&& node.properties.some((property) => ts.isPropertyAssignment(property)
&& property.name.getText(source) === "key"
&& ts.isStringLiteral(property.initializer)
&& property.initializer.text === "intelligent"));
const enterIntelligentCreate = intelligentCard.properties.find((property) =>
ts.isPropertyAssignment(property) && property.name.getText(source) === "onClick",
).initializer;

test("entering intelligent build clears the previous deployment and its reload URL", () => {
const dom = new JSDOM("", { url: "https://studio.example.test/?unrelated=keep#workspace" });
const state = { createView: null, addMenu: true, intelligentDeployment: null };
const setIntelligentDeployment = bindCallback(deploymentSetter, {
window: dom.window,
setIntelligentDeploymentState: (value) => { state.intelligentDeployment = value; },
});
const enterHome = bindCallback(enterIntelligentCreate, {
setIntelligentDeployment,
...Object.fromEntries([
"AddMenu", "ImportedDraft", "RuntimeUpdateTarget", "FocusedDeploymentTaskId",
"FocusedWorkspaceAgentId", "EditingDraftId", "MigrationProjectReturn", "CreateView",
].map((name) => [`set${name}`, (value) => {
state[name[0].toLowerCase() + name.slice(1)] = value;
}])),
editingDraftBaselineRef: { current: null },
});

try {
// Both current-session and saved-project deliveries share this navigation.
for (const project of [{}, { projectId: "project-1", versionId: "version-1" }]) {
const delivery = {
sessionId: "build-session",
artifactSha256: "a".repeat(64),
validationReportSha256: "b".repeat(64),
...project,
};
setIntelligentDeployment(delivery);
assert.equal(state.intelligentDeployment, delivery);
assert.equal(new URL(dom.window.location.href).searchParams.get("view"), "runtime-deploy");

enterHome();

assert.equal(state.createView, "intelligent");
assert.equal(state.addMenu, false);
assert.equal(state.intelligentDeployment, null, "A previous deployment must not cover the home page");
assert.equal(dom.window.location.search, "?unrelated=keep", "Reload must not restore the previous deployment");
assert.equal(dom.window.location.hash, "#workspace");

enterHome();
assert.equal(state.intelligentDeployment, null, "Repeated entry remains on the home page");
}
} finally {
dom.window.close();
}
});

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1 +1 @@
import{U as a,C as n}from"../visualizations/mermaid/mermaid.core-CY863Aa9.js";const t=(r,o)=>a.lang.round(n.parse(r)[o]);export{t as c};
import{U as a,C as n}from"../visualizations/mermaid/mermaid.core-ClBnsMg4.js";const t=(r,o)=>a.lang.round(n.parse(r)[o]);export{t as c};

Large diffs are not rendered by default.

Loading
Loading