From 430a9a8e2cacfc188d99b494d1f2ba6f303180b0 Mon Sep 17 00:00:00 2001 From: Denis Panasyuk Date: Tue, 30 Sep 2025 16:21:27 +0300 Subject: [PATCH 1/5] =?UTF-8?q?=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=BE?= =?UTF-8?q?=D0=BD=D0=B0=D0=BB=209-=D0=BE=D0=B3=D0=BE=20=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=D0=BD=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/inspectionProfiles/Project_Default.xml | 8 ++ files/Task.txt | 7 +- java-kanban.iml | 9 ++ src/http/HttpTaskServer.java | 68 ++++++++++++ src/http/adapters/DurationAdapter.java | 20 ++++ src/http/adapters/LocalDateTimeAdapter.java | 21 ++++ src/http/handlers/BaseHttpHandler.java | 50 +++++++++ src/http/handlers/EpicHandler.java | 104 +++++++++++++++++++ src/http/handlers/HistoryHandler.java | 42 ++++++++ src/http/handlers/PrioritizedHandler.java | 43 ++++++++ src/http/handlers/SubtaskHandler.java | 91 ++++++++++++++++ src/http/handlers/TaskHandler.java | 90 ++++++++++++++++ src/managers/InMemoryTaskManager.java | 12 ++- src/managers/TaskManager.java | 5 + test/HttpTaskManagerTasksTest.java | 74 +++++++++++++ 15 files changed, 636 insertions(+), 8 deletions(-) create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 src/http/HttpTaskServer.java create mode 100644 src/http/adapters/DurationAdapter.java create mode 100644 src/http/adapters/LocalDateTimeAdapter.java create mode 100644 src/http/handlers/BaseHttpHandler.java create mode 100644 src/http/handlers/EpicHandler.java create mode 100644 src/http/handlers/HistoryHandler.java create mode 100644 src/http/handlers/PrioritizedHandler.java create mode 100644 src/http/handlers/SubtaskHandler.java create mode 100644 src/http/handlers/TaskHandler.java create mode 100644 test/HttpTaskManagerTasksTest.java diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..6fea68f --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/files/Task.txt b/files/Task.txt index 24a570a..4e38695 100644 --- a/files/Task.txt +++ b/files/Task.txt @@ -1,5 +1,4 @@ id,type,name,status,description,class,epicId,startTime,duration,endTime -1,TASK,Task001,NEW,Description,Task,Null,2024-02-02T11:00,60,2024-02-02T12:00 -2,EPIC,Epic001,NEW,Description,Epic,2,2025-01-01T10:00,140,2025-01-01T12:30 -3,SUBTASK,Subtask001,NEW,Description,Subtask,2,2025-01-01T10:00,70,2025-01-01T11:10 -4,SUBTASK,Subtask002,NEW,Description,Subtask,2,2025-01-01T11:20,70,2025-01-01T12:30 +1,TASK,Task001,NEW,Description,Task,Null,Null,Null,Null +2,EPIC,Epic001,NEW,Description,Epic,2,Null,Null,Null +3,SUBTASK,Subtask001,NEW,Description,Subtask,2,Null,Null,Null diff --git a/java-kanban.iml b/java-kanban.iml index 66c15d2..595dea8 100644 --- a/java-kanban.iml +++ b/java-kanban.iml @@ -24,5 +24,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/http/HttpTaskServer.java b/src/http/HttpTaskServer.java new file mode 100644 index 0000000..1af2101 --- /dev/null +++ b/src/http/HttpTaskServer.java @@ -0,0 +1,68 @@ +package http; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.sun.net.httpserver.HttpServer; +import http.adapters.DurationAdapter; +import http.adapters.LocalDateTimeAdapter; +import http.handlers.*; +import managers.InMemoryTaskManager; +import managers.TaskManager; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.time.Duration; +import java.time.LocalDateTime; + +public class HttpTaskServer { + private static final int PORT = 8080; + + private final HttpServer kanbanServer; + private final TaskManager manager; + + + public HttpTaskServer(TaskManager manager) throws IOException { + this.manager = manager; + + kanbanServer = HttpServer.create(new InetSocketAddress(PORT), 0); + kanbanServer.createContext("/tasks", new TaskHandler(manager)); + kanbanServer.createContext("/subtasks", new SubtaskHandler(manager)); + kanbanServer.createContext("/epics", new EpicHandler(manager)); + kanbanServer.createContext("/history", new HistoryHandler(manager)); + kanbanServer.createContext("/prioritized", new PrioritizedHandler(manager)); + } + + public static Gson getGson() { + GsonBuilder gsonBuilder = new GsonBuilder(); + gsonBuilder.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter()); + gsonBuilder.registerTypeAdapter(Duration.class, new DurationAdapter()); + return gsonBuilder.create(); + } + + public void start() { + kanbanServer.start(); + System.out.println("HTTP-сервер запущен на " + PORT + " порту!"); + } + + public void stop() { + kanbanServer.stop(200); + } + + public static void main(String[] args) { + try { + TaskManager manager = new InMemoryTaskManager(); + HttpTaskServer server = new HttpTaskServer(manager); + server.start(); + + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + System.out.println("\nОстанавливаем сервер..."); + server.stop(); + })); + + System.out.println("Нажмите Ctrl+C для остановки сервера"); + + } catch (IOException e) { + System.err.println("Не удалось запустить сервер: " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/src/http/adapters/DurationAdapter.java b/src/http/adapters/DurationAdapter.java new file mode 100644 index 0000000..6afb849 --- /dev/null +++ b/src/http/adapters/DurationAdapter.java @@ -0,0 +1,20 @@ +package http.adapters; + +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 DurationAdapter extends TypeAdapter { + @Override + public void write(JsonWriter jsonWriter, java.time.Duration duration) throws IOException { + jsonWriter.value(duration.toMinutes()); + } + + @Override + public java.time.Duration read(JsonReader jsonReader) throws IOException { + return Duration.ofMinutes(jsonReader.nextInt()); + } +} diff --git a/src/http/adapters/LocalDateTimeAdapter.java b/src/http/adapters/LocalDateTimeAdapter.java new file mode 100644 index 0000000..40cdc63 --- /dev/null +++ b/src/http/adapters/LocalDateTimeAdapter.java @@ -0,0 +1,21 @@ +package http.adapters; + +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 LocalDateTimeAdapter extends TypeAdapter { + @Override + public void write(JsonWriter jsonWriter, LocalDateTime localDate) throws IOException { + jsonWriter.value(localDate.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); + } + + @Override + public LocalDateTime read(JsonReader jsonReader) throws IOException { + return LocalDateTime.parse(jsonReader.nextString(), DateTimeFormatter.ISO_LOCAL_DATE_TIME); + } +} diff --git a/src/http/handlers/BaseHttpHandler.java b/src/http/handlers/BaseHttpHandler.java new file mode 100644 index 0000000..db79411 --- /dev/null +++ b/src/http/handlers/BaseHttpHandler.java @@ -0,0 +1,50 @@ +package http.handlers; + +import com.sun.net.httpserver.HttpExchange; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; + +public class BaseHttpHandler{ + protected void sendText(HttpExchange h, String responseString, int responseCode) throws IOException { + byte[] resp = responseString.getBytes(StandardCharsets.UTF_8); + h.getResponseHeaders().set("Content-Type", "application/json;charset=utf-8"); + h.sendResponseHeaders(responseCode, resp.length); + try (OutputStream os = h.getResponseBody()) { + os.write(resp); + } + } + + protected void sendNotFound(HttpExchange h) throws IOException { + byte[] resp = "Not Found".getBytes(StandardCharsets.UTF_8); + h.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8"); + h.sendResponseHeaders(404, resp.length); + h.getResponseBody().write(resp); + h.close(); + } + + protected void sendHasOverlaps(HttpExchange h) throws IOException { + byte[] resp = "Not Acceptable".getBytes(StandardCharsets.UTF_8); + h.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8"); + h.sendResponseHeaders(406, resp.length); + h.getResponseBody().write(resp); + h.close(); + } + + protected Integer getId(String path) { + try { + String[] parts = path.split("/"); + if (parts.length >= 3) { + return Integer.parseInt(parts[2]); + } + } catch (Exception e) { + System.out.println("Cannot get ID from path: " + path); + } + return null; + } + + protected String readText(HttpExchange h) throws IOException { + return new String(h.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); + } +} \ No newline at end of file diff --git a/src/http/handlers/EpicHandler.java b/src/http/handlers/EpicHandler.java new file mode 100644 index 0000000..470dade --- /dev/null +++ b/src/http/handlers/EpicHandler.java @@ -0,0 +1,104 @@ +package http.handlers; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import exceptions.TaskValidationException; +import http.HttpTaskServer; +import managers.TaskManager; +import tasks.Epic; +import tasks.Subtask; +import tasks.Task; + +import java.io.IOException; +import java.util.List; + +public class EpicHandler extends BaseHttpHandler implements HttpHandler { + + private Gson gson; + private TaskManager taskManager; + + public EpicHandler(TaskManager taskManager) { + this.taskManager = taskManager; + this.gson = HttpTaskServer.getGson(); + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + try { + String path = exchange.getRequestURI().getPath(); + Integer idFromPath = getId(path); + String method = exchange.getRequestMethod(); + System.out.println("Request: " + method + " " + path + " (id: " + idFromPath + ")"); + switch (method) { + case "GET": { + if (idFromPath == null) { + List epicList = taskManager.getEpicList(); + String response = gson.toJson(epicList); + System.out.println("Получили список эпиков"); + sendText(exchange, response, 200); + break; + } else if (idFromPath > 0 && (path.split("/")[3]).equals("subtasks")) { + Epic epic = taskManager.getEpicForId(idFromPath); + if (epic != null) { + List epicSubList = taskManager.getEpicSubtask(idFromPath); + String response = gson.toJson(epicSubList); + System.out.println("Получили список подзадач эпика"); + sendText(exchange, response, 200); + break; + } else { + sendNotFound(exchange); + } + } else { + Epic epic = taskManager.getEpicForId(idFromPath); + if (epic != null) { + String response = gson.toJson(epic); + System.out.println("Получили эпик по id " + idFromPath); + sendText(exchange, response, 200); + } else { + sendNotFound(exchange); + } + break; + } + } + case "POST": { + String body = readText(exchange); + Epic epic = gson.fromJson(body, Epic.class); + int epicId = epic.getId(); + if (epicId > 0) { + taskManager.updateEpic(epic); + System.out.println("Обновили эпик с id: " + epicId); + exchange.sendResponseHeaders(200, -1); + } else { + try { + taskManager.addEpic(epic); + int addId = epic.getId(); + System.out.println("Создали эпик с id: " + addId); + String response = gson.toJson(epic); + sendText(exchange, response, 201); + } catch (TaskValidationException ex) { + sendHasOverlaps(exchange); + } + } + break; + } + case "DELETE": { + taskManager.removeEpicForId(idFromPath); + System.out.println("Удалили эпик по id " + idFromPath); + exchange.sendResponseHeaders(200, 0); + exchange.close(); + break; + } + default: { + System.out.println("/epics получил: " + exchange.getRequestMethod()); + exchange.sendResponseHeaders(405, 0); + exchange.close(); + break; + } + } + } catch (Exception e) { + System.err.println("Ошибка обработки: " + e.getMessage()); + e.printStackTrace(); + } + } +} diff --git a/src/http/handlers/HistoryHandler.java b/src/http/handlers/HistoryHandler.java new file mode 100644 index 0000000..c1fd0d3 --- /dev/null +++ b/src/http/handlers/HistoryHandler.java @@ -0,0 +1,42 @@ +package http.handlers; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import http.HttpTaskServer; +import managers.TaskManager; +import tasks.Task; + +import java.io.IOException; +import java.util.List; + +public class HistoryHandler extends BaseHttpHandler implements HttpHandler { + + private Gson gson; + private TaskManager taskManager; + + public HistoryHandler(TaskManager taskManager) { + this.taskManager = taskManager; + this.gson = HttpTaskServer.getGson(); + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + String method = exchange.getRequestMethod(); + switch (method) { + case "GET": { + List history = taskManager.getHistory(); + String response = gson.toJson(history); + System.out.println("Получили историю"); + sendText(exchange, response, 200); + return; + } + default: { + System.out.println("/history получил: " + exchange.getRequestMethod()); + exchange.sendResponseHeaders(405, 0); + exchange.close(); + break; + } + } + } +} diff --git a/src/http/handlers/PrioritizedHandler.java b/src/http/handlers/PrioritizedHandler.java new file mode 100644 index 0000000..4690ada --- /dev/null +++ b/src/http/handlers/PrioritizedHandler.java @@ -0,0 +1,43 @@ +package http.handlers; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import http.HttpTaskServer; +import managers.TaskManager; +import tasks.Task; + +import java.io.IOException; +import java.util.List; +import java.util.Set; + +public class PrioritizedHandler extends BaseHttpHandler implements HttpHandler { + + private Gson gson; + private TaskManager taskManager; + + public PrioritizedHandler(TaskManager taskManager) { + this.taskManager = taskManager; + this.gson = HttpTaskServer.getGson(); + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + String method = exchange.getRequestMethod(); + switch (method) { + case "GET": { + Set history = taskManager.getprioritizedTasks(); + String response = gson.toJson(history); + System.out.println("Получили приоритетный список"); + sendText(exchange, response, 200); + return; + } + default: { + System.out.println("/prioritized получил: " + exchange.getRequestMethod()); + exchange.sendResponseHeaders(405, 0); + exchange.close(); + break; + } + } + } +} diff --git a/src/http/handlers/SubtaskHandler.java b/src/http/handlers/SubtaskHandler.java new file mode 100644 index 0000000..ac007aa --- /dev/null +++ b/src/http/handlers/SubtaskHandler.java @@ -0,0 +1,91 @@ +package http.handlers; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import exceptions.TaskValidationException; +import http.HttpTaskServer; +import managers.TaskManager; +import tasks.Subtask; +import tasks.Task; + +import java.io.IOException; +import java.util.List; + +public class SubtaskHandler extends BaseHttpHandler implements HttpHandler { + + private Gson gson; + private TaskManager taskManager; + + public SubtaskHandler(TaskManager taskManager) { + this.taskManager = taskManager; + this.gson = HttpTaskServer.getGson(); + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + try { + String path = exchange.getRequestURI().getPath(); + Integer idFromPath = getId(path); + String method = exchange.getRequestMethod(); + System.out.println("Request: " + method + " " + path + " (id: " + idFromPath + ")"); + switch (method) { + case "GET": { + if (idFromPath == null) { + List subList = taskManager.getAllSubtask(); + String response = gson.toJson(subList); + System.out.println("Получили список подзадач"); + sendText(exchange, response, 200); + break; + } + Subtask subtask = taskManager.getSubtaskForId(idFromPath); + if (subtask != null) { + String response = gson.toJson(subtask); + System.out.println("Получили подзадачу по id " + idFromPath); + sendText(exchange, response, 200); + } else { + sendNotFound(exchange); + } + break; + } + case "POST": { + String body = readText(exchange); + Subtask subtask = gson.fromJson(body, Subtask.class); + int subtaskId = subtask.getId(); + if (subtaskId > 0) { + taskManager.updateSubtask(subtask); + System.out.println("Обновили подзадачу с id: " + subtaskId); + exchange.sendResponseHeaders(200, -1); + } else { + try { + taskManager.addSubtask(subtask); + int addId = subtask.getId(); + System.out.println("Создали подзадачу с id: " + addId); + String response = gson.toJson(subtask); + sendText(exchange, response, 201); + } catch (TaskValidationException ex) { + sendHasOverlaps(exchange); + } + } + break; + } + case "DELETE": { + taskManager.removeSubtaskForId(idFromPath); + System.out.println("Удалили подзадачу по id " + idFromPath); + exchange.sendResponseHeaders(200, 0); + exchange.close(); + break; + } + default: { + System.out.println("/subtasks получил: " + exchange.getRequestMethod()); + exchange.sendResponseHeaders(405, 0); + exchange.close(); + break; + } + } + } catch (Exception e) { + System.err.println("Ошибка обработки: " + e.getMessage()); + e.printStackTrace(); + } + } +} diff --git a/src/http/handlers/TaskHandler.java b/src/http/handlers/TaskHandler.java new file mode 100644 index 0000000..840da95 --- /dev/null +++ b/src/http/handlers/TaskHandler.java @@ -0,0 +1,90 @@ +package http.handlers; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import exceptions.TaskValidationException; +import http.HttpTaskServer; +import managers.TaskManager; +import tasks.Task; + +import java.io.IOException; +import java.util.List; + +public class TaskHandler extends BaseHttpHandler implements HttpHandler { + + private Gson gson; + private TaskManager taskManager; + + public TaskHandler(TaskManager taskManager) { + this.taskManager = taskManager; + this.gson = HttpTaskServer.getGson(); + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + try { + String path = exchange.getRequestURI().getPath(); + Integer idFromPath = getId(path); + String method = exchange.getRequestMethod(); + System.out.println("Request: " + method + " " + path + " (id: " + idFromPath + ")"); + switch (method) { + case "GET": { + if (idFromPath == null) { + List tList = taskManager.getTaskList(); + String response = gson.toJson(tList); + System.out.println("Получили список задач"); + sendText(exchange, response, 200); + break; + } + Task task = taskManager.getTaskForId(idFromPath); + if (task != null) { + String response = gson.toJson(task); + System.out.println("Получили задачу по id " + idFromPath); + sendText(exchange, response, 200); + } else { + sendNotFound(exchange); + } + break; + } + case "POST": { + String body = readText(exchange); + Task task = gson.fromJson(body, Task.class); + int taskId = task.getId(); + if (taskId > 0) { + taskManager.updateTask(task); + System.out.println("Обновили задачу с id: " + taskId); + exchange.sendResponseHeaders(200, -1); + } else { + try { + taskManager.addTask(task); + int addId = task.getId(); + System.out.println("Создали задачу с id: " + addId); + String response = gson.toJson(task); + sendText(exchange, response, 201); + } catch (TaskValidationException ex) { + sendHasOverlaps(exchange); + } + } + break; + } + case "DELETE": { + taskManager.removeTaskForId(idFromPath); + System.out.println("Удалили задачу с id " + idFromPath); + exchange.sendResponseHeaders(200, 0); + exchange.close(); + break; + } + default: { + System.out.println("/tasks получил: " + exchange.getRequestMethod()); + exchange.sendResponseHeaders(405, 0); + exchange.close(); + break; + } + } + } catch (Exception e) { + System.err.println("Ошибка обработки: " + e.getMessage()); + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/managers/InMemoryTaskManager.java b/src/managers/InMemoryTaskManager.java index bf4470a..1f33b7b 100644 --- a/src/managers/InMemoryTaskManager.java +++ b/src/managers/InMemoryTaskManager.java @@ -99,8 +99,8 @@ public void deleteEpicSubtask(Epic epic) { //удаление подзадача @Override public void removeTaskForId(Integer id) { - taskList.remove(id); delete(taskList.get(id)); + taskList.remove(id); historyManager.remove(id); } @@ -125,8 +125,8 @@ public void removeEpicForId(Integer id) { @Override public void removeSubtaskForId(Integer id) { int epicId = subtaskList.get(id).getEpicId(); - subtaskList.remove(id); delete(subtaskList.get(id)); + subtaskList.remove(id); checkStatus(epicList.get(epicId));//проверяем статус эпика из которого удалили подзадачу historyManager.remove(id); updateEpic(epicList.get(epicId)); @@ -154,8 +154,8 @@ public Subtask getSubtaskForId(Integer id) { public void addTask(Task task) { idCounter++; task.setId(idCounter); - taskList.put(task.getId(), task); add(task); + taskList.put(task.getId(), task); } @Override @@ -171,8 +171,8 @@ public void addSubtask(Subtask subtask) { idCounter++; subtask.setId(idCounter); int currentEpicId = subtask.getEpicId(); - subtaskList.put(subtask.getId(), subtask); add(subtask); + subtaskList.put(subtask.getId(), subtask); updateEpic(epicList.get(currentEpicId)); } @@ -302,4 +302,8 @@ private void add(Task newTask) { private void delete(Task task) { prioritizedTasks.remove(task); } + + public Set getprioritizedTasks() { + return prioritizedTasks; + } } \ No newline at end of file diff --git a/src/managers/TaskManager.java b/src/managers/TaskManager.java index 48f0b63..e73b0b5 100644 --- a/src/managers/TaskManager.java +++ b/src/managers/TaskManager.java @@ -4,6 +4,7 @@ import tasks.Subtask; import tasks.Task; import java.util.List; +import java.util.Set; public interface TaskManager { List getTaskList(); @@ -45,4 +46,8 @@ public interface TaskManager { void updateSubtask(Subtask subtask); void updateEpic(Epic epic); + + List getHistory(); + + Set getprioritizedTasks(); } diff --git a/test/HttpTaskManagerTasksTest.java b/test/HttpTaskManagerTasksTest.java new file mode 100644 index 0000000..d7152be --- /dev/null +++ b/test/HttpTaskManagerTasksTest.java @@ -0,0 +1,74 @@ +import com.google.gson.Gson; +import http.HttpTaskServer; +import managers.InMemoryTaskManager; +import managers.TaskManager; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.AfterEach; +import tasks.Task; +import tasks.TaskStatus; + +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 HttpTaskManagerTasksTest { + + // создаём экземпляр InMemoryTaskManager + TaskManager manager = new InMemoryTaskManager(); + // передаём его в качестве аргумента в конструктор HttpTaskServer + HttpTaskServer taskServer = new HttpTaskServer(manager); + Gson gson = HttpTaskServer.getGson(); + + public HttpTaskManagerTasksTest() throws IOException { + } + + @BeforeEach + public void setUp() { + manager.deleteTaskList(); + manager.deleteAllSubtask(); + manager.deleteAllEpic(); + taskServer.start(); + } + + @AfterEach + public void shutDown() { + taskServer.stop(); + } + + @Test + public void testAddTask() throws IOException, InterruptedException { + // создаём задачу + Task task = new Task("Test 2", "Testing task 2", + TaskStatus.NEW, Duration.ofMinutes(5), LocalDateTime.now()); + // конвертируем её в JSON + String taskJson = gson.toJson(task); + + // создаём HTTP-клиент и запрос + HttpClient client = HttpClient.newHttpClient(); + URI url = URI.create("http://localhost:8080/tasks"); + HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1) + .uri(url).POST(HttpRequest.BodyPublishers.ofString(taskJson)).build(); + + // вызываем рест, отвечающий за создание задач + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // проверяем код ответа + assertEquals(200, response.statusCode()); + + // проверяем, что создалась одна задача с корректным именем + List tasksFromManager = manager.getTaskList(); + + assertNotNull(tasksFromManager, "Задачи не возвращаются"); + assertEquals(1, tasksFromManager.size(), "Некорректное количество задач"); + assertEquals("Test 2", tasksFromManager.get(0).getTitle(), "Некорректное имя задачи"); + } +} \ No newline at end of file From 38597f9093f93402f4b1380653ad4a1a7683d647 Mon Sep 17 00:00:00 2001 From: Denis Panasyuk Date: Wed, 1 Oct 2025 00:41:21 +0300 Subject: [PATCH 2/5] =?UTF-8?q?=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=BE?= =?UTF-8?q?=D0=BD=D0=B0=D0=BB=209-=D0=BE=D0=B3=D0=BE=20=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=D0=BD=D1=82=D0=B0=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D1=82=D0=B5=D1=81=D1=82=D1=8B.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/http/adapters/DurationAdapter.java | 12 +- src/http/adapters/LocalDateTimeAdapter.java | 12 +- src/http/handlers/EpicHandler.java | 26 +-- src/http/handlers/HistoryHandler.java | 4 +- src/http/handlers/PrioritizedHandler.java | 5 +- src/http/handlers/SubtaskHandler.java | 26 +-- src/tasks/Epic.java | 5 + .../HttpHistoryTest.java} | 42 ++--- test/httpTest/HttpPrioritizedTest.java | 70 ++++++++ test/httpTest/HttpTaskManagerEpicsTest.java | 159 ++++++++++++++++++ .../httpTest/HttpTaskManagerSubtasksTest.java | 139 +++++++++++++++ test/httpTest/HttpTaskManagerTasksTest.java | 130 ++++++++++++++ 12 files changed, 568 insertions(+), 62 deletions(-) rename test/{HttpTaskManagerTasksTest.java => httpTest/HttpHistoryTest.java} (56%) create mode 100644 test/httpTest/HttpPrioritizedTest.java create mode 100644 test/httpTest/HttpTaskManagerEpicsTest.java create mode 100644 test/httpTest/HttpTaskManagerSubtasksTest.java create mode 100644 test/httpTest/HttpTaskManagerTasksTest.java diff --git a/src/http/adapters/DurationAdapter.java b/src/http/adapters/DurationAdapter.java index 6afb849..86b6acf 100644 --- a/src/http/adapters/DurationAdapter.java +++ b/src/http/adapters/DurationAdapter.java @@ -10,11 +10,19 @@ public class DurationAdapter extends TypeAdapter { @Override public void write(JsonWriter jsonWriter, java.time.Duration duration) throws IOException { - jsonWriter.value(duration.toMinutes()); + if (duration == null) { + jsonWriter.nullValue(); + } else { + jsonWriter.value(duration.toMinutes()); + } } @Override public java.time.Duration read(JsonReader jsonReader) throws IOException { + if (jsonReader.peek() == com.google.gson.stream.JsonToken.NULL) { + jsonReader.nextNull(); + return null; + } return Duration.ofMinutes(jsonReader.nextInt()); } -} +} \ No newline at end of file diff --git a/src/http/adapters/LocalDateTimeAdapter.java b/src/http/adapters/LocalDateTimeAdapter.java index 40cdc63..b0d3e5e 100644 --- a/src/http/adapters/LocalDateTimeAdapter.java +++ b/src/http/adapters/LocalDateTimeAdapter.java @@ -11,11 +11,19 @@ public class LocalDateTimeAdapter extends TypeAdapter { @Override public void write(JsonWriter jsonWriter, LocalDateTime localDate) throws IOException { - jsonWriter.value(localDate.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); + if (localDate == null) { + jsonWriter.nullValue(); + } else { + jsonWriter.value(localDate.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); + } } @Override public LocalDateTime read(JsonReader jsonReader) throws IOException { + if (jsonReader.peek() == com.google.gson.stream.JsonToken.NULL) { + jsonReader.nextNull(); + return null; + } return LocalDateTime.parse(jsonReader.nextString(), DateTimeFormatter.ISO_LOCAL_DATE_TIME); } -} +} \ No newline at end of file diff --git a/src/http/handlers/EpicHandler.java b/src/http/handlers/EpicHandler.java index 470dade..9e8d14d 100644 --- a/src/http/handlers/EpicHandler.java +++ b/src/http/handlers/EpicHandler.java @@ -8,7 +8,6 @@ import managers.TaskManager; import tasks.Epic; import tasks.Subtask; -import tasks.Task; import java.io.IOException; import java.util.List; @@ -38,7 +37,7 @@ public void handle(HttpExchange exchange) throws IOException { System.out.println("Получили список эпиков"); sendText(exchange, response, 200); break; - } else if (idFromPath > 0 && (path.split("/")[3]).equals("subtasks")) { + } else if ((path.split("/").length > 3) && "subtasks".equals(path.split("/")[3])) { Epic epic = taskManager.getEpicForId(idFromPath); if (epic != null) { List epicSubList = taskManager.getEpicSubtask(idFromPath); @@ -64,21 +63,14 @@ public void handle(HttpExchange exchange) throws IOException { case "POST": { String body = readText(exchange); Epic epic = gson.fromJson(body, Epic.class); - int epicId = epic.getId(); - if (epicId > 0) { - taskManager.updateEpic(epic); - System.out.println("Обновили эпик с id: " + epicId); - exchange.sendResponseHeaders(200, -1); - } else { - try { - taskManager.addEpic(epic); - int addId = epic.getId(); - System.out.println("Создали эпик с id: " + addId); - String response = gson.toJson(epic); - sendText(exchange, response, 201); - } catch (TaskValidationException ex) { - sendHasOverlaps(exchange); - } + try { + taskManager.addEpic(epic); + int epicId = epic.getId(); + System.out.println("Создали эпик с id: " + epicId); + String response = gson.toJson(epic); + sendText(exchange, response, 201); + } catch (TaskValidationException ex) { + sendHasOverlaps(exchange); } break; } diff --git a/src/http/handlers/HistoryHandler.java b/src/http/handlers/HistoryHandler.java index c1fd0d3..a8909f3 100644 --- a/src/http/handlers/HistoryHandler.java +++ b/src/http/handlers/HistoryHandler.java @@ -22,7 +22,9 @@ public HistoryHandler(TaskManager taskManager) { @Override public void handle(HttpExchange exchange) throws IOException { + String path = exchange.getRequestURI().getPath(); String method = exchange.getRequestMethod(); + System.out.println("Request: " + method + " " + path); switch (method) { case "GET": { List history = taskManager.getHistory(); @@ -39,4 +41,4 @@ public void handle(HttpExchange exchange) throws IOException { } } } -} +} \ No newline at end of file diff --git a/src/http/handlers/PrioritizedHandler.java b/src/http/handlers/PrioritizedHandler.java index 4690ada..de10ba1 100644 --- a/src/http/handlers/PrioritizedHandler.java +++ b/src/http/handlers/PrioritizedHandler.java @@ -8,7 +8,6 @@ import tasks.Task; import java.io.IOException; -import java.util.List; import java.util.Set; public class PrioritizedHandler extends BaseHttpHandler implements HttpHandler { @@ -23,7 +22,9 @@ public PrioritizedHandler(TaskManager taskManager) { @Override public void handle(HttpExchange exchange) throws IOException { + String path = exchange.getRequestURI().getPath(); String method = exchange.getRequestMethod(); + System.out.println("Request: " + method + " " + path); switch (method) { case "GET": { Set history = taskManager.getprioritizedTasks(); @@ -40,4 +41,4 @@ public void handle(HttpExchange exchange) throws IOException { } } } -} +} \ No newline at end of file diff --git a/src/http/handlers/SubtaskHandler.java b/src/http/handlers/SubtaskHandler.java index ac007aa..0ff1a90 100644 --- a/src/http/handlers/SubtaskHandler.java +++ b/src/http/handlers/SubtaskHandler.java @@ -7,7 +7,6 @@ import http.HttpTaskServer; import managers.TaskManager; import tasks.Subtask; -import tasks.Task; import java.io.IOException; import java.util.List; @@ -51,21 +50,14 @@ public void handle(HttpExchange exchange) throws IOException { case "POST": { String body = readText(exchange); Subtask subtask = gson.fromJson(body, Subtask.class); - int subtaskId = subtask.getId(); - if (subtaskId > 0) { - taskManager.updateSubtask(subtask); - System.out.println("Обновили подзадачу с id: " + subtaskId); - exchange.sendResponseHeaders(200, -1); - } else { - try { - taskManager.addSubtask(subtask); - int addId = subtask.getId(); - System.out.println("Создали подзадачу с id: " + addId); - String response = gson.toJson(subtask); - sendText(exchange, response, 201); - } catch (TaskValidationException ex) { - sendHasOverlaps(exchange); - } + try { + taskManager.addSubtask(subtask); + int addId = subtask.getId(); + System.out.println("Создали подзадачу с id: " + addId); + String response = gson.toJson(subtask); + sendText(exchange, response, 201); + } catch (TaskValidationException ex) { + sendHasOverlaps(exchange); } break; } @@ -88,4 +80,4 @@ public void handle(HttpExchange exchange) throws IOException { e.printStackTrace(); } } -} +} \ No newline at end of file diff --git a/src/tasks/Epic.java b/src/tasks/Epic.java index f4ac60e..fc7fa4f 100644 --- a/src/tasks/Epic.java +++ b/src/tasks/Epic.java @@ -1,5 +1,6 @@ package tasks; +import java.time.Duration; import java.time.LocalDateTime; public class Epic extends Task { @@ -9,6 +10,10 @@ public Epic(String title, String description, TaskStatus status) { super(title, description, status); } + public Epic(String title, String description, TaskStatus status, Duration duration, LocalDateTime startTime) { + super(title, description, status, duration, startTime); + } + @Override public TaskType getType() { return TaskType.EPIC; diff --git a/test/HttpTaskManagerTasksTest.java b/test/httpTest/HttpHistoryTest.java similarity index 56% rename from test/HttpTaskManagerTasksTest.java rename to test/httpTest/HttpHistoryTest.java index d7152be..d442d20 100644 --- a/test/HttpTaskManagerTasksTest.java +++ b/test/httpTest/HttpHistoryTest.java @@ -1,10 +1,13 @@ +package httpTest; + import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; import http.HttpTaskServer; import managers.InMemoryTaskManager; import managers.TaskManager; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import tasks.Task; import tasks.TaskStatus; @@ -15,20 +18,19 @@ import java.net.http.HttpResponse; import java.time.Duration; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -public class HttpTaskManagerTasksTest { +public class HttpHistoryTest { - // создаём экземпляр InMemoryTaskManager TaskManager manager = new InMemoryTaskManager(); - // передаём его в качестве аргумента в конструктор HttpTaskServer HttpTaskServer taskServer = new HttpTaskServer(manager); Gson gson = HttpTaskServer.getGson(); - public HttpTaskManagerTasksTest() throws IOException { + public HttpHistoryTest() throws IOException { } @BeforeEach @@ -45,30 +47,28 @@ public void shutDown() { } @Test - public void testAddTask() throws IOException, InterruptedException { - // создаём задачу - Task task = new Task("Test 2", "Testing task 2", + public void testGetHistory() throws IOException, InterruptedException { + Task task1 = new Task("Test 1", "Testing task 1", + TaskStatus.NEW, Duration.ofMinutes(5), LocalDateTime.of(2025, 1, 1, + 10, 0)); + manager.addTask(task1); + Task task2 = new Task("Test 2", "Testing task 2", TaskStatus.NEW, Duration.ofMinutes(5), LocalDateTime.now()); - // конвертируем её в JSON - String taskJson = gson.toJson(task); + manager.addTask(task2); + manager.getTaskForId(task1.getId()); + manager.getTaskForId(task2.getId()); - // создаём HTTP-клиент и запрос HttpClient client = HttpClient.newHttpClient(); - URI url = URI.create("http://localhost:8080/tasks"); + URI url = URI.create("http://localhost:8080/history"); HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1) - .uri(url).POST(HttpRequest.BodyPublishers.ofString(taskJson)).build(); + .uri(url).GET().build(); - // вызываем рест, отвечающий за создание задач HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); - - // проверяем код ответа assertEquals(200, response.statusCode()); - // проверяем, что создалась одна задача с корректным именем - List tasksFromManager = manager.getTaskList(); + List tasksFromManager = gson.fromJson(response.body(), new TypeToken>(){}.getType()); assertNotNull(tasksFromManager, "Задачи не возвращаются"); - assertEquals(1, tasksFromManager.size(), "Некорректное количество задач"); - assertEquals("Test 2", tasksFromManager.get(0).getTitle(), "Некорректное имя задачи"); + assertEquals(2, tasksFromManager.size(), "Некорректное количество задач"); } } \ No newline at end of file diff --git a/test/httpTest/HttpPrioritizedTest.java b/test/httpTest/HttpPrioritizedTest.java new file mode 100644 index 0000000..960f9e8 --- /dev/null +++ b/test/httpTest/HttpPrioritizedTest.java @@ -0,0 +1,70 @@ +package httpTest; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import http.HttpTaskServer; +import managers.InMemoryTaskManager; +import managers.TaskManager; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import tasks.Task; +import tasks.TaskStatus; + +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.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class HttpPrioritizedTest { + TaskManager manager = new InMemoryTaskManager(); + HttpTaskServer taskServer = new HttpTaskServer(manager); + Gson gson = HttpTaskServer.getGson(); + + public HttpPrioritizedTest() throws IOException { + } + + @BeforeEach + public void setUp() { + manager.deleteTaskList(); + manager.deleteAllSubtask(); + manager.deleteAllEpic(); + taskServer.start(); + } + + @AfterEach + public void shutDown() { + taskServer.stop(); + } + + @Test + public void testGetPrioritized() throws IOException, InterruptedException { + Task task1 = new Task("Test 1", "Testing task 1", + TaskStatus.NEW, Duration.ofMinutes(5), LocalDateTime.of(2025, 1, 1, + 10, 0)); + manager.addTask(task1); + Task task2 = new Task("Test 2", "Testing task 2", + TaskStatus.NEW, Duration.ofMinutes(5), LocalDateTime.now()); + manager.addTask(task2); + + HttpClient client = HttpClient.newHttpClient(); + URI url = URI.create("http://localhost:8080/prioritized"); + HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1) + .uri(url).GET().build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + Set tasksFromManager = gson.fromJson(response.body(), new TypeToken>(){}.getType()); + + assertNotNull(tasksFromManager, "Задачи не возвращаются"); + assertEquals(2, tasksFromManager.size(), "Некорректное количество задач"); + } +} \ No newline at end of file diff --git a/test/httpTest/HttpTaskManagerEpicsTest.java b/test/httpTest/HttpTaskManagerEpicsTest.java new file mode 100644 index 0000000..c4f9868 --- /dev/null +++ b/test/httpTest/HttpTaskManagerEpicsTest.java @@ -0,0 +1,159 @@ +package httpTest; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import http.HttpTaskServer; +import managers.InMemoryTaskManager; +import managers.TaskManager; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import tasks.Epic; +import tasks.Subtask; +import tasks.TaskStatus; + +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.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +public class HttpTaskManagerEpicsTest { + + TaskManager manager = new InMemoryTaskManager(); + HttpTaskServer taskServer = new HttpTaskServer(manager); + Gson gson = HttpTaskServer.getGson(); + + public HttpTaskManagerEpicsTest() throws IOException { + } + + @BeforeEach + public void setUp() { + manager.deleteTaskList(); + manager.deleteAllSubtask(); + manager.deleteAllEpic(); + taskServer.start(); + } + + @AfterEach + public void shutDown() { + taskServer.stop(); + } + + @Test + public void testAddEpic() throws IOException, InterruptedException { + Epic epic1 = new Epic("Эпик1", "Описание 1",TaskStatus.NEW, null, null); + String taskJson = gson.toJson(epic1); + + HttpClient client = HttpClient.newHttpClient(); + URI url = URI.create("http://localhost:8080/epics"); + HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1) + .uri(url).POST(HttpRequest.BodyPublishers.ofString(taskJson)).build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(201, response.statusCode()); + + List tasksFromManager = manager.getEpicList(); + + assertNotNull(tasksFromManager, "Задачи не возвращаются"); + assertEquals(1, tasksFromManager.size(), "Некорректное количество задач"); + assertEquals("Эпик1", tasksFromManager.get(0).getTitle(), "Некорректное имя задачи"); + } + + @Test + public void testGetAllEpics() throws IOException, InterruptedException { + Epic epic1 = new Epic("Эпик1", "Описание 1",TaskStatus.NEW); + manager.addEpic(epic1); + Subtask subtask = new Subtask("подзадача", "тело", epic1.getId(), TaskStatus.NEW, + Duration.ofMinutes(5), LocalDateTime.now()); + manager.addSubtask(subtask); + + HttpClient client = HttpClient.newHttpClient(); + URI url = URI.create("http://localhost:8080/epics"); + HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1) + .uri(url).GET().build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + List tasksFromManager = gson.fromJson(response.body(), new TypeToken>(){}.getType()); + + assertNotNull(tasksFromManager, "Задачи не возвращаются"); + assertEquals(1, tasksFromManager.size(), "Некорректное количество задач"); + assertEquals("Эпик1", tasksFromManager.get(0).getTitle(), "Некорректное имя задачи"); + } + + @Test + public void testGetEpicForId() throws IOException, InterruptedException { + Epic epic1 = new Epic("Эпик1", "Описание 1",TaskStatus.NEW); + manager.addEpic(epic1); + Subtask subtask = new Subtask("подзадача", "тело", epic1.getId(), TaskStatus.NEW, + Duration.ofMinutes(5), LocalDateTime.now()); + manager.addSubtask(subtask); + int epicId = epic1.getId(); + + HttpClient client = HttpClient.newHttpClient(); + URI url = URI.create("http://localhost:8080/epics" + "/" + epicId); + HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1) + .uri(url).GET().build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + Epic taskFromManager = gson.fromJson(response.body(), new TypeToken() {}.getType()); + + assertEquals(epicId, taskFromManager.getId(), "Некорректный id"); + assertEquals("Эпик1", taskFromManager.getTitle(), "Некорректное имя задачи"); + } + + @Test + public void testDeleteEpicForId() throws IOException, InterruptedException { + Epic epic1 = new Epic("Эпик1", "Описание 1",TaskStatus.NEW); + manager.addEpic(epic1); + Subtask subtask = new Subtask("подзадача", "тело", epic1.getId(), TaskStatus.NEW, + Duration.ofMinutes(5), LocalDateTime.now()); + manager.addSubtask(subtask); + int epicId = epic1.getId(); + + HttpClient client = HttpClient.newHttpClient(); + URI url = URI.create("http://localhost:8080/epics" + "/" + epicId); + HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1) + .uri(url).DELETE().build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + Epic taskFromManager = manager.getEpicForId(epicId); + + assertNull(taskFromManager, "Задача не удалена"); + } + + @Test + public void testGetEpicSubtask() throws IOException, InterruptedException { + Epic epic1 = new Epic("Эпик1", "Описание 1",TaskStatus.NEW); + manager.addEpic(epic1); + Subtask subtask = new Subtask("подзадача", "тело", epic1.getId(), TaskStatus.NEW, + Duration.ofMinutes(5), LocalDateTime.now()); + manager.addSubtask(subtask); + int epicId = epic1.getId(); + + HttpClient client = HttpClient.newHttpClient(); + URI url = URI.create("http://localhost:8080/epics" + "/" + epicId + "/subtasks"); + HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1) + .uri(url).GET().build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + List tasksFromManager = gson.fromJson(response.body(), + new TypeToken>() {}.getType()); + + assertEquals(1, tasksFromManager.size(), "Некорректный id"); + } +} \ No newline at end of file diff --git a/test/httpTest/HttpTaskManagerSubtasksTest.java b/test/httpTest/HttpTaskManagerSubtasksTest.java new file mode 100644 index 0000000..8f5f23b --- /dev/null +++ b/test/httpTest/HttpTaskManagerSubtasksTest.java @@ -0,0 +1,139 @@ +package httpTest; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import http.HttpTaskServer; +import managers.InMemoryTaskManager; +import managers.TaskManager; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import tasks.Epic; +import tasks.Subtask; +import tasks.TaskStatus; + +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.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +public class HttpTaskManagerSubtasksTest { + TaskManager manager = new InMemoryTaskManager(); + HttpTaskServer taskServer = new HttpTaskServer(manager); + Gson gson = HttpTaskServer.getGson(); + + public HttpTaskManagerSubtasksTest() throws IOException { + } + + @BeforeEach + public void setUp() { + manager.deleteTaskList(); + manager.deleteAllSubtask(); + manager.deleteAllEpic(); + taskServer.start(); + } + + @AfterEach + public void shutDown() { + taskServer.stop(); + } + + @Test + public void testAddSubtask() throws IOException, InterruptedException { + Epic epic1 = new Epic("Эпик1", "Описание 1", TaskStatus.NEW, null, null); + manager.addEpic(epic1); + Subtask subtask = new Subtask("подзадача", "тело", epic1.getId(), TaskStatus.NEW, + Duration.ofMinutes(5), LocalDateTime.now()); + String taskJson = gson.toJson(subtask); + + HttpClient client = HttpClient.newHttpClient(); + URI url = URI.create("http://localhost:8080/subtasks"); + HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1) + .uri(url).POST(HttpRequest.BodyPublishers.ofString(taskJson)).build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(201, response.statusCode()); + + List tasksFromManager = manager.getAllSubtask(); + + assertNotNull(tasksFromManager, "Задачи не возвращаются"); + assertEquals(1, tasksFromManager.size(), "Некорректное количество задач"); + assertEquals("подзадача", tasksFromManager.get(0).getTitle(), "Некорректное имя задачи"); + } + + @Test + public void testGetAllSubtasks() throws IOException, InterruptedException { + Epic epic1 = new Epic("Эпик1", "Описание 1",TaskStatus.NEW); + manager.addEpic(epic1); + Subtask subtask = new Subtask("подзадача", "тело", epic1.getId(), TaskStatus.NEW, + Duration.ofMinutes(5), LocalDateTime.now()); + manager.addSubtask(subtask); + + HttpClient client = HttpClient.newHttpClient(); + URI url = URI.create("http://localhost:8080/subtasks"); + HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1) + .uri(url).GET().build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + List tasksFromManager = gson.fromJson(response.body(), + new TypeToken>(){}.getType()); + + assertNotNull(tasksFromManager, "Задачи не возвращаются"); + assertEquals(1, tasksFromManager.size(), "Некорректное количество задач"); + assertEquals("подзадача", tasksFromManager.get(0).getTitle(), "Некорректное имя задачи"); + } + + @Test + public void testGetSubtaskForId() throws IOException, InterruptedException { + Epic epic1 = new Epic("Эпик1", "Описание 1",TaskStatus.NEW); + manager.addEpic(epic1); + Subtask subtask = new Subtask("подзадача", "тело", epic1.getId(), TaskStatus.NEW, + Duration.ofMinutes(5), LocalDateTime.now()); + manager.addSubtask(subtask); + int subId = subtask.getId(); + + HttpClient client = HttpClient.newHttpClient(); + URI url = URI.create("http://localhost:8080/subtasks" + "/" + subId); + HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1) + .uri(url).GET().build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + Subtask taskFromManager = gson.fromJson(response.body(), new TypeToken() {}.getType()); + + assertEquals(subId, taskFromManager.getId(), "Некорректный id"); + assertEquals("подзадача", taskFromManager.getTitle(), "Некорректное имя задачи"); + } + + @Test + public void testDeleteSubtaskForId() throws IOException, InterruptedException { + Epic epic1 = new Epic("Эпик1", "Описание 1",TaskStatus.NEW); + manager.addEpic(epic1); + Subtask subtask = new Subtask("подзадача", "тело", epic1.getId(), TaskStatus.NEW, + Duration.ofMinutes(5), LocalDateTime.now()); + manager.addSubtask(subtask); + int subId = subtask.getId(); + + HttpClient client = HttpClient.newHttpClient(); + URI url = URI.create("http://localhost:8080/subtasks" + "/" + subId); + HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1) + .uri(url).DELETE().build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + Subtask taskFromManager = manager.getSubtaskForId(subId); + + assertNull(taskFromManager, "Задача не удалена"); + } +} \ No newline at end of file diff --git a/test/httpTest/HttpTaskManagerTasksTest.java b/test/httpTest/HttpTaskManagerTasksTest.java new file mode 100644 index 0000000..4e95bf5 --- /dev/null +++ b/test/httpTest/HttpTaskManagerTasksTest.java @@ -0,0 +1,130 @@ +package httpTest; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import http.HttpTaskServer; +import managers.InMemoryTaskManager; +import managers.TaskManager; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.AfterEach; +import tasks.Task; +import tasks.TaskStatus; + +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.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +public class HttpTaskManagerTasksTest { + + TaskManager manager = new InMemoryTaskManager(); + HttpTaskServer taskServer = new HttpTaskServer(manager); + Gson gson = HttpTaskServer.getGson(); + + public HttpTaskManagerTasksTest() throws IOException { + } + + @BeforeEach + public void setUp() { + manager.deleteTaskList(); + manager.deleteAllSubtask(); + manager.deleteAllEpic(); + taskServer.start(); + } + + @AfterEach + public void shutDown() { + taskServer.stop(); + } + + @Test + public void testAddTask() throws IOException, InterruptedException { + Task task = new Task("Test 1", "Testing task 1", + TaskStatus.NEW, Duration.ofMinutes(5), LocalDateTime.now()); + String taskJson = gson.toJson(task); + + HttpClient client = HttpClient.newHttpClient(); + URI url = URI.create("http://localhost:8080/tasks"); + HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1) + .uri(url).POST(HttpRequest.BodyPublishers.ofString(taskJson)).build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(201, response.statusCode()); + + List tasksFromManager = manager.getTaskList(); + + assertNotNull(tasksFromManager, "Задачи не возвращаются"); + assertEquals(1, tasksFromManager.size(), "Некорректное количество задач"); + assertEquals("Test 1", tasksFromManager.get(0).getTitle(), "Некорректное имя задачи"); + } + + @Test + public void testGetAllTasks() throws IOException, InterruptedException { + Task task = new Task("Test 1", "Testing task 1", + TaskStatus.NEW, Duration.ofMinutes(5), LocalDateTime.now()); + manager.addTask(task); + + HttpClient client = HttpClient.newHttpClient(); + URI url = URI.create("http://localhost:8080/tasks"); + HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1) + .uri(url).GET().build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + List tasksFromManager = gson.fromJson(response.body(), new TypeToken>(){}.getType()); + + assertNotNull(tasksFromManager, "Задачи не возвращаются"); + assertEquals(1, tasksFromManager.size(), "Некорректное количество задач"); + assertEquals("Test 1", tasksFromManager.get(0).getTitle(), "Некорректное имя задачи"); + } + + @Test + public void testGetTaskForId() throws IOException, InterruptedException { + Task task = new Task("Test 1", "Testing task 1", + TaskStatus.NEW, Duration.ofMinutes(5), LocalDateTime.now()); + manager.addTask(task); + int taskId = task.getId(); + + HttpClient client = HttpClient.newHttpClient(); + URI url = URI.create("http://localhost:8080/tasks" + "/" + taskId); + HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1) + .uri(url).GET().build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + Task taskFromManager = gson.fromJson(response.body(), new TypeToken() {}.getType()); + + assertEquals(taskId, taskFromManager.getId(), "Некорректный id"); + assertEquals("Test 1", taskFromManager.getTitle(), "Некорректное имя задачи"); + } + + @Test + public void testDeleteTaskForId() throws IOException, InterruptedException { + Task task = new Task("Test 1", "Testing task 1", + TaskStatus.NEW, Duration.ofMinutes(5), LocalDateTime.now()); + manager.addTask(task); + int taskId = task.getId(); + + HttpClient client = HttpClient.newHttpClient(); + URI url = URI.create("http://localhost:8080/tasks" + "/" + taskId); + HttpRequest request = HttpRequest.newBuilder().version(HttpClient.Version.HTTP_1_1) + .uri(url).DELETE().build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + Task taskFromManager = manager.getTaskForId(taskId); + + assertNull(taskFromManager, "Задача не удалена"); + } +} \ No newline at end of file From 2327827cd0d357bc627f547acec60000ec2ef999 Mon Sep 17 00:00:00 2001 From: Denis Panasyuk Date: Wed, 1 Oct 2025 00:46:18 +0300 Subject: [PATCH 3/5] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20Checkstyle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/http/handlers/BaseHttpHandler.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/http/handlers/BaseHttpHandler.java b/src/http/handlers/BaseHttpHandler.java index db79411..0a2ea8f 100644 --- a/src/http/handlers/BaseHttpHandler.java +++ b/src/http/handlers/BaseHttpHandler.java @@ -7,6 +7,7 @@ import java.nio.charset.StandardCharsets; public class BaseHttpHandler{ + protected void sendText(HttpExchange h, String responseString, int responseCode) throws IOException { byte[] resp = responseString.getBytes(StandardCharsets.UTF_8); h.getResponseHeaders().set("Content-Type", "application/json;charset=utf-8"); From 222d8dd94c744f204238a95f32abefd65441fdce Mon Sep 17 00:00:00 2001 From: Denis Panasyuk Date: Wed, 1 Oct 2025 00:48:36 +0300 Subject: [PATCH 4/5] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20Checkstyle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/http/handlers/BaseHttpHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/http/handlers/BaseHttpHandler.java b/src/http/handlers/BaseHttpHandler.java index 0a2ea8f..72b7125 100644 --- a/src/http/handlers/BaseHttpHandler.java +++ b/src/http/handlers/BaseHttpHandler.java @@ -6,7 +6,7 @@ import java.io.OutputStream; import java.nio.charset.StandardCharsets; -public class BaseHttpHandler{ +public class BaseHttpHandler { protected void sendText(HttpExchange h, String responseString, int responseCode) throws IOException { byte[] resp = responseString.getBytes(StandardCharsets.UTF_8); From f2c07b2ec900ee685fdb6830bed811c0e33805e8 Mon Sep 17 00:00:00 2001 From: Denis Panasyuk Date: Wed, 1 Oct 2025 11:11:20 +0300 Subject: [PATCH 5/5] =?UTF-8?q?=D0=92=D0=BD=D0=B5=D1=81=D0=B5=D0=BD=D1=8B?= =?UTF-8?q?=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D1=81=D0=BE=D0=B3=D0=BB=D0=B0=D1=81=D0=BD=D0=BE=20?= =?UTF-8?q?=D1=80=D0=B5=D0=BA=D0=BE=D0=BC=D0=B5=D0=BD=D0=B4=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D1=8F=D0=BC.=20=D0=A1=D0=BE=D0=BA=D1=80=D0=B0=D1=89?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=B7=D0=B0=D0=B4=D0=B5=D0=B6=D1=80=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=BE=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B2=D0=BA=D0=B8?= =?UTF-8?q?=20=D1=81=D0=B5=D1=80=D0=B2=D0=B5=D1=80=D0=B0=20=D1=81=20200?= =?UTF-8?q?=D1=81=20=D0=B4=D0=BE=203=D1=81.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/http/HttpTaskServer.java | 2 +- src/http/adapters/DurationAdapter.java | 6 +++--- src/http/handlers/BaseHttpHandler.java | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/http/HttpTaskServer.java b/src/http/HttpTaskServer.java index 1af2101..6cdb7c5 100644 --- a/src/http/HttpTaskServer.java +++ b/src/http/HttpTaskServer.java @@ -45,7 +45,7 @@ public void start() { } public void stop() { - kanbanServer.stop(200); + kanbanServer.stop(3); } public static void main(String[] args) { diff --git a/src/http/adapters/DurationAdapter.java b/src/http/adapters/DurationAdapter.java index 86b6acf..002c1d9 100644 --- a/src/http/adapters/DurationAdapter.java +++ b/src/http/adapters/DurationAdapter.java @@ -7,9 +7,9 @@ import java.io.IOException; import java.time.Duration; -public class DurationAdapter extends TypeAdapter { +public class DurationAdapter extends TypeAdapter { @Override - public void write(JsonWriter jsonWriter, java.time.Duration duration) throws IOException { + public void write(JsonWriter jsonWriter, Duration duration) throws IOException { if (duration == null) { jsonWriter.nullValue(); } else { @@ -18,7 +18,7 @@ public void write(JsonWriter jsonWriter, java.time.Duration duration) throws IOE } @Override - public java.time.Duration read(JsonReader jsonReader) throws IOException { + public Duration read(JsonReader jsonReader) throws IOException { if (jsonReader.peek() == com.google.gson.stream.JsonToken.NULL) { jsonReader.nextNull(); return null; diff --git a/src/http/handlers/BaseHttpHandler.java b/src/http/handlers/BaseHttpHandler.java index 72b7125..ee9b4b0 100644 --- a/src/http/handlers/BaseHttpHandler.java +++ b/src/http/handlers/BaseHttpHandler.java @@ -19,7 +19,7 @@ protected void sendText(HttpExchange h, String responseString, int responseCode) protected void sendNotFound(HttpExchange h) throws IOException { byte[] resp = "Not Found".getBytes(StandardCharsets.UTF_8); - h.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8"); + h.getResponseHeaders().add("Content-Type", "text/plain"); h.sendResponseHeaders(404, resp.length); h.getResponseBody().write(resp); h.close(); @@ -27,7 +27,7 @@ protected void sendNotFound(HttpExchange h) throws IOException { protected void sendHasOverlaps(HttpExchange h) throws IOException { byte[] resp = "Not Acceptable".getBytes(StandardCharsets.UTF_8); - h.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8"); + h.getResponseHeaders().add("Content-Type", "text/plain"); h.sendResponseHeaders(406, resp.length); h.getResponseBody().write(resp); h.close();