From fa4f2a938a0676936428662170f9867166bc81e1 Mon Sep 17 00:00:00 2001 From: Syngnat Date: Tue, 28 Apr 2026 09:42:48 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix(jvm):=20=E7=BB=91=E5=AE=9A?= =?UTF-8?q?=E5=89=8D=E7=AB=AF=E5=8F=98=E6=9B=B4=E6=89=A7=E8=A1=8C=E5=88=B0?= =?UTF-8?q?=E9=A2=84=E8=A7=88=E4=B8=8A=E4=B8=8B=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将 JVM 资源变更执行绑定到最近一次成功预览和连接配置指纹,并遮蔽敏感快照、payload 示例和 AI 上下文中的敏感值。 --- frontend/package-lock.json | 41 ++ frontend/package.json | 2 + .../JVMResourceBrowser.interaction.test.tsx | 563 ++++++++++++++++++ .../src/components/JVMResourceBrowser.tsx | 231 ++++--- .../components/jvm/JVMChangePreviewModal.tsx | 20 +- frontend/src/types.ts | 2 + frontend/src/utils/jvmAiPlan.test.ts | 36 +- frontend/src/utils/jvmAiPlan.ts | 4 + .../src/utils/jvmResourcePresentation.test.ts | 119 ++++ frontend/src/utils/jvmResourcePresentation.ts | 70 ++- 10 files changed, 1003 insertions(+), 85 deletions(-) create mode 100644 frontend/src/components/JVMResourceBrowser.interaction.test.tsx diff --git a/frontend/package-lock.json b/frontend/package-lock.json index d6c584f..2b0ef39 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -33,8 +33,10 @@ "@types/react": "^18.2.43", "@types/react-dom": "^18.2.17", "@types/react-resizable": "^3.0.8", + "@types/react-test-renderer": "^18.0.7", "@types/uuid": "^9.0.7", "@vitejs/plugin-react": "^4.2.1", + "react-test-renderer": "^18.2.0", "typescript": "^5.2.2", "vite": "^5.0.8", "vitest": "^3.2.4" @@ -2037,6 +2039,16 @@ "@types/react": "*" } }, + "node_modules/@types/react-test-renderer": { + "version": "18.0.7", + "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-18.0.7.tgz", + "integrity": "sha512-1+ANPOWc6rB3IkSnElhjv6VLlKg2dSv/OWClUyZimbLsQyBn8Js9Vtdsi3UICJ2rIQ3k2la06dkB+C92QfhKmg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/trusted-types": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", @@ -5645,6 +5657,20 @@ "react-dom": ">= 16.3" } }, + "node_modules/react-shallow-renderer": { + "version": "16.15.0", + "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", + "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "object-assign": "^4.1.1", + "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-syntax-highlighter": { "version": "16.1.1", "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-16.1.1.tgz", @@ -5665,6 +5691,21 @@ "react": ">= 0.14.0" } }, + "node_modules/react-test-renderer": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-18.2.0.tgz", + "integrity": "sha512-JWD+aQ0lh2gvh4NM3bBM42Kx+XybOxCpgYK7F8ugAlpaTSnWsX+39Z4XkOykGZAHrjwwTZT3x3KxswVWxHPUqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "react-is": "^18.2.0", + "react-shallow-renderer": "^16.15.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, "node_modules/recharts": { "version": "3.8.1", "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.8.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index daddbfb..4181217 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -35,8 +35,10 @@ "@types/react": "^18.2.43", "@types/react-dom": "^18.2.17", "@types/react-resizable": "^3.0.8", + "@types/react-test-renderer": "^18.0.7", "@types/uuid": "^9.0.7", "@vitejs/plugin-react": "^4.2.1", + "react-test-renderer": "^18.2.0", "typescript": "^5.2.2", "vite": "^5.0.8", "vitest": "^3.2.4" diff --git a/frontend/src/components/JVMResourceBrowser.interaction.test.tsx b/frontend/src/components/JVMResourceBrowser.interaction.test.tsx new file mode 100644 index 0000000..b4f831d --- /dev/null +++ b/frontend/src/components/JVMResourceBrowser.interaction.test.tsx @@ -0,0 +1,563 @@ +import React from "react"; +import { act, create, type ReactTestRenderer } from "react-test-renderer"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; + +import JVMResourceBrowser from "./JVMResourceBrowser"; +import type { JVMValueSnapshot } from "../types"; + +const storeState = vi.hoisted(() => ({ + connections: [ + { + id: "conn-jvm-writable", + name: "orders-jvm", + config: { + host: "127.0.0.1", + user: "jmx-user", + port: 9010, + type: "jvm", + jvm: { + preferredMode: "jmx", + readOnly: false, + jmx: { + password: "initial-jmx-secret", + }, + }, + }, + }, + ], + addTab: vi.fn(), + aiPanelVisible: false, + setAIPanelVisible: vi.fn(), + theme: "light", +})); + +const backendApp = vi.hoisted(() => ({ + JVMGetValue: vi.fn(), + JVMPreviewChange: vi.fn(), + JVMApplyChange: vi.fn(), +})); + +vi.mock("@monaco-editor/react", () => ({ + default: ({ value }: { value?: string }) =>
{value}
, +})); + +vi.mock("@ant-design/icons", () => ({ + FileSearchOutlined: () => , + ReloadOutlined: () => , + RobotOutlined: () => , +})); + +vi.mock("antd", () => { + const Text = ({ children }: any) => {children}; + const Button = ({ children, disabled, loading, onClick, type, ...rest }: any) => ( + + ); + const Card = ({ children, title }: any) => ( +
+

{title}

+ {children} +
+ ); + const Descriptions: any = ({ children }: any) =>
{children}
; + Descriptions.Item = ({ children, label }: any) => ( +
+
{label}
+
{children}
+
+ ); + const Input: any = ({ value, onChange, placeholder }: any) => ( + + ); + Input.TextArea = ({ value, onChange }: any) => ( +