Meldungsbereich: Button linksbündig; leeren bei Validieren und Techn. Tests

- clearMessagesButton ist jetzt linksbündig (CENTER_LEFT statt CENTER_RIGHT)
- pendingMessages.clear() wird auch am Anfang von runValidationAction() und
  runTechnicalTestsAction() aufgerufen; jeder Durchlauf zeigt nur seine eigenen
  Befunde
- GuiValidateActionSmokeTest: Erwartung von 2 auf 1 Bestätigungsmeldung nach
  zwei Klicks angepasst (Replace- statt Akkumulierungsverhalten)
- Zwei neue Smoke-Tests: validationAction_clearsPreviousMessages und
  technicalTestsAction_clearsPreviousMessages
- Dokumentation in docs/gui-bedienanleitung.md ergänzt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-22 11:54:14 +02:00
parent 1996f31f43
commit 13e4922272
4 changed files with 89 additions and 12 deletions
+10 -5
View File
@@ -114,14 +114,19 @@ Per Rechtsklick steht zusätzlich ein Kontextmenü zur Verfügung:
#### Meldungen leeren #### Meldungen leeren
Unterhalb des Meldungsbereichs befindet sich der Button **„Meldungen leeren"**. Unterhalb des Meldungsbereichs befindet sich links der Button **„Meldungen leeren"**.
Ein Klick darauf entfernt alle aktuell angezeigten Meldungen sofort und Ein Klick darauf entfernt alle aktuell angezeigten Meldungen sofort und
vollständig. vollständig.
Beim Laden einer neuen oder bestehenden Konfiguration über **„Neu"** oder Darüber hinaus wird der Meldungsbereich in folgenden Situationen automatisch
**„Öffnen"** wird der Meldungsbereich automatisch geleert, sodass keine geleert, sodass keine Meldungen aus einem früheren Vorgang sichtbar bleiben:
Meldungen aus einer früheren Sitzung oder einer vorher geladenen Datei sichtbar
bleiben. | Aktion | Verhalten |
|--------|-----------|
| **Neu** | Meldungsbereich wird vor der neuen Konfiguration geleert |
| **Öffnen** | Meldungsbereich wird vor der geladenen Konfiguration geleert |
| **Validieren** | Meldungsbereich wird geleert; danach erscheinen ausschließlich die Befunde des aktuellen Durchlaufs |
| **Technische Tests ausführen** | Meldungsbereich wird geleert; danach erscheinen ausschließlich die Befunde des aktuellen Durchlaufs |
--- ---
@@ -1501,6 +1501,7 @@ public final class GuiConfigurationEditorWorkspace {
*/ */
private void runTechnicalTestsAction() { private void runTechnicalTestsAction() {
LOG.info("Aktion Technische Tests ausführen gestartet."); LOG.info("Aktion Technische Tests ausführen gestartet.");
pendingMessages.clear();
technicalTestsButton.setDisable(true); technicalTestsButton.setDisable(true);
technicalTestCoordinator.triggerTechnicalTests(); technicalTestCoordinator.triggerTechnicalTests();
} }
@@ -1569,7 +1570,7 @@ public final class GuiConfigurationEditorWorkspace {
clearMessagesButton.setOnAction(e -> clearMessages()); clearMessagesButton.setOnAction(e -> clearMessages());
HBox clearButtonRow = new HBox(clearMessagesButton); HBox clearButtonRow = new HBox(clearMessagesButton);
clearButtonRow.setAlignment(Pos.CENTER_RIGHT); clearButtonRow.setAlignment(Pos.CENTER_LEFT);
card.getChildren().add(clearButtonRow); card.getChildren().add(clearButtonRow);
// Populate immediately so the area is not blank before the first validation run. // Populate immediately so the area is not blank before the first validation run.
@@ -1739,6 +1740,7 @@ public final class GuiConfigurationEditorWorkspace {
*/ */
private void runValidationAction() { private void runValidationAction() {
LOG.info("Aktion Validieren ausgeführt."); LOG.info("Aktion Validieren ausgeführt.");
pendingMessages.clear();
EditorValidationInput input = buildValidationInput(); EditorValidationInput input = buildValidationInput();
EditorValidationReport report = editorValidator.validate(input); EditorValidationReport report = editorValidator.validate(input);
@@ -680,6 +680,75 @@ class GuiMessageAreaSmokeTest {
}); });
} }
// =========================================================================
// Scenario: "Validieren" clears previous messages before showing results
// =========================================================================
/**
* Smoke test: invoking {@code runValidationAction()} via the validate button removes
* pre-existing messages so that results from a previous action do not accumulate.
*/
@Test
void validationAction_clearsPreviousMessages() throws Exception {
runOnFx(() -> {
GuiConfigurationEditorWorkspace ws = new GuiConfigurationEditorWorkspace(Optional.empty());
ws.requestNewConfiguration();
// Seed a stale message that must not survive the validation action.
ws.pendingMessages.add(
GuiMessageEntry.of(GuiMessageSeverity.ERROR, "Alter Befund", "Test"));
assertFalse(ws.pendingMessages.isEmpty(),
"Pre-condition: pending messages must not be empty before Validieren");
ws.validateButton.fire();
assertFalse(
ws.pendingMessages.stream()
.anyMatch(m -> "Alter Befund".equals(m.text())),
"The stale message must have been removed after Validieren");
});
}
// =========================================================================
// Scenario: "Technische Tests ausführen" clears previous messages before starting
// =========================================================================
/**
* Smoke test: invoking the technical-tests action removes pre-existing messages so that
* results from a previous action do not accumulate.
* <p>
* The clear happens synchronously on the FX thread before the background worker starts.
* The thread factory is replaced with a no-op so no background thread is actually
* started, which prevents native dialog calls that are not supported under Monocle.
*/
@Test
void technicalTestsAction_clearsPreviousMessages() throws Exception {
runOnFx(() -> {
GuiConfigurationEditorWorkspace ws = new GuiConfigurationEditorWorkspace(Optional.empty());
ws.requestNewConfiguration();
// Replace thread factory with a no-op so no background work runs in Monocle.
ws.technicalTestCoordinator.testThreadFactory = task -> new Thread(() -> { }) {
@Override
public void start() {
// Do not start — we only verify the synchronous clear, not the test result.
}
};
ws.pendingMessages.add(
GuiMessageEntry.of(GuiMessageSeverity.WARNING, "Alte Warnung", "Test"));
assertFalse(ws.pendingMessages.isEmpty(),
"Pre-condition: pending messages must not be empty before technical tests");
ws.technicalTestsButton.fire();
assertFalse(
ws.pendingMessages.stream()
.anyMatch(m -> "Alte Warnung".equals(m.text())),
"The stale message must have been removed after Technische Tests ausführen");
});
}
// ========================================================================= // =========================================================================
// Scenario: ai.provider.active field-error label is registered and shown // Scenario: ai.provider.active field-error label is registered and shown
// ========================================================================= // =========================================================================
@@ -244,13 +244,13 @@ class GuiValidateActionSmokeTest {
} }
// ========================================================================= // =========================================================================
// Scenario: clicking twice → message appears exactly once (replace semantics) // Scenario: clicking twice → exactly one message present (replace semantics)
// ========================================================================= // =========================================================================
/** /**
* Smoke test: clicking "Validieren" twice must leave two action-confirmation * Smoke test: clicking "Validieren" twice must leave exactly one action-confirmation
* INFO messages in the message list (accumulation semantics — each click appends * INFO message in the message list. Each click clears the previous messages before
* a fresh snapshot of findings). * adding the new result, so messages from an earlier click do not accumulate.
* *
* @throws Exception if the FX thread task fails or times out * @throws Exception if the FX thread task fails or times out
*/ */
@@ -267,8 +267,9 @@ class GuiValidateActionSmokeTest {
&& ACTION_SOURCE.equals(m.source().get())) && ACTION_SOURCE.equals(m.source().get()))
.filter(m -> m.text().startsWith("Aktion Validieren wurde ausgeführt.")) .filter(m -> m.text().startsWith("Aktion Validieren wurde ausgeführt."))
.count(); .count();
assertEquals(2, confirmationCount, assertEquals(1, confirmationCount,
"After two clicks two action-confirmation INFO messages must be present"); "After two clicks exactly one action-confirmation INFO message must be present"
+ " (second click replaces messages from the first click)");
}); });
} }