Skip to content

Tests added#43

Open
eafalkens wants to merge 2 commits intomainfrom
tests-added
Open

Tests added#43
eafalkens wants to merge 2 commits intomainfrom
tests-added

Conversation

@eafalkens
Copy link

@eafalkens eafalkens commented Nov 20, 2025

Lagt till Unit tests för metoderna info(), sendMessage() och startListening() i HelloModel.

Summary by CodeRabbit

  • New Features

    • Replaced greeting display with a chat-style interface featuring message history and input field.
    • Added message sending and receiving capabilities with real-time message updates.
  • Tests

    • Added unit tests for message handling and endpoint validation.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Nov 20, 2025

Walkthrough

The PR transforms a JavaFX application from displaying static greetings to a chat-based messaging system. HelloController's initialization is reworked to manage user input and message listening, HelloModel is redesigned to integrate with an ntfy service for sending and receiving messages, the FXML view is restructured with chat-like controls, and unit tests are added.

Changes

Cohort / File(s) Summary
Controller & Model – Chat Messaging Integration
src/main/java/com/example/HelloController.java, src/main/java/com/example/HelloModel.java
HelloController's initialize() changed to public and refactored to set up UI message listening and input handling; added sendMessage() and startListeningToMessages() methods for chat workflow. HelloModel replaced greeting logic with ntfy service integration: added sendMessage() for posting, startListening() for background polling with callbacks, and info() for endpoint info; removed getGreeting().
View – Chat UI Redesign
src/main/resources/com/example/hello-view.fxml
Replaced StackPane with BorderPane layout; replaced static greeting label with ListView for messages, TextField for input, and Button for sending; added layout spacing and control IDs.
Tests – Model Coverage
src/test/java/com/example/HelloModelTest.java
New JUnit 5 test class with three tests covering info() return value, sendMessage() execution, and startListening() callback registration.

Sequence Diagram

sequenceDiagram
    participant User
    participant Controller as HelloController
    participant Model as HelloModel
    participant ntfy as ntfy Service
    participant UI as JavaFX UI

    User->>Controller: Enters message & clicks Send
    activate Controller
    Controller->>Controller: sendMessage()
    Controller->>Model: sendMessage(message)
    deactivate Controller
    activate Model
    Model->>ntfy: POST /baseUrl/topic
    ntfy-->>Model: Response
    Model-->>Controller: (async)
    deactivate Model

    Controller->>UI: Append message to ListView
    
    rect rgba(100, 200, 150, 0.2)
    Note over Controller,ntfy: Background Listening Loop
    Controller->>Controller: startListeningToMessages()
    Controller->>Model: startListening(onMessage, onError)
    activate Model
    Model->>Model: Spawn background thread
    loop Poll messages
        Model->>ntfy: GET /baseUrl/topic/json
        ntfy-->>Model: Message stream
        Model->>Controller: onMessage callback (UI thread)
    end
    deactivate Model
    end
    
    Controller->>UI: Update ListView with received messages
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • HelloModel: Introduces background threading, HTTP integration, and Consumer-based callbacks—requires verification of error handling, thread lifecycle, and callback correctness.
  • HelloController: The initialize() visibility change and new message-handling logic need review to ensure proper FXML binding and UI thread safety.
  • FXML restructuring: Verify control IDs match controller field names and layout hierarchy supports the intended chat interaction.

Possibly related PRs

  • Initial implementation of JavaFX Chat App with ntfy integration #34: Both add ntfy-based messaging (send/listen) capabilities to HelloController and HelloModel with similar service integration patterns.
  • setup #27: Implements the same chat UI and background message subscription logic, with nearly identical sendMessage and startListening patterns in controller and model classes.
  • Revert "Tests" #33: Removes the prior ChatController and chat-view.fxml, directly replaced by this PR's HelloController chat redesign and hello-view.fxml restructuring.

Poem

🐰 A chat bubbles forth where greetings once stood,
The model now listens, as service-folk should!
With threads in the background and buttons that gleam,
Our JavaFX app now lives out the chat dream.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The PR title 'Tests added' is extremely vague and does not convey meaningful information about the changeset. While technically related to the changes, it fails to specify which tests were added, what they test, or their context. The PR involves a major refactoring of HelloController and HelloModel along with UI changes in FXML, but the title only mentions tests. Use a more descriptive title that specifies what was tested, such as 'Add unit tests for HelloModel messaging methods' or 'Add tests for HelloModel info, sendMessage, and startListening'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
src/test/java/com/example/HelloModelTest.java (2)

