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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ A JavaFX-based chat client using [ntfy](https://docs.ntfy.sh/) for backend messa
2. Start with:
```bash
./mvnw clean javafx:run

## Author
Created for Lab 3 - Network Programming - Younes Ahmad
4 changes: 4 additions & 0 deletions src/main/java/com/example/model/ChatModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ public void connect() {
}

public void sendMessage(String text) throws Exception {
if (text == null || text.trim().isEmpty()) {
throw new IllegalArgumentException("Message cannot be empty");
}

NtfyMessage message = new NtfyMessage(topic, text);
networkClient.send(baseUrl, message);
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/example/model/NtfyMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public record NtfyMessage(
String event,
String topic,
String message,
String attachment // Nytt fält för filer
String attachment
) {
public NtfyMessage(String topic, String message) {
this(null, null, "message", topic, message, null);
Expand Down
53 changes: 37 additions & 16 deletions src/test/java/com/example/model/ChatModelTest.java
Original file line number Diff line number Diff line change
@@ -1,36 +1,57 @@
package com.example.model;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;

import static org.junit.jupiter.api.Assertions.*;

class ChatModelTest {

@Test
@DisplayName("NtfyMessage should be created with topic and message")
void testMessageCreation() {
NtfyMessage message = new NtfyMessage("testTopic", "Hello");
private ChatModel model;

assertEquals("testTopic", message.topic());
assertEquals("Hello", message.message());
assertNotNull(message);
@BeforeEach
void setup() {
model = new ChatModel();
}

@Test
@DisplayName("NtfyMessage should have event type")
void testMessageEvent() {
NtfyMessage message = new NtfyMessage("topic", "msg");
@DisplayName("Should have empty message list initially")
void testInitialState() {
assertNotNull(model.getMessages());
assertTrue(model.getMessages().isEmpty());
}

assertEquals("message", message.event());
@Test
@DisplayName("Should return observable list of messages")
void testGetMessages() {
assertNotNull(model.getMessages());
assertEquals(0, model.getMessages().size());
}

@Test
@DisplayName("NtfyMessage with attachment should store filename")
void testMessageWithAttachment() {
NtfyMessage message = new NtfyMessage("topic", "File sent", "test.pdf");
@DisplayName("Should allow adding messages to list")
void testAddMessageToList() {
NtfyMessage message = new NtfyMessage("testTopic", "Test message");
model.getMessages().add(message);

assertEquals("test.pdf", message.attachment());
assertEquals("File sent", message.message());
assertEquals(1, model.getMessages().size());
assertEquals("Test message", model.getMessages().get(0).message());
}

@Test
@DisplayName("Should maintain message order")
void testMessageOrder() {
NtfyMessage msg1 = new NtfyMessage("topic", "First");
NtfyMessage msg2 = new NtfyMessage("topic", "Second");
NtfyMessage msg3 = new NtfyMessage("topic", "Third");

model.getMessages().add(msg1);
model.getMessages().add(msg2);
model.getMessages().add(msg3);

assertEquals("First", model.getMessages().get(0).message());
assertEquals("Second", model.getMessages().get(1).message());
assertEquals("Third", model.getMessages().get(2).message());
}
}
99 changes: 45 additions & 54 deletions src/test/java/com/example/model/NtfyMesageTest.java
Original file line number Diff line number Diff line change
@@ -1,92 +1,83 @@
package com.example.model;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;

import static org.junit.jupiter.api.Assertions.*;

class NtfyMessageTest {

private final ObjectMapper objectMapper = new ObjectMapper();

@Test
@DisplayName("Should create message with convenience constructor")
void testConvenienceConstructor() {
@DisplayName("Should create message with topic and message text")
void testCreateMessage() {
NtfyMessage message = new NtfyMessage("testTopic", "Hello World");

assertEquals("testTopic", message.topic());
assertEquals("Hello World", message.message());
assertNotNull(message);
}

@Test
@DisplayName("Should set default event type to 'message'")
void testDefaultEventType() {
NtfyMessage message = new NtfyMessage("testTopic", "Test");

assertEquals("message", message.event());
}

@Test
@DisplayName("Should handle null id and time for new messages")
void testNewMessageHasNullIdAndTime() {
NtfyMessage message = new NtfyMessage("testTopic", "Test");

assertNull(message.id());
assertNull(message.time());
}

@Test
@DisplayName("Should deserialize JSON to NtfyMessage")
void testDeserialization() throws Exception {
String json = """
{
"id": "abc123",
"time": 1234567890,
"event": "message",
"topic": "testTopic",
"message": "Hello World"
}
""";

NtfyMessage message = objectMapper.readValue(json, NtfyMessage.class);
@DisplayName("Should create message with all fields using canonical constructor")
void testFullConstructor() {
NtfyMessage message = new NtfyMessage(
"abc123", // id
1234567890L, // time
"message", // event
"testTopic", // topic
"Hello", // message
null // attachment
);

assertNotNull(message);
assertEquals("abc123", message.id());
assertEquals(1234567890, message.time());
assertEquals(1234567890L, message.time());
assertEquals("message", message.event());
assertEquals("testTopic", message.topic());
assertEquals("Hello World", message.message());
assertEquals("Hello", message.message());
}

@Test
@DisplayName("Should serialize NtfyMessage to JSON")
void testSerialization() throws Exception {
NtfyMessage message = new NtfyMessage("testTopic", "Hello World");
@DisplayName("Should accept empty message text")
void testEmptyMessage() {
NtfyMessage message = new NtfyMessage("testTopic", "");

String json = objectMapper.writeValueAsString(message);

assertNotNull(json);
assertTrue(json.contains("\"topic\":\"testTopic\""));
assertTrue(json.contains("\"message\":\"Hello World\""));
assertTrue(json.contains("\"event\":\"message\""));
assertEquals("", message.message());
assertEquals("testTopic", message.topic());
}

@Test
@DisplayName("Should ignore unknown fields during deserialization")
void testIgnoreUnknownFields() throws Exception {
String json = """
{
"id": "xyz789",
"time": 9876543210,
"event": "message",
"topic": "testTopic",
"message": "Test",
"expires": 1761905659,
"unknownField": "should be ignored"
}
""";

NtfyMessage message = objectMapper.readValue(json, NtfyMessage.class);
@DisplayName("Should create message with attachment")
void testMessageWithAttachment() {
NtfyMessage message = new NtfyMessage("testTopic", "File sent", "test.pdf");

assertNotNull(message);
assertEquals("xyz789", message.id());
assertEquals("Test", message.message());
assertEquals("testTopic", message.topic());
assertEquals("File sent", message.message());
assertEquals("test.pdf", message.attachment());
}

@Test
@DisplayName("Should handle null values")
void testNullValues() {
NtfyMessage message = new NtfyMessage("topic", "message");
@DisplayName("Should handle special characters in message")
void testSpecialCharacters() {
String specialMessage = "Hello! 🌸 @user #topic";
NtfyMessage message = new NtfyMessage("testTopic", specialMessage);

assertNull(message.id());
assertNull(message.time());
assertNull(message.attachment());
assertEquals(specialMessage, message.message());
}
}
Loading