Start API proxy with WorkUtils
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package com.example.workutils;
|
package com.example.workutils;
|
||||||
|
|
||||||
|
import com.example.workutils.biz.apidoc.application.ApiDebugProxyLifecycle;
|
||||||
import com.example.workutils.system.config.*;
|
import com.example.workutils.system.config.*;
|
||||||
import com.example.workutils.system.plugin.Plugin;
|
import com.example.workutils.system.plugin.Plugin;
|
||||||
import com.example.workutils.system.plugin.PluginDescriptor;
|
import com.example.workutils.system.plugin.PluginDescriptor;
|
||||||
@@ -38,6 +39,7 @@ public class WorkUtilsApplication implements CommandLineRunner {
|
|||||||
private final PluginManager pluginManager;
|
private final PluginManager pluginManager;
|
||||||
private final WorkUtilsProperties properties;
|
private final WorkUtilsProperties properties;
|
||||||
private final SettingsService settingsService;
|
private final SettingsService settingsService;
|
||||||
|
private final ApiDebugProxyLifecycle apiDebugProxyLifecycle;
|
||||||
|
|
||||||
/** 主窗口引用,供内嵌插件面板使用 */
|
/** 主窗口引用,供内嵌插件面板使用 */
|
||||||
private MainWindow mainWindow;
|
private MainWindow mainWindow;
|
||||||
@@ -45,10 +47,12 @@ public class WorkUtilsApplication implements CommandLineRunner {
|
|||||||
private SettingsWindow settingsWindow;
|
private SettingsWindow settingsWindow;
|
||||||
|
|
||||||
public WorkUtilsApplication(PluginManager pluginManager, WorkUtilsProperties properties,
|
public WorkUtilsApplication(PluginManager pluginManager, WorkUtilsProperties properties,
|
||||||
SettingsService settingsService) {
|
SettingsService settingsService,
|
||||||
|
ApiDebugProxyLifecycle apiDebugProxyLifecycle) {
|
||||||
this.pluginManager = pluginManager;
|
this.pluginManager = pluginManager;
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
this.settingsService = settingsService;
|
this.settingsService = settingsService;
|
||||||
|
this.apiDebugProxyLifecycle = apiDebugProxyLifecycle;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 启动诊断 ====================
|
// ==================== 启动诊断 ====================
|
||||||
@@ -91,11 +95,16 @@ public class WorkUtilsApplication implements CommandLineRunner {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(String... args) throws Exception {
|
public void run(String... args) throws Exception {
|
||||||
|
apiDebugProxyLifecycle.start();
|
||||||
|
try {
|
||||||
if (args.length == 0) {
|
if (args.length == 0) {
|
||||||
showMainWindow();
|
showMainWindow();
|
||||||
} else {
|
} else {
|
||||||
processCommand(args);
|
processCommand(args);
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
apiDebugProxyLifecycle.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 主窗口入口 ====================
|
// ==================== 主窗口入口 ====================
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.example.workutils.biz.apidoc;
|
package com.example.workutils.biz.apidoc;
|
||||||
|
|
||||||
|
import com.example.workutils.biz.apidoc.application.ApiDebugProxyLifecycle;
|
||||||
import com.example.workutils.biz.apidoc.config.ApiBaseClassManager;
|
import com.example.workutils.biz.apidoc.config.ApiBaseClassManager;
|
||||||
import com.example.workutils.system.config.WorkUtilsProperties;
|
import com.example.workutils.system.config.WorkUtilsProperties;
|
||||||
import com.example.workutils.system.plugin.Plugin;
|
import com.example.workutils.system.plugin.Plugin;
|
||||||
@@ -40,6 +41,7 @@ public class ApiDocPlugin implements Plugin {
|
|||||||
private final WorkUtilsProperties properties;
|
private final WorkUtilsProperties properties;
|
||||||
private final FileOperationHelper fileOperationHelper;
|
private final FileOperationHelper fileOperationHelper;
|
||||||
private final ApiBaseClassManager apiBaseClassManager;
|
private final ApiBaseClassManager apiBaseClassManager;
|
||||||
|
private final ApiDebugProxyLifecycle apiDebugProxyLifecycle;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PluginDescriptor getDescriptor() { return DESCRIPTOR; }
|
public PluginDescriptor getDescriptor() { return DESCRIPTOR; }
|
||||||
@@ -55,7 +57,8 @@ public class ApiDocPlugin implements Plugin {
|
|||||||
public Parent getEmbeddedPane() {
|
public Parent getEmbeddedPane() {
|
||||||
if (embeddedRoot != null) return embeddedRoot;
|
if (embeddedRoot != null) return embeddedRoot;
|
||||||
latch = new CountDownLatch(1);
|
latch = new CountDownLatch(1);
|
||||||
window = new ApiDocWindow(fileOperationHelper, properties, latch, apiBaseClassManager);
|
window = new ApiDocWindow(fileOperationHelper, properties, latch,
|
||||||
|
apiBaseClassManager, apiDebugProxyLifecycle);
|
||||||
embeddedRoot = window.getContentPane();
|
embeddedRoot = window.getContentPane();
|
||||||
window.getStage().getScene().setRoot(new Pane());
|
window.getStage().getScene().setRoot(new Pane());
|
||||||
return embeddedRoot;
|
return embeddedRoot;
|
||||||
@@ -65,7 +68,8 @@ public class ApiDocPlugin implements Plugin {
|
|||||||
public void open(Runnable onClosed) {
|
public void open(Runnable onClosed) {
|
||||||
if (window == null) {
|
if (window == null) {
|
||||||
latch = new CountDownLatch(1);
|
latch = new CountDownLatch(1);
|
||||||
window = new ApiDocWindow(fileOperationHelper, properties, latch, apiBaseClassManager);
|
window = new ApiDocWindow(fileOperationHelper, properties, latch,
|
||||||
|
apiBaseClassManager, apiDebugProxyLifecycle);
|
||||||
}
|
}
|
||||||
if (embeddedRoot != null && window.getStage().getScene().getRoot() != embeddedRoot) {
|
if (embeddedRoot != null && window.getStage().getScene().getRoot() != embeddedRoot) {
|
||||||
window.getStage().getScene().setRoot(embeddedRoot);
|
window.getStage().getScene().setRoot(embeddedRoot);
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package com.example.workutils.biz.apidoc;
|
package com.example.workutils.biz.apidoc;
|
||||||
|
|
||||||
|
import com.example.workutils.biz.apidoc.application.ApiDebugProxyLifecycle;
|
||||||
|
import com.example.workutils.biz.apidoc.application.ApiDebugProxyLifecycle.State;
|
||||||
|
import com.example.workutils.biz.apidoc.application.ApiDebugProxyLifecycle.Status;
|
||||||
import com.example.workutils.biz.apidoc.application.ApiDocExportRequest;
|
import com.example.workutils.biz.apidoc.application.ApiDocExportRequest;
|
||||||
import com.example.workutils.biz.apidoc.application.RunApiDocExportUseCase;
|
import com.example.workutils.biz.apidoc.application.RunApiDocExportUseCase;
|
||||||
import com.example.workutils.biz.apidoc.config.ApiBaseClassManager;
|
import com.example.workutils.biz.apidoc.config.ApiBaseClassManager;
|
||||||
import com.example.workutils.biz.apidoc.generator.ApiDocGenerator;
|
import com.example.workutils.biz.apidoc.generator.ApiDocGenerator;
|
||||||
import com.example.workutils.biz.apidoc.generator.DubboDebugProxy;
|
|
||||||
import com.example.workutils.biz.apidoc.model.ApiDocModel;
|
import com.example.workutils.biz.apidoc.model.ApiDocModel;
|
||||||
import com.example.workutils.biz.apidoc.parser.JavaSourceParser;
|
import com.example.workutils.biz.apidoc.parser.JavaSourceParser;
|
||||||
import com.example.workutils.system.config.WorkUtilsProperties;
|
import com.example.workutils.system.config.WorkUtilsProperties;
|
||||||
@@ -58,6 +60,7 @@ public class ApiDocWindow {
|
|||||||
private final WorkUtilsProperties properties;
|
private final WorkUtilsProperties properties;
|
||||||
private final FileOperationHelper fileOperationHelper;
|
private final FileOperationHelper fileOperationHelper;
|
||||||
private final ApiBaseClassManager apiBaseClassManager;
|
private final ApiBaseClassManager apiBaseClassManager;
|
||||||
|
private final ApiDebugProxyLifecycle apiDebugProxyLifecycle;
|
||||||
private final RunApiDocExportUseCase exportUseCase;
|
private final RunApiDocExportUseCase exportUseCase;
|
||||||
private final AsyncOperationController<RunApiDocExportUseCase.Result> exportOperation;
|
private final AsyncOperationController<RunApiDocExportUseCase.Result> exportOperation;
|
||||||
private final HistoryFileCommands historyFileCommands;
|
private final HistoryFileCommands historyFileCommands;
|
||||||
@@ -82,7 +85,6 @@ public class ApiDocWindow {
|
|||||||
|
|
||||||
// 操作区
|
// 操作区
|
||||||
private Button exportBtn;
|
private Button exportBtn;
|
||||||
private CheckBox debugProxyCb;
|
|
||||||
private TextArea logArea;
|
private TextArea logArea;
|
||||||
|
|
||||||
// 历史记录
|
// 历史记录
|
||||||
@@ -94,13 +96,16 @@ public class ApiDocWindow {
|
|||||||
private static final String DELIMITER = "|";
|
private static final String DELIMITER = "|";
|
||||||
|
|
||||||
public ApiDocWindow(FileOperationHelper fileOperationHelper, WorkUtilsProperties properties,
|
public ApiDocWindow(FileOperationHelper fileOperationHelper, WorkUtilsProperties properties,
|
||||||
CountDownLatch closeLatch, ApiBaseClassManager apiBaseClassManager) {
|
CountDownLatch closeLatch, ApiBaseClassManager apiBaseClassManager,
|
||||||
|
ApiDebugProxyLifecycle apiDebugProxyLifecycle) {
|
||||||
this.fileOperationHelper = fileOperationHelper;
|
this.fileOperationHelper = fileOperationHelper;
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
this.closeLatch = closeLatch;
|
this.closeLatch = closeLatch;
|
||||||
this.apiBaseClassManager = apiBaseClassManager;
|
this.apiBaseClassManager = apiBaseClassManager;
|
||||||
|
this.apiDebugProxyLifecycle = Objects.requireNonNull(
|
||||||
|
apiDebugProxyLifecycle, "apiDebugProxyLifecycle");
|
||||||
this.exportUseCase = new RunApiDocExportUseCase(
|
this.exportUseCase = new RunApiDocExportUseCase(
|
||||||
() -> DubboDebugProxy.getInstance().getInvokeUrl(),
|
apiDebugProxyLifecycle::endpoint,
|
||||||
this::executeExport);
|
this::executeExport);
|
||||||
this.exportOperation = new AsyncOperationController<>(
|
this.exportOperation = new AsyncOperationController<>(
|
||||||
AppExecutors.io(), Platform::runLater);
|
AppExecutors.io(), Platform::runLater);
|
||||||
@@ -134,6 +139,25 @@ public class ApiDocWindow {
|
|||||||
private int fsBtn() { return properties.getFontButton(); }
|
private int fsBtn() { return properties.getFontButton(); }
|
||||||
private int fsBody() { return properties.getFontBody(); }
|
private int fsBody() { return properties.getFontBody(); }
|
||||||
|
|
||||||
|
static Label buildProxyStatusLabel(Status status, int fontSize) {
|
||||||
|
Objects.requireNonNull(status, "status");
|
||||||
|
boolean running = status.state() == State.RUNNING;
|
||||||
|
String reason = status.errorMessage().isBlank()
|
||||||
|
? "代理尚未启动"
|
||||||
|
: status.errorMessage();
|
||||||
|
String text = running
|
||||||
|
? "● 本地代理已启动:" + status.endpoint()
|
||||||
|
: "● 本地代理启动失败:" + reason;
|
||||||
|
Label label = new Label(text);
|
||||||
|
label.setFont(Theme.base(fontSize));
|
||||||
|
label.setTextFill(running ? Theme.SUCCESS : Theme.DANGER);
|
||||||
|
label.setAccessibleText(text);
|
||||||
|
if (!running) {
|
||||||
|
label.setTooltip(new Tooltip("本地代理启动失败:" + reason));
|
||||||
|
}
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
private void buildUI() {
|
private void buildUI() {
|
||||||
stage.setTitle("API 接口文档导出");
|
stage.setTitle("API 接口文档导出");
|
||||||
stage.setWidth(1080);
|
stage.setWidth(1080);
|
||||||
@@ -262,14 +286,11 @@ public class ApiDocWindow {
|
|||||||
exportBtn = StyledButton.primary("导出文档", Theme.bold(fsBtn()));
|
exportBtn = StyledButton.primary("导出文档", Theme.bold(fsBtn()));
|
||||||
exportBtn.setOnAction(e -> startExport());
|
exportBtn.setOnAction(e -> startExport());
|
||||||
LoadingButtonBinder.bind(exportBtn, exportOperation, "导出文档");
|
LoadingButtonBinder.bind(exportBtn, exportOperation, "导出文档");
|
||||||
debugProxyCb = new CheckBox("启用接口调试(启动本地代理)");
|
Label proxyStatus = buildProxyStatusLabel(
|
||||||
debugProxyCb.setSelected(false);
|
apiDebugProxyLifecycle.status(), fsBody() - 1);
|
||||||
debugProxyCb.setFont(Theme.base(fsBody() - 1));
|
|
||||||
debugProxyCb.setTooltip(new Tooltip(
|
|
||||||
"仅生成支持“发送调试请求”的文档时启用;普通导出无需启动代理。"));
|
|
||||||
Region actionSpacer = new Region();
|
Region actionSpacer = new Region();
|
||||||
HBox.setHgrow(actionSpacer, Priority.ALWAYS);
|
HBox.setHgrow(actionSpacer, Priority.ALWAYS);
|
||||||
actionRow.getChildren().addAll(debugProxyCb, actionSpacer, exportBtn);
|
actionRow.getChildren().addAll(proxyStatus, actionSpacer, exportBtn);
|
||||||
OperationStatusPane operationStatus = new OperationStatusPane(
|
OperationStatusPane operationStatus = new OperationStatusPane(
|
||||||
exportOperation, fsBody() - 1, false);
|
exportOperation, fsBody() - 1, false);
|
||||||
|
|
||||||
@@ -363,6 +384,9 @@ public class ApiDocWindow {
|
|||||||
private void startExport() {
|
private void startExport() {
|
||||||
try {
|
try {
|
||||||
ApiDocExportRequest request = buildRequest();
|
ApiDocExportRequest request = buildRequest();
|
||||||
|
if (apiDebugProxyLifecycle.endpoint().isBlank()) {
|
||||||
|
log("[WARN] 本地代理不可用,导出文档的接口调试功能已禁用");
|
||||||
|
}
|
||||||
exportOperation.start(
|
exportOperation.start(
|
||||||
"正在解析源码",
|
"正在解析源码",
|
||||||
context -> exportUseCase.execute(request, context),
|
context -> exportUseCase.execute(request, context),
|
||||||
@@ -376,12 +400,11 @@ public class ApiDocWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ApiDocExportRequest buildRequest() throws IOException {
|
private ApiDocExportRequest buildRequest() throws IOException {
|
||||||
boolean debugEnabled = debugProxyCb.isSelected();
|
|
||||||
if (tbCustomPath.isSelected()) {
|
if (tbCustomPath.isSelected()) {
|
||||||
return ApiDocExportRequest.path(pathField.getText(), debugEnabled);
|
return ApiDocExportRequest.path(pathField.getText());
|
||||||
}
|
}
|
||||||
if (tbFqn.isSelected()) {
|
if (tbFqn.isSelected()) {
|
||||||
return ApiDocExportRequest.fqn(fqnField.getText(), debugEnabled);
|
return ApiDocExportRequest.fqn(fqnField.getText());
|
||||||
}
|
}
|
||||||
List<String> selectedPaths = allProjectsCb.isSelected()
|
List<String> selectedPaths = allProjectsCb.isSelected()
|
||||||
? fileOperationHelper.getProjectPaths()
|
? fileOperationHelper.getProjectPaths()
|
||||||
@@ -392,8 +415,7 @@ public class ApiDocWindow {
|
|||||||
selectedPaths,
|
selectedPaths,
|
||||||
onlyInterfaceCb.isSelected(),
|
onlyInterfaceCb.isSelected(),
|
||||||
facadeNameCb.isSelected(),
|
facadeNameCb.isSelected(),
|
||||||
apiPackageOnlyCb.isSelected(),
|
apiPackageOnlyCb.isSelected());
|
||||||
debugEnabled);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void executeExport(
|
private void executeExport(
|
||||||
|
|||||||
@@ -35,22 +35,12 @@ public record ApiDocExportRequest(
|
|||||||
false, false, false);
|
false, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static ApiDocExportRequest path(String path, boolean ignored) {
|
|
||||||
return path(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ApiDocExportRequest fqn(String className) {
|
public static ApiDocExportRequest fqn(String className) {
|
||||||
return new ApiDocExportRequest(
|
return new ApiDocExportRequest(
|
||||||
Mode.FQN, className, List.of(),
|
Mode.FQN, className, List.of(),
|
||||||
false, false, false);
|
false, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static ApiDocExportRequest fqn(String className, boolean ignored) {
|
|
||||||
return fqn(className);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ApiDocExportRequest batch(
|
public static ApiDocExportRequest batch(
|
||||||
List<String> projectPaths,
|
List<String> projectPaths,
|
||||||
boolean onlyInterfaces,
|
boolean onlyInterfaces,
|
||||||
@@ -60,14 +50,4 @@ public record ApiDocExportRequest(
|
|||||||
Mode.BATCH, "", projectPaths,
|
Mode.BATCH, "", projectPaths,
|
||||||
onlyInterfaces, facadeNamesOnly, apiPackagesOnly);
|
onlyInterfaces, facadeNamesOnly, apiPackagesOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static ApiDocExportRequest batch(
|
|
||||||
List<String> projectPaths,
|
|
||||||
boolean onlyInterfaces,
|
|
||||||
boolean facadeNamesOnly,
|
|
||||||
boolean apiPackagesOnly,
|
|
||||||
boolean ignored) {
|
|
||||||
return batch(projectPaths, onlyInterfaces, facadeNamesOnly, apiPackagesOnly);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,14 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 本地 HTTP 代理,解决浏览器直连内网网关不通的问题。
|
* 本地 HTTP 代理,解决浏览器直连内网网关不通的问题。
|
||||||
* 监听 localhost 随机端口,JS 请求本代理,由 Java 侧转发到 gw.test.bestpay.net。
|
* 监听 localhost 随机端口,JS 请求本代理,由 Java 侧转发到 gw.test.bestpay.net。
|
||||||
*
|
*
|
||||||
* 单例,应用启动时创建,进程退出时自动回收。
|
* 单例,由应用生命周期统一启动和停止。
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class DubboDebugProxy {
|
public class DubboDebugProxy {
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.example.workutils.biz.apidoc;
|
||||||
|
|
||||||
|
import com.example.workutils.biz.apidoc.application.ApiDebugProxyLifecycle.State;
|
||||||
|
import com.example.workutils.biz.apidoc.application.ApiDebugProxyLifecycle.Status;
|
||||||
|
import com.example.workutils.system.ui.Theme;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static com.example.workutils.system.ui.FxTestSupport.fx;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
class ApiDebugProxyStatusLabelTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void runningStateShowsTheLocalEndpointAsSuccessfulReadOnlyStatus() throws Exception {
|
||||||
|
fx(() -> {
|
||||||
|
Label label = ApiDocWindow.buildProxyStatusLabel(
|
||||||
|
new Status(State.RUNNING,
|
||||||
|
"http://127.0.0.1:1234/dubbo/invoke", ""), 13);
|
||||||
|
|
||||||
|
assertTrue(label.getText().contains("本地代理已启动"));
|
||||||
|
assertTrue(label.getText().contains("127.0.0.1:1234"));
|
||||||
|
assertEquals(Theme.SUCCESS, label.getTextFill());
|
||||||
|
assertTrue(label.getAccessibleText().contains("本地代理已启动"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void failedStateExposesTheCompleteFailureReason() throws Exception {
|
||||||
|
fx(() -> {
|
||||||
|
Label label = ApiDocWindow.buildProxyStatusLabel(
|
||||||
|
new Status(State.FAILED, "", "端口不可用"), 13);
|
||||||
|
|
||||||
|
assertTrue(label.getText().contains("本地代理启动失败"));
|
||||||
|
assertTrue(label.getText().contains("端口不可用"));
|
||||||
|
assertEquals(Theme.DANGER, label.getTextFill());
|
||||||
|
assertTrue(label.getTooltip().getText().contains("端口不可用"));
|
||||||
|
assertTrue(label.getAccessibleText().contains("端口不可用"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,8 +21,12 @@ class ApiDocWindowArchitectureTest {
|
|||||||
assertTrue(source.contains("new Tab(\"基类配置\")"));
|
assertTrue(source.contains("new Tab(\"基类配置\")"));
|
||||||
assertTrue(source.contains("LoadingButtonBinder.bind"));
|
assertTrue(source.contains("LoadingButtonBinder.bind"));
|
||||||
assertTrue(source.contains("new ExportHistoryPane"));
|
assertTrue(source.contains("new ExportHistoryPane"));
|
||||||
|
assertTrue(source.contains("buildProxyStatusLabel"));
|
||||||
assertFalse(source.contains("new Thread("));
|
assertFalse(source.contains("new Thread("));
|
||||||
assertFalse(source.contains("setBtnLoading("));
|
assertFalse(source.contains("setBtnLoading("));
|
||||||
|
assertFalse(source.contains("debugProxyCb"));
|
||||||
|
assertFalse(source.contains("new CheckBox(\"启用接口调试"));
|
||||||
|
assertFalse(source.contains("DubboDebugProxy.getInstance()"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -67,6 +67,20 @@ class MainWindowArchitectureTest {
|
|||||||
< openPlugin.indexOf("factory.getEmbeddedPane()"));
|
< openPlugin.indexOf("factory.getEmbeddedPane()"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void applicationOwnsTheDebugProxyForTheWholeBusinessRun() throws Exception {
|
||||||
|
String application = source("src/main/java/com/example/workutils/WorkUtilsApplication.java");
|
||||||
|
String runMethod = between(application,
|
||||||
|
"public void run(String... args)",
|
||||||
|
"// ==================== 主窗口入口");
|
||||||
|
|
||||||
|
assertTrue(runMethod.contains("apiDebugProxyLifecycle.start()"));
|
||||||
|
assertTrue(runMethod.indexOf("apiDebugProxyLifecycle.start()")
|
||||||
|
< runMethod.indexOf("if (args.length == 0)"));
|
||||||
|
assertTrue(runMethod.contains("finally"));
|
||||||
|
assertTrue(runMethod.contains("apiDebugProxyLifecycle.stop()"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void headerUsesDesignTokensAndFeatherSemanticsWithoutCustomWindowChrome() throws Exception {
|
void headerUsesDesignTokensAndFeatherSemanticsWithoutCustomWindowChrome() throws Exception {
|
||||||
String mainWindow = source("src/main/java/com/example/workutils/system/ui/MainWindow.java");
|
String mainWindow = source("src/main/java/com/example/workutils/system/ui/MainWindow.java");
|
||||||
|
|||||||
Reference in New Issue
Block a user