diff --git a/.idea/libraries/gson_2_10_1.xml b/.idea/libraries/gson_2_10_1.xml new file mode 100644 index 0000000..ab53752 --- /dev/null +++ b/.idea/libraries/gson_2_10_1.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Insomnia_testTaskManager b/Insomnia_testTaskManager new file mode 100644 index 0000000..59444e1 --- /dev/null +++ b/Insomnia_testTaskManager @@ -0,0 +1 @@ +{"_type":"export","__export_format":4,"__export_date":"2024-12-13T18:57:08.076Z","__export_source":"insomnia.desktop.app:v10.2.0","resources":[{"_id":"req_ee4ebfbc33fd4b79b90ee424802fa8f0","parentId":"wrk_05194b500c0e48e38e0a11c82fa87a3c","modified":1734115048858,"created":1734076381249,"url":"http://localhost:8080/tasks","name":"/tasks","description":"","method":"GET","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/10.2.0"}],"authentication":{},"metaSortKey":-1734076418220,"isPrivate":false,"pathParameters":[],"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"wrk_05194b500c0e48e38e0a11c82fa87a3c","parentId":null,"modified":1734060176049,"created":1734060176049,"name":"Test","description":"","scope":"collection","_type":"workspace"},{"_id":"req_d77ad25d834548f9bcc8a1dc2aeb6033","parentId":"wrk_05194b500c0e48e38e0a11c82fa87a3c","modified":1734115053291,"created":1734076418120,"url":"http://localhost:8080/tasks/n","name":"/tasks/n","description":"","method":"GET","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/10.2.0"}],"authentication":{},"metaSortKey":-1734076418195,"isPrivate":false,"pathParameters":[],"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_63b3e431561540289577e0b6720478a9","parentId":"wrk_05194b500c0e48e38e0a11c82fa87a3c","modified":1734115072921,"created":1734101936571,"url":"http://localhost:8080/tasks","name":"/tasks","description":"","method":"POST","body":{"mimeType":"application/json","text":"\t{\n\t\t\"id\": 0,\n\t\t\"name\": \"Работа API1\",\n\t\t\"description\": \"Просто задача API1\",\n\t\t\"status\": \"NEW\",\n\t\t\"startTime\": \"01.05.2024 10:30:00.000\",\n\t\t\"durationTask\": \"PT50M\",\n\t\t\"endTime\": \"01.05.2024 10:55:00.000\"\n\t}\n"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/10.2.0"}],"authentication":{},"metaSortKey":-1734076418170,"isPrivate":false,"pathParameters":[],"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_93743d3cca5141748b3ece3043822c9a","parentId":"wrk_05194b500c0e48e38e0a11c82fa87a3c","modified":1734115124915,"created":1734115023700,"url":"http://localhost:8080/tasks/n","name":"/tasks/n","description":"","method":"POST","body":{"mimeType":"application/json","text":"\t{\n\t\t\"id\": 0,\n\t\t\"name\": \"Работа API\",\n\t\t\"description\": \"Просто задача API\",\n\t\t\"status\": \"IN_PROGRESS\",\n\t\t\"startTime\": \"01.05.2024 10:30:00.000\",\n\t\t\"durationTask\": \"PT50M\",\n\t\t\"endTime\": \"01.05.2024 10:55:00.000\"\n\t}\n"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/10.2.0"}],"authentication":{},"metaSortKey":-1734076418145,"isPrivate":false,"pathParameters":[],"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_7ae705c5dca8436786aa1f92b1b1d293","parentId":"wrk_05194b500c0e48e38e0a11c82fa87a3c","modified":1734109535859,"created":1734082256906,"url":"http://localhost:8080/tasks/n","name":"/tasks/n","description":"","method":"DELETE","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/10.2.0"}],"authentication":{},"metaSortKey":-1734076415815.5625,"isPrivate":false,"pathParameters":[],"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_0d93271327dc45f08981531f93ccb979","parentId":"wrk_05194b500c0e48e38e0a11c82fa87a3c","modified":1734082374532,"created":1734080250894,"url":"http://localhost:8080/subtasks","name":"/subtasks","description":"","method":"GET","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/10.2.0"}],"authentication":{},"metaSortKey":-1734076413511.125,"isPrivate":false,"pathParameters":[],"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_23d841ec7ad5498c822f67b0ce57506c","parentId":"wrk_05194b500c0e48e38e0a11c82fa87a3c","modified":1734115195379,"created":1734080264147,"url":"http://localhost:8080/subtasks/n","name":"/subtasks/n","description":"","method":"GET","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/10.2.0"}],"authentication":{},"metaSortKey":-1734076412935.0156,"isPrivate":false,"pathParameters":[],"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_47d29acc40f740f8bef4634c1fafcd31","parentId":"wrk_05194b500c0e48e38e0a11c82fa87a3c","modified":1734115361602,"created":1734115151688,"url":"http://localhost:8080/subtasks","name":"/subtasks","description":"","method":"POST","body":{"mimeType":"application/json","text":"\t{\n\t\t\"idEpic\": 5,\n\t\t\"id\": 0,\n\t\t\"name\": \"Попытка 6 API\",\n\t\t\"description\": \"Новая подзадача после загрузки API\",\n\t\t\"status\": \"NEW\",\n\t\t\"startTime\": \"01.02.2024 10:50:00.000\",\n\t\t\"durationTask\": \"PT1H\",\n\t\t\"endTime\": \"01.01.2024 11:50:00.000\"\n\t}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/10.2.0"}],"authentication":{},"metaSortKey":-1734076412790.9883,"isPrivate":false,"pathParameters":[],"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_b772aa46505e4de2a099d52b4a163352","parentId":"wrk_05194b500c0e48e38e0a11c82fa87a3c","modified":1734115432570,"created":1734115175179,"url":"http://localhost:8080/subtasks/9","name":"/subtasks/n","description":"","method":"POST","body":{"mimeType":"application/json","text":"\t{\n\t\t\"idEpic\": 5,\n\t\t\"id\": 0,\n\t\t\"name\": \"Попытка 6 API обновление\",\n\t\t\"description\": \"Новая подзадача после загрузки API изменение статуса\",\n\t\t\"status\": \"IN_PROGRESS\",\n\t\t\"startTime\": \"01.02.2024 10:50:00.000\",\n\t\t\"durationTask\": \"PT1H\",\n\t\t\"endTime\": \"01.01.2024 11:50:00.000\"\n\t}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/10.2.0"}],"authentication":{},"metaSortKey":-1734076412646.961,"isPrivate":false,"pathParameters":[],"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_0681feb005394c739009a229c0d2bfff","parentId":"wrk_05194b500c0e48e38e0a11c82fa87a3c","modified":1734085933083,"created":1734082267108,"url":"http://localhost:8080/subtasks/9","name":"/subtasks/n","description":"","method":"DELETE","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/10.2.0"}],"authentication":{},"metaSortKey":-1734076410630.5781,"isPrivate":false,"pathParameters":[],"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_6052151f581d4e1590d0ab868d495385","parentId":"wrk_05194b500c0e48e38e0a11c82fa87a3c","modified":1734082119181,"created":1734080401374,"url":"http://localhost:8080/epics","name":"/epic","description":"","method":"GET","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/10.2.0"}],"authentication":{},"metaSortKey":-1734076410054.4688,"isPrivate":false,"pathParameters":[],"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_38619b97c3b546f082294dea4311219e","parentId":"wrk_05194b500c0e48e38e0a11c82fa87a3c","modified":1734115587126,"created":1734080423768,"url":"http://localhost:8080/epics/n","name":"/epic/n","description":"","method":"GET","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/10.2.0"}],"authentication":{},"metaSortKey":-1734076409766.414,"isPrivate":false,"pathParameters":[],"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_3b38d3edd5544053b73bbe6f3018fa7c","parentId":"wrk_05194b500c0e48e38e0a11c82fa87a3c","modified":1734115609538,"created":1734080467028,"url":"http://localhost:8080/epics/n/subtasks","name":"/epic/n/subtasks","description":"","method":"GET","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/10.2.0"}],"authentication":{},"metaSortKey":-1734076409622.3867,"isPrivate":false,"pathParameters":[],"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_dc0221ebba8d44c69ee5965843ea7512","parentId":"wrk_05194b500c0e48e38e0a11c82fa87a3c","modified":1734115745614,"created":1734115537455,"url":"http://localhost:8080/epics","name":"/epic","description":"","method":"POST","body":{"mimeType":"application/json","text":"\t{\n\t\t\"id\": 0,\n\t\t\"name\": \"Новый эпик API\",\n\t\t\"description\": \"Получен через API\",\n\t\t\"status\": \"NEW\",\n\t\t\"startTime\": \"06.01.2024 12:00:00.000\",\n\t\t\"durationTask\": \"PT52H\",\n\t\t\"endTime\": \"08.01.2024 15:00:00.000\"\n\t}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/10.2.0"}],"authentication":{},"metaSortKey":-1734076409478.3594,"isPrivate":false,"pathParameters":[],"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_8c6e9c9bd0bd49629663386a164055e3","parentId":"wrk_05194b500c0e48e38e0a11c82fa87a3c","modified":1734115859430,"created":1734115567327,"url":"http://localhost:8080/epics/10","name":"/epic/n","description":"","method":"POST","body":{"mimeType":"application/json","text":"\t{\n\t\t\"id\": 10,\n\t\t\"name\": \"Новый эпик API обновление\",\n\t\t\"description\": \"Изменяется только название и описание\",\n\t\t\"status\": \"NEW\",\n\t\t\"startTime\": \"06.01.2024 12:00:00.000\",\n\t\t\"durationTask\": \"PT52H\",\n\t\t\"endTime\": \"08.01.2024 15:00:00.000\"\n\t}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/10.2.0"}],"authentication":{},"metaSortKey":-1734076407750.0312,"isPrivate":false,"pathParameters":[],"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_08f627a19b7b4a158a980cb18321d831","parentId":"wrk_05194b500c0e48e38e0a11c82fa87a3c","modified":1734085968506,"created":1734082286278,"url":"http://localhost:8080/epics/5","name":"/epic/n","description":"","method":"DELETE","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/10.2.0"}],"authentication":{},"metaSortKey":-1734076406597.8125,"isPrivate":false,"pathParameters":[],"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_1881cf394e93423b86538f3649b92080","parentId":"wrk_05194b500c0e48e38e0a11c82fa87a3c","modified":1734070242943,"created":1734070146327,"url":"http://localhost:8080/history","name":"/history","description":"","method":"GET","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/10.2.0"}],"authentication":{},"metaSortKey":-1734070146327,"isPrivate":false,"pathParameters":[],"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_06951da938d4402180313b11f2228ee1","parentId":"wrk_05194b500c0e48e38e0a11c82fa87a3c","modified":1734109303678,"created":1734060193604,"url":"http://localhost:8080/prioritized","name":"/prioritized","description":"","method":"GET","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/10.2.0"}],"authentication":{},"metaSortKey":-1734060193604,"isPrivate":false,"pathParameters":[],"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"env_594f54134db4f56865ca2a58d3ef279b7721e95e","parentId":"wrk_05194b500c0e48e38e0a11c82fa87a3c","modified":1734060176051,"created":1734060176051,"name":"Base Environment","data":{},"dataPropertyOrder":null,"color":null,"isPrivate":false,"metaSortKey":1734060176051,"environmentType":"kv","_type":"environment"},{"_id":"jar_594f54134db4f56865ca2a58d3ef279b7721e95e","parentId":"wrk_05194b500c0e48e38e0a11c82fa87a3c","modified":1734060176053,"created":1734060176053,"name":"Default Jar","cookies":[],"_type":"cookie_jar"}]} \ No newline at end of file diff --git a/README.md b/README.md index 911d410..d7c152d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,12 @@ _java-kanban_ # Трекер задач -### Согласно задания спринта № 8. +### Согласно задания спринта № 9. ## выполнено Филипповских Сергеем +В проекте в файле Insomnia_testTaskManager - шаблон для Insomnia для проведения тестов. +Получение списков, удаление и добавление новых объектов - вопросов нет. +При запросах на обновление в самом Json важно указывать существующий id, +он влияет на обработку и в строке запроса указывать его-же. + _**Когорта-53**_ diff --git a/java-kanban.iml b/java-kanban.iml index ff79d70..e9dd097 100644 --- a/java-kanban.iml +++ b/java-kanban.iml @@ -39,5 +39,6 @@ + \ No newline at end of file diff --git a/src/main/HTTPserver/BaseHttp.java b/src/main/HTTPserver/BaseHttp.java new file mode 100644 index 0000000..df875b1 --- /dev/null +++ b/src/main/HTTPserver/BaseHttp.java @@ -0,0 +1,108 @@ +package main.HTTPserver; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import com.sun.net.httpserver.HttpExchange; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Optional; + +// служебный класс с методами обработки запросов +class BaseHttp { + // Получение идентификатора задачи/подзадачи/эпика + static Optional getId(String id) { + try { + return Optional.of(Integer.parseInt(id)); + } catch (NumberFormatException exception) { + return Optional.empty(); + } + } + + // Получение и десериализация Json тела запроса -> в объекты + static T fromJsonString(HttpExchange exchange, Class clazz) throws IOException { + String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); + Gson gson = new GsonBuilder() + .setPrettyPrinting() + .serializeNulls() + .registerTypeAdapter(LocalDateTime.class, new LDTAdapter()) + .registerTypeAdapter(Duration.class, new DAdapter()) + .create(); + return gson.fromJson(body, clazz); + } + + // Сериализация объекта в JSON + static String toJsonString(Object object) { + Gson gson = new GsonBuilder() + .setPrettyPrinting() + .serializeNulls() + .registerTypeAdapter(LocalDateTime.class, new LDTAdapter()) + .registerTypeAdapter(Duration.class, new DAdapter()) + .create(); + return gson.toJson(object); + } + + // Адаптер для LocalDateTime + static class LDTAdapter extends TypeAdapter { + private static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss.SSS"); + + @Override + public void write(JsonWriter jsonWriter, LocalDateTime localDateTime) throws IOException { + if (localDateTime != null) { + jsonWriter.value(localDateTime.format(dtf)); + } else { + jsonWriter.nullValue(); + } + } + + @Override + public LocalDateTime read(final JsonReader jsonReader) throws IOException { + if (jsonReader.peek() != JsonToken.NULL) { + return LocalDateTime.parse(jsonReader.nextString(), dtf); + } else { + jsonReader.nextNull(); + return null; + } + } + } + + // Адаптер для Duration + static class DAdapter extends TypeAdapter { + @Override + public void write(JsonWriter jsonWriter, Duration duration) throws IOException { + if (duration != null) { + jsonWriter.value(duration.toString()); + } else { + jsonWriter.nullValue(); + } + } + + @Override + public Duration read(final JsonReader jsonReader) throws IOException { + if (jsonReader.peek() != JsonToken.NULL) { + return Duration.parse(jsonReader.nextString()); + } else { + jsonReader.nextNull(); + return null; + } + } + } + + // Отправка ответа на запрос + static void sendResponse(HttpExchange exchange, + String responseString, + int responseCode) throws IOException { + byte[] resp = responseString.getBytes(StandardCharsets.UTF_8); + exchange.getResponseHeaders().add("Content-Type", "application/json;charset=utf-8"); + exchange.sendResponseHeaders(responseCode, resp.length); + exchange.getResponseBody().write(resp); + exchange.close(); + } + +} diff --git a/src/main/HTTPserver/EpicHandler.java b/src/main/HTTPserver/EpicHandler.java new file mode 100644 index 0000000..710b50b --- /dev/null +++ b/src/main/HTTPserver/EpicHandler.java @@ -0,0 +1,81 @@ +package main.HTTPserver; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import main.classes.Epic; +import java.io.IOException; +import java.io.InputStream; + +import static main.HTTPserver.BaseHttp.*; +import static main.HTTPserver.HttpTaskServer.manager; + +// метод обработки ветки /epics +// в этой ветке не проводиться проверка на пересечение интервалов времени, остальное аналогично предыдущим обработкам +class EpicHandler implements HttpHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + String[] path = exchange.getRequestURI().getPath().split("/"); + String metod = exchange.getRequestMethod(); + InputStream body = exchange.getRequestBody(); + switch (metod) { + case "GET": + if (path.length <= 2) { + sendResponse(exchange, toJsonString(manager.getAllEpics()), 200); + } else { + if (getId(path[2]).isPresent()) { + Epic epic = manager.getEpic(getId(path[2]).get()); + if (epic != null) { + if (path.length == 3) { + sendResponse(exchange, + toJsonString(manager.getEpic(getId(path[2]).get())), + 200); + } else if (path[3].equals("subtasks")) { + sendResponse(exchange, + toJsonString(manager.getEpicSubTasks(getId(path[2]).get())), + 200); + } + } else { + sendResponse(exchange, + "Эпика с id = " + path[2] + " не существует !", 404); + } + break; + } + break; + } + break; + case "POST": + Epic task = fromJsonString(exchange, Epic.class); + if (path.length <= 2) { + manager.addEpic(task); + sendResponse(exchange, "Эпик добавлен !", 200); + break; + } else if (getId(path[2]).isPresent()) { + if (manager.updateEpic(task)) { + sendResponse(exchange, + "Эпик с id = " + task.getId() + " обновлен !", 201); + } else { + sendResponse(exchange, + "Эпик с id = " + path[2] + " не существует !", 404); + } + break; + } + break; + case "DELETE": + if (path.length > 2) { + if (getId(path[2]).isPresent()) { + if (manager.deleteEpic(getId(path[2]).get())) { + sendResponse(exchange, + "Эпик с id = " + path[2] + " удален !", 200); + } else { + sendResponse(exchange, + "Эпика с id = " + path[2] + " не существует !", 404); + } + break; + } + break; + } + break; + } + sendResponse(exchange, "Ошибка в запросе метода !", 400); + } +} diff --git a/src/main/HTTPserver/HistoryHandler.java b/src/main/HTTPserver/HistoryHandler.java new file mode 100644 index 0000000..5281c47 --- /dev/null +++ b/src/main/HTTPserver/HistoryHandler.java @@ -0,0 +1,18 @@ +package main.HTTPserver; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; + +import java.io.IOException; + +import static main.HTTPserver.BaseHttp.*; +import static main.HTTPserver.HttpTaskServer.manager; + +// метод обработки ветки /history +class HistoryHandler implements HttpHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + sendResponse(exchange, toJsonString(manager.getHistory()), 200); + } +} + diff --git a/src/main/HTTPserver/HttpTaskServer.java b/src/main/HTTPserver/HttpTaskServer.java new file mode 100644 index 0000000..567acab --- /dev/null +++ b/src/main/HTTPserver/HttpTaskServer.java @@ -0,0 +1,97 @@ +package main.HTTPserver; + +import com.sun.net.httpserver.HttpServer; +import main.classes.Epic; +import main.classes.Status; +import main.classes.SubTask; +import main.classes.Task; +import main.service.InMemoryTaskManager; +import main.service.Managers; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.time.Duration; +import java.time.LocalDateTime; + +public class HttpTaskServer { + + // создаём рабочие экземпляры менеджера задач и сервера + static InMemoryTaskManager manager; + private static HttpServer server; + + // создаём конструктор на тот случай, если класс будет запускаться не из самого класса, а созданием экземпляра + public HttpTaskServer(InMemoryTaskManager manager) { + this.manager = manager; + } + + public static void main(String[] args) throws IOException { + + // две заготовки для запуска внутри класса ... + + // Создаём менеджер задач на файловой основе + //File testFile; + //try { + // testFile = File.createTempFile("test", ".csv"); + //} catch (IOException e) { + // throw new ManagerSaveException("Не удалось создать временный файл"); + //} + //TaskManager taskManagerAPI = Managers.getFile(testFile); + + // Создаём менеджер задач в памяти + HttpTaskServer taskmanager = new HttpTaskServer(Managers.getDefault()); + // подгружаем тестовые данные + initTest(); + // запускаем сервер + taskmanager.run(); + + } + + // метод для запуска сервера из вне класса HttpTaskServer + public void run() throws IOException { + // настройка и запуск HTTP-сервера + server = HttpServer.create(new InetSocketAddress(8080), 0); + server.createContext("/tasks", new TasksHandler()); + server.createContext("/subtasks", new SubTaskHandler()); + server.createContext("/epics", new EpicHandler()); + server.createContext("/history", new HistoryHandler()); + server.createContext("/prioritized", new PrioritizedHandler()); + server.start(); // запускаем сервер + } + + // метод для остановки сервера из вне класса HttpTaskServer + public void stop() throws IOException { + server.stop(0); + } + + static void initTest() { + manager.addTask(new Task(0, + "Работа", "Просто задача", Status.NEW, + LocalDateTime.of(2024, 1, 1, 10, 5, 0), + Duration.ofMinutes(50))); + manager.addEpic(new Epic(0, + "Этапы", "Поэтапная работа", Status.NEW)); + manager.addSubTask(new SubTask(0, + "Этап 1", "Подготовка к работе", Status.NEW, 2, + LocalDateTime.of(2024, 1, 1, 8, 0, 0), + Duration.ofHours(23))); + manager.addTask(new Task(0, + "Отдых", "Поехать в отпуск", Status.NEW)); + manager.addEpic(new Epic(0, + "Обед", "Нужно утолить голод", Status.NEW)); + manager.addSubTask(new SubTask(0, + "Закупка", "Надо в магазин", Status.NEW, 5, + LocalDateTime.of(2024, 1, 8, 9, 0, 0), + Duration.ofHours(6))); + manager.addSubTask(new SubTask(0, + "Приготовление", "Немного постоять у плиты", Status.NEW, 5, + LocalDateTime.of(2024, 1, 6, 11, 0, 0), + Duration.ofHours(1))); + manager.addTask(new Task(0, + "Попытка 5", "Новая задача после загрузки", Status.NEW, + LocalDateTime.of(2024, 1, 6, 11, 40, 0), + Duration.ofHours(1))); + manager.addSubTask(new SubTask(0, + "Попытка 6", "Новая подзадача после загрузки", Status.NEW, 2, + LocalDateTime.of(2024, 1, 1, 10, 50, 0), + Duration.ofHours(1))); + } +} \ No newline at end of file diff --git a/src/main/HTTPserver/PrioritizedHandler.java b/src/main/HTTPserver/PrioritizedHandler.java new file mode 100644 index 0000000..4f72256 --- /dev/null +++ b/src/main/HTTPserver/PrioritizedHandler.java @@ -0,0 +1,18 @@ +package main.HTTPserver; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; + +import java.io.IOException; + +import static main.HTTPserver.BaseHttp.*; +import static main.HTTPserver.HttpTaskServer.manager; + +// метод обработки ветки /prioritized +class PrioritizedHandler implements HttpHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + sendResponse(exchange, toJsonString(manager.getPrioritizedTasks()), 200); + } +} + diff --git a/src/main/HTTPserver/SubTaskHandler.java b/src/main/HTTPserver/SubTaskHandler.java new file mode 100644 index 0000000..7cd7fe4 --- /dev/null +++ b/src/main/HTTPserver/SubTaskHandler.java @@ -0,0 +1,92 @@ +package main.HTTPserver; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import main.classes.SubTask; + +import java.io.IOException; + +import static main.HTTPserver.BaseHttp.*; +import static main.HTTPserver.HttpTaskServer.manager; + +// метод обработки ветки /subtasks +// обработка этой ветки аналогична обработке ветки /tasks +class SubTaskHandler implements HttpHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + String[] path = exchange.getRequestURI().getPath().split("/"); + String metod = exchange.getRequestMethod(); + switch (metod) { + case "GET": + if (path.length <= 2) { + sendResponse(exchange, + toJsonString(manager.getAllSubTasks()), + 200); + } else { + if (getId(path[2]).isPresent()) { + SubTask subtask = manager.getSubTask(getId(path[2]).get()); + if (subtask != null) { + sendResponse(exchange, + toJsonString(manager.getSubTask(getId(path[2]).get())), + 200); + } else { + sendResponse(exchange, + "Подзадачи с id = " + path[2] + " не существует !", + 404); + } + break; + } + break; + } + break; + case "POST": + SubTask task = fromJsonString(exchange, SubTask.class); + if (path.length <= 2) { + if (!manager.isOverlay(task)) { + manager.addSubTask(task); + sendResponse(exchange, "Подзадача добавлена !", 200); + } else { + sendResponse(exchange, + "Подзадача по времени выполнения пересекается с существующими задачами !", + 406); + } + break; + } else if (getId(path[2]).isPresent()) { + if (!manager.isOverlay(task)) { + if (manager.updateSubTask(task)) { + sendResponse(exchange, + "Подзадача с id = " + task.getId() + " обновлена !", + 201); + } else { + sendResponse(exchange, + "Подзадачи с id = " + path[2] + " не существует !", + 404); + } + } else { + sendResponse(exchange, + "Подзадача по времени выполнения пересекается с существующими задачами !", + 406); + break; + } + break; + } + break; + case "DELETE": + if (path.length > 2) { + if (getId(path[2]).isPresent()) { + if (manager.deleteSubTask(getId(path[2]).get())) { + sendResponse(exchange, + "Подзадача с id = " + path[2] + " удалена !", 200); + } else { + sendResponse(exchange, + "Подзадачи с id = " + path[2] + " не существует !", 404); + } + break; + } + break; + } + break; + } + sendResponse(exchange, "Ошибка в запросе метода !", 400); + } +} diff --git a/src/main/HTTPserver/TasksHandler.java b/src/main/HTTPserver/TasksHandler.java new file mode 100644 index 0000000..0e322fd --- /dev/null +++ b/src/main/HTTPserver/TasksHandler.java @@ -0,0 +1,108 @@ +package main.HTTPserver; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import main.classes.Task; + +import java.io.IOException; + +import static main.HTTPserver.BaseHttp.*; +import static main.HTTPserver.HttpTaskServer.manager; + +// метод обработки ветки /tasks +class TasksHandler implements HttpHandler { + + @Override + public void handle(HttpExchange exchange) throws IOException { + // получаем метод и парсим строку запроса в массив + String[] path = exchange.getRequestURI().getPath().split("/"); + String metod = exchange.getRequestMethod(); + // разделение на методы + switch (metod) { + case "GET": + // если в запросе только /tasks - отдаём все задачи + if (path.length <= 2) { + BaseHttp.sendResponse(exchange, + toJsonString(manager.getAllTasks()), + 200); + } else { + // если в запросе есть id - отдаём задачу по id, + // но только если преобразование id в int не приводит к ошибке + if (getId(path[2]).isPresent()) { + Task task = manager.getTask(getId(path[2]).get()); + // если с цифрой id нет проблем - то пробуем получить задачу по id + // если успешно - отдаём задачу, если нет - сообщаем + if (task != null) { + sendResponse(exchange, + toJsonString(manager.getTask(getId(path[2]).get())), + 200); + } else { + sendResponse(exchange, + "Задачи с id = " + path[2] + " не существует !", + 404); + } + break; + } + break; + } + break; + case "POST": + // преобразуем приходящий в теле запроса Json в объект Task + Task task = fromJsonString(exchange, Task.class); + // если в запросе только /tasks - добавляем задачу, + // предварительно проверяя пересечение интервалов времени + if (path.length <= 2) { + if (!manager.isOverlay(task)) { + manager.addTask(task); + sendResponse(exchange, "Задача добавлена !", 200); + } else { + sendResponse(exchange, + "Задача по времени выполнения пересекается с существующими задачами !", + 406); + } + break; + // если в запросе больше чем только /tasks + // проверяем - преобразование id в int не приводит к ошибке + } else if (getId(path[2]).isPresent()) { + // если с цифрой id нет проблем - то пробуем обновить задачу по id, + // предварительно проверяя пересечение интервалов времени, + // если успешно - обновляем задачу, если нет - сообщаем + if (!manager.isOverlay(task)) { + if (manager.updateTask(task)) { + sendResponse(exchange, "Задача с id = " + task.getId() + " обновлена !", + 201); + } else { + sendResponse(exchange, "Задачи с id = " + path[2] + " не существует !", + 404); + } + } else { + sendResponse(exchange, + "Задача по времени выполнения пересекается с существующими задачами !", + 406); + break; + } + break; + } + break; + case "DELETE": + // если для метода /delete есть id - удаляем задачу по id, + // предварительно проверяя правильность перевода id в int и наличие задачи по id + if (path.length > 2) { + if (getId(path[2]).isPresent()) { + if (manager.deleteTask(getId(path[2]).get())) { + sendResponse(exchange, "Задача с id = " + path[2] + " удалена !", + 200); + } else { + sendResponse(exchange, "Задачи с id = " + path[2] + " не существует !", + 404); + } + break; + } + break; + } + break; + } + // если в методах в строках запроса передаётся некорректные данные - отправляем ошибку + sendResponse(exchange, "Ошибка в запросе метода !", 400); + } +} diff --git a/src/main/Main.java b/src/main/Main.java index d794cf2..7e2a223 100644 --- a/src/main/Main.java +++ b/src/main/Main.java @@ -29,25 +29,25 @@ public static void main(String[] args) { // 1. Формируем тестовые данные System.out.println(); System.out.println(" = 1 == Формируем тестовые данные ==="); - exampleTM1.addTask(new Task(exampleTM1.getGlobalId(), + exampleTM1.addTask(new Task(0, "Работа", "Просто задача", Status.NEW, LocalDateTime.of(2024, 1, 1, 10, 5, 0), Duration.ofMinutes(50))); - exampleTM1.addEpic(new Epic(exampleTM1.getGlobalId(), + exampleTM1.addEpic(new Epic(0, "Этапы", "Поэтапная работа", Status.NEW)); - exampleTM1.addSubTask(new SubTask(exampleTM1.getGlobalId(), + exampleTM1.addSubTask(new SubTask(0, "Этап 1", "Подготовка к работе", Status.NEW, 2, LocalDateTime.of(2024, 1, 1, 8, 0, 0), Duration.ofHours(23))); - exampleTM1.addTask(new Task(exampleTM1.getGlobalId(), + exampleTM1.addTask(new Task(0, "Отдых", "Поехать в отпуск", Status.NEW)); - exampleTM1.addEpic(new Epic(exampleTM1.getGlobalId(), + exampleTM1.addEpic(new Epic(0, "Обед", "Нужно утолить голод", Status.NEW)); - exampleTM1.addSubTask(new SubTask(exampleTM1.getGlobalId(), + exampleTM1.addSubTask(new SubTask(0, "Закупка", "Надо в магазин", Status.NEW, 5, LocalDateTime.of(2024, 1, 8, 9, 0, 0), Duration.ofHours(6))); - exampleTM1.addSubTask(new SubTask(exampleTM1.getGlobalId(), + exampleTM1.addSubTask(new SubTask(0, "Приготовление", "Немного постоять у плиты", Status.NEW, 5, LocalDateTime.of(2024, 1, 6, 11, 0, 0), Duration.ofHours(1))); @@ -65,12 +65,6 @@ public static void main(String[] args) { System.out.println(exampleTM1.getHistory()); System.out.println("============================"); System.out.println(); - System.out.println("============================"); - System.out.println("============================"); - System.out.println(exampleTM1.getPrioritizedTasks()); - System.out.println("============================"); - System.out.println("============================"); - System.out.println(); // считываем файл в новый экземпляр менеджера задач и проводим проверки с ним TaskManager exampleTM2 = Managers.getFile(testFile); @@ -135,22 +129,16 @@ public static void main(String[] args) { exampleTM2.updateSubTask(new SubTask(3, "Этап 1", "Подготовка к работе", Status.DONE, 2)); System.out.println("стало - " + exampleTM2.getEpic(2)); - exampleTM2.addTask(new Task(exampleTM2.getGlobalId(), + exampleTM2.addTask(new Task(0, "Попытка 5", "Новая задача после загрузки", Status.NEW, LocalDateTime.of(2024, 1, 6, 11, 40, 0), Duration.ofHours(1))); - exampleTM2.addSubTask(new SubTask(exampleTM2.getGlobalId(), + exampleTM2.addSubTask(new SubTask(0, "Попытка 6", "Новая подзадача после загрузки", Status.NEW, 2, LocalDateTime.of(2024, 1, 1, 10, 50, 0), Duration.ofHours(1))); System.out.println("============================"); System.out.println(); - System.out.println("============================"); - System.out.println("============================"); - System.out.println(exampleTM2.getPrioritizedTasks()); - System.out.println("============================"); - System.out.println("============================"); - System.out.println(); // 5. Выводим информацию по эпику "Обед" по его id 8 // мне непонятно по ТЗ в каком виде должен быть этот список - есть два варианта diff --git a/src/main/classes/Status.java b/src/main/classes/Status.java index e149cab..ba468ff 100644 --- a/src/main/classes/Status.java +++ b/src/main/classes/Status.java @@ -1,5 +1,7 @@ package main.classes;// Задаём параметры состояний задач public enum Status { - NEW, IN_PROGRESS, DONE + NEW, + IN_PROGRESS, + DONE } diff --git a/src/main/classes/SubTask.java b/src/main/classes/SubTask.java index fbf8816..2aadc61 100644 --- a/src/main/classes/SubTask.java +++ b/src/main/classes/SubTask.java @@ -7,7 +7,7 @@ // Класс подзадач эпиков public class SubTask extends Task { - private final int idEpic; // Идентификатор родительского эпика + private int idEpic; // Идентификатор родительского эпика public SubTask(int id, String name, String description, Status status, int idEpic) { super(id, name, description, status); diff --git a/src/main/classes/Task.java b/src/main/classes/Task.java index 0588bbc..736c7e5 100644 --- a/src/main/classes/Task.java +++ b/src/main/classes/Task.java @@ -77,6 +77,14 @@ public void setDurationTask(Duration durationTask) { this.durationTask = durationTask; } + public void setEndTime() { + if (this.startTime != null && this.durationTask != null) { + this.endTime = this.startTime.plus(this.durationTask); + } else { + this.endTime = null; + } + } + public void setEndTime(LocalDateTime endTime) { this.endTime = endTime; } diff --git a/src/main/service/FileBackedTaskManager.java b/src/main/service/FileBackedTaskManager.java index a4cc800..7fc7a40 100644 --- a/src/main/service/FileBackedTaskManager.java +++ b/src/main/service/FileBackedTaskManager.java @@ -23,7 +23,7 @@ public File getFile() { return file; } - public void loadFromFile() { + private void loadFromFile() { // если файл существует, то считываем из него данные @@ -32,12 +32,9 @@ public void loadFromFile() { while (br.ready()) { String line = br.readLine(); Task loadTask = fromString(line); -/* - if (loadTask.getId() > globalId) { // если id больше чем globalId - присваиваем счётчику globalId значение id - globalId = loadTask.getId(); - } -*/ - globalId++; // увеличиваем счётчик globalId + + + // globalId++; // увеличиваем счётчик globalId switch (loadTask.getClass().getSimpleName()) { case "Task" -> addTask(loadTask); case "Epic" -> addEpic((Epic) loadTask); @@ -45,6 +42,10 @@ public void loadFromFile() { addSubTask((SubTask) loadTask); } } + // если id больше чем globalId - присваиваем счётчику globalId значение id + if (loadTask.getId() >= globalId) { + globalId = loadTask.getId() + 1; + } } } catch (IOException e) { throw new ManagerSaveException("Не удалось восстановить данные из файла или указанный файл не найден"); @@ -52,7 +53,7 @@ public void loadFromFile() { } } - public Task fromString(String value) { // метод обработки считываемой из файла строки + private Task fromString(String value) { // метод обработки считываемой из файла строки String[] str = value.split(","); int id = Integer.parseInt(str[0]); TypeTasks type = TypeTasks.valueOf(str[1]); @@ -62,7 +63,8 @@ public Task fromString(String value) { // метод обработки счит int idEpic = Integer.parseInt(str[5]); // определяем - если было записано с данными времени старта и длительности - if (!str[6].equals("0")) { - LocalDateTime startTime = LocalDateTime.parse(str[6], DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss")); + LocalDateTime startTime = LocalDateTime.parse(str[6], + DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss")); Duration duration = Duration.ofMinutes(Integer.parseInt(str[7])); switch (type) { case TASK -> { @@ -120,7 +122,7 @@ private void save() { } } - public String toString(Task task) { // метод формирования строки для файла + private String toString(Task task) { // метод формирования строки для файла String type = ""; int idEpic = 0; switch (task.getClass().getSimpleName()) { @@ -133,7 +135,8 @@ public String toString(Task task) { // метод формирования ст } return task.getId() + "," + type + "," + task.getName() + "," + task.getStatus() + "," + task.getDescription() + "," + idEpic + "," - + (task.getStartTime() == null ? "0" : task.getStartTime().format(DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss"))) + + (task.getStartTime() == null ? "0" : task.getStartTime() + .format(DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss"))) + "," + (task.getDurationTask() == null ? "0" : task.getDurationTask().toMinutes()); } diff --git a/src/main/service/InMemoryTaskManager.java b/src/main/service/InMemoryTaskManager.java index c38161d..d7c3a95 100644 --- a/src/main/service/InMemoryTaskManager.java +++ b/src/main/service/InMemoryTaskManager.java @@ -26,15 +26,21 @@ public int compare(Task o1, Task o2) { // добавляем задачу @Override - public void addTask(Task taskNew) { //добавляем задачу + public void addTask(Task taskNew) { + if (taskNew.getId() == 0) { + taskNew.setId(globalId++); + } task.put(taskNew.getId(), taskNew); - isOverlay(taskNew); + task.get(taskNew.getId()).setEndTime(); setPrioritizedTasks(taskNew); } // добавляем эпик @Override - public void addEpic(Epic epicNew) { //добавляем эпик + public void addEpic(Epic epicNew) { + if (epicNew.getId() == 0) { + epicNew.setId(globalId++); + } epic.put(epicNew.getId(), epicNew); } @@ -42,8 +48,11 @@ public void addEpic(Epic epicNew) { //добавляем эпик @Override public boolean addSubTask(SubTask subTaskNew) { if (epic.containsKey(subTaskNew.getIdEpic())) { + if (subTaskNew.getId() == 0) { + subTaskNew.setId(globalId++); + } subTask.put(subTaskNew.getId(), subTaskNew); - isOverlay(subTaskNew); + subTask.get(subTaskNew.getId()).setEndTime(); setPrioritizedTasks(subTaskNew); checkStatusEpic(subTaskNew.getIdEpic()); return true; @@ -177,6 +186,7 @@ public boolean deleteEpic(int id) { for (SubTask idEpic : getEpicSubTasks(id)) { subTask.remove(idEpic.getId()); history.remove(idEpic.getId()); + prioritizedTasks.remove(idEpic); } epic.remove(id); history.remove(id); @@ -206,12 +216,17 @@ public boolean updateTask(Task taskNew) { if (task.containsKey(taskNew.getId())) { // если id найдено в задачах - обновляем задачу task.put(taskNew.getId(), new Task(taskNew.getId(), - (taskNew.getName() == null ? task.get(taskNew.getId()).getName() : taskNew.getName()), - (taskNew.getDescription() == null ? task.get(taskNew.getId()).getDescription() : taskNew.getDescription()), - (taskNew.getStatus() == null ? task.get(taskNew.getId()).getStatus() : taskNew.getStatus()), - (taskNew.getStartTime() == null ? task.get(taskNew.getId()).getStartTime() : taskNew.getStartTime()), - (taskNew.getDurationTask() == null ? task.get(taskNew.getId()).getDurationTask() : taskNew.getDurationTask()))); - isOverlay(taskNew); + (taskNew.getName() == null ? + task.get(taskNew.getId()).getName() : taskNew.getName()), + (taskNew.getDescription() == null ? + task.get(taskNew.getId()).getDescription() : taskNew.getDescription()), + (taskNew.getStatus() == null ? + task.get(taskNew.getId()).getStatus() : taskNew.getStatus()), + (taskNew.getStartTime() == null ? + task.get(taskNew.getId()).getStartTime() : taskNew.getStartTime()), + (taskNew.getDurationTask() == null ? + task.get(taskNew.getId()).getDurationTask() : taskNew.getDurationTask()))); + task.get(taskNew.getId()).setEndTime(); setPrioritizedTasks(task.get(taskNew.getId())); return true; } else { // если id не найдено - возвращаем false @@ -224,13 +239,14 @@ public boolean updateEpic(Epic epicNew) { if (epic.containsKey(epicNew.getId())) { // если id найдено в эпиках - обновляем эпик epic.put(epicNew.getId(), new Epic(epicNew.getId(), - (epicNew.getName() == null ? epic.get(epicNew.getId()).getName() : epicNew.getName()), - (epicNew.getDescription() == null ? epic.get(epicNew.getId()).getDescription() : epicNew.getDescription()), - (epicNew.getStatus() == null ? epic.get(epicNew.getId()).getStatus() : epicNew.getStatus()), - (epicNew.getStartTime() == null ? epic.get(epicNew.getId()).getStartTime() : epicNew.getStartTime()), - (epicNew.getDurationTask() == null ? epic.get(epicNew.getId()).getDurationTask() : epicNew.getDurationTask()))); + (epicNew.getName() == null ? + epic.get(epicNew.getId()).getName() : epicNew.getName()), + (epicNew.getDescription() == null ? + epic.get(epicNew.getId()).getDescription() : epicNew.getDescription()), + (epic.get(epicNew.getId()).getStatus()), + (epic.get(epicNew.getId()).getStartTime()), + (epic.get(epicNew.getId()).getDurationTask()))); checkStatusEpic(epicNew.getId()); // поверяем статус эпика, чтобы откорректировать реальный статус - // на тот случай, если во входном эпике пришёл статус какой-либо return true; } else { // если id не найдено - возвращаем false return false; @@ -242,14 +258,20 @@ public boolean updateSubTask(SubTask subTaskNew) { if (subTask.containsKey(subTaskNew.getId())) { // если id найдено в подзадачах - обновляем подзадачу subTask.put(subTaskNew.getId(), new SubTask(subTaskNew.getId(), - (subTaskNew.getName() == null ? subTask.get(subTaskNew.getId()).getName() : subTaskNew.getName()), - (subTaskNew.getDescription() == null ? subTask.get(subTaskNew.getId()).getDescription() : subTaskNew.getDescription()), - (subTaskNew.getStatus() == null ? subTask.get(subTaskNew.getId()).getStatus() : subTaskNew.getStatus()), - (subTaskNew.getIdEpic() == 0 ? subTask.get(subTaskNew.getId()).getIdEpic() : subTaskNew.getIdEpic()), - (subTaskNew.getStartTime() == null ? subTask.get(subTaskNew.getId()).getStartTime() : subTaskNew.getStartTime()), - (subTaskNew.getDurationTask() == null ? subTask.get(subTaskNew.getId()).getDurationTask() : subTaskNew.getDurationTask()))); + (subTaskNew.getName() == null ? + subTask.get(subTaskNew.getId()).getName() : subTaskNew.getName()), + (subTaskNew.getDescription() == null ? + subTask.get(subTaskNew.getId()).getDescription() : subTaskNew.getDescription()), + (subTaskNew.getStatus() == null ? + subTask.get(subTaskNew.getId()).getStatus() : subTaskNew.getStatus()), + (subTaskNew.getIdEpic() == 0 ? + subTask.get(subTaskNew.getId()).getIdEpic() : subTaskNew.getIdEpic()), + (subTaskNew.getStartTime() == null ? + subTask.get(subTaskNew.getId()).getStartTime() : subTaskNew.getStartTime()), + (subTaskNew.getDurationTask() == null ? + subTask.get(subTaskNew.getId()).getDurationTask() : subTaskNew.getDurationTask()))); // после обновления подзадачи проводим проверку, как это повлияло на статус эпика этой задачи - isOverlay(subTaskNew); + subTask.get(subTaskNew.getId()).setEndTime(); setPrioritizedTasks(subTask.get(subTaskNew.getId())); checkStatusEpic(subTaskNew.getIdEpic()); return true; @@ -297,7 +319,8 @@ private void checkStatusEpic(int id) { .toList(); if (!listNotNull.isEmpty()) { epic.get(id).setStartTime(listNotNull.getFirst().getStartTime()); - epic.get(id).setDurationTask(Duration.between(listNotNull.getFirst().getStartTime(), listNotNull.getLast().getEndTime())); + epic.get(id).setDurationTask(Duration.between(listNotNull.getFirst().getStartTime(), + listNotNull.getLast().getEndTime())); epic.get(id).setEndTime(listNotNull.getLast().getEndTime()); } } @@ -335,7 +358,6 @@ public boolean isOverlay(Task checkTask) { && checkTask.getEndTime().isAfter(c.getEndTime())) ); } - System.out.println(ll + " пересечение - id: " + checkTask.getId() + " ! "); return ll; } } diff --git a/src/test/TestHttpApi.java b/src/test/TestHttpApi.java new file mode 100644 index 0000000..b699992 --- /dev/null +++ b/src/test/TestHttpApi.java @@ -0,0 +1,694 @@ +package test; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.TypeAdapter; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import main.classes.Epic; +import main.classes.Status; +import main.classes.SubTask; +import main.classes.Task; +import main.HTTPserver.HttpTaskServer; +import main.service.InMemoryTaskManager; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +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.time.format.DateTimeFormatter; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class TestHttpApi { + protected HttpTaskServer testserver; + protected InMemoryTaskManager taskManager; + + @BeforeEach + void initializeClass() throws IOException { + // создание и запуск сервера + taskManager = new InMemoryTaskManager(); + testserver = new HttpTaskServer(taskManager); + testserver.run(); + } + + @AfterEach + void shutdown() throws IOException { + testserver.stop(); + } + + // сами тесты + + @Test + void getAllItemsTaskAndSubTaskAndEpic() throws IOException, InterruptedException { + Gson gson = new GsonBuilder() + .setPrettyPrinting() + .serializeNulls() + .registerTypeAdapter(LocalDateTime.class, new LDTAdapter()) + .registerTypeAdapter(Duration.class, new DAdapter()) + .create(); // создаём объект Gson + + // подгружаем тестовые данные в трекер задач + initTest(taskManager); + + // создаём HTTP-клиент + HttpClient client = HttpClient.newHttpClient(); + // Создаём запросы на получение списков объектов и получаем ответы. + // Получаем список задач + URI url = URI.create("http://localhost:8080/tasks"); + HttpRequest request = HttpRequest.newBuilder().uri(url).GET().build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + List listTasks = gson.fromJson(response.body(), new TaskTypeToken().getType()); + // Получаем список эпиков + url = URI.create("http://localhost:8080/epics"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + List listEpics = gson.fromJson(response.body(), new EpicTypeToken().getType()); + // Получаем список подзадач + url = URI.create("http://localhost:8080/subtasks"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + List listSubTasks = gson.fromJson(response.body(), new SubTaskTypeToken().getType()); + + // проверяем, что мы получили 3 задачи, 4 подзадачи и 2 эпика + assertEquals(3, listTasks.size(), "Некорректное количество задач"); + assertEquals(4, listSubTasks.size(), "Некорректное количество подзадач"); + assertEquals(2, listEpics.size(), "Некорректное количество эпиков"); + } + + @Test + void getItemsOfId_GetByIdTaskAndSubTaskAndEpic() throws IOException, InterruptedException { + Gson gson = new GsonBuilder() + .setPrettyPrinting() + .serializeNulls() + .registerTypeAdapter(LocalDateTime.class, new LDTAdapter()) + .registerTypeAdapter(Duration.class, new DAdapter()) + .create(); // создаём объект Gson + + // подгружаем тестовые данные в трекер задач + initTest(taskManager); + + // создаём HTTP-клиент + HttpClient client = HttpClient.newHttpClient(); + // Создаём запросы на получение объектов по их id. + // Получаем список задач + URI url = URI.create("http://localhost:8080/tasks/8"); + HttpRequest request = HttpRequest.newBuilder().uri(url).GET().build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + Task task = gson.fromJson(response.body(), Task.class); + // Получаем список эпиков + url = URI.create("http://localhost:8080/epics/5"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + Epic epic = gson.fromJson(response.body(), Epic.class); + // Получаем список подзадач + url = URI.create("http://localhost:8080/subtasks/9"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + SubTask subTask = gson.fromJson(response.body(), SubTask.class); + + // проверяем, что мы через API получили те-же значения, что находятся и в трекере задач + assertEquals(task, + taskManager.getTask(8), "Несовпадение задач API с трекером задач"); + assertEquals(subTask, + taskManager.getSubTask(9), "Несовпадение подзадач API с трекером задач"); + assertEquals(epic, + taskManager.getEpic(5), "Несовпадение эпиков API с трекером задач"); + } + + @Test + void addItems_AddTaskAndSubTaskAndEpic() throws IOException, InterruptedException { + Gson gson = new GsonBuilder() + .setPrettyPrinting() + .serializeNulls() + .registerTypeAdapter(LocalDateTime.class, new LDTAdapter()) + .registerTypeAdapter(Duration.class, new DAdapter()) + .create(); // создаём объект Gson + + // создаём объекты для добавления. + Task task = new Task(0, "Задача 1", "Добавление задачи 1", + Status.NEW, LocalDateTime.now(), Duration.ofMinutes(5)); + Epic epic = new Epic(0, "Эпик 2", "Добавление эпика 2", + Status.NEW, LocalDateTime.now(), Duration.ofMinutes(5)); + SubTask subTask = new SubTask(0, "Подзадача 3", "Добавление подзадачи 3", + Status.NEW, 2, + LocalDateTime.now().plusHours(1), Duration.ofMinutes(5)); + + // конвертируем их в JSON + String taskJson = gson.toJson(task); + String subTaskJson = gson.toJson(subTask); + String epicJson = gson.toJson(epic); + + // создаём HTTP-клиент + HttpClient client = HttpClient.newHttpClient(); + // Проверяем добавление задачи + URI url = URI.create("http://localhost:8080/tasks"); + HttpRequest request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(taskJson)).build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + // Проверяем добавление эпика + url = URI.create("http://localhost:8080/epics"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(epicJson)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + // Проверяем добавление подзадачи + url = URI.create("http://localhost:8080/subtasks"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subTaskJson)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + + // проверяем, что создались по одному объекту каждого типа и проверяем идентичность отправленного и полученного + List tasksFromManager = taskManager.getAllTasks(); + assertNotNull(tasksFromManager, "Задача не создалась"); + assertEquals(1, tasksFromManager.size(), "Некорректное количество задач"); + assertEquals(task.getName(), + tasksFromManager.getFirst().getName(), "Несовпадение отправленного и полученного"); + List subTaskFromManager = taskManager.getAllSubTasks(); + assertNotNull(subTaskFromManager, "Подзадача не создалась"); + assertEquals(1, subTaskFromManager.size(), "Некорректное количество подзадач"); + assertEquals(subTask.getName(), + subTaskFromManager.getFirst().getName(), "Несовпадение отправленного и полученного"); + List epicFromManager = taskManager.getAllEpics(); + assertNotNull(epicFromManager, "Эпик не создался"); + assertEquals(1, epicFromManager.size(), "Некорректное количество эпиков"); + assertEquals(epic.getName(), + epicFromManager.getFirst().getName(), "Несовпадение отправленного и полученного"); + } + + @Test + void updateItemsAndStatus_updateItemsByIdAndStatusEpicByStatusSubTasks() throws IOException, InterruptedException { + Gson gson = new GsonBuilder() + .setPrettyPrinting() + .serializeNulls() + .registerTypeAdapter(LocalDateTime.class, new LDTAdapter()) + .registerTypeAdapter(Duration.class, new DAdapter()) + .create(); // создаём объект Gson + + // создаём Эпик без указания начала и конца времени выполнения и две подзадачи этого эпика. + Epic epic = new Epic(0, "Эпик 1", "Добавление эпика 1", + Status.NEW, null, null); + SubTask subTask1 = new SubTask(0, "Подзадача 2", "Добавление подзадачи 2", + Status.NEW, 1, LocalDateTime.now(), Duration.ofMinutes(15)); + SubTask subTask2 = new SubTask(0, "Подзадача 3", "Добавление подзадачи 3", + Status.NEW, 1, LocalDateTime.now().plusHours(1), + Duration.ofMinutes(15)); + + // конвертируем их в JSON + String epicJson = gson.toJson(epic); + String subTaskJson1 = gson.toJson(subTask1); + String subTaskJson2 = gson.toJson(subTask2); + + // создаём HTTP-клиент + HttpClient client = HttpClient.newHttpClient(); + // Добавляем эпик и задачи + URI url = URI.create("http://localhost:8080/epics"); + HttpRequest request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(epicJson)).build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + url = URI.create("http://localhost:8080/subtasks"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subTaskJson1)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + url = URI.create("http://localhost:8080/subtasks"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subTaskJson2)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + // Проверяем, что в трекере есть один эпик (1) и две подзадачи (3 и 4). Все они имеют статус NEW + assertEquals(Status.NEW, + taskManager.getEpic(1).getStatus(), "Статус эпика не New"); + assertEquals(Status.NEW, + taskManager.getSubTask(2).getStatus(), "Статус подзадачи не New"); + assertEquals(Status.NEW, + taskManager.getSubTask(3).getStatus(), "Статус подзадачи не New"); + // Проверяем, что время старта Эпика теперь равно времени старта первой подзадачи, + // а время завершения времени завершения второй. + assertEquals(taskManager.getSubTask(2).getStartTime(), + taskManager.getEpic(1).getStartTime(), + "Время старта эпика не равно времени старта первой подзадачи"); + assertEquals(taskManager.getSubTask(3).getEndTime(), + taskManager.getEpic(1).getEndTime(), + "Время завершения эпика не равно времени завершения второй подзадачи"); + // Вносим изменения в подзадачу 2, не изменяя время старта и продолжительность + subTask1 = new SubTask(2, "Изменения подзадачи 2", "Изменение подзадачи 2", + Status.IN_PROGRESS, 1, null, null); + subTaskJson1 = gson.toJson(subTask1); + url = URI.create("http://localhost:8080/subtasks/2"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subTaskJson1)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(201, response.statusCode()); + // Проверяем изменение названия и описания подзадачи и изменения статуса эпика на основе изменения статуса подзадачи + assertEquals(Status.IN_PROGRESS, + taskManager.getSubTask(2).getStatus(), "Статус подзадачи не IN_PROGRESS"); + assertEquals(Status.IN_PROGRESS, + taskManager.getEpic(1).getStatus(), "Статус эпика не IN_PROGRESS"); + assertEquals(subTask1.getName(), + taskManager.getSubTask(2).getName(), "Название подзадачи 2 не изменилось"); + // Изменяем статусы подзадач на Done без изменения названий, и изменяем время второй подзадачи. + subTask1 = new SubTask(2, null, null, + Status.DONE, 1, null, null); + subTask2 = new SubTask(3, null, null, + Status.DONE, 1, LocalDateTime.now().plusHours(3), + Duration.ofMinutes(30)); + subTaskJson1 = gson.toJson(subTask1); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subTaskJson1)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(201, response.statusCode()); + subTaskJson2 = gson.toJson(subTask2); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subTaskJson2)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(201, response.statusCode()); + // Проверяем изменения статусов подзадач и эпика, + // и соотвествие времени начала и завершения эпика, согласно новым данным подзадачи 3 + assertEquals(Status.DONE, + taskManager.getSubTask(2).getStatus(), "Статус подзадачи не DONE"); + assertEquals(Status.DONE, + taskManager.getSubTask(3).getStatus(), "Статус подзадачи не DONE"); + assertEquals(Status.DONE, + taskManager.getEpic(1).getStatus(), "Статус эпика не DONE"); + assertEquals(taskManager.getSubTask(2).getStartTime(), + taskManager.getEpic(1).getStartTime(), + "Время старта эпика не равно времени старта первой подзадачи"); + assertEquals(taskManager.getSubTask(3).getEndTime(), + taskManager.getEpic(1).getEndTime(), + "Время завершения эпика не равно времени завершения второй подзадачи"); + } + + @Test + void checkingOverlaysItems_ifTimeOccupiedByTask_cannotAddTaskThisTime() throws IOException, InterruptedException { + Gson gson = new GsonBuilder() + .setPrettyPrinting() + .serializeNulls() + .registerTypeAdapter(LocalDateTime.class, new LDTAdapter()) + .registerTypeAdapter(Duration.class, new DAdapter()) + .create(); // создаём объект Gson + + // создаём объекты для добавления. + Task task1 = new Task(0, "Задача 1", "Добавление задачи 1", + Status.NEW, LocalDateTime.now(), Duration.ofMinutes(120)); + SubTask subTask = new SubTask(0, "Подзадача 2", "Добавление подзадачи 2", + Status.NEW, 2, LocalDateTime.now().plusHours(6), + Duration.ofMinutes(30)); + Task task2 = new Task(0, "Задача 3", "Добавление задачи 3", + Status.NEW, LocalDateTime.now().plusHours(1), + Duration.ofMinutes(15)); + + // конвертируем их в JSON + String taskJson1 = gson.toJson(task1); + String taskJson2 = gson.toJson(task2); + String subTaskJson = gson.toJson(subTask); + + // создаём HTTP-клиент + HttpClient client = HttpClient.newHttpClient(); + // Проверяем добавление задачи 1 + URI url = URI.create("http://localhost:8080/tasks"); + HttpRequest request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(taskJson1)).build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + + // Проверяем добавление подзадачи 2 - время не пересекается с временем задачи 1 + url = URI.create("http://localhost:8080/subtasks"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subTaskJson)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + + // Проверяем добавление задачи 3 - тут время пересекается и код ответа должен быть 406 + url = URI.create("http://localhost:8080/tasks"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(taskJson2)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(406, response.statusCode()); + + // Вносим изменения времени в подзадачу и тоже получаем ответ 406 + subTask = new SubTask(2, "Изменения 2", "Изменения времени подзадачи 2", + Status.IN_PROGRESS, 2, LocalDateTime.now().plusMinutes(30), + Duration.ofMinutes(15)); + subTaskJson = gson.toJson(subTask); + url = URI.create("http://localhost:8080/subtasks/2"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subTaskJson)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(406, response.statusCode()); + } + + @Test + void deleteItems_DeleteTaskAndSubTaskAndEpics_correctlyDelete() throws IOException, InterruptedException { + // подгружаем тестовые данные в трекер задач + initTest(taskManager); + + // создаём HTTP-клиент + HttpClient client = HttpClient.newHttpClient(); + // Создаём запросы на удаление объектов по их id. + URI url = URI.create("http://localhost:8080/tasks/8"); + HttpRequest request = HttpRequest.newBuilder().uri(url).DELETE().build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + url = URI.create("http://localhost:8080/epics/5"); + request = HttpRequest.newBuilder().uri(url).DELETE().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + url = URI.create("http://localhost:8080/subtasks/9"); + request = HttpRequest.newBuilder().uri(url).DELETE().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + + // Создаём запросы на удаление объектов по их несуществующим id и получаем ответ 404 + url = URI.create("http://localhost:8080/tasks/18"); + request = HttpRequest.newBuilder().uri(url).DELETE().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(404, response.statusCode()); + url = URI.create("http://localhost:8080/epics/15"); + request = HttpRequest.newBuilder().uri(url).DELETE().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(404, response.statusCode()); + url = URI.create("http://localhost:8080/subtasks/19"); + request = HttpRequest.newBuilder().uri(url).DELETE().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(404, response.statusCode()); + + // проверяем, что количество задач, подзадач и эпиков уменьшилось согласно нашим действиям + // Задачи было 3 - станет 2 + // Подзадачи было 4 - станет 3 из-за удаления подзадачи + // Эпики было 2 - станет 1, но вместе с эпиком удалились 2 подзадачи, значит подзадач станет 1 + assertEquals(2, taskManager.getAllTasks().size(), "Неправильное количество задач"); + assertEquals(1, taskManager.getAllSubTasks().size(), "Неправильное количество подзадач"); + assertEquals(1, taskManager.getAllEpics().size(), "Неправильное количество эпиков"); + + } + + @Test + void getHistory_correctAddHistoryAndDeleteHistoryByDeleteTask() throws IOException, InterruptedException { + Gson gson = new GsonBuilder() + .setPrettyPrinting() + .serializeNulls() + .registerTypeAdapter(LocalDateTime.class, new LDTAdapter()) + .registerTypeAdapter(Duration.class, new DAdapter()) + .create(); // создаём объект Gson + + // подгружаем тестовые данные в трекер задач + initTest(taskManager); + + // создаём HTTP-клиент + HttpClient client = HttpClient.newHttpClient(); + + // Получаем историю действий + URI url = URI.create("http://localhost:8080/history"); + HttpRequest request = HttpRequest.newBuilder().uri(url).GET().build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + List listHistory = gson.fromJson(response.body(), new TaskTypeToken().getType()); + // проверяем, что в истории 2 записи при инициализации трекера задач + assertEquals(2, listHistory.size(), "История не пуста"); + + // Делаем 3 запроса на получение объекта по его id + url = URI.create("http://localhost:8080/tasks/8"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + url = URI.create("http://localhost:8080/subtasks/9"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + // Получаем историю действий + url = URI.create("http://localhost:8080/history"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + listHistory = gson.fromJson(response.body(), new TaskTypeToken().getType()); + // проверяем, что в истории плюс 2 позиции - 5 + assertEquals(4, listHistory.size(), "В истории некорректное количество записей"); + + // удаляем задачу, по которой был запрос и проверяем историю - + // удалённая задача должна выпасть из истории и там должно быть 2 записи. + url = URI.create("http://localhost:8080/tasks/8"); + request = HttpRequest.newBuilder().uri(url).DELETE().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + url = URI.create("http://localhost:8080/history"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + listHistory = gson.fromJson(response.body(), new TaskTypeToken().getType()); + // проверяем, что в истории 3 позиции + assertEquals(3, listHistory.size(), "В истории некорректное количество записей"); + } + + @Test + void getPrioritized_correctCreateListPriorityAndAutoReordering() throws IOException, InterruptedException { + Gson gson = new GsonBuilder() + .setPrettyPrinting() + .serializeNulls() + .registerTypeAdapter(LocalDateTime.class, new LDTAdapter()) + .registerTypeAdapter(Duration.class, new DAdapter()) + .create(); // создаём объект Gson + + // создаём объекты для добавления. + Task task1 = new Task(0, "Задача 1", "Добавление задачи 1", + Status.NEW, LocalDateTime.now().plusHours(2), + Duration.ofMinutes(15)); + Task task2 = new Task(0, "Задача 2", "Добавление задачи 2", + Status.NEW, LocalDateTime.now().plusHours(1), + Duration.ofMinutes(15)); + Epic epic3 = new Epic(0, "Эпик 3", "Добавление эпика 3", + Status.NEW, LocalDateTime.now(), Duration.ofMinutes(5)); + SubTask subTask4 = new SubTask(0, "Подзадача 4", "Добавление подзадачи 4", + Status.NEW, 3, LocalDateTime.now().plusHours(3), + Duration.ofMinutes(25)); + SubTask subTask5 = new SubTask(0, "Подзадача 5", "Добавление подзадачи 5", + Status.NEW, 3, LocalDateTime.now(), Duration.ofMinutes(35)); + + // конвертируем их в JSON + String taskJson1 = gson.toJson(task1); + String taskJson2 = gson.toJson(task2); + String epicJson3 = gson.toJson(epic3); + String subTaskJson4 = gson.toJson(subTask4); + String subTaskJson5 = gson.toJson(subTask5); + + // создаём HTTP-клиент + HttpClient client = HttpClient.newHttpClient(); + + // делаем запрос списка приоритета задач + URI url = URI.create("http://localhost:8080/prioritized"); + HttpRequest request = HttpRequest.newBuilder().uri(url).GET().build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + List listPrioritized = gson.fromJson(response.body(), new TaskTypeToken().getType()); + // проверяем, что в список пуст + assertEquals(0, listPrioritized.size(), "Список приоритета не пуст"); + + // Добавляем три элемента + url = URI.create("http://localhost:8080/tasks"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(taskJson1)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + url = URI.create("http://localhost:8080/tasks"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(taskJson2)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + url = URI.create("http://localhost:8080/epics"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(epicJson3)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + url = URI.create("http://localhost:8080/subtasks"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subTaskJson4)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + +// Снова запрашиваем список приоритета задач и проверяем что в нём 3 позиции + url = URI.create("http://localhost:8080/prioritized"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + listPrioritized = gson.fromJson(response.body(), new TaskTypeToken().getType()); + assertEquals(3, listPrioritized.size(), "Список не верен"); + // Проверяем правильность позиций списка + assertEquals(2, listPrioritized.get(0).getId(), "Первая задача не верна"); + assertEquals(1, listPrioritized.get(1).getId(), "Вторая задача не верна"); + assertEquals(4, listPrioritized.get(2).getId(), "Третья задача не верна"); + + // Добавляем ещё одну подзадачу и снова проверяем список и порядок в списке + url = URI.create("http://localhost:8080/subtasks"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subTaskJson5)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + url = URI.create("http://localhost:8080/prioritized"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + listPrioritized = gson.fromJson(response.body(), new TaskTypeToken().getType()); + assertEquals(4, listPrioritized.size(), "Список не верен"); + // Проверяем правильность позиций списка + assertEquals(5, listPrioritized.get(0).getId(), "Первая задача не верна"); + assertEquals(2, listPrioritized.get(1).getId(), "Первая задача не верна"); + assertEquals(1, listPrioritized.get(2).getId(), "Вторая задача не верна"); + assertEquals(4, listPrioritized.get(3).getId(), "Третья задача не верна"); + + // Удаляем эпик, а вместе с ним и 2 подзадачи. И снова проверяем список и порядок в списке + url = URI.create("http://localhost:8080/epics/3"); + request = HttpRequest.newBuilder().uri(url).DELETE().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + url = URI.create("http://localhost:8080/prioritized"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + listPrioritized = gson.fromJson(response.body(), new TaskTypeToken().getType()); + assertEquals(2, listPrioritized.size(), "Список не верен"); + // Проверяем правильность позиций списка + assertEquals(2, listPrioritized.get(0).getId(), "Первая задача не верна"); + assertEquals(1, listPrioritized.get(1).getId(), "Вторая задача не верна"); + } + + + void initTest(InMemoryTaskManager manager) { + manager.addTask(new Task(0, + "Работа", "Просто задача", Status.NEW, + LocalDateTime.of(2024, 1, 1, 10, 5, 0), + Duration.ofMinutes(50))); + manager.addEpic(new Epic(0, + "Этапы", "Поэтапная работа", Status.NEW)); + manager.addSubTask(new SubTask(0, + "Этап 1", "Подготовка к работе", Status.NEW, 2, + LocalDateTime.of(2024, 1, 1, 8, 0, 0), + Duration.ofHours(23))); + manager.addTask(new Task(0, + "Отдых", "Поехать в отпуск", Status.NEW)); + manager.addEpic(new Epic(0, + "Обед", "Нужно утолить голод", Status.NEW)); + manager.addSubTask(new SubTask(0, + "Закупка", "Надо в магазин", Status.NEW, 5, + LocalDateTime.of(2024, 1, 8, 9, 0, 0), + Duration.ofHours(6))); + manager.addSubTask(new SubTask(0, + "Приготовление", "Немного постоять у плиты", Status.NEW, 5, + LocalDateTime.of(2024, 1, 6, 11, 0, 0), + Duration.ofHours(1))); + manager.addTask(new Task(0, + "Попытка 5", "Новая задача после загрузки", Status.NEW, + LocalDateTime.of(2024, 1, 6, 11, 40, 0), + Duration.ofHours(1))); + manager.addSubTask(new SubTask(0, + "Попытка 6", "Новая подзадача после загрузки", Status.NEW, 2, + LocalDateTime.of(2024, 1, 1, 10, 50, 0), + Duration.ofHours(1))); + } + + // Адаптер для LocalDateTime + static class LDTAdapter extends TypeAdapter { + private static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss.SSS"); + + @Override + public void write(JsonWriter jsonWriter, LocalDateTime localDateTime) throws IOException { + if (localDateTime != null) { + jsonWriter.value(localDateTime.format(dtf)); + } else { + jsonWriter.nullValue(); + } + } + + @Override + public LocalDateTime read(final JsonReader jsonReader) throws IOException { + if (jsonReader.peek() != JsonToken.NULL) { + return LocalDateTime.parse(jsonReader.nextString(), dtf); + } else { + jsonReader.nextNull(); + return null; + } + } + } + + // Адаптер для Duration + static class DAdapter extends TypeAdapter { + @Override + public void write(JsonWriter jsonWriter, Duration duration) throws IOException { + if (duration != null) { + jsonWriter.value(duration.toString()); + } else { + jsonWriter.nullValue(); + } + } + + @Override + public Duration read(final JsonReader jsonReader) throws IOException { + if (jsonReader.peek() != JsonToken.NULL) { + return Duration.parse(jsonReader.nextString()); + } else { + jsonReader.nextNull(); + return null; + } + } + } + + // для разбора JSON + static class TaskTypeToken extends TypeToken> { + } + + static class SubTaskTypeToken extends TypeToken> { + } + + static class EpicTypeToken extends TypeToken> { + } + +} diff --git a/src/test/TestInMemory.java b/src/test/TestTMInMemory.java similarity index 72% rename from src/test/TestInMemory.java rename to src/test/TestTMInMemory.java index 445a075..b4840b9 100644 --- a/src/test/TestInMemory.java +++ b/src/test/TestTMInMemory.java @@ -13,7 +13,7 @@ import java.time.Duration; import java.time.LocalDateTime; -class TestInMemory { +class TestTMInMemory { private static TaskManager testManager; private static Task taskItem; @@ -22,7 +22,7 @@ class TestInMemory { @BeforeEach void initializeTaskManager() { - // Проверяем создание менеджера через утилитарный класс, используем его в тестах + // Проверяем создание менеджера через утилитарный класс, используем его в тестах testManager = Managers.getDefault(); Assertions.assertNotNull(testManager); // проверяем что менеджер создан Assertions.assertNotNull(testManager.getAllTasks()); // проверяем что список задач создан @@ -31,14 +31,14 @@ void initializeTaskManager() { Assertions.assertNotNull(testManager.getHistory()); // проверяем что история создана // Создаём элементы для добавления в менеджер - taskItem = new Task(testManager.getGlobalId(), + taskItem = new Task(0, "Работа", "Просто задача", Status.NEW, LocalDateTime.of(2024, 1, 1, 10, 5, 0), Duration.ofMinutes(50)); - epicItem = new Epic(testManager.getGlobalId(), + epicItem = new Epic(0, "Этапы", "Поэтапная работа", Status.NEW); - subTaskItem = new SubTask(testManager.getGlobalId(), - "Этап 1", "Подготовка к работе", Status.NEW,2, + subTaskItem = new SubTask(0, + "Этап 1", "Подготовка к работе", Status.NEW, 2, LocalDateTime.of(2024, 1, 1, 8, 5, 0), Duration.ofMinutes(250)); @@ -50,7 +50,7 @@ void initializeTaskManager() { } @Test - void addItem() { + void addItem_CorrectOfRecordInputAndSave() { // Проверяем, что globalId имеет последний свободный id номер Assertions.assertEquals(4, testManager.getGlobalId()); @@ -63,25 +63,34 @@ void addItem() { // Проверяем идентичность отправляемых элементов в менеджере с сохранёнными в менеджере по всем значениям // Проверяем обычные задачи - Assertions.assertEquals(taskItem.getName(), testManager.getTask(taskItem.getId()).getName()); - Assertions.assertEquals(taskItem.getDescription(), testManager.getTask(taskItem.getId()).getDescription()); - Assertions.assertEquals(taskItem.getStatus(), testManager.getTask(taskItem.getId()).getStatus()); + Assertions.assertEquals(taskItem.getName(), + testManager.getTask(taskItem.getId()).getName()); + Assertions.assertEquals(taskItem.getDescription(), + testManager.getTask(taskItem.getId()).getDescription()); + Assertions.assertEquals(taskItem.getStatus(), + testManager.getTask(taskItem.getId()).getStatus()); // Проверяем эпики - Assertions.assertEquals(epicItem.getName(), testManager.getEpic(epicItem.getId()).getName()); - Assertions.assertEquals(epicItem.getDescription(), testManager.getEpic(epicItem.getId()).getDescription()); - Assertions.assertEquals(epicItem.getStatus(), testManager.getEpic(epicItem.getId()).getStatus()); + Assertions.assertEquals(epicItem.getName(), + testManager.getEpic(epicItem.getId()).getName()); + Assertions.assertEquals(epicItem.getDescription(), + testManager.getEpic(epicItem.getId()).getDescription()); + Assertions.assertEquals(epicItem.getStatus(), + testManager.getEpic(epicItem.getId()).getStatus()); // Проверяем подзадачи - Assertions.assertEquals(subTaskItem.getName(), testManager.getSubTask(subTaskItem.getId()).getName()); + Assertions.assertEquals(subTaskItem.getName(), + testManager.getSubTask(subTaskItem.getId()).getName()); Assertions.assertEquals(subTaskItem.getDescription(), testManager.getSubTask(subTaskItem.getId()).getDescription()); - Assertions.assertEquals(subTaskItem.getStatus(), testManager.getSubTask(subTaskItem.getId()).getStatus()); - Assertions.assertEquals(subTaskItem.getIdEpic(), testManager.getSubTask(subTaskItem.getId()).getIdEpic()); + Assertions.assertEquals(subTaskItem.getStatus(), + testManager.getSubTask(subTaskItem.getId()).getStatus()); + Assertions.assertEquals(subTaskItem.getIdEpic(), + testManager.getSubTask(subTaskItem.getId()).getIdEpic()); } @Test - void testItems() { + void checkingIdentityOfItemsWithOneId() { // проверяем равенство элементов с одним и тем-же id Task taskItem1 = testManager.getTask(1); Task taskItem2 = testManager.getTask(1); @@ -96,7 +105,7 @@ void testItems() { } @Test - void testHistory1() { + void addToHistoryAndChanges_HistoryIsCreatedRecordedCorrectlyAndChanged() { // Проверяем, что в истории только 1 запись - стартовая Assertions.assertEquals(1, testManager.getHistory().size(), "В истории не одна запись."); // Добавляем элемент в историю при помощи запроса к менеджеру @@ -118,39 +127,48 @@ void testHistory1() { Assertions.assertEquals(2, testManager.getHistory().size(), "В истории не одна запись."); // Сравниваем содержимое записи истории с содержимым задачи 1 до и после изменения. // Первая запись не должна соответствовать taskItem1, а вторая должна соответствовать taskItem2. - Assertions.assertNotEquals(taskItem1, testManager.getHistory().getLast(), "записи соответствуют."); - Assertions.assertEquals(taskItem2, testManager.getHistory().getLast(), "записи не соответствуют."); + Assertions.assertNotEquals(taskItem1, + testManager.getHistory().getLast(), "записи соответствуют."); + Assertions.assertEquals(taskItem2, + testManager.getHistory().getLast(), "записи не соответствуют."); } @Test - void testHistory2() { + void checkingChangesInHistory_DeletingItem_historyIsDeletedAndNoRepeatHistory() { // Проверяем, что в истории только стартовая запись - Assertions.assertEquals(1, testManager.getHistory().size(), "В истории не одна запись."); + Assertions.assertEquals(1, + testManager.getHistory().size(), "В истории не одна запись."); // Добавляем 1 элемент в историю при помощи запроса к менеджеру Task taskItem1 = testManager.getTask(1); // проверяем, что история изменилась на 1 - Assertions.assertEquals(2, testManager.getHistory().size(), "В историю не попала 1 запись."); + Assertions.assertEquals(2, + testManager.getHistory().size(), "В историю не попала 1 запись."); // Добавляем 2 элемент в историю при помощи запроса к менеджеру taskItem1 = testManager.getSubTask(3); // проверяем, что история изменилась ещё на 1 - Assertions.assertEquals(3, testManager.getHistory().size(), "В историю не попала 2 запись."); + Assertions.assertEquals(3, + testManager.getHistory().size(), "В историю не попала 2 запись."); // При помощи запросов к менеджеру проверяем - повторный запросы увеличили ли количество запросов в истории. taskItem1 = testManager.getTask(1); taskItem1 = testManager.getSubTask(3); taskItem1 = testManager.getEpic(2); // Проверяем, что история осталась с 4 элементам. Что дублирования записей нет. - Assertions.assertEquals(3, testManager.getHistory().size(), "В истории появились дубли."); + Assertions.assertEquals(3, + testManager.getHistory().size(), "В истории появились дубли."); // удаляем задачу и проверяем состояние истории - уменьшилась ли она, и есть ли запись с удалённой задачей. testManager.deleteTask(1); - Assertions.assertEquals(2, testManager.getHistory().size(), "В истории не удалена запись."); + Assertions.assertEquals(2, + testManager.getHistory().size(), "В истории не удалена запись."); Assertions.assertNull(testManager.getTask(1), "Задача не удалена."); // повторяем то-же самое с подзадачей и эпиком testManager.deleteSubTask(3); - Assertions.assertEquals(1, testManager.getHistory().size(), "В истории не удалена запись."); + Assertions.assertEquals(1, + testManager.getHistory().size(), "В истории не удалена запись."); Assertions.assertNull(testManager.getSubTask(3), "Подзадача не удалена."); testManager.deleteEpic(2); - Assertions.assertEquals(0, testManager.getHistory().size(), "В истории не удалена запись."); + Assertions.assertEquals(0, + testManager.getHistory().size(), "В истории не удалена запись."); Assertions.assertNull(testManager.getEpic(2), "Эпик не удален."); } } \ No newline at end of file diff --git a/src/test/TestInFile.java b/src/test/TestTMWithFile.java similarity index 80% rename from src/test/TestInFile.java rename to src/test/TestTMWithFile.java index 851b563..7f4e96d 100644 --- a/src/test/TestInFile.java +++ b/src/test/TestTMWithFile.java @@ -16,7 +16,7 @@ import java.time.Duration; import java.time.LocalDateTime; -class TestInFile { +class TestTMWithFile { private static TaskManager testManager; private static Task taskItem; @@ -52,18 +52,18 @@ void initializeTaskManager() { } @Test - void testFilesOperations() { + void writeAndReadDataFile_CorrectInputOutput() { // Проверяем что менеджер сохраняет данные в файл // Создаём элементы для добавления в менеджер - taskItem = new Task(testManager.getGlobalId(), + taskItem = new Task(0, "Работа", "Просто задача", Status.NEW, LocalDateTime.of(2024, 1, 1, 10, 5, 0), Duration.ofMinutes(50)); - epicItem = new Epic(testManager.getGlobalId(), + epicItem = new Epic(0, "Этапы", "Поэтапная работа", Status.NEW); - subTaskItem = new SubTask(testManager.getGlobalId(), - "Этап 1", "Подготовка к работе", Status.NEW,2, + subTaskItem = new SubTask(0, + "Этап 1", "Подготовка к работе", Status.NEW, 2, LocalDateTime.of(2024, 1, 5, 8, 5, 0), Duration.ofMinutes(250)); @@ -103,17 +103,17 @@ void testFilesOperations() { } @Test - void addItem() { + void addItem_CorrectOfRecordInputAndSave() { // Создаём элементы для добавления в менеджер - taskItem = new Task(testManager.getGlobalId(), + taskItem = new Task(0, "Работа", "Просто задача", Status.NEW, LocalDateTime.of(2024, 1, 5, 10, 5, 0), Duration.ofMinutes(50)); - epicItem = new Epic(testManager.getGlobalId(), + epicItem = new Epic(0, "Этапы", "Поэтапная работа", Status.NEW); - subTaskItem = new SubTask(testManager.getGlobalId(), - "Этап 1", "Подготовка к работе", Status.NEW,2, + subTaskItem = new SubTask(0, + "Этап 1", "Подготовка к работе", Status.NEW, 2, LocalDateTime.of(2024, 1, 1, 8, 5, 0), Duration.ofMinutes(250)); @@ -133,35 +133,44 @@ void addItem() { // Проверяем идентичность отправляемых элементов в менеджере с сохранёнными в менеджере по всем значениям // Проверяем обычные задачи - Assertions.assertEquals(taskItem.getName(), testManager.getTask(taskItem.getId()).getName()); - Assertions.assertEquals(taskItem.getDescription(), testManager.getTask(taskItem.getId()).getDescription()); - Assertions.assertEquals(taskItem.getStatus(), testManager.getTask(taskItem.getId()).getStatus()); + Assertions.assertEquals(taskItem.getName(), + testManager.getTask(taskItem.getId()).getName()); + Assertions.assertEquals(taskItem.getDescription(), + testManager.getTask(taskItem.getId()).getDescription()); + Assertions.assertEquals(taskItem.getStatus(), + testManager.getTask(taskItem.getId()).getStatus()); // Проверяем эпики - Assertions.assertEquals(epicItem.getName(), testManager.getEpic(epicItem.getId()).getName()); - Assertions.assertEquals(epicItem.getDescription(), testManager.getEpic(epicItem.getId()).getDescription()); - Assertions.assertEquals(epicItem.getStatus(), testManager.getEpic(epicItem.getId()).getStatus()); + Assertions.assertEquals(epicItem.getName(), + testManager.getEpic(epicItem.getId()).getName()); + Assertions.assertEquals(epicItem.getDescription(), + testManager.getEpic(epicItem.getId()).getDescription()); + Assertions.assertEquals(epicItem.getStatus(), + testManager.getEpic(epicItem.getId()).getStatus()); // Проверяем подзадачи - Assertions.assertEquals(subTaskItem.getName(), testManager.getSubTask(subTaskItem.getId()).getName()); + Assertions.assertEquals(subTaskItem.getName(), + testManager.getSubTask(subTaskItem.getId()).getName()); Assertions.assertEquals(subTaskItem.getDescription(), testManager.getSubTask(subTaskItem.getId()).getDescription()); - Assertions.assertEquals(subTaskItem.getStatus(), testManager.getSubTask(subTaskItem.getId()).getStatus()); - Assertions.assertEquals(subTaskItem.getIdEpic(), testManager.getSubTask(subTaskItem.getId()).getIdEpic()); + Assertions.assertEquals(subTaskItem.getStatus(), + testManager.getSubTask(subTaskItem.getId()).getStatus()); + Assertions.assertEquals(subTaskItem.getIdEpic(), + testManager.getSubTask(subTaskItem.getId()).getIdEpic()); } @Test - void testItems() { + void checkingIdentityOfItemsWithOneId() { // Создаём элементы для добавления в менеджер - taskItem = new Task(testManager.getGlobalId(), + taskItem = new Task(0, "Работа", "Просто задача", Status.NEW, LocalDateTime.of(2024, 1, 1, 10, 5, 0), Duration.ofMinutes(50)); - epicItem = new Epic(testManager.getGlobalId(), + epicItem = new Epic(0, "Этапы", "Поэтапная работа", Status.NEW); - subTaskItem = new SubTask(testManager.getGlobalId(), - "Этап 1", "Подготовка к работе", Status.NEW,2, + subTaskItem = new SubTask(0, + "Этап 1", "Подготовка к работе", Status.NEW, 2, LocalDateTime.of(2024, 1, 1, 10, 5, 0), Duration.ofMinutes(250)); @@ -184,17 +193,17 @@ void testItems() { } @Test - void testHistory1() { + void addToHistoryAndChanges_HistoryIsCreatedRecordedCorrectlyAndChanged() { // Создаём элементы для добавления в менеджер - taskItem = new Task(testManager.getGlobalId(), + taskItem = new Task(0, "Работа", "Просто задача", Status.NEW, LocalDateTime.of(2024, 1, 1, 12, 5, 0), Duration.ofMinutes(50)); - epicItem = new Epic(testManager.getGlobalId(), + epicItem = new Epic(0, "Этапы", "Поэтапная работа", Status.NEW); - subTaskItem = new SubTask(testManager.getGlobalId(), - "Этап 1", "Подготовка к работе", Status.NEW,2, + subTaskItem = new SubTask(0, + "Этап 1", "Подготовка к работе", Status.NEW, 2, LocalDateTime.of(2024, 1, 1, 8, 5, 0), Duration.ofMinutes(250)); @@ -224,23 +233,25 @@ void testHistory1() { Assertions.assertEquals(2, testManager.getHistory().size(), "В истории не одна запись."); // Сравниваем содержимое записи истории с содержимым задачи 1 до и после изменения. // Первая запись не должна соответствовать taskItem1, а вторая должна соответствовать taskItem2. - Assertions.assertNotEquals(taskItem1, testManager.getHistory().getLast(), "записи соответствуют."); - Assertions.assertEquals(taskItem2, testManager.getHistory().getLast(), "записи не соответствуют."); + Assertions.assertNotEquals(taskItem1, + testManager.getHistory().getLast(), "записи соответствуют."); + Assertions.assertEquals(taskItem2, + testManager.getHistory().getLast(), "записи не соответствуют."); } @Test - void testHistory2() { + void checkingChangesInHistory_DeletingItem_historyIsDeletedAndNoRepeatHistory() { // Создаём элементы для добавления в менеджер - taskItem = new Task(testManager.getGlobalId(), + taskItem = new Task(0, "Работа", "Просто задача", Status.NEW, LocalDateTime.of(2024, 3, 1, 10, 5, 0), Duration.ofMinutes(50)); - epicItem = new Epic(testManager.getGlobalId(), + epicItem = new Epic(0, "Этапы", "Поэтапная работа", Status.NEW); - subTaskItem = new SubTask(testManager.getGlobalId(), - "Этап 1", "Подготовка к работе", Status.NEW,2, + subTaskItem = new SubTask(0, + "Этап 1", "Подготовка к работе", Status.NEW, 2, LocalDateTime.of(2024, 1, 1, 8, 5, 0), Duration.ofMinutes(250)); @@ -254,27 +265,33 @@ void testHistory2() { // Добавляем 1 элемент в историю при помощи запроса к менеджеру Task taskItem1 = testManager.getTask(1); // проверяем, что история изменилась на 1 - Assertions.assertEquals(2, testManager.getHistory().size(), "В историю не попала 1 запись."); + Assertions.assertEquals(2, + testManager.getHistory().size(), "В историю не попала 1 запись."); // Добавляем 2 элемент в историю при помощи запроса к менеджеру taskItem1 = testManager.getSubTask(3); // проверяем, что история изменилась ещё на 1 - Assertions.assertEquals(3, testManager.getHistory().size(), "В историю не попала 2 запись."); + Assertions.assertEquals(3, + testManager.getHistory().size(), "В историю не попала 2 запись."); // При помощи запросов к менеджеру проверяем - повторный запросы увеличили ли количество запросов в истории. taskItem1 = testManager.getTask(1); taskItem1 = testManager.getSubTask(3); taskItem1 = testManager.getEpic(2); // Проверяем, что история осталась с 3 элементам. Что дублирования записей нет. - Assertions.assertEquals(3, testManager.getHistory().size(), "В истории появились дубли."); + Assertions.assertEquals(3, + testManager.getHistory().size(), "В истории появились дубли."); // удаляем задачу и проверяем состояние истории - уменьшилась ли она, и есть ли запись с удалённой задачей. testManager.deleteTask(1); - Assertions.assertEquals(2, testManager.getHistory().size(), "В истории не удалена запись."); + Assertions.assertEquals(2, + testManager.getHistory().size(), "В истории не удалена запись."); Assertions.assertNull(testManager.getTask(1), "Задача не удалена."); // повторяем то-же самое с подзадачей и эпиком testManager.deleteSubTask(3); - Assertions.assertEquals(1, testManager.getHistory().size(), "В истории не удалена запись."); + Assertions.assertEquals(1, + testManager.getHistory().size(), "В истории не удалена запись."); Assertions.assertNull(testManager.getSubTask(3), "Подзадача не удалена."); testManager.deleteEpic(2); - Assertions.assertEquals(0, testManager.getHistory().size(), "В истории не удалена запись."); + Assertions.assertEquals(0, + testManager.getHistory().size(), "В истории не удалена запись."); Assertions.assertNull(testManager.getEpic(2), "Эпик не удален."); } } \ No newline at end of file diff --git a/test/TestHttpApi.java b/test/TestHttpApi.java new file mode 100644 index 0000000..b699992 --- /dev/null +++ b/test/TestHttpApi.java @@ -0,0 +1,694 @@ +package test; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.TypeAdapter; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import main.classes.Epic; +import main.classes.Status; +import main.classes.SubTask; +import main.classes.Task; +import main.HTTPserver.HttpTaskServer; +import main.service.InMemoryTaskManager; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +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.time.format.DateTimeFormatter; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class TestHttpApi { + protected HttpTaskServer testserver; + protected InMemoryTaskManager taskManager; + + @BeforeEach + void initializeClass() throws IOException { + // создание и запуск сервера + taskManager = new InMemoryTaskManager(); + testserver = new HttpTaskServer(taskManager); + testserver.run(); + } + + @AfterEach + void shutdown() throws IOException { + testserver.stop(); + } + + // сами тесты + + @Test + void getAllItemsTaskAndSubTaskAndEpic() throws IOException, InterruptedException { + Gson gson = new GsonBuilder() + .setPrettyPrinting() + .serializeNulls() + .registerTypeAdapter(LocalDateTime.class, new LDTAdapter()) + .registerTypeAdapter(Duration.class, new DAdapter()) + .create(); // создаём объект Gson + + // подгружаем тестовые данные в трекер задач + initTest(taskManager); + + // создаём HTTP-клиент + HttpClient client = HttpClient.newHttpClient(); + // Создаём запросы на получение списков объектов и получаем ответы. + // Получаем список задач + URI url = URI.create("http://localhost:8080/tasks"); + HttpRequest request = HttpRequest.newBuilder().uri(url).GET().build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + List listTasks = gson.fromJson(response.body(), new TaskTypeToken().getType()); + // Получаем список эпиков + url = URI.create("http://localhost:8080/epics"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + List listEpics = gson.fromJson(response.body(), new EpicTypeToken().getType()); + // Получаем список подзадач + url = URI.create("http://localhost:8080/subtasks"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + List listSubTasks = gson.fromJson(response.body(), new SubTaskTypeToken().getType()); + + // проверяем, что мы получили 3 задачи, 4 подзадачи и 2 эпика + assertEquals(3, listTasks.size(), "Некорректное количество задач"); + assertEquals(4, listSubTasks.size(), "Некорректное количество подзадач"); + assertEquals(2, listEpics.size(), "Некорректное количество эпиков"); + } + + @Test + void getItemsOfId_GetByIdTaskAndSubTaskAndEpic() throws IOException, InterruptedException { + Gson gson = new GsonBuilder() + .setPrettyPrinting() + .serializeNulls() + .registerTypeAdapter(LocalDateTime.class, new LDTAdapter()) + .registerTypeAdapter(Duration.class, new DAdapter()) + .create(); // создаём объект Gson + + // подгружаем тестовые данные в трекер задач + initTest(taskManager); + + // создаём HTTP-клиент + HttpClient client = HttpClient.newHttpClient(); + // Создаём запросы на получение объектов по их id. + // Получаем список задач + URI url = URI.create("http://localhost:8080/tasks/8"); + HttpRequest request = HttpRequest.newBuilder().uri(url).GET().build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + Task task = gson.fromJson(response.body(), Task.class); + // Получаем список эпиков + url = URI.create("http://localhost:8080/epics/5"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + Epic epic = gson.fromJson(response.body(), Epic.class); + // Получаем список подзадач + url = URI.create("http://localhost:8080/subtasks/9"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + SubTask subTask = gson.fromJson(response.body(), SubTask.class); + + // проверяем, что мы через API получили те-же значения, что находятся и в трекере задач + assertEquals(task, + taskManager.getTask(8), "Несовпадение задач API с трекером задач"); + assertEquals(subTask, + taskManager.getSubTask(9), "Несовпадение подзадач API с трекером задач"); + assertEquals(epic, + taskManager.getEpic(5), "Несовпадение эпиков API с трекером задач"); + } + + @Test + void addItems_AddTaskAndSubTaskAndEpic() throws IOException, InterruptedException { + Gson gson = new GsonBuilder() + .setPrettyPrinting() + .serializeNulls() + .registerTypeAdapter(LocalDateTime.class, new LDTAdapter()) + .registerTypeAdapter(Duration.class, new DAdapter()) + .create(); // создаём объект Gson + + // создаём объекты для добавления. + Task task = new Task(0, "Задача 1", "Добавление задачи 1", + Status.NEW, LocalDateTime.now(), Duration.ofMinutes(5)); + Epic epic = new Epic(0, "Эпик 2", "Добавление эпика 2", + Status.NEW, LocalDateTime.now(), Duration.ofMinutes(5)); + SubTask subTask = new SubTask(0, "Подзадача 3", "Добавление подзадачи 3", + Status.NEW, 2, + LocalDateTime.now().plusHours(1), Duration.ofMinutes(5)); + + // конвертируем их в JSON + String taskJson = gson.toJson(task); + String subTaskJson = gson.toJson(subTask); + String epicJson = gson.toJson(epic); + + // создаём HTTP-клиент + HttpClient client = HttpClient.newHttpClient(); + // Проверяем добавление задачи + URI url = URI.create("http://localhost:8080/tasks"); + HttpRequest request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(taskJson)).build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + // Проверяем добавление эпика + url = URI.create("http://localhost:8080/epics"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(epicJson)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + // Проверяем добавление подзадачи + url = URI.create("http://localhost:8080/subtasks"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subTaskJson)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + + // проверяем, что создались по одному объекту каждого типа и проверяем идентичность отправленного и полученного + List tasksFromManager = taskManager.getAllTasks(); + assertNotNull(tasksFromManager, "Задача не создалась"); + assertEquals(1, tasksFromManager.size(), "Некорректное количество задач"); + assertEquals(task.getName(), + tasksFromManager.getFirst().getName(), "Несовпадение отправленного и полученного"); + List subTaskFromManager = taskManager.getAllSubTasks(); + assertNotNull(subTaskFromManager, "Подзадача не создалась"); + assertEquals(1, subTaskFromManager.size(), "Некорректное количество подзадач"); + assertEquals(subTask.getName(), + subTaskFromManager.getFirst().getName(), "Несовпадение отправленного и полученного"); + List epicFromManager = taskManager.getAllEpics(); + assertNotNull(epicFromManager, "Эпик не создался"); + assertEquals(1, epicFromManager.size(), "Некорректное количество эпиков"); + assertEquals(epic.getName(), + epicFromManager.getFirst().getName(), "Несовпадение отправленного и полученного"); + } + + @Test + void updateItemsAndStatus_updateItemsByIdAndStatusEpicByStatusSubTasks() throws IOException, InterruptedException { + Gson gson = new GsonBuilder() + .setPrettyPrinting() + .serializeNulls() + .registerTypeAdapter(LocalDateTime.class, new LDTAdapter()) + .registerTypeAdapter(Duration.class, new DAdapter()) + .create(); // создаём объект Gson + + // создаём Эпик без указания начала и конца времени выполнения и две подзадачи этого эпика. + Epic epic = new Epic(0, "Эпик 1", "Добавление эпика 1", + Status.NEW, null, null); + SubTask subTask1 = new SubTask(0, "Подзадача 2", "Добавление подзадачи 2", + Status.NEW, 1, LocalDateTime.now(), Duration.ofMinutes(15)); + SubTask subTask2 = new SubTask(0, "Подзадача 3", "Добавление подзадачи 3", + Status.NEW, 1, LocalDateTime.now().plusHours(1), + Duration.ofMinutes(15)); + + // конвертируем их в JSON + String epicJson = gson.toJson(epic); + String subTaskJson1 = gson.toJson(subTask1); + String subTaskJson2 = gson.toJson(subTask2); + + // создаём HTTP-клиент + HttpClient client = HttpClient.newHttpClient(); + // Добавляем эпик и задачи + URI url = URI.create("http://localhost:8080/epics"); + HttpRequest request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(epicJson)).build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + url = URI.create("http://localhost:8080/subtasks"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subTaskJson1)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + url = URI.create("http://localhost:8080/subtasks"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subTaskJson2)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + // Проверяем, что в трекере есть один эпик (1) и две подзадачи (3 и 4). Все они имеют статус NEW + assertEquals(Status.NEW, + taskManager.getEpic(1).getStatus(), "Статус эпика не New"); + assertEquals(Status.NEW, + taskManager.getSubTask(2).getStatus(), "Статус подзадачи не New"); + assertEquals(Status.NEW, + taskManager.getSubTask(3).getStatus(), "Статус подзадачи не New"); + // Проверяем, что время старта Эпика теперь равно времени старта первой подзадачи, + // а время завершения времени завершения второй. + assertEquals(taskManager.getSubTask(2).getStartTime(), + taskManager.getEpic(1).getStartTime(), + "Время старта эпика не равно времени старта первой подзадачи"); + assertEquals(taskManager.getSubTask(3).getEndTime(), + taskManager.getEpic(1).getEndTime(), + "Время завершения эпика не равно времени завершения второй подзадачи"); + // Вносим изменения в подзадачу 2, не изменяя время старта и продолжительность + subTask1 = new SubTask(2, "Изменения подзадачи 2", "Изменение подзадачи 2", + Status.IN_PROGRESS, 1, null, null); + subTaskJson1 = gson.toJson(subTask1); + url = URI.create("http://localhost:8080/subtasks/2"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subTaskJson1)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(201, response.statusCode()); + // Проверяем изменение названия и описания подзадачи и изменения статуса эпика на основе изменения статуса подзадачи + assertEquals(Status.IN_PROGRESS, + taskManager.getSubTask(2).getStatus(), "Статус подзадачи не IN_PROGRESS"); + assertEquals(Status.IN_PROGRESS, + taskManager.getEpic(1).getStatus(), "Статус эпика не IN_PROGRESS"); + assertEquals(subTask1.getName(), + taskManager.getSubTask(2).getName(), "Название подзадачи 2 не изменилось"); + // Изменяем статусы подзадач на Done без изменения названий, и изменяем время второй подзадачи. + subTask1 = new SubTask(2, null, null, + Status.DONE, 1, null, null); + subTask2 = new SubTask(3, null, null, + Status.DONE, 1, LocalDateTime.now().plusHours(3), + Duration.ofMinutes(30)); + subTaskJson1 = gson.toJson(subTask1); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subTaskJson1)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(201, response.statusCode()); + subTaskJson2 = gson.toJson(subTask2); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subTaskJson2)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(201, response.statusCode()); + // Проверяем изменения статусов подзадач и эпика, + // и соотвествие времени начала и завершения эпика, согласно новым данным подзадачи 3 + assertEquals(Status.DONE, + taskManager.getSubTask(2).getStatus(), "Статус подзадачи не DONE"); + assertEquals(Status.DONE, + taskManager.getSubTask(3).getStatus(), "Статус подзадачи не DONE"); + assertEquals(Status.DONE, + taskManager.getEpic(1).getStatus(), "Статус эпика не DONE"); + assertEquals(taskManager.getSubTask(2).getStartTime(), + taskManager.getEpic(1).getStartTime(), + "Время старта эпика не равно времени старта первой подзадачи"); + assertEquals(taskManager.getSubTask(3).getEndTime(), + taskManager.getEpic(1).getEndTime(), + "Время завершения эпика не равно времени завершения второй подзадачи"); + } + + @Test + void checkingOverlaysItems_ifTimeOccupiedByTask_cannotAddTaskThisTime() throws IOException, InterruptedException { + Gson gson = new GsonBuilder() + .setPrettyPrinting() + .serializeNulls() + .registerTypeAdapter(LocalDateTime.class, new LDTAdapter()) + .registerTypeAdapter(Duration.class, new DAdapter()) + .create(); // создаём объект Gson + + // создаём объекты для добавления. + Task task1 = new Task(0, "Задача 1", "Добавление задачи 1", + Status.NEW, LocalDateTime.now(), Duration.ofMinutes(120)); + SubTask subTask = new SubTask(0, "Подзадача 2", "Добавление подзадачи 2", + Status.NEW, 2, LocalDateTime.now().plusHours(6), + Duration.ofMinutes(30)); + Task task2 = new Task(0, "Задача 3", "Добавление задачи 3", + Status.NEW, LocalDateTime.now().plusHours(1), + Duration.ofMinutes(15)); + + // конвертируем их в JSON + String taskJson1 = gson.toJson(task1); + String taskJson2 = gson.toJson(task2); + String subTaskJson = gson.toJson(subTask); + + // создаём HTTP-клиент + HttpClient client = HttpClient.newHttpClient(); + // Проверяем добавление задачи 1 + URI url = URI.create("http://localhost:8080/tasks"); + HttpRequest request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(taskJson1)).build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + + // Проверяем добавление подзадачи 2 - время не пересекается с временем задачи 1 + url = URI.create("http://localhost:8080/subtasks"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subTaskJson)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + + // Проверяем добавление задачи 3 - тут время пересекается и код ответа должен быть 406 + url = URI.create("http://localhost:8080/tasks"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(taskJson2)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(406, response.statusCode()); + + // Вносим изменения времени в подзадачу и тоже получаем ответ 406 + subTask = new SubTask(2, "Изменения 2", "Изменения времени подзадачи 2", + Status.IN_PROGRESS, 2, LocalDateTime.now().plusMinutes(30), + Duration.ofMinutes(15)); + subTaskJson = gson.toJson(subTask); + url = URI.create("http://localhost:8080/subtasks/2"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subTaskJson)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(406, response.statusCode()); + } + + @Test + void deleteItems_DeleteTaskAndSubTaskAndEpics_correctlyDelete() throws IOException, InterruptedException { + // подгружаем тестовые данные в трекер задач + initTest(taskManager); + + // создаём HTTP-клиент + HttpClient client = HttpClient.newHttpClient(); + // Создаём запросы на удаление объектов по их id. + URI url = URI.create("http://localhost:8080/tasks/8"); + HttpRequest request = HttpRequest.newBuilder().uri(url).DELETE().build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + url = URI.create("http://localhost:8080/epics/5"); + request = HttpRequest.newBuilder().uri(url).DELETE().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + url = URI.create("http://localhost:8080/subtasks/9"); + request = HttpRequest.newBuilder().uri(url).DELETE().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + + // Создаём запросы на удаление объектов по их несуществующим id и получаем ответ 404 + url = URI.create("http://localhost:8080/tasks/18"); + request = HttpRequest.newBuilder().uri(url).DELETE().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(404, response.statusCode()); + url = URI.create("http://localhost:8080/epics/15"); + request = HttpRequest.newBuilder().uri(url).DELETE().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(404, response.statusCode()); + url = URI.create("http://localhost:8080/subtasks/19"); + request = HttpRequest.newBuilder().uri(url).DELETE().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(404, response.statusCode()); + + // проверяем, что количество задач, подзадач и эпиков уменьшилось согласно нашим действиям + // Задачи было 3 - станет 2 + // Подзадачи было 4 - станет 3 из-за удаления подзадачи + // Эпики было 2 - станет 1, но вместе с эпиком удалились 2 подзадачи, значит подзадач станет 1 + assertEquals(2, taskManager.getAllTasks().size(), "Неправильное количество задач"); + assertEquals(1, taskManager.getAllSubTasks().size(), "Неправильное количество подзадач"); + assertEquals(1, taskManager.getAllEpics().size(), "Неправильное количество эпиков"); + + } + + @Test + void getHistory_correctAddHistoryAndDeleteHistoryByDeleteTask() throws IOException, InterruptedException { + Gson gson = new GsonBuilder() + .setPrettyPrinting() + .serializeNulls() + .registerTypeAdapter(LocalDateTime.class, new LDTAdapter()) + .registerTypeAdapter(Duration.class, new DAdapter()) + .create(); // создаём объект Gson + + // подгружаем тестовые данные в трекер задач + initTest(taskManager); + + // создаём HTTP-клиент + HttpClient client = HttpClient.newHttpClient(); + + // Получаем историю действий + URI url = URI.create("http://localhost:8080/history"); + HttpRequest request = HttpRequest.newBuilder().uri(url).GET().build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + List listHistory = gson.fromJson(response.body(), new TaskTypeToken().getType()); + // проверяем, что в истории 2 записи при инициализации трекера задач + assertEquals(2, listHistory.size(), "История не пуста"); + + // Делаем 3 запроса на получение объекта по его id + url = URI.create("http://localhost:8080/tasks/8"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + url = URI.create("http://localhost:8080/subtasks/9"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + // Получаем историю действий + url = URI.create("http://localhost:8080/history"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + listHistory = gson.fromJson(response.body(), new TaskTypeToken().getType()); + // проверяем, что в истории плюс 2 позиции - 5 + assertEquals(4, listHistory.size(), "В истории некорректное количество записей"); + + // удаляем задачу, по которой был запрос и проверяем историю - + // удалённая задача должна выпасть из истории и там должно быть 2 записи. + url = URI.create("http://localhost:8080/tasks/8"); + request = HttpRequest.newBuilder().uri(url).DELETE().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + url = URI.create("http://localhost:8080/history"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + listHistory = gson.fromJson(response.body(), new TaskTypeToken().getType()); + // проверяем, что в истории 3 позиции + assertEquals(3, listHistory.size(), "В истории некорректное количество записей"); + } + + @Test + void getPrioritized_correctCreateListPriorityAndAutoReordering() throws IOException, InterruptedException { + Gson gson = new GsonBuilder() + .setPrettyPrinting() + .serializeNulls() + .registerTypeAdapter(LocalDateTime.class, new LDTAdapter()) + .registerTypeAdapter(Duration.class, new DAdapter()) + .create(); // создаём объект Gson + + // создаём объекты для добавления. + Task task1 = new Task(0, "Задача 1", "Добавление задачи 1", + Status.NEW, LocalDateTime.now().plusHours(2), + Duration.ofMinutes(15)); + Task task2 = new Task(0, "Задача 2", "Добавление задачи 2", + Status.NEW, LocalDateTime.now().plusHours(1), + Duration.ofMinutes(15)); + Epic epic3 = new Epic(0, "Эпик 3", "Добавление эпика 3", + Status.NEW, LocalDateTime.now(), Duration.ofMinutes(5)); + SubTask subTask4 = new SubTask(0, "Подзадача 4", "Добавление подзадачи 4", + Status.NEW, 3, LocalDateTime.now().plusHours(3), + Duration.ofMinutes(25)); + SubTask subTask5 = new SubTask(0, "Подзадача 5", "Добавление подзадачи 5", + Status.NEW, 3, LocalDateTime.now(), Duration.ofMinutes(35)); + + // конвертируем их в JSON + String taskJson1 = gson.toJson(task1); + String taskJson2 = gson.toJson(task2); + String epicJson3 = gson.toJson(epic3); + String subTaskJson4 = gson.toJson(subTask4); + String subTaskJson5 = gson.toJson(subTask5); + + // создаём HTTP-клиент + HttpClient client = HttpClient.newHttpClient(); + + // делаем запрос списка приоритета задач + URI url = URI.create("http://localhost:8080/prioritized"); + HttpRequest request = HttpRequest.newBuilder().uri(url).GET().build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + List listPrioritized = gson.fromJson(response.body(), new TaskTypeToken().getType()); + // проверяем, что в список пуст + assertEquals(0, listPrioritized.size(), "Список приоритета не пуст"); + + // Добавляем три элемента + url = URI.create("http://localhost:8080/tasks"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(taskJson1)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + url = URI.create("http://localhost:8080/tasks"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(taskJson2)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + url = URI.create("http://localhost:8080/epics"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(epicJson3)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + url = URI.create("http://localhost:8080/subtasks"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subTaskJson4)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + +// Снова запрашиваем список приоритета задач и проверяем что в нём 3 позиции + url = URI.create("http://localhost:8080/prioritized"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + listPrioritized = gson.fromJson(response.body(), new TaskTypeToken().getType()); + assertEquals(3, listPrioritized.size(), "Список не верен"); + // Проверяем правильность позиций списка + assertEquals(2, listPrioritized.get(0).getId(), "Первая задача не верна"); + assertEquals(1, listPrioritized.get(1).getId(), "Вторая задача не верна"); + assertEquals(4, listPrioritized.get(2).getId(), "Третья задача не верна"); + + // Добавляем ещё одну подзадачу и снова проверяем список и порядок в списке + url = URI.create("http://localhost:8080/subtasks"); + request = HttpRequest.newBuilder().uri(url) + .POST(HttpRequest.BodyPublishers.ofString(subTaskJson5)).build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + + url = URI.create("http://localhost:8080/prioritized"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + listPrioritized = gson.fromJson(response.body(), new TaskTypeToken().getType()); + assertEquals(4, listPrioritized.size(), "Список не верен"); + // Проверяем правильность позиций списка + assertEquals(5, listPrioritized.get(0).getId(), "Первая задача не верна"); + assertEquals(2, listPrioritized.get(1).getId(), "Первая задача не верна"); + assertEquals(1, listPrioritized.get(2).getId(), "Вторая задача не верна"); + assertEquals(4, listPrioritized.get(3).getId(), "Третья задача не верна"); + + // Удаляем эпик, а вместе с ним и 2 подзадачи. И снова проверяем список и порядок в списке + url = URI.create("http://localhost:8080/epics/3"); + request = HttpRequest.newBuilder().uri(url).DELETE().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + url = URI.create("http://localhost:8080/prioritized"); + request = HttpRequest.newBuilder().uri(url).GET().build(); + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // проверяем код ответа + assertEquals(200, response.statusCode()); + listPrioritized = gson.fromJson(response.body(), new TaskTypeToken().getType()); + assertEquals(2, listPrioritized.size(), "Список не верен"); + // Проверяем правильность позиций списка + assertEquals(2, listPrioritized.get(0).getId(), "Первая задача не верна"); + assertEquals(1, listPrioritized.get(1).getId(), "Вторая задача не верна"); + } + + + void initTest(InMemoryTaskManager manager) { + manager.addTask(new Task(0, + "Работа", "Просто задача", Status.NEW, + LocalDateTime.of(2024, 1, 1, 10, 5, 0), + Duration.ofMinutes(50))); + manager.addEpic(new Epic(0, + "Этапы", "Поэтапная работа", Status.NEW)); + manager.addSubTask(new SubTask(0, + "Этап 1", "Подготовка к работе", Status.NEW, 2, + LocalDateTime.of(2024, 1, 1, 8, 0, 0), + Duration.ofHours(23))); + manager.addTask(new Task(0, + "Отдых", "Поехать в отпуск", Status.NEW)); + manager.addEpic(new Epic(0, + "Обед", "Нужно утолить голод", Status.NEW)); + manager.addSubTask(new SubTask(0, + "Закупка", "Надо в магазин", Status.NEW, 5, + LocalDateTime.of(2024, 1, 8, 9, 0, 0), + Duration.ofHours(6))); + manager.addSubTask(new SubTask(0, + "Приготовление", "Немного постоять у плиты", Status.NEW, 5, + LocalDateTime.of(2024, 1, 6, 11, 0, 0), + Duration.ofHours(1))); + manager.addTask(new Task(0, + "Попытка 5", "Новая задача после загрузки", Status.NEW, + LocalDateTime.of(2024, 1, 6, 11, 40, 0), + Duration.ofHours(1))); + manager.addSubTask(new SubTask(0, + "Попытка 6", "Новая подзадача после загрузки", Status.NEW, 2, + LocalDateTime.of(2024, 1, 1, 10, 50, 0), + Duration.ofHours(1))); + } + + // Адаптер для LocalDateTime + static class LDTAdapter extends TypeAdapter { + private static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss.SSS"); + + @Override + public void write(JsonWriter jsonWriter, LocalDateTime localDateTime) throws IOException { + if (localDateTime != null) { + jsonWriter.value(localDateTime.format(dtf)); + } else { + jsonWriter.nullValue(); + } + } + + @Override + public LocalDateTime read(final JsonReader jsonReader) throws IOException { + if (jsonReader.peek() != JsonToken.NULL) { + return LocalDateTime.parse(jsonReader.nextString(), dtf); + } else { + jsonReader.nextNull(); + return null; + } + } + } + + // Адаптер для Duration + static class DAdapter extends TypeAdapter { + @Override + public void write(JsonWriter jsonWriter, Duration duration) throws IOException { + if (duration != null) { + jsonWriter.value(duration.toString()); + } else { + jsonWriter.nullValue(); + } + } + + @Override + public Duration read(final JsonReader jsonReader) throws IOException { + if (jsonReader.peek() != JsonToken.NULL) { + return Duration.parse(jsonReader.nextString()); + } else { + jsonReader.nextNull(); + return null; + } + } + } + + // для разбора JSON + static class TaskTypeToken extends TypeToken> { + } + + static class SubTaskTypeToken extends TypeToken> { + } + + static class EpicTypeToken extends TypeToken> { + } + +} diff --git a/test/TestInMemory.java b/test/TestTMInMemory.java similarity index 69% rename from test/TestInMemory.java rename to test/TestTMInMemory.java index 645928c..b4840b9 100644 --- a/test/TestInMemory.java +++ b/test/TestTMInMemory.java @@ -10,7 +10,10 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -class TestInMemory { +import java.time.Duration; +import java.time.LocalDateTime; + +class TestTMInMemory { private static TaskManager testManager; private static Task taskItem; @@ -19,7 +22,7 @@ class TestInMemory { @BeforeEach void initializeTaskManager() { - // Проверяем создание менеджера через утилитарный класс, используем его в тестах + // Проверяем создание менеджера через утилитарный класс, используем его в тестах testManager = Managers.getDefault(); Assertions.assertNotNull(testManager); // проверяем что менеджер создан Assertions.assertNotNull(testManager.getAllTasks()); // проверяем что список задач создан @@ -28,12 +31,16 @@ void initializeTaskManager() { Assertions.assertNotNull(testManager.getHistory()); // проверяем что история создана // Создаём элементы для добавления в менеджер - taskItem = new Task(testManager.getGlobalId(), - "Работа", "Просто задача", Status.NEW); - epicItem = new Epic(testManager.getGlobalId(), + taskItem = new Task(0, + "Работа", "Просто задача", Status.NEW, + LocalDateTime.of(2024, 1, 1, 10, 5, 0), + Duration.ofMinutes(50)); + epicItem = new Epic(0, "Этапы", "Поэтапная работа", Status.NEW); - subTaskItem = new SubTask(testManager.getGlobalId(), - "Этап 1", "Подготовка к работе", Status.NEW,2); + subTaskItem = new SubTask(0, + "Этап 1", "Подготовка к работе", Status.NEW, 2, + LocalDateTime.of(2024, 1, 1, 8, 5, 0), + Duration.ofMinutes(250)); // Добавляем элементы в менеджер testManager.addTask(taskItem); @@ -43,7 +50,7 @@ void initializeTaskManager() { } @Test - void addItem() { + void addItem_CorrectOfRecordInputAndSave() { // Проверяем, что globalId имеет последний свободный id номер Assertions.assertEquals(4, testManager.getGlobalId()); @@ -56,25 +63,34 @@ void addItem() { // Проверяем идентичность отправляемых элементов в менеджере с сохранёнными в менеджере по всем значениям // Проверяем обычные задачи - Assertions.assertEquals(taskItem.getName(), testManager.getTask(taskItem.getId()).getName()); - Assertions.assertEquals(taskItem.getDescription(), testManager.getTask(taskItem.getId()).getDescription()); - Assertions.assertEquals(taskItem.getStatus(), testManager.getTask(taskItem.getId()).getStatus()); + Assertions.assertEquals(taskItem.getName(), + testManager.getTask(taskItem.getId()).getName()); + Assertions.assertEquals(taskItem.getDescription(), + testManager.getTask(taskItem.getId()).getDescription()); + Assertions.assertEquals(taskItem.getStatus(), + testManager.getTask(taskItem.getId()).getStatus()); // Проверяем эпики - Assertions.assertEquals(epicItem.getName(), testManager.getEpic(epicItem.getId()).getName()); - Assertions.assertEquals(epicItem.getDescription(), testManager.getEpic(epicItem.getId()).getDescription()); - Assertions.assertEquals(epicItem.getStatus(), testManager.getEpic(epicItem.getId()).getStatus()); + Assertions.assertEquals(epicItem.getName(), + testManager.getEpic(epicItem.getId()).getName()); + Assertions.assertEquals(epicItem.getDescription(), + testManager.getEpic(epicItem.getId()).getDescription()); + Assertions.assertEquals(epicItem.getStatus(), + testManager.getEpic(epicItem.getId()).getStatus()); // Проверяем подзадачи - Assertions.assertEquals(subTaskItem.getName(), testManager.getSubTask(subTaskItem.getId()).getName()); + Assertions.assertEquals(subTaskItem.getName(), + testManager.getSubTask(subTaskItem.getId()).getName()); Assertions.assertEquals(subTaskItem.getDescription(), testManager.getSubTask(subTaskItem.getId()).getDescription()); - Assertions.assertEquals(subTaskItem.getStatus(), testManager.getSubTask(subTaskItem.getId()).getStatus()); - Assertions.assertEquals(subTaskItem.getIdEpic(), testManager.getSubTask(subTaskItem.getId()).getIdEpic()); + Assertions.assertEquals(subTaskItem.getStatus(), + testManager.getSubTask(subTaskItem.getId()).getStatus()); + Assertions.assertEquals(subTaskItem.getIdEpic(), + testManager.getSubTask(subTaskItem.getId()).getIdEpic()); } @Test - void testItems() { + void checkingIdentityOfItemsWithOneId() { // проверяем равенство элементов с одним и тем-же id Task taskItem1 = testManager.getTask(1); Task taskItem2 = testManager.getTask(1); @@ -89,7 +105,7 @@ void testItems() { } @Test - void testHistory1() { + void addToHistoryAndChanges_HistoryIsCreatedRecordedCorrectlyAndChanged() { // Проверяем, что в истории только 1 запись - стартовая Assertions.assertEquals(1, testManager.getHistory().size(), "В истории не одна запись."); // Добавляем элемент в историю при помощи запроса к менеджеру @@ -111,39 +127,48 @@ void testHistory1() { Assertions.assertEquals(2, testManager.getHistory().size(), "В истории не одна запись."); // Сравниваем содержимое записи истории с содержимым задачи 1 до и после изменения. // Первая запись не должна соответствовать taskItem1, а вторая должна соответствовать taskItem2. - Assertions.assertNotEquals(taskItem1, testManager.getHistory().getLast(), "записи соответствуют."); - Assertions.assertEquals(taskItem2, testManager.getHistory().getLast(), "записи не соответствуют."); + Assertions.assertNotEquals(taskItem1, + testManager.getHistory().getLast(), "записи соответствуют."); + Assertions.assertEquals(taskItem2, + testManager.getHistory().getLast(), "записи не соответствуют."); } @Test - void testHistory2() { + void checkingChangesInHistory_DeletingItem_historyIsDeletedAndNoRepeatHistory() { // Проверяем, что в истории только стартовая запись - Assertions.assertEquals(1, testManager.getHistory().size(), "В истории не одна запись."); + Assertions.assertEquals(1, + testManager.getHistory().size(), "В истории не одна запись."); // Добавляем 1 элемент в историю при помощи запроса к менеджеру Task taskItem1 = testManager.getTask(1); // проверяем, что история изменилась на 1 - Assertions.assertEquals(2, testManager.getHistory().size(), "В историю не попала 1 запись."); + Assertions.assertEquals(2, + testManager.getHistory().size(), "В историю не попала 1 запись."); // Добавляем 2 элемент в историю при помощи запроса к менеджеру taskItem1 = testManager.getSubTask(3); // проверяем, что история изменилась ещё на 1 - Assertions.assertEquals(3, testManager.getHistory().size(), "В историю не попала 2 запись."); + Assertions.assertEquals(3, + testManager.getHistory().size(), "В историю не попала 2 запись."); // При помощи запросов к менеджеру проверяем - повторный запросы увеличили ли количество запросов в истории. taskItem1 = testManager.getTask(1); taskItem1 = testManager.getSubTask(3); taskItem1 = testManager.getEpic(2); // Проверяем, что история осталась с 4 элементам. Что дублирования записей нет. - Assertions.assertEquals(3, testManager.getHistory().size(), "В истории появились дубли."); + Assertions.assertEquals(3, + testManager.getHistory().size(), "В истории появились дубли."); // удаляем задачу и проверяем состояние истории - уменьшилась ли она, и есть ли запись с удалённой задачей. testManager.deleteTask(1); - Assertions.assertEquals(2, testManager.getHistory().size(), "В истории не удалена запись."); + Assertions.assertEquals(2, + testManager.getHistory().size(), "В истории не удалена запись."); Assertions.assertNull(testManager.getTask(1), "Задача не удалена."); // повторяем то-же самое с подзадачей и эпиком testManager.deleteSubTask(3); - Assertions.assertEquals(1, testManager.getHistory().size(), "В истории не удалена запись."); + Assertions.assertEquals(1, + testManager.getHistory().size(), "В истории не удалена запись."); Assertions.assertNull(testManager.getSubTask(3), "Подзадача не удалена."); testManager.deleteEpic(2); - Assertions.assertEquals(0, testManager.getHistory().size(), "В истории не удалена запись."); + Assertions.assertEquals(0, + testManager.getHistory().size(), "В истории не удалена запись."); Assertions.assertNull(testManager.getEpic(2), "Эпик не удален."); } } \ No newline at end of file diff --git a/test/TestInFile.java b/test/TestTMWithFile.java similarity index 74% rename from test/TestInFile.java rename to test/TestTMWithFile.java index e7d8ec2..7f4e96d 100644 --- a/test/TestInFile.java +++ b/test/TestTMWithFile.java @@ -13,8 +13,10 @@ import java.io.File; import java.io.IOException; +import java.time.Duration; +import java.time.LocalDateTime; -class TestInFile { +class TestTMWithFile { private static TaskManager testManager; private static Task taskItem; @@ -50,16 +52,20 @@ void initializeTaskManager() { } @Test - void testFilesOperations() { + void writeAndReadDataFile_CorrectInputOutput() { // Проверяем что менеджер сохраняет данные в файл // Создаём элементы для добавления в менеджер - taskItem = new Task(testManager.getGlobalId(), - "Работа", "Просто задача", Status.NEW); - epicItem = new Epic(testManager.getGlobalId(), + taskItem = new Task(0, + "Работа", "Просто задача", Status.NEW, + LocalDateTime.of(2024, 1, 1, 10, 5, 0), + Duration.ofMinutes(50)); + epicItem = new Epic(0, "Этапы", "Поэтапная работа", Status.NEW); - subTaskItem = new SubTask(testManager.getGlobalId(), - "Этап 1", "Подготовка к работе", Status.NEW, 2); + subTaskItem = new SubTask(0, + "Этап 1", "Подготовка к работе", Status.NEW, 2, + LocalDateTime.of(2024, 1, 5, 8, 5, 0), + Duration.ofMinutes(250)); // Добавляем элементы в менеджер testManager.addTask(taskItem); @@ -97,15 +103,19 @@ void testFilesOperations() { } @Test - void addItem() { + void addItem_CorrectOfRecordInputAndSave() { // Создаём элементы для добавления в менеджер - taskItem = new Task(testManager.getGlobalId(), - "Работа", "Просто задача", Status.NEW); - epicItem = new Epic(testManager.getGlobalId(), + taskItem = new Task(0, + "Работа", "Просто задача", Status.NEW, + LocalDateTime.of(2024, 1, 5, 10, 5, 0), + Duration.ofMinutes(50)); + epicItem = new Epic(0, "Этапы", "Поэтапная работа", Status.NEW); - subTaskItem = new SubTask(testManager.getGlobalId(), - "Этап 1", "Подготовка к работе", Status.NEW, 2); + subTaskItem = new SubTask(0, + "Этап 1", "Подготовка к работе", Status.NEW, 2, + LocalDateTime.of(2024, 1, 1, 8, 5, 0), + Duration.ofMinutes(250)); // Добавляем элементы в менеджер testManager.addTask(taskItem); @@ -123,33 +133,46 @@ void addItem() { // Проверяем идентичность отправляемых элементов в менеджере с сохранёнными в менеджере по всем значениям // Проверяем обычные задачи - Assertions.assertEquals(taskItem.getName(), testManager.getTask(taskItem.getId()).getName()); - Assertions.assertEquals(taskItem.getDescription(), testManager.getTask(taskItem.getId()).getDescription()); - Assertions.assertEquals(taskItem.getStatus(), testManager.getTask(taskItem.getId()).getStatus()); + Assertions.assertEquals(taskItem.getName(), + testManager.getTask(taskItem.getId()).getName()); + Assertions.assertEquals(taskItem.getDescription(), + testManager.getTask(taskItem.getId()).getDescription()); + Assertions.assertEquals(taskItem.getStatus(), + testManager.getTask(taskItem.getId()).getStatus()); // Проверяем эпики - Assertions.assertEquals(epicItem.getName(), testManager.getEpic(epicItem.getId()).getName()); - Assertions.assertEquals(epicItem.getDescription(), testManager.getEpic(epicItem.getId()).getDescription()); - Assertions.assertEquals(epicItem.getStatus(), testManager.getEpic(epicItem.getId()).getStatus()); + Assertions.assertEquals(epicItem.getName(), + testManager.getEpic(epicItem.getId()).getName()); + Assertions.assertEquals(epicItem.getDescription(), + testManager.getEpic(epicItem.getId()).getDescription()); + Assertions.assertEquals(epicItem.getStatus(), + testManager.getEpic(epicItem.getId()).getStatus()); // Проверяем подзадачи - Assertions.assertEquals(subTaskItem.getName(), testManager.getSubTask(subTaskItem.getId()).getName()); + Assertions.assertEquals(subTaskItem.getName(), + testManager.getSubTask(subTaskItem.getId()).getName()); Assertions.assertEquals(subTaskItem.getDescription(), testManager.getSubTask(subTaskItem.getId()).getDescription()); - Assertions.assertEquals(subTaskItem.getStatus(), testManager.getSubTask(subTaskItem.getId()).getStatus()); - Assertions.assertEquals(subTaskItem.getIdEpic(), testManager.getSubTask(subTaskItem.getId()).getIdEpic()); + Assertions.assertEquals(subTaskItem.getStatus(), + testManager.getSubTask(subTaskItem.getId()).getStatus()); + Assertions.assertEquals(subTaskItem.getIdEpic(), + testManager.getSubTask(subTaskItem.getId()).getIdEpic()); } @Test - void testItems() { + void checkingIdentityOfItemsWithOneId() { // Создаём элементы для добавления в менеджер - taskItem = new Task(testManager.getGlobalId(), - "Работа", "Просто задача", Status.NEW); - epicItem = new Epic(testManager.getGlobalId(), + taskItem = new Task(0, + "Работа", "Просто задача", Status.NEW, + LocalDateTime.of(2024, 1, 1, 10, 5, 0), + Duration.ofMinutes(50)); + epicItem = new Epic(0, "Этапы", "Поэтапная работа", Status.NEW); - subTaskItem = new SubTask(testManager.getGlobalId(), - "Этап 1", "Подготовка к работе", Status.NEW, 2); + subTaskItem = new SubTask(0, + "Этап 1", "Подготовка к работе", Status.NEW, 2, + LocalDateTime.of(2024, 1, 1, 10, 5, 0), + Duration.ofMinutes(250)); // Добавляем элементы в менеджер testManager.addTask(taskItem); @@ -170,15 +193,19 @@ void testItems() { } @Test - void testHistory1() { + void addToHistoryAndChanges_HistoryIsCreatedRecordedCorrectlyAndChanged() { // Создаём элементы для добавления в менеджер - taskItem = new Task(testManager.getGlobalId(), - "Работа", "Просто задача", Status.NEW); - epicItem = new Epic(testManager.getGlobalId(), + taskItem = new Task(0, + "Работа", "Просто задача", Status.NEW, + LocalDateTime.of(2024, 1, 1, 12, 5, 0), + Duration.ofMinutes(50)); + epicItem = new Epic(0, "Этапы", "Поэтапная работа", Status.NEW); - subTaskItem = new SubTask(testManager.getGlobalId(), - "Этап 1", "Подготовка к работе", Status.NEW, 2); + subTaskItem = new SubTask(0, + "Этап 1", "Подготовка к работе", Status.NEW, 2, + LocalDateTime.of(2024, 1, 1, 8, 5, 0), + Duration.ofMinutes(250)); // Добавляем элементы в менеджер testManager.addTask(taskItem); @@ -206,21 +233,27 @@ void testHistory1() { Assertions.assertEquals(2, testManager.getHistory().size(), "В истории не одна запись."); // Сравниваем содержимое записи истории с содержимым задачи 1 до и после изменения. // Первая запись не должна соответствовать taskItem1, а вторая должна соответствовать taskItem2. - Assertions.assertNotEquals(taskItem1, testManager.getHistory().getLast(), "записи соответствуют."); - Assertions.assertEquals(taskItem2, testManager.getHistory().getLast(), "записи не соответствуют."); + Assertions.assertNotEquals(taskItem1, + testManager.getHistory().getLast(), "записи соответствуют."); + Assertions.assertEquals(taskItem2, + testManager.getHistory().getLast(), "записи не соответствуют."); } @Test - void testHistory2() { + void checkingChangesInHistory_DeletingItem_historyIsDeletedAndNoRepeatHistory() { // Создаём элементы для добавления в менеджер - taskItem = new Task(testManager.getGlobalId(), - "Работа", "Просто задача", Status.NEW); - epicItem = new Epic(testManager.getGlobalId(), + taskItem = new Task(0, + "Работа", "Просто задача", Status.NEW, + LocalDateTime.of(2024, 3, 1, 10, 5, 0), + Duration.ofMinutes(50)); + epicItem = new Epic(0, "Этапы", "Поэтапная работа", Status.NEW); - subTaskItem = new SubTask(testManager.getGlobalId(), - "Этап 1", "Подготовка к работе", Status.NEW, 2); + subTaskItem = new SubTask(0, + "Этап 1", "Подготовка к работе", Status.NEW, 2, + LocalDateTime.of(2024, 1, 1, 8, 5, 0), + Duration.ofMinutes(250)); // Добавляем элементы в менеджер testManager.addTask(taskItem); @@ -232,27 +265,33 @@ void testHistory2() { // Добавляем 1 элемент в историю при помощи запроса к менеджеру Task taskItem1 = testManager.getTask(1); // проверяем, что история изменилась на 1 - Assertions.assertEquals(2, testManager.getHistory().size(), "В историю не попала 1 запись."); + Assertions.assertEquals(2, + testManager.getHistory().size(), "В историю не попала 1 запись."); // Добавляем 2 элемент в историю при помощи запроса к менеджеру taskItem1 = testManager.getSubTask(3); // проверяем, что история изменилась ещё на 1 - Assertions.assertEquals(3, testManager.getHistory().size(), "В историю не попала 2 запись."); + Assertions.assertEquals(3, + testManager.getHistory().size(), "В историю не попала 2 запись."); // При помощи запросов к менеджеру проверяем - повторный запросы увеличили ли количество запросов в истории. taskItem1 = testManager.getTask(1); taskItem1 = testManager.getSubTask(3); taskItem1 = testManager.getEpic(2); // Проверяем, что история осталась с 3 элементам. Что дублирования записей нет. - Assertions.assertEquals(3, testManager.getHistory().size(), "В истории появились дубли."); + Assertions.assertEquals(3, + testManager.getHistory().size(), "В истории появились дубли."); // удаляем задачу и проверяем состояние истории - уменьшилась ли она, и есть ли запись с удалённой задачей. testManager.deleteTask(1); - Assertions.assertEquals(2, testManager.getHistory().size(), "В истории не удалена запись."); + Assertions.assertEquals(2, + testManager.getHistory().size(), "В истории не удалена запись."); Assertions.assertNull(testManager.getTask(1), "Задача не удалена."); // повторяем то-же самое с подзадачей и эпиком testManager.deleteSubTask(3); - Assertions.assertEquals(1, testManager.getHistory().size(), "В истории не удалена запись."); + Assertions.assertEquals(1, + testManager.getHistory().size(), "В истории не удалена запись."); Assertions.assertNull(testManager.getSubTask(3), "Подзадача не удалена."); testManager.deleteEpic(2); - Assertions.assertEquals(0, testManager.getHistory().size(), "В истории не удалена запись."); + Assertions.assertEquals(0, + testManager.getHistory().size(), "В истории не удалена запись."); Assertions.assertNull(testManager.getEpic(2), "Эпик не удален."); } } \ No newline at end of file