9-13: Hard‑coded URL in test tightly couples to HelloModel internals

info_returnsCorrectUrl (Line 9–Line 13) asserts against a literal "https://ntfy.sh/java25-erika-chat", so any change to baseUrl or topic in HelloModel will require test updates. Consider deriving the expected value from a shared constant or configuration to reduce duplication.


15-19: sendMessage_doesNotThrow has very limited value with current implementation

HelloModel.sendMessage catches Exception internally, so this test will almost never fail even if networking is misconfigured. If you want a stronger test, consider refactoring HelloModel to inject an HTTP client or base URL so you can:

  • Verify that a POST is issued to the right endpoint, or
  • Simulate failures and assert on error handling behavior.
src/main/java/com/example/HelloModel.java (2)

13-29: sendMessage blocks caller thread and lacks timeouts/charset handling

sendMessage (Line 13–Line 29) runs the HTTP POST synchronously on the calling thread (in this app, the JavaFX event thread), with no connect/read timeouts and using the platform default encoding via getBytes(). This can freeze the UI on slow networks and makes behavior depend on platform encoding.

Consider:

  • Moving the HTTP call off the UI thread (e.g. using a background Thread/ExecutorService), and
  • Adding timeouts and explicit UTF‑8 encoding, plus try‑with‑resources for the output stream.

Example of the core change inside sendMessage:

-            var url = new URL(baseUrl + "/" + topic);
-            var conn = (HttpURLConnection) url.openConnection();
-
-            conn.setRequestMethod("POST");
-            conn.setDoOutput(true);
-
-            conn.getOutputStream().write(message.getBytes());
-
-            System.out.println("Skickat till " + url + ": " + message);
-            conn.disconnect();
+            var url = new URL(baseUrl + "/" + topic);
+            var conn = (HttpURLConnection) url.openConnection();
+            conn.setRequestMethod("POST");
+            conn.setDoOutput(true);
+            conn.setConnectTimeout(5000);
+            conn.setReadTimeout(5000);
+
+            try (var out = conn.getOutputStream()) {
+                out.write(message.getBytes(java.nio.charset.StandardCharsets.UTF_8));
+            }
+
+            System.out.println("Skickat till " + url + ": " + message);
+            conn.disconnect();

(Plus moving this whole block off the JavaFX thread when called from the controller.)


31-59: Listener thread never closed, no timeouts, and may keep JVM alive

In startListening (Line 31–Line 59):

  • The new Thread is non‑daemon and blocks on readLine() against the ntfy JSON endpoint, with no timeouts.
  • BufferedReader and the HttpURLConnection are never explicitly closed.
  • There is no way to stop the listener from outside.

This can lead to:

  • Resource leaks (open connections/streams), and
  • The JVM staying alive because of the non‑daemon listener thread after the UI is closed or tests finish.

Consider:

  • Marking the thread as daemon.
  • Using try‑with‑resources for the InputStream/BufferedReader, and calling conn.disconnect() in a finally block.
  • Optionally exposing a stop mechanism if you expect to start/stop listening during app lifetime.

Example skeleton:

-    public void startListening(Consumer<String> onMessage, Consumer<Throwable> onError) {
-        new Thread(() -> {
+    public void startListening(Consumer<String> onMessage, Consumer<Throwable> onError) {
+        Thread t = new Thread(() -> {
             try {
                 var url = new URL(baseUrl + "/" + topic + "/json");
                 var conn = (HttpURLConnection) url.openConnection();
                 conn.setRequestMethod("GET");
-
-                var reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
-                String line;
-
-                while ((line = reader.readLine()) != null) {
+                try (var in = conn.getInputStream();
+                     var reader = new BufferedReader(new InputStreamReader(in))) {
+                    String line;
+                    while ((line = reader.readLine()) != null) {
                         // parsing logic...
-                }
-
-            } catch (Throwable ex) {
-                if (onError != null) onError.accept(ex);
-            }
-        }).start();
+                    }
+                } finally {
+                    conn.disconnect();
+                }
+            } catch (Throwable ex) {
+                if (onError != null) onError.accept(ex);
+            }
+        }, "ntfy-listener");
+        t.setDaemon(true);
+        t.start();
     }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 21c51e8 and 783f85b.

📒 Files selected for processing (4)
  • src/main/java/com/example/HelloController.java (1 hunks)
  • src/main/java/com/example/HelloModel.java (1 hunks)
  • src/main/resources/com/example/hello-view.fxml (1 hunks)
  • src/test/java/com/example/HelloModelTest.java (1 hunks)
