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(); + + } +}