diff --git a/.idea/dbnavigator.xml b/.idea/dbnavigator.xml
index c87a7de..73447bd 100644
--- a/.idea/dbnavigator.xml
+++ b/.idea/dbnavigator.xml
@@ -10,6 +10,12 @@
+
+
+
+
+
+
diff --git a/functional-requirements.md b/functional-requirements.md
new file mode 100644
index 0000000..eb49954
--- /dev/null
+++ b/functional-requirements.md
@@ -0,0 +1,10 @@
+Project 1: Väder-baserad Klädväljare
+
+FR1: Returnera "Vinterjacka" om temperaturen understiger 0 grader;
+FR2: Returnera "Tshirt" om temperaturen överstiger 15 grader;
+FR3: Lägg till "ta med Paraply" om nederbörd;
+FR4: Hantera undantag.
+
+Project 2: Prishantering
+
+FR1:
\ No newline at end of file
diff --git a/opencode.json b/opencode.json
new file mode 100644
index 0000000..1b0f8dd
--- /dev/null
+++ b/opencode.json
@@ -0,0 +1,16 @@
+{
+ "$schema": "https://opencode.ai/config.json",
+ "permission": {
+ "edit": {
+ "pom.xml": "deny"
+ }
+
+},
+"mcp":{
+ "context7": {
+ "type": "remote",
+ "url" : "https://mcp.context7.com/mcp",
+ "enabled": true
+ }
+}
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 776cf47..5fee14a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,18 @@
3.27.6
test
-
+
+ org.mockito
+ mockito-junit-jupiter
+ 5.21.0
+ test
+
+
+ org.awaitility
+ awaitility
+ 4.2.0
+ test
+
diff --git a/src/main/java/org/example/Bowling.java b/src/main/java/org/example/Bowling.java
new file mode 100644
index 0000000..dd7ce41
--- /dev/null
+++ b/src/main/java/org/example/Bowling.java
@@ -0,0 +1,53 @@
+package org.example;
+
+public class Bowling {
+ private int[] rolls = new int[20];
+ private int rollCount = 0;
+
+
+
+ public void roll(int pins){
+ if (pins == 10)
+ rollCount++;
+ rolls[rollCount++] = pins;
+ }
+
+ private boolean isFinalFrame(){
+ return rollCount > 18;
+ }
+ public int score(){
+ int score = 0;
+ for (int i = 0; i < rolls.length; i+=2) {
+ if(isStrike(i))
+ score += strikeBonus(i);
+ else if(isSpare(i)){
+ score += rolls[i] + rolls[i + 1] + spareBonus(i);
+ } else
+ score += rolls[i] + rolls[i + 1];
+
+ }
+ return score;
+ }
+
+ private int spareBonus(int i){
+ return rolls[i + 2];
+ }
+
+ private int strikeBonus(int i){
+ if (i == 16)
+ return rolls[i+1] + rolls[i+2];
+ if(rolls[i + 2] == 10)
+ return rolls[i + 2] + rolls[i + 4];
+ return rolls[i + 2] + rolls[i + 3];
+ }
+
+ public boolean isStrike(int i){
+ return rolls[i] == 10;
+
+ }
+
+ public boolean isSpare(int i){
+
+ return rolls[i] == 0 && rolls[i + 1] == 10;
+ }
+}
diff --git a/src/main/java/org/example/CSV/CsvTodoStorage.java b/src/main/java/org/example/CSV/CsvTodoStorage.java
new file mode 100644
index 0000000..657b3da
--- /dev/null
+++ b/src/main/java/org/example/CSV/CsvTodoStorage.java
@@ -0,0 +1,30 @@
+package org.example.CSV;
+
+import org.example.todolist.TodoItem;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.List;
+
+public class CsvTodoStorage {
+
+
+ public void write(List items, Writer out) throws IOException {
+ out.write("id,task,due\n");
+
+ for (TodoItem item : items) {
+ out.write(item.getId() + ",\"Buy milk, \"\"organic\"\"\"");
+ out.write(escapeCsv(item.getTask()) + ",");
+ out.write(item.getDue() + "\n");
+ }
+ }
+
+ private String escapeCsv(String s) {
+ if (s == null) return "";
+ boolean needsQuotes =
+ s.contains(",") || s.contains("\"") || s.contains("\n");
+
+ String escaped = s.replace("\"", "\"\"");
+ return needsQuotes ? "\"" + escaped + "\"" : escaped;
+ }
+}
diff --git a/src/main/java/org/example/CSV/saveToFile.java b/src/main/java/org/example/CSV/saveToFile.java
new file mode 100644
index 0000000..4b3a097
--- /dev/null
+++ b/src/main/java/org/example/CSV/saveToFile.java
@@ -0,0 +1,21 @@
+import org.example.todolist.TodoItem;
+
+import java.io.BufferedWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.*;
+
+import static java.nio.file.Files.write;
+
+public void saveToFile(List items, Path path) throws Exception {
+ try (BufferedWriter writer =
+ Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
+ write(items, writer);
+ }
+}
+
+private void write(List items, BufferedWriter writer) {
+}
+
+void main() {
+
+}
diff --git a/src/main/java/org/example/Calculator.java b/src/main/java/org/example/Calculator.java
index 0a31456..627d5a1 100644
--- a/src/main/java/org/example/Calculator.java
+++ b/src/main/java/org/example/Calculator.java
@@ -14,9 +14,11 @@ public static int add(int a, int b){
}
- public static int add(int a, int b,int c){
+ public static int add(int a, int b,int c)
+ {
return a + b + c;
}
+
public static int add(int... numbers){
int sum = 0;
for(int number : numbers){
@@ -37,4 +39,8 @@ public static int divide(int a, int b) {
return a / b;
}
+ public static float divide(float a, float b) {
+ return a / b;
+ }
+
}
diff --git a/src/main/java/org/example/price/NotificationService.java b/src/main/java/org/example/price/NotificationService.java
new file mode 100644
index 0000000..26b8b64
--- /dev/null
+++ b/src/main/java/org/example/price/NotificationService.java
@@ -0,0 +1,7 @@
+package org.example.price;
+
+public interface NotificationService {
+
+ void notify(String productName, int price);
+ boolean isSent();
+}
diff --git a/src/main/java/org/example/price/PriceWatcher.java b/src/main/java/org/example/price/PriceWatcher.java
new file mode 100644
index 0000000..23dea7b
--- /dev/null
+++ b/src/main/java/org/example/price/PriceWatcher.java
@@ -0,0 +1,17 @@
+package org.example.price;
+
+public class PriceWatcher {
+ Priceservice priceService;
+ NotificationService notificationService;
+
+ PriceWatcher(Priceservice priceService, NotificationService notificationService){
+ this.priceService = priceService;
+ this.notificationService = notificationService;
+ }
+ public void checkPrices(){
+ int price = priceService.getPrice("T-SHIRT");
+ if (price < 100)
+ notificationService.notify("T-SHIRT", priceService.getPrice("T-SHIRT"));
+
+ }
+}
diff --git a/src/main/java/org/example/price/Priceservice.java b/src/main/java/org/example/price/Priceservice.java
new file mode 100644
index 0000000..48a8ae5
--- /dev/null
+++ b/src/main/java/org/example/price/Priceservice.java
@@ -0,0 +1,7 @@
+package org.example.price;
+
+public interface Priceservice {
+ int getPrice(String productName);
+
+
+}
diff --git a/src/main/java/org/example/socket/SimpleClient.java b/src/main/java/org/example/socket/SimpleClient.java
new file mode 100644
index 0000000..a832081
--- /dev/null
+++ b/src/main/java/org/example/socket/SimpleClient.java
@@ -0,0 +1,21 @@
+package org.example.socket;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+public class SimpleClient {
+
+ static void main(){
+ int port = 3000;
+ String serverIp = "127.0.0.1";
+
+ try(Socket socket = new Socket(serverIp, port)){
+
+ } catch (UnknownHostException e){
+ throw new RuntimeException(e);
+ } catch (IOException e){
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/src/main/java/org/example/socket/SimpleServer.java b/src/main/java/org/example/socket/SimpleServer.java
new file mode 100644
index 0000000..b5522c9
--- /dev/null
+++ b/src/main/java/org/example/socket/SimpleServer.java
@@ -0,0 +1,52 @@
+package org.example.socket;
+
+import java.io.*;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.Arrays;
+
+public class SimpleServer {
+
+ static void main(){
+
+ int port = 3000;
+
+ try(ServerSocket serverSocket = new ServerSocket(port, 5,
+ InetAddress.ofLiteral("127.0.0.1"))){
+ System.out.println("" + serverSocket.getLocalPort() + " is the port");
+
+ while(true) {
+ Socket socket = serverSocket.accept();
+ Thread.ofVirtual().start(() -> {
+ try {
+ handleClient(socket);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ private static void handleClient(Socket socket ) throws IOException {
+ try (Socket client = socket) {
+ System.out.println("Client connected: " + socket.getRemoteSocketAddress());
+ BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+ InputStream input = socket.getInputStream();
+ OutputStream output = socket.getOutputStream();
+ PrintWriter writer = new PrintWriter(output, true);
+ IO.readln();
+
+ writer.println("Hello client!");
+ socket.close();
+ } catch(IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
diff --git a/src/main/java/org/example/toDoList.java b/src/main/java/org/example/toDoList.java
new file mode 100644
index 0000000..1cbf3f2
--- /dev/null
+++ b/src/main/java/org/example/toDoList.java
@@ -0,0 +1,18 @@
+package org.example;
+//
+public class toDoList {
+
+
+ private int nextId = 1;
+
+
+ public TodoItem add(String text) {
+ return new TodoItem(nextId++);
+ }
+
+ public int size(int size){
+ return size = 0;
+ }
+
+ }
+
diff --git a/src/main/java/org/example/todolist/TodoItem.java b/src/main/java/org/example/todolist/TodoItem.java
new file mode 100644
index 0000000..b48a0df
--- /dev/null
+++ b/src/main/java/org/example/todolist/TodoItem.java
@@ -0,0 +1,47 @@
+package org.example.todolist;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+public class TodoItem {
+ private final int id;
+ private final String task;
+ private final LocalDate due;
+ private boolean done;
+
+
+ public TodoItem(int id, String task, LocalDate due) {
+ this.id = id;
+ this.task = task;
+ this.due = due;
+ this.done = done;
+ }
+
+
+
+ public int getId() {
+ return id;
+ }
+
+ public String getTask() {
+ return task;
+ }
+
+ public LocalDate getDue() {
+
+ return due;
+
+ }
+ @Override
+ public String toString() {
+ return "Id: " + id;
+ }
+
+ public boolean isDone() {
+ return done;
+ }
+
+ public void markDone() {
+ done = true;
+ }
+}
diff --git a/src/main/java/org/example/todolist/TodoList.java b/src/main/java/org/example/todolist/TodoList.java
new file mode 100644
index 0000000..046eb55
--- /dev/null
+++ b/src/main/java/org/example/todolist/TodoList.java
@@ -0,0 +1,44 @@
+package org.example.todolist;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.List;
+
+public class TodoList {
+
+ private int nextId = 1;
+ private int size = 0;
+ private final List items = new ArrayList<>();
+ private TodoItem item;
+ private boolean done = false;
+
+
+
+ public int size(){
+ return items.size();
+
+ }
+ public TodoItem add(String task, LocalDate due) {
+
+ TodoItem item = new TodoItem(nextId++, task, due);
+ items.add(item);
+ return item;
+ }
+ public TodoItem get(int index){
+ return items.get(index);
+ }
+ public TodoItem add() {
+ items.add(item);
+ return item;
+ }
+
+ public boolean markDone(int id) {
+ for (TodoItem item : items) {
+ if (item.getId() == id) {
+ item.markDone();
+ return true;
+ }
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/example/todolist/TodoListTask.java b/src/main/java/org/example/todolist/TodoListTask.java
new file mode 100644
index 0000000..d8f9ddb
--- /dev/null
+++ b/src/main/java/org/example/todolist/TodoListTask.java
@@ -0,0 +1,17 @@
+package org.example.todolist;
+
+public class TodoListTask {
+ String task;
+ boolean done;
+
+
+ public String TodoListTask(String task) {
+ return task;
+ }
+ public TodoListTask task(String text) {
+ return new TodoListTask();
+ }
+ public String getTask(){
+ return task;
+ }
+}
diff --git a/src/main/java/org/example/utils/PhoneNumberValidator.java b/src/main/java/org/example/utils/PhoneNumberValidator.java
new file mode 100644
index 0000000..c047914
--- /dev/null
+++ b/src/main/java/org/example/utils/PhoneNumberValidator.java
@@ -0,0 +1,16 @@
+package org.example.utils;
+
+import java.util.function.Predicate;
+
+public class PhoneNumberValidator implements Predicate{
+
+ @Override
+ public boolean test(String phoneNumber){
+ return phoneNumber.startsWith("+44") &&
+ phoneNumber.length() == 13;
+
+ }
+
+ }
+
+
diff --git a/src/main/java/org/example/weather/WeatherService.java b/src/main/java/org/example/weather/WeatherService.java
new file mode 100644
index 0000000..1ea027e
--- /dev/null
+++ b/src/main/java/org/example/weather/WeatherService.java
@@ -0,0 +1,8 @@
+package org.example.weather;
+
+public interface WeatherService {
+
+ float getTemperature();
+
+
+}
diff --git a/src/main/java/org/example/weather/outFitAdvisor.java b/src/main/java/org/example/weather/outFitAdvisor.java
new file mode 100644
index 0000000..2206ec7
--- /dev/null
+++ b/src/main/java/org/example/weather/outFitAdvisor.java
@@ -0,0 +1,24 @@
+package org.example.weather;
+
+public class outFitAdvisor {
+
+ private final WeatherService weatherService;
+
+ public outFitAdvisor(WeatherService weatherService){
+ this.weatherService = weatherService;
+
+ }
+ public String getClothingAdvice() {
+ try {
+ var temp = weatherService.getTemperature();
+ if (temp < 0)
+ return "Vinterjacka";
+ if (temp >= 15)
+ return "Sweatpants";
+ return null;
+ } catch(IllegalStateException e) {
+ return "Jeans and Jacket";
+
+ }
+ }
+}
diff --git a/src/test/java/org/example/BowlingTest.java b/src/test/java/org/example/BowlingTest.java
new file mode 100644
index 0000000..b39e0d6
--- /dev/null
+++ b/src/test/java/org/example/BowlingTest.java
@@ -0,0 +1,84 @@
+package org.example;
+
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+public class BowlingTest {
+
+
+ @Test
+ void gutterGameGivesZeroScore() {
+ Bowling bowlingGame = new Bowling();
+
+ for(int i = 0; i < 20; i++){
+ bowlingGame.roll(0);
+ }
+
+ assertThat(bowlingGame.score()).isEqualTo(0);
+
+ }
+
+ @Test
+ void allOneGivesScoreTwenty(){
+ Bowling bowlingGame = new Bowling();
+
+ for(int i = 0; i < 20; i++){
+ bowlingGame.roll(1);
+ }
+ assertThat(bowlingGame.score()).isEqualTo(20);
+ }
+
+ @Test
+ void oneSpareGivesScoreTwnetyNine(){
+ Bowling bowlingGame = new Bowling();
+
+ bowlingGame.roll(5);
+ bowlingGame.roll(5);
+ for(int i = 0; i < 18; i++){
+ bowlingGame.roll(1);
+ }
+
+ assertThat(bowlingGame.score()).isEqualTo(29);
+ }
+ @Test
+ void oneStrikeGivesScoreTwentyFour(){
+ Bowling bowlingGame = new Bowling();
+ bowlingGame.roll(10);
+ bowlingGame.roll(3);
+ bowlingGame.roll(4);
+
+ for(int i = 0; i < 16; i++){
+ bowlingGame.roll(1);
+ }
+
+ assertThat(bowlingGame.score()).isEqualTo(40);
+
+ }
+ @Test
+ void perfectGameGivesScore300(){
+ Bowling bowlingGame = new Bowling();
+ for(int i = 0; i < 12; i++){
+ bowlingGame.roll(10);
+ }
+ assertThat(bowlingGame.score()).isEqualTo(300);
+ }
+ @Test
+ void normalGame(){
+ Bowling bowlingGame = new Bowling();
+ bowlingGame.roll(10);
+ bowlingGame.roll(3);
+ bowlingGame.roll(7);
+ bowlingGame.roll(1);
+ bowlingGame.roll(9);
+ bowlingGame.roll(0);
+ bowlingGame.roll(4);
+ bowlingGame.roll(10);
+ bowlingGame.roll(2);
+ bowlingGame.roll(8);
+
+ assertThat(bowlingGame.score()).isEqualTo(59);
+
+ }
+}
diff --git a/src/test/java/org/example/CSV/CsvTodoStorageTest.java b/src/test/java/org/example/CSV/CsvTodoStorageTest.java
new file mode 100644
index 0000000..705c5cb
--- /dev/null
+++ b/src/test/java/org/example/CSV/CsvTodoStorageTest.java
@@ -0,0 +1,49 @@
+package org.example.CSV;
+
+import org.example.CSV.CsvTodoStorage;
+import org.example.todolist.TodoItem;
+import org.junit.jupiter.api.Test;
+
+import java.io.StringWriter;
+import java.time.LocalDate;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.*;
+
+class CsvTodoStorageTest {
+
+ @Test
+ void savesTodosAsCsvWithIdTaskAndDue() throws Exception {
+ List items = List.of(
+ new TodoItem(1, "Buy milk", LocalDate.of(2026, 1, 20)),
+ new TodoItem(2, "Bread", LocalDate.of(2026, 1, 21))
+ );
+
+ CsvTodoStorage storage = new CsvTodoStorage();
+ StringWriter out = new StringWriter();
+
+ storage.write(items, out);
+
+ assertThat(out.toString()).isEqualTo(
+ "id,task,due\n" +
+ "1,Buy milk,2026-01-20\n" +
+ "2,Bread,2026-01-21\n"
+ );
+ }
+ @Test
+ void savesTaskWithCommaAndQuotesUsingCsvEscaping() throws Exception {
+ List items = List.of(
+ new TodoItem(1, "Buy milk, \"organic\"", LocalDate.of(2026, 1, 20))
+ );
+
+ CsvTodoStorage storage = new CsvTodoStorage();
+ StringWriter out = new StringWriter();
+
+ storage.write(items, out);
+
+ assertThat(out.toString()).isEqualTo(
+ "id,task,due\n" +
+ "1,\"Buy milk, \"\"organic\"\"\",2026-01-20\n"
+ );
+ }
+}
diff --git a/src/test/java/org/example/CalculatorTest.java b/src/test/java/org/example/CalculatorTest.java
index 0d96bb5..4f948ed 100644
--- a/src/test/java/org/example/CalculatorTest.java
+++ b/src/test/java/org/example/CalculatorTest.java
@@ -34,4 +34,5 @@ public void subtractNumbers() {
}
+
}
\ No newline at end of file
diff --git a/src/test/java/org/example/PhoneNumberValidatorTest.java b/src/test/java/org/example/PhoneNumberValidatorTest.java
new file mode 100644
index 0000000..78c1c56
--- /dev/null
+++ b/src/test/java/org/example/PhoneNumberValidatorTest.java
@@ -0,0 +1,67 @@
+package org.example;
+
+import org.example.utils.PhoneNumberValidator;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+
+
+class PhoneNumberValidatorTest {
+
+ private PhoneNumberValidator underTest;
+
+ @BeforeEach
+ void setUp() {
+ underTest = new PhoneNumberValidator();
+ }
+
+ @ParameterizedTest
+ @CsvSource({"+447000000000, TRUE"})
+ void itShouldValidatePhoneNumber(String phoneNumber, String expected){
+
+
+ //Act
+ boolean isValid = underTest.test(phoneNumber);
+
+ //Assert
+ assertThat(isValid).isEqualTo(Boolean.valueOf(expected));
+
+ }
+ @Test
+ @DisplayName("Should fail when length bigger than 13")
+ void itShouldValidatePhoneNumberWhenIncorrectAndLengthIsBiggerThan13(){
+
+ //Arrange
+ String phoneNumber = "+447000000008888";
+
+ //Act
+ boolean isValid = underTest.test(phoneNumber);
+
+ //Assert
+ assertThat(isValid).isFalse();
+
+ }
+ @Test
+
+ @DisplayName("Should fail when does not start with +")
+ void itShouldValidatePhoneNumberWhenPhoneNumberDoesNotStartWithPlus(){
+
+ //Arrange
+ String phoneNumber = "447000000008888";
+
+ //Act
+ boolean isValid = underTest.test(phoneNumber);
+
+ //Assert
+ assertThat(isValid).isFalse();
+
+ }
+
+
+
+}
diff --git a/src/test/java/org/example/TodoListTest.java b/src/test/java/org/example/TodoListTest.java
new file mode 100644
index 0000000..4ead3c7
--- /dev/null
+++ b/src/test/java/org/example/TodoListTest.java
@@ -0,0 +1,99 @@
+package org.example;
+
+import org.example.todolist.TodoItem;
+import org.example.todolist.TodoList;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.time.LocalDate;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+public class TodoListTest {
+
+
+ @Test
+ void toDoListIsEmpty(){
+ TodoList todo = new TodoList();
+
+ assertThat(todo.size()).isZero();
+ }
+
+ @Test
+ void toDoListId() {
+ TodoList list = new TodoList();
+
+ TodoItem item = list.add("Milk", LocalDate.of(2026, 1, 20));
+
+ assertThat(item.toString()).isEqualTo("Id: 1");
+
+ }
+
+ @DisplayName("När jag lägger till items får de id1 och id2")
+ @Test
+ void toDoListTwoIds(){
+ TodoList list = new TodoList();
+
+ TodoItem item = list.add("Milk", LocalDate.of(2026, 1, 20));
+ TodoItem item2 = list.add("Bread", LocalDate.of(2026, 1, 20));
+
+ assertThat(item.toString()).isEqualTo("Id: 1");
+ assertThat(item2.toString()).isEqualTo("Id: 2");
+
+ }
+
+ @Test
+ void todoListRemembersItems() {
+ TodoList list = new TodoList();
+
+ list.add("Milk", LocalDate.of(2026, 1, 20));
+ list.add("Bread", LocalDate.of(2026, 1, 20));
+
+ assertThat(list.size()).isEqualTo(2);
+ }
+
+ @Test
+ void addStoresTaskAndDueInItem() {
+ TodoList list = new TodoList();
+
+ TodoItem item = list.add("Buy milk", LocalDate.of(2026, 1, 20));
+
+ assertThat(item.getTask()).isEqualTo("Buy milk");
+ assertThat(item.getDue()).isEqualTo(LocalDate.of(2026, 1, 20));
+ }
+ @Test
+ void differentTodosHaveDifferentTasksAndDueDates() {
+ TodoList list = new TodoList();
+
+ TodoItem a = list.add("Buy milk", LocalDate.of(2026, 1, 20));
+ TodoItem b = list.add("Walk dog", LocalDate.of(2026, 1, 21));
+
+ assertThat(a.getTask()).isEqualTo("Buy milk");
+ assertThat(b.getTask()).isEqualTo("Walk dog");
+ }
+ @Test
+ void listStoresAndReturnsItemsInInsertionOrder() {
+ TodoList list = new TodoList();
+
+ list.add("Buy milk", LocalDate.of(2026, 1, 20));
+ list.add("Walk dog", LocalDate.of(2026, 1, 21));
+
+ assertThat(list.size()).isEqualTo(2);
+ assertThat(list.get(0).getTask()).isEqualTo("Buy milk");
+ assertThat(list.get(1).getTask()).isEqualTo("Walk dog");
+ }
+ @Test
+ void canMarkTodoAsDoneById() {
+ TodoList list = new TodoList();
+
+ TodoItem item = list.add("Buy milk", LocalDate.of(2026, 1, 20));
+
+ assertThat(item.isDone()).isFalse();
+
+ boolean result = list.markDone(1);
+
+ assertThat(result).isTrue();
+ assertThat(item.isDone()).isTrue();
+ }
+
+ }
diff --git a/src/test/java/org/example/WeatherTest.java b/src/test/java/org/example/WeatherTest.java
new file mode 100644
index 0000000..73ea9aa
--- /dev/null
+++ b/src/test/java/org/example/WeatherTest.java
@@ -0,0 +1,57 @@
+package org.example;
+
+
+import org.example.weather.WeatherService;
+import org.example.weather.outFitAdvisor;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+@ExtendWith(MockitoExtension.class)
+public class WeatherTest {
+
+ @Mock
+ WeatherService weatherService;
+
+ @InjectMocks
+ outFitAdvisor advisor;
+
+// @BeforeEach
+// void setup() {
+//
+// WeatherService weatherService;
+// outFitAdvisor advisor;
+// }
+
+
+ @Test
+ void freezingTemps(){
+ Mockito.when(weatherService.getTemperature()).thenReturn((float) -5.0);
+ String advice = advisor.getClothingAdvice();
+ assertThat(advice).isEqualTo("VinterJacka");
+
+ }
+
+ @Test
+ void summerTemps(){
+ Mockito.when(weatherService.getTemperature()).thenReturn((float) 15.0);
+ String advice = advisor.getClothingAdvice();
+ assertThat(advice).isEqualTo("Sweatpants");
+ }
+ @Test
+ void defaultAdvice(){
+ Mockito.when(weatherService.getTemperature())
+ .thenThrow(new IllegalStateException());
+
+ assertThat(advisor.getClothingAdvice()).
+ isEqualTo("Jeans and Jacket");
+
+
+ }
+
+}
diff --git a/src/test/java/org/example/priceTest/AsyncNotificationService.java b/src/test/java/org/example/priceTest/AsyncNotificationService.java
new file mode 100644
index 0000000..43b32bc
--- /dev/null
+++ b/src/test/java/org/example/priceTest/AsyncNotificationService.java
@@ -0,0 +1,28 @@
+package org.example.priceTest;
+
+import org.example.price.NotificationService;
+
+public class AsyncNotificationService implements NotificationService {
+
+ private boolean isSent = false;
+
+
+ @Override
+ public void notify(String productName, int price) {
+ new Thread(() -> {
+ try {
+ Thread.sleep(5000);
+
+ isSent = true;
+ System.out.println("Sending notification for " + productName + " at " + price);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }).start();
+ }
+
+ @Override
+ public boolean isSent() {
+ return isSent;
+ }
+}
diff --git a/src/test/java/org/example/priceTest/PriceWatcherAsyncTest.java b/src/test/java/org/example/priceTest/PriceWatcherAsyncTest.java
new file mode 100644
index 0000000..043fb83
--- /dev/null
+++ b/src/test/java/org/example/priceTest/PriceWatcherAsyncTest.java
@@ -0,0 +1,46 @@
+package org.example.priceTest;
+
+import org.awaitility.Awaitility;
+import org.example.price.NotificationService;
+import org.example.price.PriceWatcher;
+import org.example.price.Priceservice;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.concurrent.TimeUnit;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+@ExtendWith(MockitoExtension.class)
+public class PriceWatcherAsyncTest {
+
+ @Mock
+ Priceservice priceService;
+
+ @Spy
+ NotificationService notificationService = new AsyncNotificationService();
+
+ @InjectMocks
+ PriceWatcher priceWatcher;
+
+
+ @Test
+ void sendNotlificationWhenPriceLowerThanThreshold(){
+ Mockito.when(priceService.getPrice(("T-SHIRT")))
+ .thenReturn(95);
+
+ priceWatcher.checkPrices();
+
+ Awaitility.await().atMost(5, TimeUnit.SECONDS)
+ .until(notificationService::isSent);
+
+ assertThat(notificationService.isSent()).isTrue();
+
+
+ }
+}
diff --git a/src/test/java/org/example/priceTest/PriceWatcherTest.java b/src/test/java/org/example/priceTest/PriceWatcherTest.java
new file mode 100644
index 0000000..ad680de
--- /dev/null
+++ b/src/test/java/org/example/priceTest/PriceWatcherTest.java
@@ -0,0 +1,39 @@
+package org.example.priceTest;
+
+
+import org.example.price.NotificationService;
+import org.example.price.PriceWatcher;
+import org.example.price.Priceservice;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+@ExtendWith(MockitoExtension.class)
+public class PriceWatcherTest {
+
+ @Mock
+ Priceservice priceService;
+
+ @Mock
+ NotificationService notificationService;
+
+ @InjectMocks
+ PriceWatcher priceWatcher;
+
+ @Test
+ void sendNotificationWhenPriceLowerThanThreshold(){
+ Mockito.when(priceService.getPrice(("T-SHIRT")))
+ .thenReturn(95);
+
+ priceWatcher.checkPrices();
+
+ Mockito.verify(notificationService,
+ Mockito.times(1))
+ .notify("T-SHIRT", 95);
+ notificationService.isSent();
+
+ }
+}