🔇 Additional comments (2)
src/main/resources/com/example/hello-view.fxml (1)

9-28: FXML IDs and layout align well with HelloController

The BorderPane + HBox structure is clear, and messages, inputField, and sendBtn IDs match the controller fields. Looks good for the chat use case.

src/main/java/com/example/HelloController.java (1)

51-61: Good use of Platform.runLater to update UI from listener callbacks

startListeningToMessages correctly wraps messages.getItems().add(...) calls in Platform.runLater, so UI updates happen on the JavaFX Application Thread despite the background listener.

Comment on lines +29 to +31
// När man trycker på Skicka-knappen
sendBtn.setOnAction(_ -> sendMessage());
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

❓ Verification inconclusive

Lambda parameter _ is not valid in modern Java versions

On Line 30, sendBtn.setOnAction(_ -> sendMessage()); uses _ as the lambda parameter name. In Java 9+ _ is a reserved identifier and this will fail to compile. Use a conventional name instead, e.g.:

-        sendBtn.setOnAction(_ -> sendMessage());
+        sendBtn.setOnAction(event -> sendMessage());

Lambda parameter _ is not valid in modern Java versions

On Line 30, sendBtn.setOnAction(_ -> sendMessage()); uses _ as the lambda parameter name. In Java 9+, it is a compile-time error if a lambda parameter has the name _. This restriction was introduced in Java 9. Use a conventional name instead, e.g.:

-        sendBtn.setOnAction(_ -> sendMessage());
+        sendBtn.setOnAction(event -> sendMessage());
🤖 Prompt for AI Agents
In src/main/java/com/example/HelloController.java around lines 29 to 31, the
lambda uses `_` as the parameter name which is a compile-time error in Java 9+;
replace the underscore with a valid identifier (for example `e`, `event`, or
`actionEvent`) or use a no-arg lambda form if appropriate, e.g. change
`sendBtn.setOnAction(_ -> sendMessage());` to `sendBtn.setOnAction(e ->
sendMessage());` so the code compiles on modern Java versions.

Comment on lines +21 to +25
@Test
void startListening_doesNotThrow() {
HelloModel model = new HelloModel();
assertDoesNotThrow(() -> model.startListening(msg -> {}, err -> {}));
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

startListening_doesNotThrow can leak a long‑running background thread

startListening starts a new non‑daemon thread that blocks on reader.readLine() against the live ntfy endpoint. The test only asserts the call does not throw; it does not wait for or stop the listener. This can:

  • Leave a background thread running after the test finishes, and
  • Make tests depend on external network availability.

Consider either:

  • Refactoring HelloModel so the listener thread can be stopped (and doing that in the test), or
  • Abstracting the network layer so the test can run against a stub instead of the real ntfy service.

I'll verify the review comment by examining the codebase to understand the actual implementation of HelloModel and the test setup.


---

🏁 Script executed:

```shell
#!/bin/bash
# Find HelloModel class
fd -type f -name "HelloModel.java"

Length of output: 170


🏁 Script executed:

#!/bin/bash
# Search for startListening method definition and usage
rg -n "startListening" --type=java -C 5

Length of output: 3648


🏁 Script executed:

#!/bin/bash
# Check for test lifecycle methods in HelloModelTest.java
rg -n "@Before|@After|@BeforeEach|@AfterEach" src/test/java/com/example/HelloModelTest.java -C 3

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Look for thread creation and daemon status
rg -n "new Thread|setDaemon|Thread\(" --type=java -C 4

Length of output: 786


🏁 Script executed:

#!/bin/bash
# Check HelloModelTest.java structure for any listeners or cleanup
cat src/test/java/com/example/HelloModelTest.java

Length of output: 730


I need to see the complete startListening() implementation to confirm the thread behavior:


---

🏁 Script executed:

```shell
#!/bin/bash
# View full HelloModel.java file
cat src/main/java/com/example/HelloModel.java

Length of output: 2241


Fix the thread leak in startListening_doesNotThrow by implementing listener cleanup

The issue is confirmed: HelloModel.startListening() creates a non-daemon thread that blocks indefinitely on reader.readLine() against the live ntfy endpoint (line 42 in src/main/java/com/example/HelloModel.java). The test starts this listener but never stops it, leaving a background thread running after the test completes.

Recommended fixes:

  1. Refactor HelloModel.startListening() to return a Closeable or AutoCloseable reference so tests can stop the listener, then use try-with-resources in the test.
  2. Mock or stub the HTTP layer in tests to avoid external network dependencies and eliminate the blocking I/O.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant