diff --git a/.idea/libraries/gson_2_9_0.xml b/.idea/libraries/gson_2_9_0.xml new file mode 100644 index 0000000..e55b005 --- /dev/null +++ b/.idea/libraries/gson_2_9_0.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/java-kanban.iml b/java-kanban.iml index 66c15d2..48a7097 100644 --- a/java-kanban.iml +++ b/java-kanban.iml @@ -24,5 +24,6 @@ + \ No newline at end of file diff --git a/src/ru/yandex/javacourse/exceptions/NotFoundException.java b/src/ru/yandex/javacourse/exceptions/NotFoundException.java new file mode 100644 index 0000000..457253b --- /dev/null +++ b/src/ru/yandex/javacourse/exceptions/NotFoundException.java @@ -0,0 +1,7 @@ +package ru.yandex.javacourse.exceptions; + +public class NotFoundException extends RuntimeException { + public NotFoundException(String message) { + super(message); + } +} diff --git a/src/ru/yandex/javacourse/http/HttpStatusCode.java b/src/ru/yandex/javacourse/http/HttpStatusCode.java new file mode 100644 index 0000000..e57db7e --- /dev/null +++ b/src/ru/yandex/javacourse/http/HttpStatusCode.java @@ -0,0 +1,19 @@ +package ru.yandex.javacourse.http; + +public enum HttpStatusCode { + OK(200), + CREATED(201), + NOT_FOUND(404), + NOT_ACCEPTABLE(406), + INTERNAL_SERVER_ERROR(500); + + final int code; + + HttpStatusCode(int code) { + this.code = code; + } + + public int getCode() { + return code; + } +} diff --git a/src/ru/yandex/javacourse/http/HttpTaskServer.java b/src/ru/yandex/javacourse/http/HttpTaskServer.java new file mode 100644 index 0000000..1cc9800 --- /dev/null +++ b/src/ru/yandex/javacourse/http/HttpTaskServer.java @@ -0,0 +1,92 @@ +package ru.yandex.javacourse.http; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.sun.net.httpserver.HttpServer; +import ru.yandex.javacourse.http.adapter.DurationTypeAdapter; +import ru.yandex.javacourse.http.adapter.LocalDateTimeTypeAdapter; +import ru.yandex.javacourse.http.handler.*; +import ru.yandex.javacourse.model.Epic; +import ru.yandex.javacourse.model.Subtask; +import ru.yandex.javacourse.model.Task; +import ru.yandex.javacourse.service.Managers; +import ru.yandex.javacourse.service.TaskManager; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.time.Duration; +import java.time.LocalDateTime; + +public class HttpTaskServer { + private final int port; + private final TaskManager taskManager; + private HttpServer httpServer; + private static Gson gson = new GsonBuilder() + .setPrettyPrinting() + .serializeNulls() + .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeTypeAdapter()) + .registerTypeAdapter(Duration.class, new DurationTypeAdapter()) + .create(); + + public HttpTaskServer() { + taskManager = Managers.getDefault(); + port = 8080; + gson = new GsonBuilder() + .setPrettyPrinting() + .serializeNulls() + .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeTypeAdapter()) + .registerTypeAdapter(Duration.class, new DurationTypeAdapter()) + .create(); + } + + public HttpTaskServer(TaskManager taskManager) { + this.taskManager = taskManager; + port = 8080; + } + + public HttpTaskServer(TaskManager taskManager, int port) { + this.taskManager = taskManager; + this.port = port; + } + + public static Gson getGson() { + return gson; + } + + public static void main(String[] args) throws IOException { + HttpTaskServer httpTaskServer = new HttpTaskServer(); + httpTaskServer.start(); + httpTaskServer.taskManager.addTask(new Task("Звонок бабушке", + "Позвонить, чтобы узнать новости")); + httpTaskServer.taskManager.addTask(new Task("Стирка", + "Постирать белые вещи")); + + Epic epic1 = httpTaskServer.taskManager.addEpic(new Epic("Сделать домашнее задание", + "Задание для 6 спринта")); + httpTaskServer.taskManager.addSubtask(new Subtask("Изучить теорию", + "Прочитать теорию на сайте", epic1.getId())); + httpTaskServer.taskManager.addSubtask(new Subtask("Освоить тренажёр", + "Выполнить все задания", epic1.getId())); + httpTaskServer.taskManager.addSubtask(new Subtask("Прослушать вебинар", + "Подключиться на вебинар в среду", epic1.getId())); + + //httpTaskServer.stop(); + + } + + public void start() throws IOException { + httpServer = HttpServer.create(new InetSocketAddress(port), 0); + httpServer.createContext("/tasks", new TaskHandler(taskManager, gson)); + httpServer.createContext("/subtasks", new SubtaskHandler(taskManager, gson)); + httpServer.createContext("/epics", new EpicHandler(taskManager, gson)); + httpServer.createContext("/history", new HistoryHandler(taskManager, gson)); + httpServer.createContext("/prioritized", new PrioritizedHandler(taskManager, gson)); + httpServer.start(); + System.out.println("HTTP-сервер запущен на " + port + " порту!"); + } + + public void stop() { + httpServer.stop(1); + System.out.println("HTTP-сервер остановлен на " + port + " порту!"); + } +} \ No newline at end of file diff --git a/src/ru/yandex/javacourse/http/adapter/DurationTypeAdapter.java b/src/ru/yandex/javacourse/http/adapter/DurationTypeAdapter.java new file mode 100644 index 0000000..83089d0 --- /dev/null +++ b/src/ru/yandex/javacourse/http/adapter/DurationTypeAdapter.java @@ -0,0 +1,33 @@ +package ru.yandex.javacourse.http.adapter; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; + +import java.io.IOException; +import java.time.Duration; + +public class DurationTypeAdapter extends TypeAdapter { + @Override + public void write(JsonWriter jsonWriter, Duration duration) throws IOException { + if (duration == null) { + jsonWriter.nullValue(); + } else { + jsonWriter.value(String.valueOf(duration.toMinutes())); + } + } + + @Override + public Duration read(JsonReader jsonReader) throws IOException { + try { + String value = jsonReader.nextString(); + if (value == null || value.equals("null")) { + return null; + } + return Duration.ofMinutes(Long.parseLong(value)); + } catch (Exception e) { + jsonReader.nextNull(); + return null; + } + } +} diff --git a/src/ru/yandex/javacourse/http/adapter/LocalDateTimeTypeAdapter.java b/src/ru/yandex/javacourse/http/adapter/LocalDateTimeTypeAdapter.java new file mode 100644 index 0000000..64ff0b0 --- /dev/null +++ b/src/ru/yandex/javacourse/http/adapter/LocalDateTimeTypeAdapter.java @@ -0,0 +1,36 @@ +package ru.yandex.javacourse.http.adapter; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class LocalDateTimeTypeAdapter extends TypeAdapter { + private final DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss"); + + @Override + public void write(JsonWriter jsonWriter, LocalDateTime localDateTime) throws IOException { + if (localDateTime == null) { + jsonWriter.nullValue(); + } else { + jsonWriter.value(localDateTime.format(timeFormatter)); + } + } + + @Override + public LocalDateTime read(JsonReader jsonReader) throws IOException { + try { + String value = jsonReader.nextString(); + if (value == null || value.equals("null")) { + return null; + } + return LocalDateTime.parse(value, timeFormatter); + } catch (Exception exception) { + jsonReader.nextNull(); + return null; + } + } +} diff --git a/src/ru/yandex/javacourse/http/handler/BaseHttpHandler.java b/src/ru/yandex/javacourse/http/handler/BaseHttpHandler.java new file mode 100644 index 0000000..5fb14e5 --- /dev/null +++ b/src/ru/yandex/javacourse/http/handler/BaseHttpHandler.java @@ -0,0 +1,96 @@ +package ru.yandex.javacourse.http.handler; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import ru.yandex.javacourse.http.HttpStatusCode; +import ru.yandex.javacourse.service.TaskManager; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Optional; + +abstract class BaseHttpHandler implements HttpHandler { + private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; + protected TaskManager taskManager; + protected Gson gson; + + protected BaseHttpHandler(TaskManager taskManager, Gson gson) { + this.taskManager = taskManager; + this.gson = gson; + } + + /** + * Основной метод, который обрабатывает входящий запрос + */ + @Override + public abstract void handle(HttpExchange exchange) throws IOException; + + /** + * Отправляет ответ от сервера клиенту с указанным кодом. + * Используется для отправки 200 и 201 ответов + */ + protected void sendText(HttpExchange exchange, String response, int responseCode) { + try (OutputStream outputStream = exchange.getResponseBody()) { + exchange.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8"); + exchange.sendResponseHeaders(responseCode, 0); + outputStream.write(response.getBytes(DEFAULT_CHARSET)); + } catch (IOException exception) { + System.out.println("Возникла проблема при отправке ответа выполнения метода"); + } + } + + /** + * Отправляет ответ от сервера клиенту с кодом 404. + * Используется для отправки сообщения о том, что элемент не найден + */ + protected void sendNotFound(HttpExchange exchange, String response) { + try (OutputStream outputStream = exchange.getResponseBody()) { + exchange.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8"); + exchange.sendResponseHeaders(HttpStatusCode.NOT_FOUND.getCode(), 0); + outputStream.write(response.getBytes(DEFAULT_CHARSET)); + } catch (IOException exception) { + System.out.println("Возникла проблема при отправке ответа о том, что элемент не найден"); + } + } + + /** + * Отправляет ответ от сервера клиенту с кодом 406. + * Используется для отправки сообщения о том, что элемент пересекается с уже существующими + */ + protected void sendHasInteractions(HttpExchange exchange, String response) { + try (OutputStream outputStream = exchange.getResponseBody()) { + exchange.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8"); + exchange.sendResponseHeaders(HttpStatusCode.NOT_ACCEPTABLE.getCode(), 0); + outputStream.write(response.getBytes(DEFAULT_CHARSET)); + } catch (IOException exception) { + System.out.println("Возникла проблема при отправке ответа о том, что объект пересекается с существующим"); + } + } + + /** + * Возвращает Id задачи из запроса + */ + public Optional getIdFromRequestBody(String requestBody) { + JsonElement jsonElement = JsonParser.parseString(requestBody); + + if (!jsonElement.isJsonObject()) { + System.out.println("Невозможно получить номер задачи. Проверьте корректность запроса"); + return Optional.empty(); + } + + JsonObject jsonObject = jsonElement.getAsJsonObject(); + JsonElement idElement = jsonObject.get("id"); + + if (idElement == null || idElement.getAsInt() == 0) { + return Optional.empty(); + } + + return Optional.of(idElement.getAsInt()); + } +} \ No newline at end of file diff --git a/src/ru/yandex/javacourse/http/handler/EpicHandler.java b/src/ru/yandex/javacourse/http/handler/EpicHandler.java new file mode 100644 index 0000000..6e0c496 --- /dev/null +++ b/src/ru/yandex/javacourse/http/handler/EpicHandler.java @@ -0,0 +1,161 @@ +package ru.yandex.javacourse.http.handler; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.sun.net.httpserver.HttpExchange; +import ru.yandex.javacourse.exceptions.NotFoundException; +import ru.yandex.javacourse.http.HttpStatusCode; +import ru.yandex.javacourse.model.Epic; +import ru.yandex.javacourse.model.Subtask; +import ru.yandex.javacourse.service.TaskManager; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Optional; + +public class EpicHandler extends BaseHttpHandler { + public EpicHandler(TaskManager taskManager, Gson gson) { + super(taskManager, gson); + } + + /** + * Основной метод, который обрабатывает входящий запрос + */ + @Override + public void handle(HttpExchange exchange) throws IOException { + String[] pathSplitValues = exchange.getRequestURI().getPath().split("/"); + String requestMethod = exchange.getRequestMethod(); + String requestBody = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); + + if (pathSplitValues.length == 2) { + switch (requestMethod) { + case "GET": + getAllEpics(exchange); + break; + case "POST": + processingRequestedEpic(exchange, requestBody); + break; + default: + sendNotFound(exchange, "Некорректный метод"); + } + } else if (pathSplitValues.length == 3) { + String epicId = pathSplitValues[2]; + switch (requestMethod) { + case "GET": + getEpicById(exchange, epicId); + break; + case "DELETE": + deleteEpicById(exchange, epicId); + break; + default: + sendNotFound(exchange, "Некорректный метод"); + } + } else if (pathSplitValues.length == 4) { + String epicId = pathSplitValues[2]; + if (requestMethod.equals("GET")) { + getSubtasksByEpicId(exchange, epicId); + } else { + sendNotFound(exchange, "Некорректный метод"); + } + } else { + sendNotFound(exchange, "Некорректный метод"); + } + } + + /** + * Возвращает все эпики, которые хранятся в менеджере + */ + public void getAllEpics(HttpExchange exchange) { + List epics = taskManager.getAllEpics(); + String epicsJson = gson.toJson(epics); + sendText(exchange, epicsJson, HttpStatusCode.OK.getCode()); + } + + /** + * Добавляет или обновляет эпик в менеджере, который был прислан в запросе + */ + public void processingRequestedEpic(HttpExchange exchange, String requestBody) { + try { + Epic requestEpic = getEpicFromRequestBody(requestBody); + + Optional epicId = getIdFromRequestBody(requestBody); + + if (epicId.isPresent()) { + taskManager.updateEpic(requestEpic); + String response = "Эпик с id " + requestEpic.getId() + " успешно обновлён"; + sendText(exchange, response, HttpStatusCode.OK.getCode()); + } else { + Epic createdEpic = taskManager.addEpic(requestEpic); + String response = "Эпик с id " + createdEpic.getId() + " успешно добавлен"; + sendText(exchange, response, HttpStatusCode.CREATED.getCode()); + } + } catch (NotFoundException exception) { + sendNotFound(exchange, "Эпик для обработки не найден"); + } + } + + /** + * Возвращает эпик по id, который был прислан в запросе + */ + public void getEpicById(HttpExchange exchange, String epicIdStr) { + try { + int epicId = Integer.parseInt(epicIdStr); + Epic returnedEpic = taskManager.getEpicById(epicId); + String returnedEpicJson = gson.toJson(returnedEpic); + sendText(exchange, returnedEpicJson, HttpStatusCode.OK.getCode()); + } catch (NumberFormatException exception) { + sendText(exchange, "Ошибка в работе метода", HttpStatusCode.INTERNAL_SERVER_ERROR.getCode()); + } catch (NotFoundException exception) { + sendNotFound(exchange, "Эпик с id " + epicIdStr + " не найден"); + } + } + + /** + * Удаляет эпик по id, который был прислан в запросе + */ + public void deleteEpicById(HttpExchange exchange, String epicIdStr) { + try { + int epicId = Integer.parseInt(epicIdStr); + taskManager.deleteEpicById(epicId); + String response = "Эпик с id " + epicId + " успешно удалён"; + sendText(exchange, response, HttpStatusCode.OK.getCode()); + } catch (NumberFormatException exception) { + sendText(exchange, "Ошибка в работе метода", HttpStatusCode.INTERNAL_SERVER_ERROR.getCode()); + } catch (NotFoundException exception) { + sendNotFound(exchange, "Эпик с id " + epicIdStr + " не найден"); + } + } + + /** + * Возвращает все подзадачи эпика, id которого был прислан в запросе + */ + public void getSubtasksByEpicId(HttpExchange exchange, String epicIdStr) { + try { + int epicId = Integer.parseInt(epicIdStr); + List subtasksByEpicId = taskManager.getAllSubtasksByEpicId(epicId); + String subtasksByEpicIdJson = gson.toJson(subtasksByEpicId); + sendText(exchange, subtasksByEpicIdJson, HttpStatusCode.OK.getCode()); + } catch (NumberFormatException exception) { + sendText(exchange, "Ошибка в работе метода", HttpStatusCode.INTERNAL_SERVER_ERROR.getCode()); + } catch (NotFoundException exception) { + sendNotFound(exchange, "Эпик с id " + epicIdStr + " не найден"); + } + } + + /** + * Десериализует эпик из запроса + */ + public Epic getEpicFromRequestBody(String requestBody) { + JsonElement jsonElement = JsonParser.parseString(requestBody); + + if (!jsonElement.isJsonObject()) { + System.out.println("Невозможно получить эпик. Проверьте корректность запроса"); + return null; + } + JsonObject jsonObject = jsonElement.getAsJsonObject(); + return gson.fromJson(jsonObject, Epic.class); + } +} \ No newline at end of file diff --git a/src/ru/yandex/javacourse/http/handler/HistoryHandler.java b/src/ru/yandex/javacourse/http/handler/HistoryHandler.java new file mode 100644 index 0000000..ca5c9f3 --- /dev/null +++ b/src/ru/yandex/javacourse/http/handler/HistoryHandler.java @@ -0,0 +1,39 @@ +package ru.yandex.javacourse.http.handler; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import ru.yandex.javacourse.http.HttpStatusCode; +import ru.yandex.javacourse.model.Task; +import ru.yandex.javacourse.service.TaskManager; + +import java.util.List; + +public class HistoryHandler extends BaseHttpHandler { + public HistoryHandler(TaskManager taskManager, Gson gson) { + super(taskManager, gson); + } + + /** + * Основной метод, который обрабатывает входящий запрос + */ + @Override + public void handle(HttpExchange exchange) { + String[] pathSplitValues = exchange.getRequestURI().getPath().split("/"); + String requestMethod = exchange.getRequestMethod(); + + if (pathSplitValues.length == 2 && requestMethod.equals("GET")) { + getHistory(exchange); + } else { + sendNotFound(exchange, "Некорректный метод"); + } + } + + /** + * Возвращает историю вызовов задач, которые хранятся в менеджере + */ + public void getHistory(HttpExchange exchange) { + List history = taskManager.getHistory(); + String response = gson.toJson(history); + sendText(exchange, response, HttpStatusCode.OK.getCode()); + } +} diff --git a/src/ru/yandex/javacourse/http/handler/PrioritizedHandler.java b/src/ru/yandex/javacourse/http/handler/PrioritizedHandler.java new file mode 100644 index 0000000..f822908 --- /dev/null +++ b/src/ru/yandex/javacourse/http/handler/PrioritizedHandler.java @@ -0,0 +1,39 @@ +package ru.yandex.javacourse.http.handler; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import ru.yandex.javacourse.http.HttpStatusCode; +import ru.yandex.javacourse.model.Task; +import ru.yandex.javacourse.service.TaskManager; + +import java.util.TreeSet; + +public class PrioritizedHandler extends BaseHttpHandler { + public PrioritizedHandler(TaskManager taskManager, Gson gson) { + super(taskManager, gson); + } + + /** + * Основной метод, который обрабатывает входящий запрос + */ + @Override + public void handle(HttpExchange exchange) { + String[] pathSplitValues = exchange.getRequestURI().getPath().split("/"); + String requestMethod = exchange.getRequestMethod(); + + if (pathSplitValues.length == 2 && requestMethod.equals("GET")) { + getPrioritizedTasks(exchange); + } else { + sendNotFound(exchange, "Некорректный метод"); + } + } + + /** + * Возвращает приоритизированные задач, которые хранятся в менеджере + */ + public void getPrioritizedTasks(HttpExchange exchange) { + TreeSet prioritizedTasks = taskManager.getPrioritizedTasks(); + String response = gson.toJson(prioritizedTasks); + sendText(exchange, response, HttpStatusCode.OK.getCode()); + } +} diff --git a/src/ru/yandex/javacourse/http/handler/SubtaskHandler.java b/src/ru/yandex/javacourse/http/handler/SubtaskHandler.java new file mode 100644 index 0000000..91699e0 --- /dev/null +++ b/src/ru/yandex/javacourse/http/handler/SubtaskHandler.java @@ -0,0 +1,141 @@ +package ru.yandex.javacourse.http.handler; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.sun.net.httpserver.HttpExchange; +import ru.yandex.javacourse.exceptions.NotFoundException; +import ru.yandex.javacourse.http.HttpStatusCode; +import ru.yandex.javacourse.model.Subtask; +import ru.yandex.javacourse.service.TaskManager; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Optional; + +public class SubtaskHandler extends BaseHttpHandler { + public SubtaskHandler(TaskManager taskManager, Gson gson) { + super(taskManager, gson); + } + + /** + * Основной метод, который обрабатывает входящий запрос + */ + @Override + public void handle(HttpExchange exchange) throws IOException { + String[] pathSplitValues = exchange.getRequestURI().getPath().split("/"); + String requestMethod = exchange.getRequestMethod(); + String requestBody = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); + + if (pathSplitValues.length == 2) { + switch (requestMethod) { + case "GET": + getAllSubtasks(exchange); + break; + case "POST": + processingRequestedSubtask(exchange, requestBody); + break; + default: + sendNotFound(exchange, "Некорректный метод"); + } + } else if (pathSplitValues.length == 3) { + String subtaskId = pathSplitValues[2]; + switch (requestMethod) { + case "GET": + getSubtaskById(exchange, subtaskId); + break; + case "DELETE": + deleteSubtaskById(exchange, subtaskId); + break; + default: + sendNotFound(exchange, "Некорректный метод"); + } + } else { + sendNotFound(exchange, "Некорректный метод"); + } + } + + /** + * Возвращает все подзадачи, которые хранятся в менеджере + */ + public void getAllSubtasks(HttpExchange exchange) { + List subtasks = taskManager.getAllSubtasks(); + String subtasksJson = gson.toJson(subtasks); + sendText(exchange, subtasksJson, HttpStatusCode.OK.getCode()); + } + + /** + * Добавляет или обновляет подзадачу в менеджере, которая была прислана в запросе + */ + public void processingRequestedSubtask(HttpExchange exchange, String requestBody) { + try { + Subtask requestSubtask = getSubtaskFromRequestBody(requestBody); + Optional subtaskId = getIdFromRequestBody(requestBody); + + if (subtaskId.isPresent()) { + taskManager.updateSubtask(requestSubtask); + String response = "Подзадача с id " + requestSubtask.getId() + " успешно обновлена"; + sendText(exchange, response, HttpStatusCode.OK.getCode()); + } else { + try { + Subtask createdSubtask = taskManager.addSubtask(requestSubtask); + String response = "Подзадача с id " + createdSubtask.getId() + " успешно добавлена"; + sendText(exchange, response, HttpStatusCode.CREATED.getCode()); + } catch (NotFoundException exception) { + sendHasInteractions(exchange, + "Добавление подзадачи невозможно. Она пересекается с уже существующими задачами"); + } + } + } catch (NotFoundException exception) { + sendNotFound(exchange, "Подзадача для обработки не найдена"); + } + } + + /** + * Возвращает подзадачу по id, который был прислан в запросе + */ + public void getSubtaskById(HttpExchange exchange, String subtaskIdStr) { + try { + int subtaskId = Integer.parseInt(subtaskIdStr); + Subtask returnedSubtask = taskManager.getSubtaskById(subtaskId); + String returnedSubtaskJson = gson.toJson(returnedSubtask); + sendText(exchange, returnedSubtaskJson, HttpStatusCode.OK.getCode()); + } catch (NumberFormatException e) { + sendText(exchange, "Ошибка в работе метода", HttpStatusCode.INTERNAL_SERVER_ERROR.getCode()); + } catch (NotFoundException exception) { + sendNotFound(exchange, "Подзадача с id " + subtaskIdStr + " не найдена"); + } + } + + /** + * Удаляет подзадачу по id, который был прислан в запросе + */ + public void deleteSubtaskById(HttpExchange exchange, String subtaskIdStr) { + try { + int subtaskId = Integer.parseInt(subtaskIdStr); + taskManager.deleteSubtaskById(subtaskId); + String response = "Подзадача с id " + subtaskId + " успешно удалена"; + sendText(exchange, response, HttpStatusCode.OK.getCode()); + } catch (NumberFormatException exception) { + sendText(exchange, "Ошибка в работе метода", HttpStatusCode.INTERNAL_SERVER_ERROR.getCode()); + } catch (NotFoundException exception) { + sendNotFound(exchange, "Подзадача с id " + subtaskIdStr + " не найдена"); + } + } + + /** + * Десериализует подзадачу из запроса + */ + public Subtask getSubtaskFromRequestBody(String requestBody) { + JsonElement jsonElement = JsonParser.parseString(requestBody); + + if (!jsonElement.isJsonObject()) { + System.out.println("Невозможно получить подзадачу. Проверьте корректность запроса"); + return null; + } + JsonObject jsonObject = jsonElement.getAsJsonObject(); + return gson.fromJson(jsonObject, Subtask.class); + } +} \ No newline at end of file diff --git a/src/ru/yandex/javacourse/http/handler/TaskHandler.java b/src/ru/yandex/javacourse/http/handler/TaskHandler.java new file mode 100644 index 0000000..d6afabe --- /dev/null +++ b/src/ru/yandex/javacourse/http/handler/TaskHandler.java @@ -0,0 +1,141 @@ +package ru.yandex.javacourse.http.handler; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.sun.net.httpserver.HttpExchange; +import ru.yandex.javacourse.exceptions.NotFoundException; +import ru.yandex.javacourse.http.HttpStatusCode; +import ru.yandex.javacourse.model.Task; +import ru.yandex.javacourse.service.TaskManager; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Optional; + +public class TaskHandler extends BaseHttpHandler { + public TaskHandler(TaskManager taskManager, Gson gson) { + super(taskManager, gson); + } + + /** + * Основной метод, который обрабатывает входящий запрос + */ + @Override + public void handle(HttpExchange exchange) throws IOException { + String[] pathSplitValues = exchange.getRequestURI().getPath().split("/"); + String requestMethod = exchange.getRequestMethod(); + String requestBody = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); + + if (pathSplitValues.length == 2) { + switch (requestMethod) { + case "GET": + getAllTasks(exchange); + break; + case "POST": + processingRequestedTask(exchange, requestBody); + break; + default: + sendNotFound(exchange, "Некорректный метод"); + } + } else if (pathSplitValues.length == 3) { + String taskId = pathSplitValues[2]; + switch (requestMethod) { + case "GET": + getTaskById(exchange, taskId); + break; + case "DELETE": + deleteTaskById(exchange, taskId); + break; + default: + sendNotFound(exchange, "Некорректный метод"); + } + } else { + sendNotFound(exchange, "Некорректный метод"); + } + } + + /** + * Возвращает все задачи, которые хранятся в менеджере + */ + public void getAllTasks(HttpExchange exchange) { + List tasks = taskManager.getAllTasks(); + String tasksJson = gson.toJson(tasks); + sendText(exchange, tasksJson, HttpStatusCode.OK.getCode()); + } + + /** + * Добавляет или обновляет задачу в менеджере, которая была прислана в запросе + */ + public void processingRequestedTask(HttpExchange exchange, String requestBody) { + try { + Task requestTask = getTaskFromRequestBody(requestBody); + Optional taskId = getIdFromRequestBody(requestBody); + + if (taskId.isPresent()) { + taskManager.updateTask(requestTask); + String response = "Задача с id " + requestTask.getId() + " успешно обновлена"; + sendText(exchange, response, HttpStatusCode.OK.getCode()); + } else { + try { + Task createdTask = taskManager.addTask(requestTask); + String response = "Задача с id " + createdTask.getId() + " успешно добавлена"; + sendText(exchange, response, HttpStatusCode.CREATED.getCode()); + } catch (NotFoundException exception) { + sendHasInteractions(exchange, + "Добавление задачи невозможно. Она пересекается с уже существующими задачами"); + } + } + } catch (NotFoundException exception) { + sendNotFound(exchange, "Задача для обработки не найдена"); + } + } + + /** + * Возвращает задачу по id, который был прислан в запросе + */ + public void getTaskById(HttpExchange exchange, String taskIdStr) { + try { + int taskId = Integer.parseInt(taskIdStr); + Task returnedTask = taskManager.getTaskById(taskId); + String returnedTaskJson = gson.toJson(returnedTask); + sendText(exchange, returnedTaskJson, HttpStatusCode.OK.getCode()); + } catch (NumberFormatException exception) { + sendText(exchange, "Ошибка в работе метода", HttpStatusCode.INTERNAL_SERVER_ERROR.getCode()); + } catch (NotFoundException exception) { + sendNotFound(exchange, "Задача с id " + taskIdStr + " не найдена"); + } + } + + /** + * Удаляет задачу по id, который был прислан в запросе + */ + public void deleteTaskById(HttpExchange exchange, String taskIdStr) { + try { + int taskId = Integer.parseInt(taskIdStr); + taskManager.deleteTaskById(taskId); + String response = "Задача с id " + taskId + " успешно удалена"; + sendText(exchange, response, HttpStatusCode.OK.getCode()); + } catch (NumberFormatException exception) { + sendText(exchange, "Ошибка в работе метода", HttpStatusCode.INTERNAL_SERVER_ERROR.getCode()); + } catch (NotFoundException exception) { + sendNotFound(exchange, "Задача с id " + taskIdStr + " не найдена"); + } + } + + /** + * Десериализует задачу из запроса + */ + public Task getTaskFromRequestBody(String requestBody) { + JsonElement jsonElement = JsonParser.parseString(requestBody); + + if (!jsonElement.isJsonObject()) { + System.out.println("Невозможно получить задачу. Проверьте корректность запроса"); + return null; + } + JsonObject jsonObject = jsonElement.getAsJsonObject(); + return gson.fromJson(jsonObject, Task.class); + } +} \ No newline at end of file diff --git a/src/ru/yandex/javacourse/model/Epic.java b/src/ru/yandex/javacourse/model/Epic.java index e2c3057..503135d 100644 --- a/src/ru/yandex/javacourse/model/Epic.java +++ b/src/ru/yandex/javacourse/model/Epic.java @@ -48,7 +48,9 @@ public Epic getCopy() { Epic epicCopy = new Epic(this.getName(), this.getDescription()); epicCopy.setId(this.getId()); epicCopy.setStatus(this.getStatus()); - epicCopy.setSubtasksIdList(new ArrayList<>(this.getSubtasksIdList())); + if (this.getSubtasksIdList() != null) { + epicCopy.setSubtasksIdList(new ArrayList<>(this.getSubtasksIdList())); + } epicCopy.setDuration(this.getDuration()); epicCopy.setStartTime(this.getStartTime()); return epicCopy; diff --git a/src/ru/yandex/javacourse/model/Task.java b/src/ru/yandex/javacourse/model/Task.java index eda486d..c83eeb3 100644 --- a/src/ru/yandex/javacourse/model/Task.java +++ b/src/ru/yandex/javacourse/model/Task.java @@ -27,6 +27,7 @@ public Task(String name, String description, TaskStatus status) { public Task(String name, String description, Duration duration, LocalDateTime startTime) { this.name = name; this.description = description; + this.status = TaskStatus.NEW; this.duration = duration; this.startTime = startTime; } diff --git a/src/ru/yandex/javacourse/service/InMemoryTaskManager.java b/src/ru/yandex/javacourse/service/InMemoryTaskManager.java index 0078f69..23d10c4 100644 --- a/src/ru/yandex/javacourse/service/InMemoryTaskManager.java +++ b/src/ru/yandex/javacourse/service/InMemoryTaskManager.java @@ -1,5 +1,6 @@ package ru.yandex.javacourse.service; +import ru.yandex.javacourse.exceptions.NotFoundException; import ru.yandex.javacourse.model.*; import java.time.Duration; import java.time.LocalDateTime; @@ -47,7 +48,7 @@ public void deleteAllTasks() { public Task getTaskById(int id) { Task returnedTask = tasks.get(id); if (returnedTask == null) { - return null; + throw new NotFoundException("Задача не найдена"); } historyManager.add(returnedTask); return returnedTask.getCopy(); @@ -63,12 +64,12 @@ public Task getTaskById(int id) { @Override public Task addTask(Task task) { if (task == null) { - return null; + throw new NotFoundException("Задача не найдена"); } boolean hasCross = hasCrossInTimeWithManagerTasks(task); if (hasCross) { - return null; + throw new NotFoundException("Задача не добавлена"); } Task createdTask = task.getCopy(); @@ -86,18 +87,20 @@ public Task addTask(Task task) { @Override public void updateTask(Task task) { if (task == null) { - return; + throw new NotFoundException("Задача не найдена"); } boolean hasCross = hasCrossInTimeWithManagerTasks(task); if (hasCross) { - return; + throw new NotFoundException("Задача не добавлена"); } boolean isTaskExists = tasks.containsKey(task.getId()); if (isTaskExists) { Task updatedTask = task.getCopy(); tasks.put(updatedTask.getId(), updatedTask); + } else { + throw new NotFoundException("Задача не найден"); } } @@ -106,6 +109,10 @@ public void updateTask(Task task) { */ @Override public void deleteTaskById(int id) { + Task task = tasks.get(id); + if (task == null) { + throw new NotFoundException("Задача не найдена"); + } historyManager.remove(id); tasks.remove(id); } @@ -137,7 +144,7 @@ public void deleteAllEpics() { public Epic getEpicById(int id) { Epic returnedEpic = epics.get(id); if (returnedEpic == null) { - return null; + throw new NotFoundException("Эпик не найден"); } historyManager.add(returnedEpic); return returnedEpic.getCopy(); @@ -153,12 +160,14 @@ public Epic getEpicById(int id) { @Override public Epic addEpic(Epic epic) { if (epic == null) { - return null; + throw new NotFoundException("Эпик не найден"); } Epic createdEpic = epic.getCopy(); createdEpic.setId(generateId()); createdEpic.deleteSubtasksIdList(); epics.put(createdEpic.getId(), createdEpic); + updateEpicStatus(createdEpic); + updateEpicDates(createdEpic); return createdEpic.getCopy(); } @@ -171,7 +180,7 @@ public Epic addEpic(Epic epic) { @Override public void updateEpic(Epic epic) { if (epic == null) { - return; + throw new NotFoundException("Эпик не найден"); } boolean isEpicExists = epics.containsKey(epic.getId()); if (isEpicExists) { @@ -182,6 +191,8 @@ public void updateEpic(Epic epic) { updateEpicStatus(updatedEpic); updateEpicDates(updatedEpic); epics.put(updatedEpic.getId(), updatedEpic); + } else { + throw new NotFoundException("Эпик не найден"); } } @@ -191,6 +202,11 @@ public void updateEpic(Epic epic) { */ @Override public void deleteEpicById(int id) { + Epic epic = epics.get(id); + if (epic == null) { + throw new NotFoundException("Эпик не найден"); + } + historyManager.remove(id); epics.remove(id); ArrayList subtasksToRemove = subtasks.values().stream() @@ -237,7 +253,7 @@ public void deleteAllSubtasks() { public Subtask getSubtaskById(int id) { Subtask returnedSubtask = subtasks.get(id); if (returnedSubtask == null) { - return null; + throw new NotFoundException("Подзадача не найдена"); } historyManager.add(returnedSubtask); return returnedSubtask.getCopy(); @@ -255,17 +271,21 @@ public Subtask getSubtaskById(int id) { @Override public Subtask addSubtask(Subtask subtask) { if (subtask == null) { - return null; + throw new NotFoundException("Подзадача не найдена"); } boolean hasCross = hasCrossInTimeWithManagerTasks(subtask); if (hasCross) { - return null; + throw new NotFoundException("Подзадача не добавлена"); } Epic epic = epics.get(subtask.getEpicId()); - if (epic == null || subtask.getEpicId() == subtask.getId()) { - return null; + if (epic == null) { + throw new NotFoundException("Эпик для подзадачи не найден"); + } + + if (subtask.getEpicId() == subtask.getId()) { + throw new NotFoundException("Подзадача не добавлена"); } Subtask createdSubtask = subtask.getCopy(); createdSubtask.setId(generateId()); @@ -286,13 +306,17 @@ public Subtask addSubtask(Subtask subtask) { */ @Override public void updateSubtask(Subtask subtask) { - if (subtask == null || subtask.getEpicId() == subtask.getId()) { - return; + if (subtask == null) { + throw new NotFoundException("Подзадача для обновления не найдена"); + } + + if (subtask.getEpicId() == subtask.getId()) { + throw new NotFoundException("Подзадача не обновлена"); } boolean hasCross = hasCrossInTimeWithManagerTasks(subtask); if (hasCross) { - return; + throw new NotFoundException("Подзадача не обновлена"); } boolean isSubtaskExists = subtasks.containsKey(subtask.getId()); @@ -302,6 +326,8 @@ public void updateSubtask(Subtask subtask) { Epic epic = epics.get(updatedSubtask.getEpicId()); updateEpicStatus(epic); updateEpicDates(epic); + } else { + throw new NotFoundException("Подзадача не обновлена"); } } @@ -314,7 +340,7 @@ public void updateSubtask(Subtask subtask) { public void deleteSubtaskById(int id) { Subtask subtask = subtasks.get(id); if (subtask == null) { - return; + throw new NotFoundException("Подзадача не найдена"); } Epic epic = epics.get(subtask.getEpicId()); epic.deleteSubtaskId(id); @@ -348,7 +374,7 @@ public ArrayList getAllSubtasksByEpicId(int epicId) { @Override public void updateEpicStatus(Epic epic) { if (epic == null) { - return; + throw new NotFoundException("Эпик не найден"); } ArrayList epicSubtasksId = epic.getSubtasksIdList(); int subtasksCount = epicSubtasksId.size(); @@ -389,7 +415,7 @@ public List getHistory() { @Override public void updateEpicDates(Epic epic) { if (epic == null) { - return; + throw new NotFoundException("Эпик не найден"); } Optional epicStartTime = epic.getSubtasksIdList().stream() diff --git a/test/ru/yandex/javacourse/http/HttpTaskServerEpicsTest.java b/test/ru/yandex/javacourse/http/HttpTaskServerEpicsTest.java new file mode 100644 index 0000000..36cf1fc --- /dev/null +++ b/test/ru/yandex/javacourse/http/HttpTaskServerEpicsTest.java @@ -0,0 +1,282 @@ +package ru.yandex.javacourse.http; + +import com.google.gson.Gson; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import ru.yandex.javacourse.model.Epic; +import ru.yandex.javacourse.service.InMemoryTaskManager; +import ru.yandex.javacourse.service.TaskManager; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class HttpTaskServerEpicsTest { + private static final String EPIC_NAME = "Эпик"; + private static final String EPIC_DESCRIPTION = "Новый эпик"; + private static final String EPIC_NAME_UPDATED = "Обновлённый эпик"; + private static final String EPIC_DESCRIPTION_UPDATED = "Новый эпик"; + TaskManager manager = new InMemoryTaskManager(); + HttpTaskServer taskServer = new HttpTaskServer(manager); + HttpClient client = HttpClient.newHttpClient(); + Gson gson = HttpTaskServer.getGson(); + + @BeforeEach + public void setUp() { + manager.deleteAllTasks(); + manager.deleteAllSubtasks(); + manager.deleteAllEpics(); + try { + taskServer.start(); + } catch (IOException exception) { + System.out.println("Возникла ошибка во время старта тестов"); + } + } + + @AfterEach + public void shutDown() { + taskServer.stop(); + } + + @Test + @DisplayName("Должен сохранять эпик в менеджер при отправке запроса в HttpServer") + public void test_AddEpic_WhenSendEpicWithId_ManagerShouldStore() throws IOException, InterruptedException { + //given + URI url = URI.create("http://localhost:8080/epics"); + Epic epic = new Epic(EPIC_NAME, EPIC_DESCRIPTION); + + String epicJson = gson.toJson(epic); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .POST(HttpRequest.BodyPublishers.ofString(epicJson)) + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + List epicsFromManager = manager.getAllEpics(); + + // then + assertEquals(HttpStatusCode.CREATED.getCode(), response.statusCode()); + assertNotNull(epicsFromManager, "Эпики не возвращаются"); + assertEquals(1, epicsFromManager.size(), "Некорректное количество эпиков"); + assertEquals(EPIC_NAME, epicsFromManager.get(0).getName(), "Некорректное имя эпиков"); + } + + @Test + @DisplayName("Должен обновлять эпик в менеджере при отправке запроса в HttpServer") + public void test_UpdateEpic_WhenSendEpicWithId_ManagerShouldStoreUpdate() throws IOException, InterruptedException { + //given + URI url = URI.create("http://localhost:8080/epics"); + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + Epic updatedEpic = new Epic(EPIC_NAME_UPDATED, EPIC_DESCRIPTION_UPDATED); + updatedEpic.setId(epic.getId()); + String epicJson = gson.toJson(updatedEpic); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .POST(HttpRequest.BodyPublishers.ofString(epicJson)) + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + List epicsFromManager = manager.getAllEpics(); + + // then + assertEquals(HttpStatusCode.OK.getCode(), response.statusCode()); + assertNotNull(epicsFromManager, "Эпики не возвращаются"); + assertEquals(1, epicsFromManager.size(), "Некорректное количество эпиков"); + assertEquals(EPIC_NAME_UPDATED, epicsFromManager.get(0).getName(), "Некорректное имя эпика"); + } + + @Test + @DisplayName("Должен возвращать эпик по id из менеджера при отправке запроса в HttpServer") + public void test_GetEpicById_WhenSendRequest_ShouldReturnById() throws IOException, InterruptedException { + //given + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + URI url = URI.create("http://localhost:8080/epics/" + epic.getId()); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .GET() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + List epicsFromManager = manager.getAllEpics(); + + // then + assertEquals(HttpStatusCode.OK.getCode(), response.statusCode()); + assertNotNull(epicsFromManager, "Эпики не возвращаются"); + assertEquals(1, epicsFromManager.size(), "Некорректное количество эпиков"); + assertEquals(EPIC_NAME, epicsFromManager.get(0).getName(), "Некорректное имя эпика"); + } + + @Test + @DisplayName("Должен удалять эпик по id в менеджере при отправке запроса в HttpServer") + public void test_DeleteEpicById_WhenSendCorrectId_ShouldReturnNull() throws IOException, InterruptedException { + //given + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + URI url = URI.create("http://localhost:8080/epics" + "/" + epic.getId()); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .DELETE() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + List epicsFromManager = manager.getAllEpics(); + + // then + assertEquals(HttpStatusCode.OK.getCode(), response.statusCode()); + assertNotNull(epicsFromManager, "Эпики не возвращаются"); + assertEquals(0, epicsFromManager.size(), "Некорректное количество эпиков"); + } + + @Test + @DisplayName("Должен возвращать все эпики из менеджера при отправке запроса в HttpServer") + public void test_GetAllEpics_WhenSendRequest_ShouldReturnAll() throws IOException, InterruptedException { + //given + manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + manager.addEpic(new Epic(EPIC_NAME_UPDATED, EPIC_DESCRIPTION_UPDATED)); + URI url = URI.create("http://localhost:8080/epics"); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .GET() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + List epicsFromManager = manager.getAllEpics(); + + // then + assertEquals(HttpStatusCode.OK.getCode(), response.statusCode()); + assertNotNull(epicsFromManager, "Эпики не возвращаются"); + assertEquals(2, epicsFromManager.size(), "Некорректное количество эпиков"); + assertEquals(EPIC_NAME, epicsFromManager.get(0).getName(), "Некорректное имя эпика"); + assertEquals(EPIC_NAME_UPDATED, epicsFromManager.get(1).getName(), "Некорректное имя эпика"); + } + + @Test + @DisplayName("Не должен сохранять эпик в менеджер при отправке запроса по некорректному адресу") + public void test_AddEpic_WhenIncorrectURL_ShouldReturn404() throws IOException, InterruptedException { + //given + URI incorrectUrl = URI.create("http://localhost:8080/addEpic"); + Epic epic = new Epic(EPIC_NAME, EPIC_DESCRIPTION); + String epicJson = gson.toJson(epic); + HttpRequest request = HttpRequest.newBuilder() + .uri(incorrectUrl) + .POST(HttpRequest.BodyPublishers.ofString(epicJson)) + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertEquals(HttpStatusCode.NOT_FOUND.getCode(), response.statusCode(), + "Не должен добавлять эпик при некорректном URL"); + } + + @Test + @DisplayName("Не должен обновлять эпик в менеджере при отправке запроса с несуществующим id") + public void test_UpdateEpic_WhenIdNotExist_ShouldReturn404() throws IOException, InterruptedException { + //given + URI url = URI.create("http://localhost:8080/epics"); + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + Epic updatedEpic = new Epic(EPIC_NAME_UPDATED, EPIC_DESCRIPTION_UPDATED); + updatedEpic.setId(epic.getId() + 1); + String epicJson = gson.toJson(updatedEpic); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .POST(HttpRequest.BodyPublishers.ofString(epicJson)) + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertEquals(HttpStatusCode.NOT_FOUND.getCode(), response.statusCode(), + "Не должен обновлять эпик по несуществующему id"); + } + + @Test + @DisplayName("Не должен возвращать эпик из менеджера при отправке запроса с несуществующим id ") + public void test_GetEpicById_WhenIdNotExist_ShouldReturn404() throws IOException, InterruptedException { + //given + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + URI url = URI.create("http://localhost:8080/epics/" + (epic.getId() + 1)); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .GET() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertEquals(HttpStatusCode.NOT_FOUND.getCode(), response.statusCode(), + "Не должен возвращать эпик по несуществующему id"); + } + + @Test + @DisplayName("Не должен возвращать эпик из менеджера при отправке запроса с некорректным id ") + public void test_GetEpicById_WhenIdNotAcceptable_ShouldReturn500() throws IOException, InterruptedException { + //given + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + URI url = URI.create("http://localhost:8080/epics/" + epic.getId() + "test"); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .GET() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertEquals(HttpStatusCode.INTERNAL_SERVER_ERROR.getCode(), response.statusCode(), + "Не должен возвращать эпик по некорректному id"); + } + + @Test + @DisplayName("Не должен удалять эпик в менеджере при отправке запроса с несуществующим id ") + public void test_DeleteEpicById_WhenIdNotExist_ShouldReturn404() throws IOException, InterruptedException { + //given + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + URI url = URI.create("http://localhost:8080/epics/" + (epic.getId() + 1)); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .DELETE() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertEquals(HttpStatusCode.NOT_FOUND.getCode(), response.statusCode(), + "Не должен удалять эпик по несуществующему id"); + } + + @Test + @DisplayName("Не должен удалять эпик в менеджере при отправке запроса с некорректным id ") + public void test_DeleteEpicById_WhenIdNotAcceptable_ShouldReturn500() throws IOException, InterruptedException { + //given + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + URI url = URI.create("http://localhost:8080/epics/" + epic.getId() + "test"); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .DELETE() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertEquals(HttpStatusCode.INTERNAL_SERVER_ERROR.getCode(), response.statusCode(), + "Не должен удалять эпик по некорректному id"); + } +} \ No newline at end of file diff --git a/test/ru/yandex/javacourse/http/HttpTaskServerHistoryTest.java b/test/ru/yandex/javacourse/http/HttpTaskServerHistoryTest.java new file mode 100644 index 0000000..96009b6 --- /dev/null +++ b/test/ru/yandex/javacourse/http/HttpTaskServerHistoryTest.java @@ -0,0 +1,101 @@ +package ru.yandex.javacourse.http; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import ru.yandex.javacourse.model.Epic; +import ru.yandex.javacourse.model.Subtask; +import ru.yandex.javacourse.model.Task; +import ru.yandex.javacourse.service.InMemoryTaskManager; +import ru.yandex.javacourse.service.TaskManager; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class HttpTaskServerHistoryTest { + private static final String EPIC_NAME = "Эпик"; + private static final String EPIC_DESCRIPTION = "Новый эпик"; + private static final String SUBTASK_NAME_1 = "Подзадача 1"; + private static final String SUBTASK_DESCRIPTION_1 = "Первая подзадача"; + private static final String SUBTASK_NAME_2 = "Подзадача 2"; + private static final String SUBTASK_DESCRIPTION_2 = "Вторая подзадача"; + + TaskManager manager = new InMemoryTaskManager(); + HttpTaskServer taskServer = new HttpTaskServer(manager); + HttpClient client = HttpClient.newHttpClient(); + + @BeforeEach + public void setUp() { + manager.deleteAllTasks(); + manager.deleteAllSubtasks(); + manager.deleteAllEpics(); + + try { + taskServer.start(); + } catch (IOException exception) { + System.out.println("Возникла ошибка во время старта тестов"); + } + } + + @AfterEach + public void shutDown() { + taskServer.stop(); + } + + @Test + @DisplayName("Должен возвращать историю вызовов задач при отправке запроса в HttpServer при корректном URL") + public void test_getHistory_WhenCorrectURL_ShouldReturnHistory() throws IOException, InterruptedException { + //given + URI url = URI.create("http://localhost:8080/history"); + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + Subtask subtask1 = manager.addSubtask(new Subtask(SUBTASK_NAME_1, SUBTASK_DESCRIPTION_1, epic.getId())); + Subtask subtask2 = manager.addSubtask(new Subtask(SUBTASK_NAME_2, SUBTASK_DESCRIPTION_2, epic.getId())); + manager.getSubtaskById(subtask1.getId()); + manager.getSubtaskById(subtask2.getId()); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .GET() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + List historyFromManager = manager.getHistory(); + + // then + assertEquals(HttpStatusCode.OK.getCode(), response.statusCode()); + assertNotNull(historyFromManager, "История не возвращаются"); + assertEquals(2, historyFromManager.size(), "Некорректное количество задач в истории"); + assertEquals(SUBTASK_NAME_1, historyFromManager.get(0).getName(), "Некорректное имя задачи в истории"); + assertEquals(SUBTASK_NAME_2, historyFromManager.get(1).getName(), "Некорректное имя задачи в истории"); + } + + @Test + @DisplayName("Не должен возвращать историю вызовов задач при отправке запроса в HttpServer при некорректном URL") + public void test_getHistory_WhenNotCorrectURL_ShouldReturn404() throws IOException, InterruptedException { + //given + URI url = URI.create("http://localhost:8080/getHistory"); + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + Subtask subtask1 = manager.addSubtask(new Subtask(SUBTASK_NAME_1, SUBTASK_DESCRIPTION_1, epic.getId())); + Subtask subtask2 = manager.addSubtask(new Subtask(SUBTASK_NAME_2, SUBTASK_DESCRIPTION_2, epic.getId())); + manager.getSubtaskById(subtask1.getId()); + manager.getSubtaskById(subtask2.getId()); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .GET() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertEquals(HttpStatusCode.NOT_FOUND.getCode(), response.statusCode()); + } +} diff --git a/test/ru/yandex/javacourse/http/HttpTaskServerPrioritizedTest.java b/test/ru/yandex/javacourse/http/HttpTaskServerPrioritizedTest.java new file mode 100644 index 0000000..bd4e693 --- /dev/null +++ b/test/ru/yandex/javacourse/http/HttpTaskServerPrioritizedTest.java @@ -0,0 +1,105 @@ +package ru.yandex.javacourse.http; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import ru.yandex.javacourse.model.Epic; +import ru.yandex.javacourse.model.Subtask; +import ru.yandex.javacourse.model.Task; +import ru.yandex.javacourse.service.InMemoryTaskManager; +import ru.yandex.javacourse.service.TaskManager; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.TreeSet; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class HttpTaskServerPrioritizedTest { + private static final String EPIC_NAME = "Эпик"; + private static final String EPIC_DESCRIPTION = "Новый эпик"; + private static final String SUBTASK_NAME_1 = "Подзадача 1"; + private static final String SUBTASK_DESCRIPTION_1 = "Первая подзадача"; + private static final String SUBTASK_NAME_2 = "Подзадача 2"; + private static final String SUBTASK_DESCRIPTION_2 = "Вторая подзадача"; + + TaskManager manager = new InMemoryTaskManager(); + HttpTaskServer taskServer = new HttpTaskServer(manager); + HttpClient client = HttpClient.newHttpClient(); + + @BeforeEach + public void setUp() { + manager.deleteAllTasks(); + manager.deleteAllSubtasks(); + manager.deleteAllEpics(); + + try { + taskServer.start(); + } catch (IOException exception) { + System.out.println("Возникла ошибка во время старта тестов"); + } + } + + @AfterEach + public void shutDown() { + taskServer.stop(); + } + + @Test + @DisplayName("Должен возвращать приоритизированные задачи при отправке запроса в HttpServer при корректном URL") + public void test_getPrioritizedTasks_WhenCorrectURL_ShouldReturnHistory() throws IOException, InterruptedException { + //given + URI url = URI.create("http://localhost:8080/prioritized"); + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + manager.addSubtask(new Subtask(SUBTASK_NAME_1, SUBTASK_DESCRIPTION_1, epic.getId(), + Duration.ofMinutes(30), LocalDateTime.now())); + manager.addSubtask(new Subtask(SUBTASK_NAME_2, SUBTASK_DESCRIPTION_2, epic.getId(), + Duration.ofMinutes(30), LocalDateTime.now().plusHours(1))); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .GET() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + TreeSet tasksFromManager = manager.getPrioritizedTasks(); + + // then + assertEquals(HttpStatusCode.OK.getCode(), response.statusCode()); + assertNotNull(tasksFromManager, "История не возвращаются"); + assertEquals(2, tasksFromManager.size(), "Некорректное количество задач в истории"); + assertEquals(SUBTASK_NAME_1, tasksFromManager.getFirst().getName(), + "Некорректное имя задачи в истории"); + assertEquals(SUBTASK_NAME_2, tasksFromManager.getLast().getName(), + "Некорректное имя задачи в истории"); + } + + @Test + @DisplayName("Не должен возвращать приоритизированные задачи при отправке запроса при некорректном URL") + public void test_getHistory_WhenNotCorrectURL_ShouldReturn404() throws IOException, InterruptedException { + //given + URI url = URI.create("http://localhost:8080/getPrioritized"); + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + manager.addSubtask(new Subtask(SUBTASK_NAME_1, SUBTASK_DESCRIPTION_1, epic.getId(), + Duration.ofMinutes(30), LocalDateTime.now())); + manager.addSubtask(new Subtask(SUBTASK_NAME_2, SUBTASK_DESCRIPTION_2, epic.getId(), + Duration.ofMinutes(30), LocalDateTime.now().plusHours(1))); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .GET() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertEquals(HttpStatusCode.NOT_FOUND.getCode(), response.statusCode()); + } +} diff --git a/test/ru/yandex/javacourse/http/HttpTaskServerSubtasksTest.java b/test/ru/yandex/javacourse/http/HttpTaskServerSubtasksTest.java new file mode 100644 index 0000000..5b32968 --- /dev/null +++ b/test/ru/yandex/javacourse/http/HttpTaskServerSubtasksTest.java @@ -0,0 +1,303 @@ +package ru.yandex.javacourse.http; + +import com.google.gson.Gson; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import ru.yandex.javacourse.model.Epic; +import ru.yandex.javacourse.model.Subtask; +import ru.yandex.javacourse.service.InMemoryTaskManager; +import ru.yandex.javacourse.service.TaskManager; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class HttpTaskServerSubtasksTest { + private static final String EPIC_NAME = "Эпик"; + private static final String EPIC_DESCRIPTION = "Новый эпик"; + private static final String SUBTASK_NAME_1 = "Подзадача 1"; + private static final String SUBTASK_DESCRIPTION_1 = "Первая подзадача"; + private static final String SUBTASK_NAME_2 = "Подзадача 2"; + private static final String SUBTASK_DESCRIPTION_2 = "Вторая подзадача"; + + TaskManager manager = new InMemoryTaskManager(); + HttpTaskServer taskServer = new HttpTaskServer(manager); + HttpClient client = HttpClient.newHttpClient(); + Gson gson = HttpTaskServer.getGson(); + + @BeforeEach + public void setUp() { + manager.deleteAllTasks(); + manager.deleteAllSubtasks(); + manager.deleteAllEpics(); + + try { + taskServer.start(); + } catch (IOException exception) { + System.out.println("Возникла ошибка во время старта тестов"); + } + } + + @AfterEach + public void shutDown() { + taskServer.stop(); + } + + @Test + @DisplayName("Должен сохранять подзадачу в менеджер при отправке запроса в HttpServer") + public void test_AddSubtask_WhenSendSubtask_ManagerShouldStore() throws IOException, InterruptedException { + //given + URI url = URI.create("http://localhost:8080/subtasks"); + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + Subtask subtask = new Subtask(SUBTASK_NAME_1, SUBTASK_DESCRIPTION_1, epic.getId()); + + epic.setStartTime(LocalDateTime.now()); + epic.setDuration(Duration.ofMinutes(5)); + String subtaskJson = gson.toJson(subtask); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subtaskJson)) + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + List subtasksFromManager = manager.getAllSubtasks(); + + // then + assertEquals(HttpStatusCode.CREATED.getCode(), response.statusCode()); + assertNotNull(subtasksFromManager, "Подзадачи не возвращаются"); + assertEquals(1, subtasksFromManager.size(), "Некорректное количество подзадач"); + assertEquals(SUBTASK_NAME_1, subtasksFromManager.get(0).getName(), "Некорректное имя подзадачи"); + } + + @Test + @DisplayName("Должен обновлять подзадачу в менеджере при отправке запроса в HttpServer") + public void test_UpdateSubtask_WhenSendSubtaskWithId_ManagerShouldStoreUpdate() + throws IOException, InterruptedException { + //given + URI url = URI.create("http://localhost:8080/subtasks"); + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + Subtask subtask = manager.addSubtask(new Subtask(SUBTASK_NAME_1, SUBTASK_DESCRIPTION_1, epic.getId())); + Subtask updatedSubtask = new Subtask(SUBTASK_NAME_2, SUBTASK_DESCRIPTION_2, epic.getId()); + updatedSubtask.setId(subtask.getId()); + String subtaskJson = gson.toJson(updatedSubtask); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subtaskJson)) + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + List subtasksFromManager = manager.getAllSubtasks(); + + // then + assertEquals(HttpStatusCode.OK.getCode(), response.statusCode()); + assertNotNull(subtasksFromManager, "Подзадачи не возвращаются"); + assertEquals(1, subtasksFromManager.size(), "Некорректное количество подзадач"); + assertEquals(SUBTASK_NAME_2, subtasksFromManager.get(0).getName(), "Некорректное имя подзадачи"); + } + + @Test + @DisplayName("Должен возвращать подзадачу по id из менеджера при отправке запроса в HttpServer") + public void test_GetSubtaskById_WhenSendRequest_ShouldReturnById() throws IOException, InterruptedException { + //given + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + Subtask subtask = manager.addSubtask(new Subtask(SUBTASK_NAME_1, SUBTASK_DESCRIPTION_1, epic.getId())); + URI url = URI.create("http://localhost:8080/subtasks/" + subtask.getId()); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .GET() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + List subtasksFromManager = manager.getAllSubtasks(); + + // then + assertEquals(HttpStatusCode.OK.getCode(), response.statusCode()); + assertNotNull(subtasksFromManager, "Эпики не возвращаются"); + assertEquals(1, subtasksFromManager.size(), "Некорректное количество подзадач"); + assertEquals(SUBTASK_NAME_1, subtasksFromManager.get(0).getName(), "Некорректное имя подзадачи"); + } + + @Test + @DisplayName("Должен удалять подзадачу по id в менеджере при отправке запроса в HttpServer") + public void test_DeleteSubtaskById_WhenSendCorrectId_ShouldReturnNull() throws IOException, InterruptedException { + //given + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + Subtask subtask = manager.addSubtask(new Subtask(SUBTASK_NAME_1, SUBTASK_DESCRIPTION_1, epic.getId())); + URI url = URI.create("http://localhost:8080/subtasks/" + subtask.getId()); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .DELETE() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + List subtasksFromManager = manager.getAllSubtasks(); + + // then + assertEquals(HttpStatusCode.OK.getCode(), response.statusCode()); + assertNotNull(subtasksFromManager, "Подзадачи не возвращаются"); + assertEquals(0, subtasksFromManager.size(), "Некорректное количество подзадач"); + } + + @Test + @DisplayName("Должен возвращать все подзадачи из менеджера при отправке запроса в HttpServer") + public void test_GetAllSubtasks_WhenSendRequest_ShouldReturnAll() throws IOException, InterruptedException { + //given + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + manager.addSubtask(new Subtask(SUBTASK_NAME_1, SUBTASK_DESCRIPTION_1, epic.getId())); + manager.addSubtask(new Subtask(SUBTASK_NAME_2, SUBTASK_DESCRIPTION_2, epic.getId())); + URI url = URI.create("http://localhost:8080/subtasks"); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .GET() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + List subtasksFromManager = manager.getAllSubtasks(); + + // then + assertEquals(HttpStatusCode.OK.getCode(), response.statusCode()); + assertNotNull(subtasksFromManager, "Подзадачи не возвращаются"); + assertEquals(2, subtasksFromManager.size(), "Некорректное количество подзадач"); + assertEquals(SUBTASK_NAME_1, subtasksFromManager.get(0).getName(), "Некорректное имя подзадачи"); + assertEquals(SUBTASK_NAME_2, subtasksFromManager.get(1).getName(), "Некорректное имя подзадачи"); + } + + @Test + @DisplayName("Не должен сохранять подзадачу в менеджер при отправке запроса по некорректному адресу") + public void test_AddSubtask_WhenIncorrectURL_ShouldReturn404() throws IOException, InterruptedException { + //given + URI incorrectUrl = URI.create("http://localhost:8080/addSubtask"); + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + Subtask subtask = new Subtask(SUBTASK_NAME_1, SUBTASK_DESCRIPTION_1, epic.getId()); + String subtaskJson = gson.toJson(subtask); + HttpRequest request = HttpRequest.newBuilder() + .uri(incorrectUrl) + .POST(HttpRequest.BodyPublishers.ofString(subtaskJson)) + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertEquals(HttpStatusCode.NOT_FOUND.getCode(), response.statusCode(), + "Не должен добавлять подзадачу при некорректном URL"); + } + + @Test + @DisplayName("Не должен обновлять подзадачу в менеджере при отправке запроса с несуществующим id") + public void test_UpdateSubtask_WhenIdNotExist_ShouldReturn404() throws IOException, InterruptedException { + //given + URI url = URI.create("http://localhost:8080/subtasks"); + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + Subtask subtask = manager.addSubtask(new Subtask(SUBTASK_NAME_1, SUBTASK_DESCRIPTION_1, epic.getId())); + Subtask updatedSubtask = new Subtask(SUBTASK_NAME_2, SUBTASK_DESCRIPTION_2, epic.getId()); + updatedSubtask.setId(subtask.getId() + 1); + String subtaskJson = gson.toJson(updatedSubtask); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subtaskJson)) + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertEquals(HttpStatusCode.NOT_FOUND.getCode(), response.statusCode(), + "Не должен обновлять подзадачу по несуществующему id"); + } + + @Test + @DisplayName("Не должен возвращать подзадачу из менеджера при отправке запроса с несуществующим id ") + public void test_GetSubtaskById_WhenIdNotExist_ShouldReturn404() throws IOException, InterruptedException { + //given + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + Subtask subtask = manager.addSubtask(new Subtask(SUBTASK_NAME_1, SUBTASK_DESCRIPTION_1, epic.getId())); + URI url = URI.create("http://localhost:8080/subtasks/" + (subtask.getId() + 1)); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .GET() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertEquals(HttpStatusCode.NOT_FOUND.getCode(), response.statusCode(), + "Не должен возвращать подзадачу по несуществующему id"); + } + + @Test + @DisplayName("Не должен возвращать подзадачу из менеджера при отправке запроса с некорректным id ") + public void test_GetSubtaskById_WhenIdNotAcceptable_ShouldReturn500() throws IOException, InterruptedException { + //given + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + Subtask subtask = manager.addSubtask(new Subtask(SUBTASK_NAME_1, SUBTASK_DESCRIPTION_1, epic.getId())); + URI url = URI.create("http://localhost:8080/subtasks/" + subtask.getId() + "test"); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .GET() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertEquals(HttpStatusCode.INTERNAL_SERVER_ERROR.getCode(), response.statusCode(), + "Не должен возвращать подзадачу по некорректному id"); + } + + @Test + @DisplayName("Не должен удалять подзадачу в менеджере при отправке запроса с несуществующим id ") + public void test_DeleteSubtaskById_WhenIdNotExist_ShouldReturn404() throws IOException, InterruptedException { + //given + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + Subtask subtask = manager.addSubtask(new Subtask(SUBTASK_NAME_1, SUBTASK_DESCRIPTION_1, epic.getId())); + URI url = URI.create("http://localhost:8080/subtasks/" + (subtask.getId() + 1)); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .DELETE() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertEquals(HttpStatusCode.NOT_FOUND.getCode(), response.statusCode(), + "Не должен удалять подзадачу по несуществующему id"); + } + + @Test + @DisplayName("Не должен удалять подзадачу в менеджере при отправке запроса с некорректным id ") + public void test_DeleteSubtaskById_WhenIdNotAcceptable_ShouldReturn500() throws IOException, InterruptedException { + //given + Epic epic = manager.addEpic(new Epic(EPIC_NAME, EPIC_DESCRIPTION)); + Subtask subtask = manager.addSubtask(new Subtask(SUBTASK_NAME_1, SUBTASK_DESCRIPTION_1, epic.getId())); + URI url = URI.create("http://localhost:8080/subtasks/" + subtask.getId() + "test"); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .DELETE() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertEquals(HttpStatusCode.INTERNAL_SERVER_ERROR.getCode(), response.statusCode(), + "Не должен удалять подзадачу по некорректному id"); + } +} \ No newline at end of file diff --git a/test/ru/yandex/javacourse/http/HttpTaskServerTasksTest.java b/test/ru/yandex/javacourse/http/HttpTaskServerTasksTest.java new file mode 100644 index 0000000..24e3263 --- /dev/null +++ b/test/ru/yandex/javacourse/http/HttpTaskServerTasksTest.java @@ -0,0 +1,301 @@ +package ru.yandex.javacourse.http; + +import com.google.gson.Gson; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import ru.yandex.javacourse.model.Task; +import ru.yandex.javacourse.model.TaskStatus; +import ru.yandex.javacourse.service.InMemoryTaskManager; +import ru.yandex.javacourse.service.TaskManager; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class HttpTaskServerTasksTest { + private static final String TASK_NAME = "Задача"; + private static final String TASK_DESCRIPTION = "Новая задача"; + private static final String TASK_NAME_UPDATED = "Обновлённая задача"; + private static final String TASK_DESCRIPTION_UPDATED = "Новая задача"; + TaskManager manager = new InMemoryTaskManager(); + HttpTaskServer taskServer = new HttpTaskServer(manager); + HttpClient client = HttpClient.newHttpClient(); + Gson gson = HttpTaskServer.getGson(); + + @BeforeEach + public void setUp() { + manager.deleteAllTasks(); + manager.deleteAllSubtasks(); + manager.deleteAllEpics(); + try { + taskServer.start(); + } catch (IOException exception) { + System.out.println("Возникла ошибка во время старта тестов"); + } + } + + @AfterEach + public void shutDown() { + taskServer.stop(); + } + + @Test + @DisplayName("Должен сохранять задачу в менеджер при отправке запроса в HttpServer") + public void test_AddTask_WhenSendTaskWithId_ManagerShouldStore() throws IOException, InterruptedException { + //given + URI url = URI.create("http://localhost:8080/tasks"); + Task task = new Task(TASK_NAME, TASK_DESCRIPTION, TaskStatus.NEW, Duration.ofMinutes(5), LocalDateTime.now()); + String taskJson = gson.toJson(task); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .POST(HttpRequest.BodyPublishers.ofString(taskJson)) + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + List tasksFromManager = manager.getAllTasks(); + + // then + assertEquals(HttpStatusCode.CREATED.getCode(), response.statusCode()); + assertNotNull(tasksFromManager, "Задачи не возвращаются"); + assertEquals(1, tasksFromManager.size(), "Некорректное количество задач"); + assertEquals(TASK_NAME, tasksFromManager.get(0).getName(), "Некорректное имя задачи"); + } + + @Test + @DisplayName("Должен обновлять задачу в менеджере при отправке запроса в HttpServer") + public void test_UpdateTask_WhenSendTaskWithId_ManagerShouldStoreUpdate() throws IOException, InterruptedException { + //given + URI url = URI.create("http://localhost:8080/tasks"); + Task task = manager.addTask(new Task(TASK_NAME, TASK_DESCRIPTION, TaskStatus.NEW, Duration.ofMinutes(5), + LocalDateTime.now())); + Task updatedTask = new Task(TASK_NAME_UPDATED, TASK_DESCRIPTION_UPDATED, TaskStatus.IN_PROGRESS, + Duration.ofMinutes(5), LocalDateTime.now()); + updatedTask.setId(task.getId()); + String taskJson = gson.toJson(updatedTask); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .POST(HttpRequest.BodyPublishers.ofString(taskJson)) + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + List tasksFromManager = manager.getAllTasks(); + + + // then + assertEquals(HttpStatusCode.OK.getCode(), response.statusCode()); + assertNotNull(tasksFromManager, "Задачи не возвращаются"); + assertEquals(1, tasksFromManager.size(), "Некорректное количество задач"); + assertEquals(TASK_NAME_UPDATED, tasksFromManager.get(0).getName(), "Некорректное имя задачи"); + } + + @Test + @DisplayName("Должен возвращать задачу по id из менеджера при отправке запроса в HttpServer") + public void test_GetTaskById_WhenSendRequest_ShouldReturnById() throws IOException, InterruptedException { + //given + Task task = manager.addTask(new Task(TASK_NAME, TASK_DESCRIPTION, TaskStatus.NEW, Duration.ofMinutes(5), + LocalDateTime.now())); + URI url = URI.create("http://localhost:8080/tasks/" + task.getId()); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .GET() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + List tasksFromManager = manager.getAllTasks(); + + + // then + assertEquals(HttpStatusCode.OK.getCode(), response.statusCode()); + assertNotNull(tasksFromManager, "Задачи не возвращаются"); + assertEquals(1, tasksFromManager.size(), "Некорректное количество задач"); + assertEquals(TASK_NAME, tasksFromManager.get(0).getName(), "Некорректное имя задачи"); + } + + @Test + @DisplayName("Должен удалять задачу по id в менеджере при отправке запроса в HttpServer") + public void test_DeleteTaskById_WhenSendCorrectId_ShouldReturnNull() throws IOException, InterruptedException { + //given + Task task = manager.addTask(new Task(TASK_NAME, TASK_DESCRIPTION, TaskStatus.NEW, Duration.ofMinutes(5), + LocalDateTime.now())); + URI url = URI.create("http://localhost:8080/tasks" + "/" + task.getId()); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .DELETE() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + List tasksFromManager = manager.getAllTasks(); + + + // then + assertEquals(HttpStatusCode.OK.getCode(), response.statusCode()); + assertNotNull(tasksFromManager, "Задачи не возвращаются"); + assertEquals(0, tasksFromManager.size(), "Некорректное количество задач"); + } + + @Test + @DisplayName("Должен возвращать все задачи из менеджера при отправке запроса в HttpServer") + public void test_GetAllTasks_WhenSendRequest_ShouldReturnAll() throws IOException, InterruptedException { + //given + manager.addTask(new Task(TASK_NAME, TASK_DESCRIPTION, TaskStatus.NEW, Duration.ofMinutes(5), + LocalDateTime.now())); + manager.addTask(new Task(TASK_NAME_UPDATED, TASK_DESCRIPTION_UPDATED, TaskStatus.NEW, Duration.ofMinutes(5), + LocalDateTime.now().plusHours(1))); + URI url = URI.create("http://localhost:8080/tasks"); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .GET() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + List tasksFromManager = manager.getAllTasks(); + + + // then + assertEquals(HttpStatusCode.OK.getCode(), response.statusCode()); + assertNotNull(tasksFromManager, "Задачи не возвращаются"); + assertEquals(2, tasksFromManager.size(), "Некорректное количество задач"); + assertEquals(TASK_NAME, tasksFromManager.get(0).getName(), "Некорректное имя задачи"); + assertEquals(TASK_NAME_UPDATED, tasksFromManager.get(1).getName(), "Некорректное имя задачи"); + } + + @Test + @DisplayName("Не должен сохранять задачу в менеджер при отправке запроса по некорректному адресу") + public void test_AddTask_WhenIncorrectURL_ShouldReturn404() throws IOException, InterruptedException { + //given + URI incorrectUrl = URI.create("http://localhost:8080/addTask"); + Task task = new Task(TASK_NAME, TASK_DESCRIPTION, TaskStatus.NEW, Duration.ofMinutes(5), LocalDateTime.now()); + String taskJson = gson.toJson(task); + HttpRequest request = HttpRequest.newBuilder() + .uri(incorrectUrl) + .POST(HttpRequest.BodyPublishers.ofString(taskJson)) + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertEquals(HttpStatusCode.NOT_FOUND.getCode(), response.statusCode(), + "Не должен добавлять задачу при некорректном URL"); + } + + @Test + @DisplayName("Не должен обновлять задачу из менеджера при отправке запроса с несуществующим id") + public void test_UpdateTask_WhenIdNotExist_ShouldReturn404() throws IOException, InterruptedException { + //given + URI url = URI.create("http://localhost:8080/tasks"); + Task task = manager.addTask(new Task(TASK_NAME, TASK_DESCRIPTION, TaskStatus.NEW, Duration.ofMinutes(5), + LocalDateTime.now())); + Task updatedTask = new Task(TASK_NAME_UPDATED, TASK_DESCRIPTION_UPDATED, TaskStatus.IN_PROGRESS, + Duration.ofMinutes(5), LocalDateTime.now()); + updatedTask.setId(task.getId() + 1); + String taskJson = gson.toJson(updatedTask); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .POST(HttpRequest.BodyPublishers.ofString(taskJson)) + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertEquals(HttpStatusCode.NOT_FOUND.getCode(), response.statusCode(), + "Не должен обновлять задачу по несуществующему id"); + } + + @Test + @DisplayName("Не должен возвращать задачу из менеджера при отправке запроса с несуществующим id ") + public void test_GetTaskById_WhenIdNotExist_ShouldReturn404() throws IOException, InterruptedException { + //given + Task task = manager.addTask(new Task(TASK_NAME, TASK_DESCRIPTION, TaskStatus.NEW, Duration.ofMinutes(5), + LocalDateTime.now())); + URI url = URI.create("http://localhost:8080/tasks/" + (task.getId() + 1)); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .GET() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertEquals(HttpStatusCode.NOT_FOUND.getCode(), response.statusCode(), + "Не должен возвращать задачу по несуществующему id"); + } + + @Test + @DisplayName("Не должен возвращать задачу в менеджере при отправке запроса с некорректным id ") + public void test_GetTaskById_WhenIdNotAcceptable_ShouldReturn500() throws IOException, InterruptedException { + //given + Task task = manager.addTask(new Task(TASK_NAME, TASK_DESCRIPTION, TaskStatus.NEW, Duration.ofMinutes(5), + LocalDateTime.now())); + URI url = URI.create("http://localhost:8080/tasks/" + task.getId() + "test"); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .GET() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertEquals(HttpStatusCode.INTERNAL_SERVER_ERROR.getCode(), response.statusCode(), + "Не должен возвращать задачу по некорректному id"); + } + + @Test + @DisplayName("Не должен удалять задачу в менеджере при отправке запроса с несуществующим id ") + public void test_DeleteTaskById_WhenIdNotExist_ShouldReturn404() throws IOException, InterruptedException { + //given + Task task = manager.addTask(new Task(TASK_NAME, TASK_DESCRIPTION, TaskStatus.NEW, Duration.ofMinutes(5), + LocalDateTime.now())); + URI url = URI.create("http://localhost:8080/tasks/" + (task.getId() + 1)); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .DELETE() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertEquals(HttpStatusCode.NOT_FOUND.getCode(), response.statusCode(), + "Не должен удалять задачу по несуществующему id"); + } + + @Test + @DisplayName("Не должен удалять задачу в менеджере при отправке запроса с некорректным id ") + public void test_DeleteTaskById_WhenIdNotAcceptable_ShouldReturn500() throws IOException, InterruptedException { + //given + Task task = manager.addTask(new Task(TASK_NAME, TASK_DESCRIPTION, TaskStatus.NEW, Duration.ofMinutes(5), + LocalDateTime.now())); + URI url = URI.create("http://localhost:8080/tasks/" + task.getId() + "test"); + HttpRequest request = HttpRequest.newBuilder() + .uri(url) + .DELETE() + .build(); + + //when + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertEquals(HttpStatusCode.INTERNAL_SERVER_ERROR.getCode(), response.statusCode(), + "Не должен удалять задачу по некорректному id"); + } +} + diff --git a/test/ru/yandex/javacourse/model/EpicTest.java b/test/ru/yandex/javacourse/model/EpicTest.java index 2b3a222..ee45e38 100644 --- a/test/ru/yandex/javacourse/model/EpicTest.java +++ b/test/ru/yandex/javacourse/model/EpicTest.java @@ -2,6 +2,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import ru.yandex.javacourse.exceptions.NotFoundException; import ru.yandex.javacourse.service.Managers; import ru.yandex.javacourse.service.TaskManager; import static org.junit.jupiter.api.Assertions.*; @@ -21,97 +22,95 @@ class EpicTest { @DisplayName("Должен возвращать true при сравнении двух эпиков с одинаковым ID") public void test_Equals_WhenEpicsHaveSameId_ShouldReturnTrue() { //given - Epic epic1 = new Epic(EPIC_NAME_1,EPIC_DESCRIPTION_1); + Epic epic1 = new Epic(EPIC_NAME_1, EPIC_DESCRIPTION_1); epic1.setId(EPIC_ID); //when - Epic epic2 = new Epic(EPIC_NAME_2,EPIC_DESCRIPTION_2); + Epic epic2 = new Epic(EPIC_NAME_2, EPIC_DESCRIPTION_2); epic2.setId(EPIC_ID); //then - assertEquals(epic1,epic2, "Эпики не равны"); + assertEquals(epic1, epic2, "Эпики не равны"); } @Test - @DisplayName("Должен возвращать null при попытке добавить эпик в качестве собственной подзадачи") - public void test_AddSubtask_WhenEpicAddedAsOwnSubtask_ShouldReturnNull() { - //given - Epic epic = taskManager.addEpic(new Epic(EPIC_NAME_1,EPIC_DESCRIPTION_1)); + @DisplayName("Должен возвращать NotFoundException при попытке добавить эпик в качестве собственной подзадачи") + public void test_AddSubtask_WhenEpicAddedAsOwnSubtask_ShouldReturnNotFoundException() { + //given && when + Epic epic = taskManager.addEpic(new Epic(EPIC_NAME_1, EPIC_DESCRIPTION_1)); Subtask subtask = new Subtask(epic.getName(), epic.getDescription(), epic.getId()); subtask.setId(epic.getId()); - //when - Subtask resultSubtask = taskManager.addSubtask(subtask); - //then - assertNull(resultSubtask, "Смогли добавить эпик в качестве собственной подзадачи"); + assertThrows(NotFoundException.class, () -> taskManager.addSubtask(subtask), + "Должно быть исключение при попытке добавить эпик в качестве собственной подзадачи"); } @Test @DisplayName("При добавлении подзадач со статусом NEW у эпика тоже должен быть статус NEW") public void test_AddSubtask_WhenAllSubtasksNew_EpicStatusNew() { //given - Epic epic = taskManager.addEpic(new Epic(EPIC_NAME_1,EPIC_DESCRIPTION_1)); + Epic epic = taskManager.addEpic(new Epic(EPIC_NAME_1, EPIC_DESCRIPTION_1)); //when - taskManager.addSubtask(new Subtask(SUBTASK_NAME,SUBTASK_DESCRIPTION, + taskManager.addSubtask(new Subtask(SUBTASK_NAME, SUBTASK_DESCRIPTION, epic.getId())); - taskManager.addSubtask(new Subtask(SUBTASK_NAME,SUBTASK_DESCRIPTION, + taskManager.addSubtask(new Subtask(SUBTASK_NAME, SUBTASK_DESCRIPTION, epic.getId())); Epic returnedEpic = taskManager.getEpicById(epic.getId()); //then - assertEquals("NEW",returnedEpic.getStatus().toString(), "Статус эпика должен быть NEW"); + assertEquals("NEW", returnedEpic.getStatus().toString(), "Статус эпика должен быть NEW"); } @Test @DisplayName("При добавлении подзадач со статусом DONE у эпика тоже должен быть статус DONE") public void test_AddSubtask_WhenAllSubtasksDone_EpicStatusDone() { //given - Epic epic = taskManager.addEpic(new Epic(EPIC_NAME_1,EPIC_DESCRIPTION_1)); + Epic epic = taskManager.addEpic(new Epic(EPIC_NAME_1, EPIC_DESCRIPTION_1)); //when - taskManager.addSubtask(new Subtask(SUBTASK_NAME,SUBTASK_DESCRIPTION, TaskStatus.DONE, + taskManager.addSubtask(new Subtask(SUBTASK_NAME, SUBTASK_DESCRIPTION, TaskStatus.DONE, epic.getId())); - taskManager.addSubtask(new Subtask(SUBTASK_NAME,SUBTASK_DESCRIPTION, TaskStatus.DONE, + taskManager.addSubtask(new Subtask(SUBTASK_NAME, SUBTASK_DESCRIPTION, TaskStatus.DONE, epic.getId())); Epic returnedEpic = taskManager.getEpicById(epic.getId()); //then - assertEquals("DONE",returnedEpic.getStatus().toString(), "Статус эпика должен быть DONE"); + assertEquals("DONE", returnedEpic.getStatus().toString(), "Статус эпика должен быть DONE"); } @Test @DisplayName("При добавлении подзадач со статусом IN_PROGRESS у эпика тоже должен быть статус IN_PROGRESS") public void test_AddSubtask_WhenAllSubtasksInProgress_EpicStatusInProgress() { //given - Epic epic = taskManager.addEpic(new Epic(EPIC_NAME_1,EPIC_DESCRIPTION_1)); + Epic epic = taskManager.addEpic(new Epic(EPIC_NAME_1, EPIC_DESCRIPTION_1)); //when - taskManager.addSubtask(new Subtask(SUBTASK_NAME,SUBTASK_DESCRIPTION, TaskStatus.IN_PROGRESS, + taskManager.addSubtask(new Subtask(SUBTASK_NAME, SUBTASK_DESCRIPTION, TaskStatus.IN_PROGRESS, epic.getId())); - taskManager.addSubtask(new Subtask(SUBTASK_NAME,SUBTASK_DESCRIPTION, TaskStatus.IN_PROGRESS, + taskManager.addSubtask(new Subtask(SUBTASK_NAME, SUBTASK_DESCRIPTION, TaskStatus.IN_PROGRESS, epic.getId())); Epic returnedEpic = taskManager.getEpicById(epic.getId()); //then - assertEquals("IN_PROGRESS",returnedEpic.getStatus().toString(), "Статус эпика должен быть DONE"); + assertEquals("IN_PROGRESS", returnedEpic.getStatus().toString(), "Статус эпика должен быть DONE"); } @Test @DisplayName("При добавлении подзадач с разными статусами у эпика должен быть статус IN_PROGRESS") public void test_AddSubtask_WhenSubtasksInProgressDone_EpicStatusInProgress() { //given - Epic epic = taskManager.addEpic(new Epic(EPIC_NAME_1,EPIC_DESCRIPTION_1)); + Epic epic = taskManager.addEpic(new Epic(EPIC_NAME_1, EPIC_DESCRIPTION_1)); //when - taskManager.addSubtask(new Subtask(SUBTASK_NAME,SUBTASK_DESCRIPTION, TaskStatus.IN_PROGRESS, + taskManager.addSubtask(new Subtask(SUBTASK_NAME, SUBTASK_DESCRIPTION, TaskStatus.IN_PROGRESS, epic.getId())); - taskManager.addSubtask(new Subtask(SUBTASK_NAME,SUBTASK_DESCRIPTION, TaskStatus.DONE, + taskManager.addSubtask(new Subtask(SUBTASK_NAME, SUBTASK_DESCRIPTION, TaskStatus.DONE, epic.getId())); Epic returnedEpic = taskManager.getEpicById(epic.getId()); //then - assertEquals("IN_PROGRESS",returnedEpic.getStatus().toString(), "Статус эпика должен быть DONE"); + assertEquals("IN_PROGRESS", returnedEpic.getStatus().toString(), "Статус эпика должен быть DONE"); } } \ No newline at end of file diff --git a/test/ru/yandex/javacourse/model/SubtaskTest.java b/test/ru/yandex/javacourse/model/SubtaskTest.java index 30613c2..14efa34 100644 --- a/test/ru/yandex/javacourse/model/SubtaskTest.java +++ b/test/ru/yandex/javacourse/model/SubtaskTest.java @@ -2,6 +2,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import ru.yandex.javacourse.exceptions.NotFoundException; import ru.yandex.javacourse.service.Managers; import ru.yandex.javacourse.service.TaskManager; @@ -21,36 +22,34 @@ class SubtaskTest { @DisplayName("Должен возвращать true при сравнении двух подзадач с одинаковым ID") public void test_Equals_WhenSubtasksHaveSameId_ShouldReturnTrue() { //given - Subtask subtask1 = new Subtask(SUBTASK_NAME_1,SUBTASK_DESCRIPTION_1, EPIC_ID); + Subtask subtask1 = new Subtask(SUBTASK_NAME_1, SUBTASK_DESCRIPTION_1, EPIC_ID); subtask1.setId(SUBTASK_ID); //when - Subtask subtask2 = new Subtask(SUBTASK_NAME_2,SUBTASK_DESCRIPTION_2, EPIC_ID); + Subtask subtask2 = new Subtask(SUBTASK_NAME_2, SUBTASK_DESCRIPTION_2, EPIC_ID); subtask2.setId(SUBTASK_ID); //then - assertEquals(subtask1,subtask2, "Подзадачи не равны"); + assertEquals(subtask1, subtask2, "Подзадачи не равны"); } @Test - @DisplayName("Должен возвращать null при попытке добавить подзадачу с ID равным ID эпика") - public void test_AddSubtask_WhenSubtaskAddedLikeOwnEpic_ShouldReturnNull() { - //given - Subtask subtask = new Subtask(SUBTASK_NAME_1,SUBTASK_DESCRIPTION_1 , EPIC_ID); + @DisplayName("Должен возвращать NotFoundException при попытке добавить подзадачу с ID равным ID эпика") + public void test_AddSubtask_WhenSubtaskAddedLikeOwnEpic_ShouldReturnNotFoundException() { + //given && when + Subtask subtask = new Subtask(SUBTASK_NAME_1, SUBTASK_DESCRIPTION_1, EPIC_ID); subtask.setId(subtask.getEpicId()); - //when - Subtask resultSubtask = taskManager.addSubtask(subtask); - //then - assertNull(resultSubtask, "Удалось добавить подзадачу в качестве собственного эпика"); + assertThrows(NotFoundException.class, () -> taskManager.addSubtask(subtask), + "Должно быть исключение при попытке добавить сабтаску как собственный эпик"); } @Test @DisplayName("Должен возвращать не null EpicId при попытке добавить подзадачу") public void test_AddSubtask_WhenSubtaskAdded_ShouldHasEpicId() { //given - Subtask subtask = new Subtask(SUBTASK_NAME_1,SUBTASK_DESCRIPTION_1 , EPIC_ID); + Subtask subtask = new Subtask(SUBTASK_NAME_1, SUBTASK_DESCRIPTION_1, EPIC_ID); //when Integer resultSubtaskEpicId = subtask.getEpicId(); diff --git a/test/ru/yandex/javacourse/service/InMemoryTaskManagerTest.java b/test/ru/yandex/javacourse/service/InMemoryTaskManagerTest.java index 1af8949..71268db 100644 --- a/test/ru/yandex/javacourse/service/InMemoryTaskManagerTest.java +++ b/test/ru/yandex/javacourse/service/InMemoryTaskManagerTest.java @@ -2,6 +2,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import ru.yandex.javacourse.exceptions.NotFoundException; import ru.yandex.javacourse.model.Task; import java.time.Duration; import java.time.LocalDateTime; @@ -24,13 +25,13 @@ public void test_ifTasksCrossInTime_WhenTaskEquals_ShouldReturnFalse() { //given LocalDateTime now = LocalDateTime.now(); Duration taskDuration = Duration.ofMinutes(30); - Task task = taskManager.addTask(new Task(TASK_NAME, TASK_DESCRIPTION,taskDuration, now)); + Task task = taskManager.addTask(new Task(TASK_NAME, TASK_DESCRIPTION, taskDuration, now)); task.setId(TASK_ID); //when Task firstTask = taskManager.getTaskById(task.getId()); Task secondTask = taskManager.getTaskById(task.getId()); - boolean hasCross = taskManager.ifTasksCrossInTime(firstTask,secondTask); + boolean hasCross = taskManager.ifTasksCrossInTime(firstTask, secondTask); //then assertFalse(hasCross, "Пересечение не должно считаться, если задача сравнивается сама с собой."); @@ -43,13 +44,13 @@ public void test_ifTasksCrossInTime_WhenTaskStartsBeforeOtherFinish_ShouldReturn LocalDateTime now = LocalDateTime.now(); LocalDateTime nowPlus = now.plusHours(1); Duration taskDuration = Duration.ofHours(10); - Task firstTask = new Task(TASK_NAME, TASK_DESCRIPTION,taskDuration, now); + Task firstTask = new Task(TASK_NAME, TASK_DESCRIPTION, taskDuration, now); firstTask.setId(TASK_ID); - Task secondTask = new Task(TASK_NAME, TASK_DESCRIPTION,taskDuration, nowPlus); + Task secondTask = new Task(TASK_NAME, TASK_DESCRIPTION, taskDuration, nowPlus); secondTask.setId(TASK_ID + 1); //when - boolean hasCross = taskManager.ifTasksCrossInTime(firstTask,secondTask); + boolean hasCross = taskManager.ifTasksCrossInTime(firstTask, secondTask); //then assertTrue(hasCross, "Задача не может начаться пока другая задача не закончится."); @@ -64,13 +65,13 @@ public void test_ifTasksCrossInTime_WhenTaskStartsBeforeOtherFinishSwitch_Should Duration firstDuration = Duration.ofHours(10); Duration secondDuration = Duration.ofHours(4); - Task firstTask = new Task(TASK_NAME, TASK_DESCRIPTION,firstDuration, firstStart); + Task firstTask = new Task(TASK_NAME, TASK_DESCRIPTION, firstDuration, firstStart); firstTask.setId(TASK_ID); - Task secondTask = new Task(TASK_NAME, TASK_DESCRIPTION,secondDuration, secondStart); + Task secondTask = new Task(TASK_NAME, TASK_DESCRIPTION, secondDuration, secondStart); secondTask.setId(TASK_ID + 1); //when - boolean hasCross = taskManager.ifTasksCrossInTime(firstTask,secondTask); + boolean hasCross = taskManager.ifTasksCrossInTime(firstTask, secondTask); //then assertTrue(hasCross, "Задача не может начаться пока другая задача не закончится."); @@ -82,31 +83,30 @@ public void test_ifTasksCrossInTime_WhenTaskHasSameStart_ShouldReturnTrue() { //given LocalDateTime now = LocalDateTime.now(); Duration taskDuration = Duration.ofMinutes(30); - Task firstTask = new Task(TASK_NAME, TASK_DESCRIPTION,taskDuration, now); + Task firstTask = new Task(TASK_NAME, TASK_DESCRIPTION, taskDuration, now); firstTask.setId(TASK_ID); - Task secondTask = new Task(TASK_NAME, TASK_DESCRIPTION,taskDuration, now); - firstTask.setId(TASK_ID+1); + Task secondTask = new Task(TASK_NAME, TASK_DESCRIPTION, taskDuration, now); + firstTask.setId(TASK_ID + 1); //when - boolean hasCross = taskManager.ifTasksCrossInTime(firstTask,secondTask); + boolean hasCross = taskManager.ifTasksCrossInTime(firstTask, secondTask); //then assertTrue(hasCross, "Задача не должна пересекаться по времени сама с собой."); } @Test - @DisplayName("Должен возвращать null при попытке добавить в менеджер задачу, пересекающуюся по времени" + + @DisplayName("Должен возвращать NotFoundException при попытке добавить в менеджер задачу, пересекающуюся по времени" + " с уже добавленной") - public void test_hasCrossInTimeWithManagerTasks_WhenTaskHasSameStart_ShouldReturnNull() { - //given + public void test_hasCrossInTimeWithManagerTasks_WhenTaskHasSameStart_ShouldReturnNotFoundException() { + //given && when LocalDateTime now = LocalDateTime.now(); Duration taskDuration = Duration.ofDays(30); - taskManager.addTask(new Task(TASK_NAME, TASK_DESCRIPTION,taskDuration, now)); - - //when - Task secondTask = taskManager.addTask(new Task(TASK_NAME, TASK_DESCRIPTION,taskDuration, now)); + taskManager.addTask(new Task(TASK_NAME, TASK_DESCRIPTION, taskDuration, now)); //then - assertNull(secondTask, "Задача не может быть добавлена в менеджер, если есть пересечение по времени"); + assertThrows(NotFoundException.class, + () -> taskManager.addTask(new Task(TASK_NAME, TASK_DESCRIPTION, taskDuration, now)), + "Задача не может быть добавлена в менеджер, если есть пересечение по времени"); } } \ No newline at end of file