diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..869c305 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/.idea/libraries/gson_2_9_0.xml b/.idea/libraries/gson_2_9_0.xml new file mode 100644 index 0000000..2377008 --- /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 635e7f3..6982687 100644 --- a/java-kanban.iml +++ b/java-kanban.iml @@ -40,5 +40,6 @@ + \ No newline at end of file diff --git a/src/Main.java b/src/Main.java index a17bfa5..b3a2f0a 100644 --- a/src/Main.java +++ b/src/Main.java @@ -9,7 +9,7 @@ public class Main { - public static void main(String[] args) { + public static void main(String[] args) throws InterruptedException { final long MINUTES_IN_DAY = 60 * 24; final LocalDateTime TASK_START_TIME = LocalDateTime.now(); System.out.println("Поехали!"); diff --git a/src/tracker/adapter/LocalDateAdapter.java b/src/tracker/adapter/LocalDateAdapter.java new file mode 100644 index 0000000..976e3a5 --- /dev/null +++ b/src/tracker/adapter/LocalDateAdapter.java @@ -0,0 +1,23 @@ +package tracker.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 LocalDateAdapter extends TypeAdapter { + private static final DateTimeFormatter dtf = DateTimeFormatter.ISO_LOCAL_DATE_TIME; + + @Override + public void write(final JsonWriter jsonWriter, final LocalDateTime localDate) throws IOException { + jsonWriter.value(localDate.format(dtf)); + } + + @Override + public LocalDateTime read(final JsonReader jsonReader) throws IOException { + return LocalDateTime.parse(jsonReader.nextString(), dtf); + } +} diff --git a/src/tracker/controllers/InMemoryTaskManager.java b/src/tracker/controllers/InMemoryTaskManager.java index 4c6e9c5..794aaf3 100644 --- a/src/tracker/controllers/InMemoryTaskManager.java +++ b/src/tracker/controllers/InMemoryTaskManager.java @@ -1,5 +1,6 @@ package tracker.controllers; +import tracker.exceptions.OverlapsException; import tracker.model.Epic; import tracker.model.Status; import tracker.model.Subtask; @@ -134,26 +135,20 @@ public ArrayList getEpicsSubtasks(int epicId) { // Создание. Сам объект должен передаваться в качестве параметра. @Override public void createTask(Task task) { - if (noIntersectionWithTasks(task)) { - tasks.put(taskId, task); - sortedTasks.add(task); - taskId++; - } else { - System.out.println("Пересечение с текущими задачами"); - } + hasIntersectionWithTasks(task); + tasks.put(taskId, task); + sortedTasks.add(task); + taskId++; } @Override public void createSubtask(Subtask task) { - if (noIntersectionWithTasks(task)) { - subtasks.put(taskId, task); - sortedTasks.add(task); - updateEpicStatus(task.getEpic()); - updateEpicEndTimeAndDuration(task.getEpic()); - taskId++; - } else { - System.out.println("Пересечение с текущими задачами."); - } + hasIntersectionWithTasks(task); + subtasks.put(taskId, task); + sortedTasks.add(task); + updateEpicStatus(task.getEpic()); + updateEpicEndTimeAndDuration(task.getEpic()); + taskId++; } @Override @@ -169,13 +164,10 @@ public void updateTask(Task task) { if (updatedTask == null) { System.out.println("Задача с id = " + task.getId() + " не найдена"); } - if (noIntersectionWithTasks(task)) { - sortedTasks.remove(updatedTask); - tasks.put(task.getId(), task); - sortedTasks.add(task); - } else { - System.out.println("Пересечение с текущими задачами"); - } + hasIntersectionWithTasks(task); + sortedTasks.remove(updatedTask); + tasks.put(task.getId(), task); + sortedTasks.add(task); } @Override @@ -184,15 +176,12 @@ public void updateSubtask(Subtask task) { if (updatedTask == null) { System.out.println("Задача с id = " + task.getId() + " не найдена"); } - if (noIntersectionWithTasks(task)) { - sortedTasks.remove(updatedTask); - subtasks.put(task.getId(), task); - sortedTasks.add(task); - updateEpicStatus(task.getEpic()); - updateEpicEndTimeAndDuration(task.getEpic()); - } else { - System.out.println("Пересечение с текущими задачами"); - } + hasIntersectionWithTasks(task); + sortedTasks.remove(updatedTask); + subtasks.put(task.getId(), task); + sortedTasks.add(task); + updateEpicStatus(task.getEpic()); + updateEpicEndTimeAndDuration(task.getEpic()); } @Override @@ -303,12 +292,14 @@ private boolean intersectionChecked(T task1, T task2) { && (endTime1.isAfter(endTime2) || endTime1.isEqual(endTime2)); } - private boolean noIntersectionWithTasks(T task) { + private void hasIntersectionWithTasks(T task) { List intersectedTasks = sortedTasks.stream() .filter(currentTask -> !currentTask.equals(task)) .filter(currentTask -> intersectionChecked(task, currentTask)) .toList(); - return intersectedTasks.isEmpty(); + if (!intersectedTasks.isEmpty()) { + throw new OverlapsException("Есть пересечение с текущими задачами"); + } } } diff --git a/src/tracker/exceptions/OverlapsException.java b/src/tracker/exceptions/OverlapsException.java new file mode 100644 index 0000000..887d7a0 --- /dev/null +++ b/src/tracker/exceptions/OverlapsException.java @@ -0,0 +1,7 @@ +package tracker.exceptions; + +public class OverlapsException extends RuntimeException { + public OverlapsException(final String message) { + super(message); + } +} diff --git a/src/tracker/handler/BaseHttpHandler.java b/src/tracker/handler/BaseHttpHandler.java new file mode 100644 index 0000000..c3a310d --- /dev/null +++ b/src/tracker/handler/BaseHttpHandler.java @@ -0,0 +1,44 @@ +package tracker.handler; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import tracker.controllers.TaskManager; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +public abstract class BaseHttpHandler implements HttpHandler { + protected final Gson gson; + protected final TaskManager taskManager; + protected final Charset charset = StandardCharsets.UTF_8; + + public BaseHttpHandler(Gson gson, TaskManager taskManager) { + this.gson = gson; + this.taskManager = taskManager; + } + + public static void sendText(HttpExchange httpExchange, String text, int code) throws IOException { + byte[] response = text.getBytes(StandardCharsets.UTF_8); + httpExchange.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8"); + httpExchange.sendResponseHeaders(code, response.length); + httpExchange.getResponseBody().write(response); + httpExchange.close(); + } + + public static void sendNotFound(HttpExchange httpExchange) throws IOException { + httpExchange.sendResponseHeaders(404, 0); + httpExchange.close(); + } + + public static void sendHasOverlaps(HttpExchange httpExchange) throws IOException { + httpExchange.sendResponseHeaders(406, 0); + httpExchange.close(); + } + + public static void sendServerError(HttpExchange httpExchange) throws IOException { + httpExchange.sendResponseHeaders(500, 0); + httpExchange.close(); + } +} diff --git a/src/tracker/handler/EpicsHandler.java b/src/tracker/handler/EpicsHandler.java new file mode 100644 index 0000000..5b450fa --- /dev/null +++ b/src/tracker/handler/EpicsHandler.java @@ -0,0 +1,82 @@ +package tracker.handler; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import tracker.controllers.TaskManager; +import tracker.model.Epic; + +import java.io.IOException; +import java.io.InputStream; + +public class EpicsHandler extends BaseHttpHandler { + public EpicsHandler(Gson gson, TaskManager taskManager) { + super(gson, taskManager); + } + + @Override + public void handle(HttpExchange httpExchange) throws IOException { + String method = httpExchange.getRequestMethod(); + String path = httpExchange.getRequestURI().getPath(); + String[] partsOfPath = path.split("/"); + switch (method) { + case "GET" -> { + if (partsOfPath.length == 2) { + BaseHttpHandler.sendText(httpExchange, gson.toJson(taskManager.getEpics()), 200); + return; + } else if (partsOfPath.length == 3) { + int id = Integer.parseInt(partsOfPath[2]); + Epic epic = taskManager.getEpicById(id); + if (epic == null) { + BaseHttpHandler.sendNotFound(httpExchange); + } else { + BaseHttpHandler.sendText(httpExchange, gson.toJson(epic), 200); + } + } else if (partsOfPath.length == 4 && partsOfPath[3].equals("subtasks")) { + int id = Integer.parseInt(partsOfPath[2]); + Epic epic = taskManager.getEpicById(id); + if (epic == null) { + BaseHttpHandler.sendNotFound(httpExchange); + } else { + BaseHttpHandler.sendText(httpExchange, gson.toJson(taskManager.getEpicsSubtasks(id)), + 200); + } + } else { + BaseHttpHandler.sendServerError(httpExchange); + } + httpExchange.close(); + } + case "POST" -> { + if (partsOfPath.length == 2) { + InputStream inputStream = httpExchange.getRequestBody(); + String body = new String(inputStream.readAllBytes(), charset); + if (body.isEmpty()) { + BaseHttpHandler.sendServerError(httpExchange); + } else { + Epic epic = gson.fromJson(body, Epic.class); + taskManager.createEpic(epic); + BaseHttpHandler.sendText(httpExchange, gson.toJson(epic), 201); + } + } else { + BaseHttpHandler.sendServerError(httpExchange); + } + httpExchange.close(); + } + case "DELETE" -> { + if (partsOfPath.length == 3) { + int id = Integer.parseInt(partsOfPath[2]); + Epic epic = taskManager.getEpicById(id); + if (epic == null) { + BaseHttpHandler.sendNotFound(httpExchange); + } else { + taskManager.deleteEpic(epic); + BaseHttpHandler.sendText(httpExchange, gson.toJson(epic), 200); + } + } else { + BaseHttpHandler.sendServerError(httpExchange); + } + httpExchange.close(); + } + default -> BaseHttpHandler.sendServerError(httpExchange); + } + } +} diff --git a/src/tracker/handler/HistoryHandler.java b/src/tracker/handler/HistoryHandler.java new file mode 100644 index 0000000..d863443 --- /dev/null +++ b/src/tracker/handler/HistoryHandler.java @@ -0,0 +1,31 @@ +package tracker.handler; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import tracker.controllers.TaskManager; + +import java.io.IOException; + +public class HistoryHandler extends BaseHttpHandler { + public HistoryHandler(Gson gson, TaskManager taskManager) { + super(gson, taskManager); + } + + @Override + public void handle(HttpExchange httpExchange) throws IOException { + String method = httpExchange.getRequestMethod(); + String path = httpExchange.getRequestURI().getPath(); + String[] partsOfPath = path.split("/"); + if (method.equals("GET")) { + if (partsOfPath.length == 2) { + BaseHttpHandler.sendText(httpExchange, gson.toJson(taskManager.getHistory()), 200); + return; + } else { + BaseHttpHandler.sendServerError(httpExchange); + } + httpExchange.close(); + } else { + BaseHttpHandler.sendServerError(httpExchange); + } + } +} diff --git a/src/tracker/handler/PrioritizedHandler.java b/src/tracker/handler/PrioritizedHandler.java new file mode 100644 index 0000000..3615b4d --- /dev/null +++ b/src/tracker/handler/PrioritizedHandler.java @@ -0,0 +1,31 @@ +package tracker.handler; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import tracker.controllers.TaskManager; + +import java.io.IOException; + +public class PrioritizedHandler extends BaseHttpHandler { + public PrioritizedHandler(Gson gson, TaskManager taskManager) { + super(gson, taskManager); + } + + @Override + public void handle(HttpExchange httpExchange) throws IOException { + String method = httpExchange.getRequestMethod(); + String path = httpExchange.getRequestURI().getPath(); + String[] partsOfPath = path.split("/"); + if (method.equals("GET")) { + if (partsOfPath.length == 2) { + BaseHttpHandler.sendText(httpExchange, gson.toJson(taskManager.getPrioritizedTasks()), 200); + return; + } else { + BaseHttpHandler.sendServerError(httpExchange); + } + httpExchange.close(); + } else { + BaseHttpHandler.sendServerError(httpExchange); + } + } +} diff --git a/src/tracker/handler/SubtasksHandler.java b/src/tracker/handler/SubtasksHandler.java new file mode 100644 index 0000000..0016dcb --- /dev/null +++ b/src/tracker/handler/SubtasksHandler.java @@ -0,0 +1,93 @@ +package tracker.handler; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import tracker.controllers.TaskManager; +import tracker.exceptions.OverlapsException; +import tracker.model.Subtask; + +import java.io.IOException; +import java.io.InputStream; + +public class SubtasksHandler extends BaseHttpHandler { + public SubtasksHandler(Gson gson, TaskManager taskManager) { + super(gson, taskManager); + } + + @Override + public void handle(HttpExchange httpExchange) throws IOException { + String method = httpExchange.getRequestMethod(); + String path = httpExchange.getRequestURI().getPath(); + String[] partsOfPath = path.split("/"); + switch (method) { + case "GET" -> { + if (partsOfPath.length == 2) { + BaseHttpHandler.sendText(httpExchange, gson.toJson(taskManager.getSubtasks()), 200); + return; + } else if (partsOfPath.length == 3) { + int id = Integer.parseInt(partsOfPath[2]); + Subtask task = taskManager.getSubtaskById(id); + if (task == null) { + BaseHttpHandler.sendNotFound(httpExchange); + } else { + BaseHttpHandler.sendText(httpExchange, gson.toJson(task), 200); + } + } else { + BaseHttpHandler.sendServerError(httpExchange); + } + httpExchange.close(); + } + case "POST" -> { + if (partsOfPath.length == 2) { + InputStream inputStream = httpExchange.getRequestBody(); + String body = new String(inputStream.readAllBytes(), charset); + Subtask task = gson.fromJson(body, Subtask.class); + if (body.isEmpty()) { + BaseHttpHandler.sendServerError(httpExchange); + } else { + if (task.getId() != 0) { + try { + taskManager.updateSubtask(task); + } catch (OverlapsException e) { + BaseHttpHandler.sendHasOverlaps(httpExchange); + } + } else { + try { + taskManager.createSubtask(new Subtask(task.getName(), task.getDescription(), + taskManager.getTaskId(), task.getStatus(), task.getEpic(), task.getDuration(), + task.getStartTime())); + } catch (OverlapsException e) { + BaseHttpHandler.sendHasOverlaps(httpExchange); + } + } + BaseHttpHandler.sendText(httpExchange, gson.toJson(task), 201); + } + try { + taskManager.createSubtask(task); + } catch (OverlapsException e) { + BaseHttpHandler.sendHasOverlaps(httpExchange); + } + } else { + BaseHttpHandler.sendHasOverlaps(httpExchange); + } + httpExchange.close(); + } + case "DELETE" -> { + if (partsOfPath.length == 3) { + int id = Integer.parseInt(partsOfPath[2]); + Subtask task = taskManager.getSubtaskById(id); + if (task == null) { + BaseHttpHandler.sendNotFound(httpExchange); + } else { + taskManager.deleteSubtask(task); + BaseHttpHandler.sendText(httpExchange, gson.toJson(task), 200); + } + } else { + BaseHttpHandler.sendServerError(httpExchange); + } + httpExchange.close(); + } + default -> BaseHttpHandler.sendServerError(httpExchange); + } + } +} diff --git a/src/tracker/handler/TasksHandler.java b/src/tracker/handler/TasksHandler.java new file mode 100644 index 0000000..0f08596 --- /dev/null +++ b/src/tracker/handler/TasksHandler.java @@ -0,0 +1,88 @@ +package tracker.handler; + +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import tracker.controllers.TaskManager; +import tracker.exceptions.OverlapsException; +import tracker.model.Task; + +import java.io.IOException; +import java.io.InputStream; + +public class TasksHandler extends BaseHttpHandler { + public TasksHandler(Gson gson, TaskManager taskManager) { + super(gson, taskManager); + } + + @Override + public void handle(HttpExchange httpExchange) throws IOException { + String method = httpExchange.getRequestMethod(); + String path = httpExchange.getRequestURI().getPath(); + String[] partsOfPath = path.split("/"); + switch (method) { + case "GET" -> { + if (partsOfPath.length == 2) { + BaseHttpHandler.sendText(httpExchange, gson.toJson(taskManager.getTasks()), 200); + return; + } else if (partsOfPath.length == 3) { + int id = Integer.parseInt(partsOfPath[2]); + Task task = taskManager.getTaskById(id); + if (task == null) { + BaseHttpHandler.sendNotFound(httpExchange); + } else { + BaseHttpHandler.sendText(httpExchange, gson.toJson(task), 200); + } + } else { + BaseHttpHandler.sendServerError(httpExchange); + } + httpExchange.close(); + } + case "POST" -> { + if (partsOfPath.length == 2) { + InputStream inputStream = httpExchange.getRequestBody(); + String body = new String(inputStream.readAllBytes(), charset); + if (body.isEmpty()) { + BaseHttpHandler.sendServerError(httpExchange); + } else { + Task task = gson.fromJson(body, Task.class); + if (task.getId() != 0) { + try { + taskManager.updateTask(task); + } catch (OverlapsException e) { + BaseHttpHandler.sendHasOverlaps(httpExchange); + } + } else { + try { + taskManager.createTask(new Task(task.getName(), task.getDescription(), + taskManager.getTaskId(), task.getStatus(), task.getDuration(), + task.getStartTime())); + } catch (OverlapsException e) { + BaseHttpHandler.sendHasOverlaps(httpExchange); + } + } + BaseHttpHandler.sendText(httpExchange, gson.toJson(task), 201); + } + } else { + BaseHttpHandler.sendServerError(httpExchange); + } + httpExchange.close(); + } + case "DELETE" -> { + if (partsOfPath.length == 3) { + int id = Integer.parseInt(partsOfPath[2]); + Task task = taskManager.getTaskById(id); + if (task == null) { + BaseHttpHandler.sendNotFound(httpExchange); + } else { + taskManager.deleteTask(task); + BaseHttpHandler.sendText(httpExchange, gson.toJson(task), 200); + } + } else { + BaseHttpHandler.sendServerError(httpExchange); + } + httpExchange.close(); + } + default -> BaseHttpHandler.sendNotFound(httpExchange); + } + } +} diff --git a/src/tracker/server/HttpTaskServer.java b/src/tracker/server/HttpTaskServer.java new file mode 100644 index 0000000..1508e8e --- /dev/null +++ b/src/tracker/server/HttpTaskServer.java @@ -0,0 +1,76 @@ +package tracker.server; + +import com.google.gson.*; +import com.sun.net.httpserver.HttpServer; +import tracker.controllers.Managers; +import tracker.controllers.TaskManager; +import tracker.handler.*; +import tracker.model.Epic; +import tracker.adapter.LocalDateAdapter; +import tracker.model.Subtask; +import tracker.model.Task; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.time.LocalDateTime; + +public class HttpTaskServer { + final TaskManager taskManager; + + private final HttpServer httpServer; + + public HttpTaskServer(int port, TaskManager taskManager) throws IOException { + this.taskManager = taskManager; + Gson gson = new GsonBuilder() + .serializeNulls() + .registerTypeAdapter(LocalDateTime.class, new LocalDateAdapter()) + .create(); + + httpServer = HttpServer.create(); + httpServer.bind(new InetSocketAddress(port), 0); + httpServer.createContext("/tasks", new TasksHandler(gson, taskManager)); + httpServer.createContext("/subtasks", new SubtasksHandler(gson, taskManager)); + httpServer.createContext("/epics", new EpicsHandler(gson, taskManager)); + httpServer.createContext("/history", new HistoryHandler(gson, taskManager)); + httpServer.createContext("/prioritized", new PrioritizedHandler(gson, taskManager)); + } + + public static void main(String[] args) throws IOException { + final long MINUTES_IN_DAY = 60 * 24; + final LocalDateTime TASK_START_TIME = LocalDateTime.now(); + TaskManager inMemoryTaskManager = Managers.getDefault(); + HttpTaskServer taskServer = new HttpTaskServer(8080, inMemoryTaskManager); + taskServer.start(); + + // Создайте две задачи, а также эпик с двумя подзадачами и эпик с одной подзадачей + Task task1 = new Task("tracker.model.Task 1", "Do task 1", inMemoryTaskManager.getTaskId(), + MINUTES_IN_DAY, TASK_START_TIME.minusDays(4)); + inMemoryTaskManager.createTask(task1); + Task task2 = new Task("tracker.model.Task 2", "Do task 2", inMemoryTaskManager.getTaskId(), + MINUTES_IN_DAY, TASK_START_TIME.minusDays(3)); + inMemoryTaskManager.createTask(task2); + Epic epic1 = new Epic("tracker.model.Epic 1", "Do all subtasks from epic 1", + inMemoryTaskManager.getTaskId()); + inMemoryTaskManager.createEpic(epic1); + Epic epic2 = new Epic("tracker.model.Epic 2", "Do all subtasks from epic 2", + inMemoryTaskManager.getTaskId()); + inMemoryTaskManager.createEpic(epic2); + Subtask subtask1 = new Subtask("tracker.model.Subtask 1", "Do subtask 1", inMemoryTaskManager.getTaskId(), + epic1, MINUTES_IN_DAY, TASK_START_TIME.minusDays(2)); + inMemoryTaskManager.createSubtask(subtask1); + Subtask subtask2 = new Subtask("tracker.model.Subtask 2", "Do subtask 2", inMemoryTaskManager.getTaskId(), + epic1, MINUTES_IN_DAY, TASK_START_TIME.minusDays(1)); + inMemoryTaskManager.createSubtask(subtask2); + Subtask subtask3 = new Subtask("tracker.model.Subtask 3", "Do subtask 3", inMemoryTaskManager.getTaskId(), + epic2, MINUTES_IN_DAY, TASK_START_TIME); + inMemoryTaskManager.createSubtask(subtask3); + } + + public void start() { + httpServer.start(); + } + + public void stop() { + httpServer.stop(0); + } +} diff --git a/test/tracker/HttpTaskManagerTasksTest.java b/test/tracker/HttpTaskManagerTasksTest.java new file mode 100644 index 0000000..a737518 --- /dev/null +++ b/test/tracker/HttpTaskManagerTasksTest.java @@ -0,0 +1,217 @@ +package tracker; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.AfterEach; +import tracker.controllers.InMemoryTaskManager; +import tracker.controllers.TaskManager; +import tracker.model.Epic; +import tracker.model.Subtask; +import tracker.model.Task; +import tracker.server.HttpTaskServer; + +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.LocalDateTime; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +public class HttpTaskManagerTasksTest { + + TaskManager taskManager = new InMemoryTaskManager(); + HttpTaskServer taskServer = new HttpTaskServer(8080, taskManager); + + final long MINUTES_IN_DAY = 60 * 24; + final LocalDateTime TASK_START_TIME = LocalDateTime.now(); + + public HttpTaskManagerTasksTest() throws IOException { + } + + @BeforeEach + public void setUp() { + taskServer.start(); + } + + @AfterEach + public void shutDown() { + taskServer.stop(); + } + + @Test + public void testTasks() throws IOException, InterruptedException { + String task1Json = "{\"name\":\"Task 1\",\"description\":\"Do task 1\",\"status\":\"NEW\"" + + ",\"duration\":" + MINUTES_IN_DAY + ",\"startTime\": \"" + TASK_START_TIME.minusDays(4) + "\"}"; + String task2Json = "{\"name\":\"Task 2\",\"description\":\"Do task 2\",\"status\":\"NEW\"" + + ",\"duration\":" + MINUTES_IN_DAY + ",\"startTime\": \"" + TASK_START_TIME.minusDays(4) + "\"}"; + URI urlTasks = URI.create("http://localhost:8080/tasks"); + + HttpResponse response; + HttpRequest request; + + // 1. создаем 1 задачу + HttpClient client = HttpClient.newHttpClient(); + request = HttpRequest.newBuilder().uri(urlTasks).POST(HttpRequest.BodyPublishers.ofString(task1Json)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(201, response.statusCode()); + List tasksFromManager = taskManager.getTasks(); + + assertNotNull(tasksFromManager, "Список задач пуст"); + assertEquals(1, tasksFromManager.size(), "Некорректное количество задач"); + assertEquals("Task 1", tasksFromManager.get(0).getName(), "Некорректное имя задачи"); + + // 2. создаем 2 задачу + request = HttpRequest.newBuilder().uri(urlTasks).POST(HttpRequest.BodyPublishers.ofString(task2Json)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(406, response.statusCode()); + + task2Json = "{\"name\":\"Task 2\",\"description\":\"Do task 2\",\"status\":\"NEW\"" + + ",\"duration\":" + MINUTES_IN_DAY + ",\"startTime\": \"" + TASK_START_TIME.minusDays(3) + "\"}"; + request = HttpRequest.newBuilder().uri(urlTasks).POST(HttpRequest.BodyPublishers.ofString(task2Json)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(201, response.statusCode()); + + tasksFromManager = taskManager.getTasks(); + assertNotNull(tasksFromManager, "Список задач пуст"); + assertEquals(2, tasksFromManager.size(), "Некорректное количество задач"); + assertEquals("Task 1", tasksFromManager.get(0).getName(), "Некорректное имя задачи"); + assertEquals("Task 2", tasksFromManager.get(1).getName(), "Некорректное имя задачи"); + + // 3. удаляем 1 задачу + request = HttpRequest.newBuilder().uri(URI.create("http://localhost:8080/tasks/1")).DELETE() + .build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + tasksFromManager = taskManager.getTasks(); + assertNotNull(tasksFromManager, "Список задач пуст"); + assertEquals(1, tasksFromManager.size(), "Некорректное количество задач"); + assertEquals("Task 2", tasksFromManager.get(0).getName(), "Некорректное имя задачи"); + + // 4. удаляем 2 задачу + request = HttpRequest.newBuilder().uri(URI.create("http://localhost:8080/tasks/2")).DELETE() + .build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + tasksFromManager = taskManager.getTasks(); + assertEquals(0, tasksFromManager.size(), "Некорректное количество задач"); + } + + @Test + public void checkEpicsAndSubtasks() throws IOException, InterruptedException { + String epic1Json = "{\"endTime\":\"1970-01-01T00:00:00\",\"emptyDateTime\":\"1970-01-01T00:00:00\"" + + ",\"name\":\"Epic 1\",\"description\":\"Do all subtasks from epic 1\",\"id\":1,\"status\":null" + + ",\"duration\":0,\"startTime\":\"1970-01-01T00:00:00\"}"; + String epic2Json = "{\"endTime\":\"1970-01-01T00:00:00\",\"emptyDateTime\":\"1970-01-01T00:00:00\"" + + ",\"name\":\"Epic 2\",\"description\":\"Do all subtasks from epic 2\",\"id\":2,\"status\":null" + + ",\"duration\":0,\"startTime\":\"1970-01-01T00:00:00\"}"; + String subtask1Json = "{\"epic\":{\"endTime\":\"1970-01-01T00:00:00\",\"emptyDateTime\":\"1970-01-01T00:00:00\"" + + ",\"name\":\"Epic 1\",\"description\":\"Do all subtasks from epic 1\",\"id\":1,\"status\":null" + + ",\"duration\":0,\"startTime\":\"1970-01-01T00:00:00\"},\"name\":\"Subtask 1\"" + + ",\"description\":\"Do subtask 1\",\"status\":\"NEW\",\"duration\":" + MINUTES_IN_DAY + + ",\"startTime\":\"" + TASK_START_TIME.minusDays(3) + "\"}"; + String subtask2Json = "{\"epic\":{\"endTime\":\"1970-01-01T00:00:00\",\"emptyDateTime\":\"1970-01-01T00:00:00\"" + + ",\"name\":\"Epic 1\",\"description\":\"Do all subtasks from epic 1\",\"id\":1,\"status\":null" + + ",\"duration\":0,\"startTime\":\"1970-01-01T00:00:00\"},\"name\":\"Subtask 2\"" + + ",\"description\":\"Do subtask 2\",\"status\":\"NEW\",\"duration\":" + MINUTES_IN_DAY + + ",\"startTime\":\"" + TASK_START_TIME.minusDays(2) + "\"}"; + String subtask3Json = "{\"epic\":{\"endTime\":\"1970-01-01T00:00:00\",\"emptyDateTime\":\"1970-01-01T00:00:00\"" + + ",\"name\":\"Epic 2\",\"description\":\"Do all subtasks from epic 2\",\"id\":2,\"status\":null" + + ",\"duration\":0,\"startTime\":\"1970-01-01T00:00:00\"},\"name\":\"Subtask 3\"" + + ",\"description\":\"Do subtask 3\",\"status\":\"NEW\",\"duration\":" + MINUTES_IN_DAY + + ",\"startTime\":\"" + TASK_START_TIME.minusDays(2) + "\"}"; + + URI urlEpics = URI.create("http://localhost:8080/epics"); + URI urlSubtasks = URI.create("http://localhost:8080/subtasks"); + + HttpRequest request; + HttpResponse response; + // 1. Создаем эпики + HttpClient client = HttpClient.newHttpClient(); + request = HttpRequest.newBuilder().uri(urlEpics).POST(HttpRequest.BodyPublishers.ofString(epic1Json)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(201, response.statusCode()); + + request = HttpRequest.newBuilder().uri(urlEpics).POST(HttpRequest.BodyPublishers.ofString(epic2Json)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(201, response.statusCode()); + + List epicsFromManager = taskManager.getEpics(); + + assertNotNull(epicsFromManager, "Список задач пуст"); + assertEquals(2, epicsFromManager.size(), "Некорректное количество эпиков"); + assertEquals("Epic 1", epicsFromManager.get(0).getName(), "Некорректное имя эпика"); + assertEquals("Epic 2", epicsFromManager.get(1).getName(), "Некорректное имя эпика"); + + // 2. Создаем подзадачи + request = HttpRequest.newBuilder().uri(urlSubtasks).POST(HttpRequest.BodyPublishers.ofString(subtask1Json)) + .build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(201, response.statusCode()); + + request = HttpRequest.newBuilder().uri(urlSubtasks).POST(HttpRequest.BodyPublishers.ofString(subtask2Json)). + build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(201, response.statusCode()); + + request = HttpRequest.newBuilder().uri(urlSubtasks).POST(HttpRequest.BodyPublishers.ofString(subtask3Json)) + .build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(406, response.statusCode()); + + subtask3Json = "{\"epic\":{\"endTime\":\"1970-01-01T00:00:00\",\"emptyDateTime\":\"1970-01-01T00:00:00\"" + + ",\"name\":\"Epic 2\",\"description\":\"Do all subtasks from epic 2\",\"id\":2,\"status\":null" + + ",\"duration\":0,\"startTime\":\"1970-01-01T00:00:00\"},\"name\":\"Subtask 3\"" + + ",\"description\":\"Do subtask 3\",\"status\":\"NEW\",\"duration\":" + MINUTES_IN_DAY + + ",\"startTime\":\"" + TASK_START_TIME.minusDays(1) + "\"}"; + request = HttpRequest.newBuilder().uri(urlSubtasks).POST(HttpRequest.BodyPublishers.ofString(subtask3Json)) + .build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(201, response.statusCode()); + + List subtasksFromManager = taskManager.getSubtasks(); + + assertNotNull(subtasksFromManager, "Список задач пуст"); + assertEquals(3, subtasksFromManager.size(), "Некорректное количество подзадач"); + assertEquals("Subtask 1", subtasksFromManager.get(0).getName(), "Некорректное имя подзадачи"); + assertEquals("Subtask 2", subtasksFromManager.get(1).getName(), "Некорректное имя подзадачи"); + assertEquals("Subtask 3", subtasksFromManager.get(2).getName(), "Некорректное имя подзадачи"); + + // 3. удаляем подзадачи + request = HttpRequest.newBuilder().uri(URI.create("http://localhost:8080/subtasks/3")) + .DELETE().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + request = HttpRequest.newBuilder().uri(URI.create("http://localhost:8080/subtasks/4")) + .DELETE().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + request = HttpRequest.newBuilder().uri(URI.create("http://localhost:8080/subtasks/5")) + .DELETE().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + subtasksFromManager = taskManager.getSubtasks(); + assertEquals(0, subtasksFromManager.size(), "Некорректное количество задач"); + + // 4. удаляем эпики + request = HttpRequest.newBuilder().uri(URI.create("http://localhost:8080/epics/1")) + .DELETE().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + request = HttpRequest.newBuilder().uri(URI.create("http://localhost:8080/epics/2")) + .DELETE().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + epicsFromManager = taskManager.getEpics(); + assertEquals(0, epicsFromManager.size(), "Некорректное количество задач"); + } +} \ No newline at end of file diff --git a/test/tracker/controllers/FileBackedTaskManagerTest.java b/test/tracker/controllers/FileBackedTaskManagerTest.java index 63e270a..317a05a 100644 --- a/test/tracker/controllers/FileBackedTaskManagerTest.java +++ b/test/tracker/controllers/FileBackedTaskManagerTest.java @@ -31,7 +31,7 @@ void initializeTask() { @Override @Test - void checkEpic() { + void checkEpic() throws InterruptedException { super.checkEpic(); } @@ -44,7 +44,7 @@ void checkImportFromEmptyFile() { } @Test - void checkImportFromFile() { + void checkImportFromFile() throws InterruptedException { Task task1 = new Task("task 1", "task 1", 1, Status.NEW, MINUTES_IN_DAY, TASK_START_TIME.minusDays(4)); Task task2 = new Task("task 2", "task 2", 2, Status.NEW, MINUTES_IN_DAY, diff --git a/test/tracker/controllers/InMemoryHistoryManagerTest.java b/test/tracker/controllers/InMemoryHistoryManagerTest.java index 1e883d4..7e5d3e4 100644 --- a/test/tracker/controllers/InMemoryHistoryManagerTest.java +++ b/test/tracker/controllers/InMemoryHistoryManagerTest.java @@ -20,7 +20,7 @@ void initializeTask() { taskManager = Managers.getDefault(); } @Test - void checkInMemoryHistoryManager() { + void checkInMemoryHistoryManager() throws InterruptedException { Task task1 = new Task("Task 1", "Do task 1", taskManager.getTaskId(), MINUTES_IN_DAY, TASK_START_TIME.minusDays(4)); taskManager.createTask(task1); diff --git a/test/tracker/controllers/TaskManagerTest.java b/test/tracker/controllers/TaskManagerTest.java index 1db1a53..1383f47 100644 --- a/test/tracker/controllers/TaskManagerTest.java +++ b/test/tracker/controllers/TaskManagerTest.java @@ -1,6 +1,7 @@ package tracker.controllers; import org.junit.jupiter.api.Test; +import tracker.exceptions.OverlapsException; import tracker.model.Epic; import tracker.model.Status; import tracker.model.Subtask; @@ -17,7 +18,7 @@ abstract class TaskManagerTest { final LocalDateTime TASK_START_TIME = LocalDateTime.now(); @Test - void checkEpic() { + void checkEpic() throws InterruptedException { Task task1 = new Task("Task 1", "Do task 1", taskManager.getTaskId(), MINUTES_IN_DAY, TASK_START_TIME.minusDays(4)); taskManager.createTask(task1); @@ -48,7 +49,7 @@ void checkEpic() { } @Test - void checkEpicStatus() { + void checkEpicStatus() throws OverlapsException { // Все подзадачи со статусом NEW. Epic epic1 = new Epic("Epic 1", "Do all subtasks from epic 1", taskManager.getTaskId()); taskManager.createEpic(epic1); @@ -88,17 +89,20 @@ void checkEpicStatus() { } @Test - void checkTaskIntersection() { + void checkTaskIntersection() throws OverlapsException { // При наличии пересечения по времени выполнения задача не будет создана Task task1 = new Task("Task 1", "Do task 1", taskManager.getTaskId(), MINUTES_IN_DAY, TASK_START_TIME); taskManager.createTask(task1); Task task2 = new Task("Task 2", "Do task 2", taskManager.getTaskId(), MINUTES_IN_DAY, TASK_START_TIME); - taskManager.createTask(task2); - assertEquals(1, taskManager.getTaskById(task1.getId()).getId(), "Неверный Id"); - assertEquals(1, taskManager.getTasks().size(), "Неверное количество задач"); - task2.setStartTime(TASK_START_TIME.plusDays(1)); + try { + taskManager.createTask(task2); + } catch (OverlapsException e) { + assertEquals(1, taskManager.getTaskById(task1.getId()).getId(), "Неверный Id"); + assertEquals(1, taskManager.getTasks().size(), "Неверное количество задач"); + task2.setStartTime(TASK_START_TIME.plusDays(1)); + } taskManager.createTask(task2); assertEquals(2, taskManager.getTaskById(task2.getId()).getId(), "Неверный Id"); } diff --git a/test/tracker/model/SubtaskTest.java b/test/tracker/model/SubtaskTest.java index eb685ba..89a8f2f 100644 --- a/test/tracker/model/SubtaskTest.java +++ b/test/tracker/model/SubtaskTest.java @@ -20,7 +20,7 @@ void initializeTask() { } @Test - void checkSubtask() { + void checkSubtask() throws InterruptedException { Epic epic1 = new Epic("Epic 1", "Do all subtasks from epic 1", inMemoryTaskManager.getTaskId()); inMemoryTaskManager.createEpic(epic1); diff --git a/test/tracker/model/TaskTest.java b/test/tracker/model/TaskTest.java index 103526d..0177174 100644 --- a/test/tracker/model/TaskTest.java +++ b/test/tracker/model/TaskTest.java @@ -16,7 +16,7 @@ void initializeTask() { } @Test - void checkTask() { + void checkTask() throws InterruptedException { Task task1 = new Task("Task 1", "Do task 1", 1); inMemoryTaskManager.createTask(task1); Task task2 = new Task("Task 2", "Do task 2", 1);