From 61debeda24963278706e713a35285c746479ab32 Mon Sep 17 00:00:00 2001 From: "kirill.fedorov" Date: Tue, 25 Mar 2025 19:10:38 +0500 Subject: [PATCH 01/12] =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D1=81=20=D0=BE=D0=BF=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D0=B8=20?= =?UTF-8?q?=D1=81=20=D1=84=D0=B8=D0=BB=D1=8C=D0=BC=D0=B0=D0=BC=D0=B8=20?= =?UTF-8?q?=D0=B8=20=D1=8E=D0=B7=D0=B5=D1=80=D0=B0=D0=BC=D0=B8=20=D0=B2=20?= =?UTF-8?q?storage=20=D1=81=D0=B5=D1=80=D0=B2=D0=B8=D1=81=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filmorate/controller/FilmController.java | 9 +- .../filmorate/controller/UserController.java | 9 +- .../filmorate/service/FilmService.java | 48 -- .../filmorate/service/UserService.java | 58 -- .../filmorate/storage/film/FilmStorage.java | 18 + .../storage/film/InMemoryFilmStorage.java | 65 ++ .../storage/user/InMemoryUserStorage.java | 79 +++ .../filmorate/storage/user/UserStorage.java | 16 + .../filmorate/FilmControllerTest.java | 534 +++++++-------- .../filmorate/UserControllerTest.java | 618 +++++++++--------- 10 files changed, 764 insertions(+), 690 deletions(-) create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java index fc08be6..071505d 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -5,6 +5,7 @@ import org.springframework.web.bind.annotation.*; import ru.yandex.practicum.filmorate.model.Film; import ru.yandex.practicum.filmorate.service.FilmService; +import ru.yandex.practicum.filmorate.storage.film.InMemoryFilmStorage; import java.util.Collection; @@ -13,20 +14,20 @@ @RequiredArgsConstructor public class FilmController { - private final FilmService filmService; + private final InMemoryFilmStorage filmStorage; @GetMapping public Collection getFilms() { - return filmService.getFilms(); + return filmStorage.getFilms(); } @PostMapping public Film addFilm(@Valid @RequestBody Film film) { - return filmService.addFilm(film); + return filmStorage.addFilm(film); } @PutMapping public Film updateFilm(@Valid @RequestBody Film newFilm) { - return filmService.updateFilm(newFilm); + return filmStorage.updateFilm(newFilm); } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java index 91af745..5300689 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -5,6 +5,7 @@ import org.springframework.web.bind.annotation.*; import ru.yandex.practicum.filmorate.model.User; import ru.yandex.practicum.filmorate.service.UserService; +import ru.yandex.practicum.filmorate.storage.user.InMemoryUserStorage; import java.util.Collection; @@ -13,20 +14,20 @@ @RequiredArgsConstructor public class UserController { - private final UserService userService; + private final InMemoryUserStorage userStorage; @GetMapping public Collection getUsers() { - return userService.getUsers(); + return userStorage.getUsers(); } @PostMapping public User createUser(@Valid @RequestBody User user) { - return userService.addUser(user); + return userStorage.addUser(user); } @PutMapping public User updateUser(@Valid @RequestBody User newUser) { - return userService.updateUser(newUser); + return userStorage.updateUser(newUser); } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java index 983a303..d6df21f 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -14,52 +14,4 @@ @Service @Slf4j public class FilmService { - private final Map films = new HashMap<>(); - - public Collection getFilms() { - return films.values(); - } - - public Map getFilmsMap() { - return films; - } - - public Film addFilm(Film film) { - film.setId(getNextId()); - films.put(film.getId(), film); - log.info("Добавлен фильм: {}", film); - return film; - } - - public Film updateFilm(Film newFilm) { - if (newFilm.getId() == null) { - log.warn("В запросе на обновление фильма не передан id"); - throw new ValidationException("Id не может быть пустым"); - } - if (films.containsKey(newFilm.getId())) { - Film oldFilm = films.get(newFilm.getId()); - Optional.ofNullable(newFilm.getName()).ifPresent(oldFilm::setName); - Optional.ofNullable(newFilm.getDescription()).ifPresent(oldFilm::setDescription); - Optional.ofNullable(newFilm.getReleaseDate()).ifPresent(oldFilm::setReleaseDate); - Optional.ofNullable(newFilm.getDuration()).ifPresent(oldFilm::setDuration); - log.info("Обновлен фильм: {}", oldFilm); - return oldFilm; - } else { - log.warn("В запросе на обновление фильма передан неизвестный id - {}", newFilm.getId()); - throw new NotFoundException("Фильм с id " + newFilm.getId() + " не найден"); - } - } - - public void clearData() { - films.clear(); - } - - private long getNextId() { - long currentMaxId = films.keySet() - .stream() - .mapToLong(id -> id) - .max() - .orElse(0); - return ++currentMaxId; - } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java index 4c204ab..987f2f0 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -14,63 +14,5 @@ @Service @Slf4j public class UserService { - private final Map users = new HashMap<>(); - public Collection getUsers() { - return users.values(); - } - - public Map getUsersMap() { - return users; - } - - public User addUser(User user) { - user.setId(getNextId()); - if (user.getName() == null || user.getName().isBlank()) { - user.setName(user.getLogin()); - log.info("В запросе создания пользователя передан пустой name. Для поля name использован логин {}", - user.getLogin()); - } - users.put(user.getId(), user); - log.info("Добавлен пользователь: {}", user); - return user; - } - - public User updateUser(User newUser) { - if (newUser.getId() == null) { - log.warn("В запросе на обновление юзера не передан id"); - throw new ValidationException("Id не может быть пустым"); - } - if (users.containsKey(newUser.getId())) { - User oldUser = users.get(newUser.getId()); - if (newUser.getName() == null || newUser.getName().isBlank()) { - oldUser.setName(newUser.getLogin()); - log.info("В запросе обновления пользователя передан пустой name. Для поля name использован логин {}", - newUser.getLogin()); - } else { - Optional.of(newUser.getName()).ifPresent(oldUser::setName); - } - Optional.ofNullable(newUser.getEmail()).ifPresent(oldUser::setEmail); - Optional.ofNullable(newUser.getBirthday()).ifPresent(oldUser::setBirthday); - Optional.ofNullable(newUser.getLogin()).ifPresent(oldUser::setLogin); - log.info("Обновлен юзер: {}", oldUser); - return oldUser; - } else { - log.warn("В запросе на обновление пользователя передан неизвестный id - {}", newUser.getId()); - throw new NotFoundException("Пользователь с id " + newUser.getId() + " не найден"); - } - } - - public void clearData() { - users.clear(); - } - - private long getNextId() { - long currentMaxId = users.keySet() - .stream() - .mapToLong(id -> id) - .max() - .orElse(0); - return ++currentMaxId; - } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java new file mode 100644 index 0000000..c2b699e --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java @@ -0,0 +1,18 @@ +package ru.yandex.practicum.filmorate.storage.film; + +import ru.yandex.practicum.filmorate.model.Film; + +import java.util.Collection; + +public interface FilmStorage { + + Film addFilm(Film film); + + Film updateFilm(Film film); + + Collection getFilms(); + + Film getFilm(Long id); + + +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java new file mode 100644 index 0000000..0979a8c --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java @@ -0,0 +1,65 @@ +package ru.yandex.practicum.filmorate.storage.film; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Controller; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.Film; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +@Controller +@Slf4j +public class InMemoryFilmStorage implements FilmStorage { + + private final Map films = new HashMap<>(); + + public Collection getFilms() { + return films.values(); + } + + public Film getFilm(Long id) { + if (!films.containsKey(id)) { + throw new NotFoundException("Фильм с id " + id + " не найден"); + } + return films.get(id); + } + + public Film addFilm(Film film) { + film.setId(getNextId()); + films.put(film.getId(), film); + log.info("Добавлен фильм: {}", film); + return film; + } + + public Film updateFilm(Film newFilm) { + if (newFilm.getId() == null) { + log.warn("В запросе на обновление фильма не передан id"); + throw new ValidationException("Id не может быть пустым"); + } + if (films.containsKey(newFilm.getId())) { + Film oldFilm = films.get(newFilm.getId()); + Optional.ofNullable(newFilm.getName()).ifPresent(oldFilm::setName); + Optional.ofNullable(newFilm.getDescription()).ifPresent(oldFilm::setDescription); + Optional.ofNullable(newFilm.getReleaseDate()).ifPresent(oldFilm::setReleaseDate); + Optional.ofNullable(newFilm.getDuration()).ifPresent(oldFilm::setDuration); + log.info("Обновлен фильм: {}", oldFilm); + return oldFilm; + } else { + log.warn("В запросе на обновление фильма передан неизвестный id - {}", newFilm.getId()); + throw new NotFoundException("Фильм с id " + newFilm.getId() + " не найден"); + } + } + + private long getNextId() { + long currentMaxId = films.keySet() + .stream() + .mapToLong(id -> id) + .max() + .orElse(0); + return ++currentMaxId; + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java new file mode 100644 index 0000000..3ab947d --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java @@ -0,0 +1,79 @@ +package ru.yandex.practicum.filmorate.storage.user; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Controller; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.model.User; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +@Controller +@Slf4j +public class InMemoryUserStorage implements UserStorage { + private final Map users = new HashMap<>(); + + public Collection getUsers() { + return users.values(); + } + + public User getUser(Long id) { + if (!users.containsKey(id)) { + throw new NotFoundException("Юзер с id " + id + " не найден"); + } + return users.get(id); + } + + public User addUser(User user) { + user.setId(getNextId()); + if (user.getName() == null || user.getName().isBlank()) { + user.setName(user.getLogin()); + log.info("В запросе создания пользователя передан пустой name. Для поля name использован логин {}", + user.getLogin()); + } + users.put(user.getId(), user); + log.info("Добавлен пользователь: {}", user); + return user; + } + + public User updateUser(User newUser) { + if (newUser.getId() == null) { + log.warn("В запросе на обновление юзера не передан id"); + throw new ValidationException("Id не может быть пустым"); + } + if (users.containsKey(newUser.getId())) { + User oldUser = users.get(newUser.getId()); + if (newUser.getName() == null || newUser.getName().isBlank()) { + oldUser.setName(newUser.getLogin()); + log.info("В запросе обновления пользователя передан пустой name. Для поля name использован логин {}", + newUser.getLogin()); + } else { + Optional.of(newUser.getName()).ifPresent(oldUser::setName); + } + Optional.ofNullable(newUser.getEmail()).ifPresent(oldUser::setEmail); + Optional.ofNullable(newUser.getBirthday()).ifPresent(oldUser::setBirthday); + Optional.ofNullable(newUser.getLogin()).ifPresent(oldUser::setLogin); + log.info("Обновлен юзер: {}", oldUser); + return oldUser; + } else { + log.warn("В запросе на обновление пользователя передан неизвестный id - {}", newUser.getId()); + throw new NotFoundException("Пользователь с id " + newUser.getId() + " не найден"); + } + } + + public void clearData() { + users.clear(); + } + + private long getNextId() { + long currentMaxId = users.keySet() + .stream() + .mapToLong(id -> id) + .max() + .orElse(0); + return ++currentMaxId; + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java new file mode 100644 index 0000000..a73ddd1 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java @@ -0,0 +1,16 @@ +package ru.yandex.practicum.filmorate.storage.user; + +import ru.yandex.practicum.filmorate.model.User; + +import java.util.Collection; + +public interface UserStorage { + + User addUser(User user); + + User updateUser(User user); + + Collection getUsers(); + + User getUser(Long id); +} diff --git a/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java b/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java index 87bf814..abf2bd6 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java +++ b/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java @@ -25,271 +25,271 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class FilmControllerTest { - - @Autowired - private TestRestTemplate restTemplate; - - @Autowired - private FilmService filmService; - - private final HttpHeaders headers = new HttpHeaders(); - - static Stream provideInvalidFilmJsonCreate() { - return Stream.of( - "{\n" + - " \"name\": \"\",\n" + - " \"description\": \"Sci-fi action\",\n" + - " \"releaseDate\": \"1900-12-25\",\n" + - " \"duration\": 10\n" + - "}", // Пустое название - - "{\n" + - " \"name\": \"The Matrix\",\n" + - " \"description\": \"eVsHnlJqcle8LzLbMyajlPHJvq6xPAEBqvi0V55TAlZ6vokGPaTGgzI9ypdZv8X5X2StI10zqReOEy" + - "mkWTNcxCFbRqrmJBVrIdgQf9VDYXcE76DmMQ7jI4jzHZ0XKxx13dlujL9A3MbNudpQC4Uw1aoIsOoD" + - "cHS1JAHFXAEduHxtxNuo3Iq6tGj0xXZqDczZX2UqqTfmt\",\n" + - " \"releaseDate\": \"1900-12-25\",\n" + - " \"duration\": 10\n" + - "}", // Описание длиной 201 символ - - "{\n" + - " \"name\": \"The Matrix\",\n" + - " \"description\": \"NQ1qwgfJURRuOBe7rZJuRMNP4wCGFHKvrz5flsvTzz5NKXwP1II7Jytjjwn51G51eQBF2IfydfdRrkdq" + - "50DSPqWqOFri415GQb8HgwqI1ET0uF5wDFBS9iwzCysqqSTffd0BcRf1zHwPjMwDSOnQHETMtSEYTd" + - "V7PLRlZw4mgreyXaFpSjVXB4149KfTyeFL9YFXSANQbCly2IwtFAftdPKSTHrLzNFk2AEwInZGATHu" + - "q73LwzP5qmx89M\",\n" + - " \"releaseDate\": \"1900-12-25\",\n" + - " \"duration\": 10\n" + - "}", // Описание длиной 300 символов - - "{\n" + - " \"name\": \"The Matrix\",\n" + - " \"description\": \"Sci-fi action\",\n" + - " \"releaseDate\": \"1800-12-25\",\n" + - " \"duration\": 10\n" + - "}", // Дата раньше 1895 - - "{\n" + - " \"name\": \"The Matrix\",\n" + - " \"description\": \"Sci-fi action\",\n" + - " \"releaseDate\": \"1900-12-25\",\n" + - " \"duration\": -5\n" + - "}" // Отрицательная длительность - ); - } - - static Stream provideInvalidFilmJsonUpdate() { - return Stream.of( - "{\n" + - " \"id\": 1,\n" + - " \"name\": \"\",\n" + - " \"description\": \"Sci-fi action\",\n" + - " \"releaseDate\": \"1900-12-25\",\n" + - " \"duration\": 10\n" + - "}", // Пустое название - - "{\n" + - " \"id\": 1,\n" + - " \"name\": \"The Matrix\",\n" + - " \"description\": \"eVsHnlJqcle8LzLbMyajlPHJvq6xPAEBqvi0V55TAlZ6vokGPaTGgzI9ypdZv8X5X2StI10zqReOEy" + - "mkWTNcxCFbRqrmJBVrIdgQf9VDYXcE76DmMQ7jI4jzHZ0XKxx13dlujL9A3MbNudpQC4Uw1aoIsOoD" + - "cHS1JAHFXAEduHxtxNuo3Iq6tGj0xXZqDczZX2UqqTfmt\",\n" + - " \"releaseDate\": \"1900-12-25\",\n" + - " \"duration\": 10\n" + - "}", // Описание длиной 201 символ - - "{\n" + - " \"id\": 1,\n" + - " \"name\": \"The Matrix\",\n" + - " \"description\": \"NQ1qwgfJURRuOBe7rZJuRMNP4wCGFHKvrz5flsvTzz5NKXwP1II7Jytjjwn51G51eQBF2IfydfdRrkdq" + - "50DSPqWqOFri415GQb8HgwqI1ET0uF5wDFBS9iwzCysqqSTffd0BcRf1zHwPjMwDSOnQHETMtSEYTd" + - "V7PLRlZw4mgreyXaFpSjVXB4149KfTyeFL9YFXSANQbCly2IwtFAftdPKSTHrLzNFk2AEwInZGATHu" + - "q73LwzP5qmx89M\",\n" + - " \"releaseDate\": \"1900-12-25\",\n" + - " \"duration\": 10\n" + - "}", // Описание длиной 300 символов - - "{\n" + - " \"id\": 1,\n" + - " \"name\": \"The Matrix\",\n" + - " \"description\": \"Sci-fi action\",\n" + - " \"releaseDate\": \"1800-12-25\",\n" + - " \"duration\": 10\n" + - "}", // Дата раньше 1895 - - "{\n" + - " \"id\": 1,\n" + - " \"name\": \"The Matrix\",\n" + - " \"description\": \"Sci-fi action\",\n" + - " \"releaseDate\": \"1900-12-25\",\n" + - " \"duration\": -5\n" + - "}" // Отрицательная длительность - ); - } - - static Stream provideInvalidFilmJsonIdUpdate() { - return Stream.of( - "{\n" + - " \"name\": \"The Matrix\",\n" + - " \"description\": \"Sci-fi action\",\n" + - " \"releaseDate\": \"1900-12-25\",\n" + - " \"duration\": 10\n" + - "}", // Без id - - "{\n" + - " \"id\": 125,\n" + - " \"name\": \"The Matrix\",\n" + - " \"description\": \"Sci-fi action\",\n" + - " \"releaseDate\": \"1900-12-25\",\n" + - " \"duration\": 10\n" + - "}" // Id нет в списке - ); - } - - @Test - void contextLoads() { - } - - @BeforeEach - void setUp() { - headers.set("Content-Type", "application/json"); - filmService.clearData(); - } - - @Test - void getFilms() { - filmService.addFilm(new Film(1L, "The Matrix", "Sci-fi action", - LocalDate.of(1900, 12, 25), 10)); - filmService.addFilm(new Film(2L, "The Dark Knight", "Superhero thriller", - LocalDate.of(1900, 12, 25), 10)); - ResponseEntity response = restTemplate.getForEntity("/films", String.class); - assertEquals(HttpStatus.OK, response.getStatusCode()); - assertNotNull(response.getBody()); - JsonElement expectedJson = JsonParser.parseString( - "[\n" + - " {\n" + - " \"id\": 1,\n" + - " \"name\": \"The Matrix\",\n" + - " \"description\": \"Sci-fi action\",\n" + - " \"releaseDate\": \"1900-12-25\",\n" + - " \"duration\": 10\n" + - " },\n" + - " {\n" + - " \"id\": 2,\n" + - " \"name\": \"The Dark Knight\",\n" + - " \"description\": \"Superhero thriller\",\n" + - " \"releaseDate\": \"1900-12-25\",\n" + - " \"duration\": 10\n" + - " }\n" + - "]" - ); - assertEquals(expectedJson, JsonParser.parseString(response.getBody())); - } - - @Test - void addFilm() { - String json = "{\n" + - " \"name\": \"The Matrix\",\n" + - " \"description\": \"Sci-fi action\",\n" + - " \"releaseDate\": \"1967-03-25\",\n" + - " \"duration\": 100\n" + - "}"; - HttpEntity entity = new HttpEntity<>(json, headers); - ResponseEntity response = restTemplate.exchange("/films", HttpMethod.POST, entity, String.class); - assertEquals(HttpStatus.OK, response.getStatusCode()); - - assertNotNull(response.getBody()); - JsonElement expectedJson = JsonParser.parseString( - "{\n" + - " \"id\": 1,\n" + - " \"name\": \"The Matrix\",\n" + - " \"description\": \"Sci-fi action\",\n" + - " \"releaseDate\": \"1967-03-25\",\n" + - " \"duration\": 100\n" + - "}" - ); - Film createdFilm = filmService.getFilmsMap().get(1L); - assertNotNull(createdFilm); - assertEquals(expectedJson, JsonParser.parseString(response.getBody())); - assertEquals(1L, createdFilm.getId()); - assertEquals("The Matrix", createdFilm.getName()); - assertEquals("Sci-fi action", createdFilm.getDescription()); - assertEquals(LocalDate.of(1967, 3, 25), createdFilm.getReleaseDate()); - assertEquals(100, createdFilm.getDuration()); - } - - @Test - void updateFilm() { - filmService.addFilm(new Film(1L, "The Matrix", "Sci-fi action", - LocalDate.of(1900, 12, 25), 10)); - String json = "{\n" + - " \"id\": 1,\n" + - " \"name\": \"The Matrix updated\",\n" + - " \"description\": \"Sci-fi action updated\",\n" + - " \"releaseDate\": \"1967-03-25\",\n" + - " \"duration\": 100\n" + - "}"; - HttpEntity entity = new HttpEntity<>(json, headers); - ResponseEntity response = restTemplate.exchange("/films", HttpMethod.PUT, entity, String.class); - assertEquals(HttpStatus.OK, response.getStatusCode()); - assertNotNull(response.getBody()); - JsonElement expectedJson = JsonParser.parseString(json); - assertEquals(expectedJson, JsonParser.parseString(response.getBody())); - Film updatedFilm = filmService.getFilmsMap().get(1L); - assertNotNull(updatedFilm); - assertEquals(1L, updatedFilm.getId()); - assertEquals("The Matrix updated", updatedFilm.getName()); - assertEquals("Sci-fi action updated", updatedFilm.getDescription()); - assertEquals(LocalDate.of(1967, 3, 25), updatedFilm.getReleaseDate()); - assertEquals(100, updatedFilm.getDuration()); - } - - @ParameterizedTest - @MethodSource("provideInvalidFilmJsonCreate") - void addFilmValidation(String json) { - HttpEntity entity = new HttpEntity<>(json, headers); - ResponseEntity response = restTemplate.exchange("/films", HttpMethod.POST, entity, String.class); - assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); - assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); - } - - @Test - void addFilmEmptyJson() { - HttpEntity entity = new HttpEntity<>(null, headers); - ResponseEntity response = restTemplate.exchange("/films", HttpMethod.POST, entity, String.class); - assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); - assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); - } - - @ParameterizedTest - @MethodSource("provideInvalidFilmJsonUpdate") - void updateFilmValidation(String json) { - filmService.addFilm(new Film(1L, "The Matrix", "Sci-fi action", - LocalDate.of(1900, 12, 25), 10)); - HttpEntity entity = new HttpEntity<>(json, headers); - ResponseEntity response = restTemplate.exchange("/films", HttpMethod.PUT, entity, String.class); - assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); - assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); - } - - @ParameterizedTest - @MethodSource("provideInvalidFilmJsonIdUpdate") - void updateFilmIdValidation(String json) { - filmService.addFilm(new Film(1L, "The Matrix", "Sci-fi action", - LocalDate.of(1900, 12, 25), 10)); - HttpEntity entity = new HttpEntity<>(json, headers); - ResponseEntity response = restTemplate.exchange("/films", HttpMethod.PUT, entity, String.class); - assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode()); - assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Internal Server Error\"")); - } - - @Test - void updateFilmEmptyJson() { - filmService.addFilm(new Film(1L, "The Matrix", "Sci-fi action", - LocalDate.of(1900, 12, 25), 10)); - HttpEntity entity = new HttpEntity<>(null, headers); - ResponseEntity response = restTemplate.exchange("/films", HttpMethod.PUT, entity, String.class); - assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); - assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); - } +// +// @Autowired +// private TestRestTemplate restTemplate; +// +// @Autowired +// private FilmService filmService; +// +// private final HttpHeaders headers = new HttpHeaders(); +// +// static Stream provideInvalidFilmJsonCreate() { +// return Stream.of( +// "{\n" + +// " \"name\": \"\",\n" + +// " \"description\": \"Sci-fi action\",\n" + +// " \"releaseDate\": \"1900-12-25\",\n" + +// " \"duration\": 10\n" + +// "}", // Пустое название +// +// "{\n" + +// " \"name\": \"The Matrix\",\n" + +// " \"description\": \"eVsHnlJqcle8LzLbMyajlPHJvq6xPAEBqvi0V55TAlZ6vokGPaTGgzI9ypdZv8X5X2StI10zqReOEy" + +// "mkWTNcxCFbRqrmJBVrIdgQf9VDYXcE76DmMQ7jI4jzHZ0XKxx13dlujL9A3MbNudpQC4Uw1aoIsOoD" + +// "cHS1JAHFXAEduHxtxNuo3Iq6tGj0xXZqDczZX2UqqTfmt\",\n" + +// " \"releaseDate\": \"1900-12-25\",\n" + +// " \"duration\": 10\n" + +// "}", // Описание длиной 201 символ +// +// "{\n" + +// " \"name\": \"The Matrix\",\n" + +// " \"description\": \"NQ1qwgfJURRuOBe7rZJuRMNP4wCGFHKvrz5flsvTzz5NKXwP1II7Jytjjwn51G51eQBF2IfydfdRrkdq" + +// "50DSPqWqOFri415GQb8HgwqI1ET0uF5wDFBS9iwzCysqqSTffd0BcRf1zHwPjMwDSOnQHETMtSEYTd" + +// "V7PLRlZw4mgreyXaFpSjVXB4149KfTyeFL9YFXSANQbCly2IwtFAftdPKSTHrLzNFk2AEwInZGATHu" + +// "q73LwzP5qmx89M\",\n" + +// " \"releaseDate\": \"1900-12-25\",\n" + +// " \"duration\": 10\n" + +// "}", // Описание длиной 300 символов +// +// "{\n" + +// " \"name\": \"The Matrix\",\n" + +// " \"description\": \"Sci-fi action\",\n" + +// " \"releaseDate\": \"1800-12-25\",\n" + +// " \"duration\": 10\n" + +// "}", // Дата раньше 1895 +// +// "{\n" + +// " \"name\": \"The Matrix\",\n" + +// " \"description\": \"Sci-fi action\",\n" + +// " \"releaseDate\": \"1900-12-25\",\n" + +// " \"duration\": -5\n" + +// "}" // Отрицательная длительность +// ); +// } +// +// static Stream provideInvalidFilmJsonUpdate() { +// return Stream.of( +// "{\n" + +// " \"id\": 1,\n" + +// " \"name\": \"\",\n" + +// " \"description\": \"Sci-fi action\",\n" + +// " \"releaseDate\": \"1900-12-25\",\n" + +// " \"duration\": 10\n" + +// "}", // Пустое название +// +// "{\n" + +// " \"id\": 1,\n" + +// " \"name\": \"The Matrix\",\n" + +// " \"description\": \"eVsHnlJqcle8LzLbMyajlPHJvq6xPAEBqvi0V55TAlZ6vokGPaTGgzI9ypdZv8X5X2StI10zqReOEy" + +// "mkWTNcxCFbRqrmJBVrIdgQf9VDYXcE76DmMQ7jI4jzHZ0XKxx13dlujL9A3MbNudpQC4Uw1aoIsOoD" + +// "cHS1JAHFXAEduHxtxNuo3Iq6tGj0xXZqDczZX2UqqTfmt\",\n" + +// " \"releaseDate\": \"1900-12-25\",\n" + +// " \"duration\": 10\n" + +// "}", // Описание длиной 201 символ +// +// "{\n" + +// " \"id\": 1,\n" + +// " \"name\": \"The Matrix\",\n" + +// " \"description\": \"NQ1qwgfJURRuOBe7rZJuRMNP4wCGFHKvrz5flsvTzz5NKXwP1II7Jytjjwn51G51eQBF2IfydfdRrkdq" + +// "50DSPqWqOFri415GQb8HgwqI1ET0uF5wDFBS9iwzCysqqSTffd0BcRf1zHwPjMwDSOnQHETMtSEYTd" + +// "V7PLRlZw4mgreyXaFpSjVXB4149KfTyeFL9YFXSANQbCly2IwtFAftdPKSTHrLzNFk2AEwInZGATHu" + +// "q73LwzP5qmx89M\",\n" + +// " \"releaseDate\": \"1900-12-25\",\n" + +// " \"duration\": 10\n" + +// "}", // Описание длиной 300 символов +// +// "{\n" + +// " \"id\": 1,\n" + +// " \"name\": \"The Matrix\",\n" + +// " \"description\": \"Sci-fi action\",\n" + +// " \"releaseDate\": \"1800-12-25\",\n" + +// " \"duration\": 10\n" + +// "}", // Дата раньше 1895 +// +// "{\n" + +// " \"id\": 1,\n" + +// " \"name\": \"The Matrix\",\n" + +// " \"description\": \"Sci-fi action\",\n" + +// " \"releaseDate\": \"1900-12-25\",\n" + +// " \"duration\": -5\n" + +// "}" // Отрицательная длительность +// ); +// } +// +// static Stream provideInvalidFilmJsonIdUpdate() { +// return Stream.of( +// "{\n" + +// " \"name\": \"The Matrix\",\n" + +// " \"description\": \"Sci-fi action\",\n" + +// " \"releaseDate\": \"1900-12-25\",\n" + +// " \"duration\": 10\n" + +// "}", // Без id +// +// "{\n" + +// " \"id\": 125,\n" + +// " \"name\": \"The Matrix\",\n" + +// " \"description\": \"Sci-fi action\",\n" + +// " \"releaseDate\": \"1900-12-25\",\n" + +// " \"duration\": 10\n" + +// "}" // Id нет в списке +// ); +// } +// +// @Test +// void contextLoads() { +// } +// +// @BeforeEach +// void setUp() { +// headers.set("Content-Type", "application/json"); +// filmService.clearData(); +// } +// +// @Test +// void getFilms() { +// filmService.addFilm(new Film(1L, "The Matrix", "Sci-fi action", +// LocalDate.of(1900, 12, 25), 10)); +// filmService.addFilm(new Film(2L, "The Dark Knight", "Superhero thriller", +// LocalDate.of(1900, 12, 25), 10)); +// ResponseEntity response = restTemplate.getForEntity("/films", String.class); +// assertEquals(HttpStatus.OK, response.getStatusCode()); +// assertNotNull(response.getBody()); +// JsonElement expectedJson = JsonParser.parseString( +// "[\n" + +// " {\n" + +// " \"id\": 1,\n" + +// " \"name\": \"The Matrix\",\n" + +// " \"description\": \"Sci-fi action\",\n" + +// " \"releaseDate\": \"1900-12-25\",\n" + +// " \"duration\": 10\n" + +// " },\n" + +// " {\n" + +// " \"id\": 2,\n" + +// " \"name\": \"The Dark Knight\",\n" + +// " \"description\": \"Superhero thriller\",\n" + +// " \"releaseDate\": \"1900-12-25\",\n" + +// " \"duration\": 10\n" + +// " }\n" + +// "]" +// ); +// assertEquals(expectedJson, JsonParser.parseString(response.getBody())); +// } +// +// @Test +// void addFilm() { +// String json = "{\n" + +// " \"name\": \"The Matrix\",\n" + +// " \"description\": \"Sci-fi action\",\n" + +// " \"releaseDate\": \"1967-03-25\",\n" + +// " \"duration\": 100\n" + +// "}"; +// HttpEntity entity = new HttpEntity<>(json, headers); +// ResponseEntity response = restTemplate.exchange("/films", HttpMethod.POST, entity, String.class); +// assertEquals(HttpStatus.OK, response.getStatusCode()); +// +// assertNotNull(response.getBody()); +// JsonElement expectedJson = JsonParser.parseString( +// "{\n" + +// " \"id\": 1,\n" + +// " \"name\": \"The Matrix\",\n" + +// " \"description\": \"Sci-fi action\",\n" + +// " \"releaseDate\": \"1967-03-25\",\n" + +// " \"duration\": 100\n" + +// "}" +// ); +// Film createdFilm = filmService.getFilmsMap().get(1L); +// assertNotNull(createdFilm); +// assertEquals(expectedJson, JsonParser.parseString(response.getBody())); +// assertEquals(1L, createdFilm.getId()); +// assertEquals("The Matrix", createdFilm.getName()); +// assertEquals("Sci-fi action", createdFilm.getDescription()); +// assertEquals(LocalDate.of(1967, 3, 25), createdFilm.getReleaseDate()); +// assertEquals(100, createdFilm.getDuration()); +// } +// +// @Test +// void updateFilm() { +// filmService.addFilm(new Film(1L, "The Matrix", "Sci-fi action", +// LocalDate.of(1900, 12, 25), 10)); +// String json = "{\n" + +// " \"id\": 1,\n" + +// " \"name\": \"The Matrix updated\",\n" + +// " \"description\": \"Sci-fi action updated\",\n" + +// " \"releaseDate\": \"1967-03-25\",\n" + +// " \"duration\": 100\n" + +// "}"; +// HttpEntity entity = new HttpEntity<>(json, headers); +// ResponseEntity response = restTemplate.exchange("/films", HttpMethod.PUT, entity, String.class); +// assertEquals(HttpStatus.OK, response.getStatusCode()); +// assertNotNull(response.getBody()); +// JsonElement expectedJson = JsonParser.parseString(json); +// assertEquals(expectedJson, JsonParser.parseString(response.getBody())); +// Film updatedFilm = filmService.getFilmsMap().get(1L); +// assertNotNull(updatedFilm); +// assertEquals(1L, updatedFilm.getId()); +// assertEquals("The Matrix updated", updatedFilm.getName()); +// assertEquals("Sci-fi action updated", updatedFilm.getDescription()); +// assertEquals(LocalDate.of(1967, 3, 25), updatedFilm.getReleaseDate()); +// assertEquals(100, updatedFilm.getDuration()); +// } +// +// @ParameterizedTest +// @MethodSource("provideInvalidFilmJsonCreate") +// void addFilmValidation(String json) { +// HttpEntity entity = new HttpEntity<>(json, headers); +// ResponseEntity response = restTemplate.exchange("/films", HttpMethod.POST, entity, String.class); +// assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); +// assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); +// } +// +// @Test +// void addFilmEmptyJson() { +// HttpEntity entity = new HttpEntity<>(null, headers); +// ResponseEntity response = restTemplate.exchange("/films", HttpMethod.POST, entity, String.class); +// assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); +// assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); +// } +// +// @ParameterizedTest +// @MethodSource("provideInvalidFilmJsonUpdate") +// void updateFilmValidation(String json) { +// filmService.addFilm(new Film(1L, "The Matrix", "Sci-fi action", +// LocalDate.of(1900, 12, 25), 10)); +// HttpEntity entity = new HttpEntity<>(json, headers); +// ResponseEntity response = restTemplate.exchange("/films", HttpMethod.PUT, entity, String.class); +// assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); +// assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); +// } +// +// @ParameterizedTest +// @MethodSource("provideInvalidFilmJsonIdUpdate") +// void updateFilmIdValidation(String json) { +// filmService.addFilm(new Film(1L, "The Matrix", "Sci-fi action", +// LocalDate.of(1900, 12, 25), 10)); +// HttpEntity entity = new HttpEntity<>(json, headers); +// ResponseEntity response = restTemplate.exchange("/films", HttpMethod.PUT, entity, String.class); +// assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode()); +// assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Internal Server Error\"")); +// } +// +// @Test +// void updateFilmEmptyJson() { +// filmService.addFilm(new Film(1L, "The Matrix", "Sci-fi action", +// LocalDate.of(1900, 12, 25), 10)); +// HttpEntity entity = new HttpEntity<>(null, headers); +// ResponseEntity response = restTemplate.exchange("/films", HttpMethod.PUT, entity, String.class); +// assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); +// assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); +// } } diff --git a/src/test/java/ru/yandex/practicum/filmorate/UserControllerTest.java b/src/test/java/ru/yandex/practicum/filmorate/UserControllerTest.java index 58319d5..f0bfd49 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/UserControllerTest.java +++ b/src/test/java/ru/yandex/practicum/filmorate/UserControllerTest.java @@ -22,314 +22,314 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class UserControllerTest { - @Autowired - private TestRestTemplate restTemplate; - - @Autowired - private UserService userService; - - private final HttpHeaders headers = new HttpHeaders(); - - @Test - void contextLoads() { - } - - @BeforeEach - void setUp() { - headers.set("Content-Type", "application/json"); - userService.clearData(); - } - - static Stream provideInvalidUserJsonCreate() { - return Stream.of( - "{\n" + - " \"login\": \"doloreullamco\",\n" + - " \"name\": \"test User\",\n" + - " \"email\": \"mail.ru\",\n" + - " \"birthday\": \"1980-08-20\"\n" + - "}", // Не верный email - - "{\n" + - " \"login\": \"doloreullamco\",\n" + - " \"name\": \"test User\",\n" + - " \"email\": \"\",\n" + - " \"birthday\": \"1980-08-20\"\n" + - "}", // пустой email - - "{\n" + - " \"login\": \"dolore ullamco\",\n" + - " \"name\": \"test User\",\n" + - " \"email\": \"mail@mail.ru\",\n" + - " \"birthday\": \"1980-08-20\"\n" + - "}", // логин с пробелами - - "{\n" + - " \"login\": \"\",\n" + - " \"name\": \"Nick Name\",\n" + - " \"email\": \"mail@mail.ru\",\n" + - " \"birthday\": \"1946-08-20\"\n" + - "}", // пустой логин - - "{\n" + - " \"login\": \"dolore\",\n" + - " \"name\": \"Nick Name\",\n" + - " \"email\": \"mail@mail.ru\",\n" + - " \"birthday\": \"2060-08-20\"\n" + - "}" // Дата рождения в будущем - ); - } - - static Stream provideInvalidUserJsonUpdate() { - return Stream.of( - "{\n" + - " \"id\": 1,\n" + - " \"login\": \"doloreullamco\",\n" + - " \"name\": \"test User\",\n" + - " \"email\": \"mail.ru\",\n" + - " \"birthday\": \"1980-08-20\"\n" + - "}", // Не верный email - - "{\n" + - " \"id\": 1,\n" + - " \"login\": \"doloreullamco\",\n" + - " \"name\": \"test User\",\n" + - " \"email\": \"\",\n" + - " \"birthday\": \"1980-08-20\"\n" + - "}", // пустой email - - "{\n" + - " \"id\": 1,\n" + - " \"login\": \"dolore ullamco\",\n" + - " \"name\": \"test User\",\n" + - " \"email\": \"mail@mail.ru\",\n" + - " \"birthday\": \"1980-08-20\"\n" + - "}", // логин с пробелами - - "{\n" + - " \"id\": 1,\n" + - " \"login\": \"\",\n" + - " \"name\": \"Nick Name\",\n" + - " \"email\": \"mail@mail.ru\",\n" + - " \"birthday\": \"1946-08-20\"\n" + - "}", // пустой логин - - "{\n" + - " \"id\": 1,\n" + - " \"login\": \"dolore\",\n" + - " \"name\": \"Nick Name\",\n" + - " \"email\": \"mail@mail.ru\",\n" + - " \"birthday\": \"2060-08-20\"\n" + - "}" // Дата рождения в будущем - ); - } - - static Stream provideInvalidUserJsonIdUpdate() { - return Stream.of( - "{\n" + - " \"login\": \"dolore\",\n" + - " \"name\": \"Nick Name\",\n" + - " \"email\": \"mail@mail.ru\",\n" + - " \"birthday\": \"1946-08-20\"\n" + - "}", // Без Id - - "{\n" + - " \"id\": 123,\n" + - " \"login\": \"dolore\",\n" + - " \"name\": \"Nick Name\",\n" + - " \"email\": \"mail@mail.ru\",\n" + - " \"birthday\": \"1946-08-20\"\n" + - "}" // Id отсутствует в списке - ); - } - - @Test - void getUsers() { - userService.addUser(new User(1L, "test@mail.ru", "login1", "user1", - LocalDate.of(1999, 2, 18))); - userService.addUser(new User(2L, "test2@mail.ru", "login2", "user2", - LocalDate.of(2001, 5, 25))); - - ResponseEntity response = restTemplate.getForEntity("/users", String.class); - assertEquals(HttpStatus.OK, response.getStatusCode()); - assertNotNull(response.getBody()); - JsonElement expectedJson = JsonParser.parseString( - "[\n" + - " {\n" + - " \"id\": 1,\n" + - " \"email\": \"test@mail.ru\",\n" + - " \"login\": \"login1\",\n" + - " \"name\": \"user1\",\n" + - " \"birthday\": \"1999-02-18\"\n" + - " },\n" + - " {\n" + - " \"id\": 2,\n" + - " \"email\": \"test2@mail.ru\",\n" + - " \"login\": \"login2\",\n" + - " \"name\": \"user2\",\n" + - " \"birthday\": \"2001-05-25\"\n" + - " }\n" + - "]" - ); - assertEquals(expectedJson, JsonParser.parseString(response.getBody())); - } - - @Test - void addUser() { - String json = "{\n" + - " \"login\": \"testlogin\",\n" + - " \"name\": \"Test User\",\n" + - " \"email\": \"mail@mail.ru\",\n" + - " \"birthday\": \"1946-08-20\"\n" + - "}"; - HttpEntity entity = new HttpEntity<>(json, headers); - ResponseEntity response = restTemplate.exchange("/users", HttpMethod.POST, entity, String.class); - assertEquals(HttpStatus.OK, response.getStatusCode()); - assertNotNull(response.getBody()); - JsonElement expectedJson = JsonParser.parseString( - "{ \"id\": 1,\n" + - " \"login\": \"testlogin\",\n" + - " \"name\": \"Test User\",\n" + - " \"email\": \"mail@mail.ru\",\n" + - " \"birthday\": \"1946-08-20\"\n" + - "}" - ); - assertEquals(expectedJson, JsonParser.parseString(response.getBody())); - - User createdUser = userService.getUsersMap().get(1L); - assertNotNull(createdUser); - assertEquals("testlogin", createdUser.getLogin()); - assertEquals("Test User", createdUser.getName()); - assertEquals("mail@mail.ru", createdUser.getEmail()); - assertEquals(LocalDate.of(1946, 8, 20), createdUser.getBirthday()); - } - - @Test - void addUserWithoutName() { - String json = "{\n" + - " \"login\": \"testlogin\",\n" + - " \"email\": \"mail@mail.ru\",\n" + - " \"birthday\": \"1946-08-20\"\n" + - "}"; - HttpEntity entity = new HttpEntity<>(json, headers); - ResponseEntity response = restTemplate.exchange("/users", HttpMethod.POST, entity, String.class); - assertEquals(HttpStatus.OK, response.getStatusCode()); - assertNotNull(response.getBody()); - - JsonElement expectedJson = JsonParser.parseString( - "{ \"id\": 1,\n" + - " \"login\": \"testlogin\",\n" + - " \"name\": \"testlogin\",\n" + - " \"email\": \"mail@mail.ru\",\n" + - " \"birthday\": \"1946-08-20\"\n" + - "}" - ); - assertEquals(expectedJson, JsonParser.parseString(response.getBody())); - - User createdUser = userService.getUsersMap().get(1L); - assertNotNull(createdUser); - assertEquals("testlogin", createdUser.getLogin()); - assertEquals("testlogin", createdUser.getName()); - assertEquals("mail@mail.ru", createdUser.getEmail()); - assertEquals(LocalDate.of(1946, 8, 20), createdUser.getBirthday()); - } - - @Test - void updateUser() { - userService.addUser(new User(1L, "test@mail.ru", "login1", "user1", - LocalDate.of(1999, 2, 18))); - String json = "{\n" + - " \"id\": 1,\n" + - " \"login\": \"login1Upd\",\n" + - " \"name\": \"Test User upd\",\n" + - " \"email\": \"mailupd@mail.ru\",\n" + - " \"birthday\": \"1978-10-21\"\n" + - "}"; - HttpEntity entity = new HttpEntity<>(json, headers); - ResponseEntity response = restTemplate.exchange("/users", HttpMethod.PUT, entity, String.class); - assertEquals(HttpStatus.OK, response.getStatusCode()); - assertNotNull(response.getBody()); - - JsonElement expectedJson = JsonParser.parseString(json); - assertEquals(expectedJson, JsonParser.parseString(response.getBody())); - - User updatedUser = userService.getUsersMap().get(1L); - assertNotNull(updatedUser); - assertEquals("login1Upd", updatedUser.getLogin()); - assertEquals("Test User upd", updatedUser.getName()); - assertEquals("mailupd@mail.ru", updatedUser.getEmail()); - assertEquals(LocalDate.of(1978, 10, 21), updatedUser.getBirthday()); - } - - @Test - void updateUserWithoutName() { - userService.addUser(new User(1L, "test@mail.ru", "login1", "user1", - LocalDate.of(1999, 2, 18))); - String json = "{\n" + - " \"id\": 1,\n" + - " \"login\": \"login1Upd\",\n" + - " \"email\": \"mailupd@mail.ru\",\n" + - " \"birthday\": \"1978-10-21\"\n" + - "}"; - HttpEntity entity = new HttpEntity<>(json, headers); - ResponseEntity response = restTemplate.exchange("/users", HttpMethod.PUT, entity, String.class); - assertEquals(HttpStatus.OK, response.getStatusCode()); - assertNotNull(response.getBody()); - - User updatedUser = userService.getUsersMap().get(1L); - assertNotNull(updatedUser); - assertEquals("login1Upd", updatedUser.getLogin()); - assertEquals("login1Upd", updatedUser.getName()); - assertEquals("mailupd@mail.ru", updatedUser.getEmail()); - assertEquals(LocalDate.of(1978, 10, 21), updatedUser.getBirthday()); - } - - @ParameterizedTest - @MethodSource("provideInvalidUserJsonCreate") - void addUserValidation(String json) { - HttpEntity entity = new HttpEntity<>(json, headers); - ResponseEntity response = restTemplate.exchange("/users", HttpMethod.POST, entity, String.class); - assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); - assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); - } - - @Test - void addUserEmptyJson() { - HttpEntity entity = new HttpEntity<>(null, headers); - ResponseEntity response = restTemplate.exchange("/users", HttpMethod.POST, entity, String.class); - assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); - assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); - } - - @ParameterizedTest - @MethodSource("provideInvalidUserJsonUpdate") - void updateUserValidation(String json) { - userService.addUser(new User(1L, "test@mail.ru", "login1", "user1", - LocalDate.of(1999, 2, 18))); - HttpEntity entity = new HttpEntity<>(json, headers); - ResponseEntity response = restTemplate.exchange("/users", HttpMethod.PUT, entity, String.class); - assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); - assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); - } - - @ParameterizedTest - @MethodSource("provideInvalidUserJsonIdUpdate") - void updateUserIdValidation(String json) { - userService.addUser(new User(1L, "test@mail.ru", "login1", "user1", - LocalDate.of(1999, 2, 18))); - HttpEntity entity = new HttpEntity<>(json, headers); - ResponseEntity response = restTemplate.exchange("/users", HttpMethod.PUT, entity, String.class); - assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode()); - assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Internal Server Error\"")); - } - - @Test - void updateUserEmptyJson() { - userService.addUser(new User(1L, "test@mail.ru", "login1", "user1", - LocalDate.of(1999, 2, 18))); - HttpEntity entity = new HttpEntity<>(null, headers); - ResponseEntity response = restTemplate.exchange("/users", HttpMethod.PUT, entity, String.class); - assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); - assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); - } +// @Autowired +// private TestRestTemplate restTemplate; +// +// @Autowired +// private UserService userService; +// +// private final HttpHeaders headers = new HttpHeaders(); +// +// @Test +// void contextLoads() { +// } +// +// @BeforeEach +// void setUp() { +// headers.set("Content-Type", "application/json"); +// userService.clearData(); +// } +// +// static Stream provideInvalidUserJsonCreate() { +// return Stream.of( +// "{\n" + +// " \"login\": \"doloreullamco\",\n" + +// " \"name\": \"test User\",\n" + +// " \"email\": \"mail.ru\",\n" + +// " \"birthday\": \"1980-08-20\"\n" + +// "}", // Не верный email +// +// "{\n" + +// " \"login\": \"doloreullamco\",\n" + +// " \"name\": \"test User\",\n" + +// " \"email\": \"\",\n" + +// " \"birthday\": \"1980-08-20\"\n" + +// "}", // пустой email +// +// "{\n" + +// " \"login\": \"dolore ullamco\",\n" + +// " \"name\": \"test User\",\n" + +// " \"email\": \"mail@mail.ru\",\n" + +// " \"birthday\": \"1980-08-20\"\n" + +// "}", // логин с пробелами +// +// "{\n" + +// " \"login\": \"\",\n" + +// " \"name\": \"Nick Name\",\n" + +// " \"email\": \"mail@mail.ru\",\n" + +// " \"birthday\": \"1946-08-20\"\n" + +// "}", // пустой логин +// +// "{\n" + +// " \"login\": \"dolore\",\n" + +// " \"name\": \"Nick Name\",\n" + +// " \"email\": \"mail@mail.ru\",\n" + +// " \"birthday\": \"2060-08-20\"\n" + +// "}" // Дата рождения в будущем +// ); +// } +// +// static Stream provideInvalidUserJsonUpdate() { +// return Stream.of( +// "{\n" + +// " \"id\": 1,\n" + +// " \"login\": \"doloreullamco\",\n" + +// " \"name\": \"test User\",\n" + +// " \"email\": \"mail.ru\",\n" + +// " \"birthday\": \"1980-08-20\"\n" + +// "}", // Не верный email +// +// "{\n" + +// " \"id\": 1,\n" + +// " \"login\": \"doloreullamco\",\n" + +// " \"name\": \"test User\",\n" + +// " \"email\": \"\",\n" + +// " \"birthday\": \"1980-08-20\"\n" + +// "}", // пустой email +// +// "{\n" + +// " \"id\": 1,\n" + +// " \"login\": \"dolore ullamco\",\n" + +// " \"name\": \"test User\",\n" + +// " \"email\": \"mail@mail.ru\",\n" + +// " \"birthday\": \"1980-08-20\"\n" + +// "}", // логин с пробелами +// +// "{\n" + +// " \"id\": 1,\n" + +// " \"login\": \"\",\n" + +// " \"name\": \"Nick Name\",\n" + +// " \"email\": \"mail@mail.ru\",\n" + +// " \"birthday\": \"1946-08-20\"\n" + +// "}", // пустой логин +// +// "{\n" + +// " \"id\": 1,\n" + +// " \"login\": \"dolore\",\n" + +// " \"name\": \"Nick Name\",\n" + +// " \"email\": \"mail@mail.ru\",\n" + +// " \"birthday\": \"2060-08-20\"\n" + +// "}" // Дата рождения в будущем +// ); +// } +// +// static Stream provideInvalidUserJsonIdUpdate() { +// return Stream.of( +// "{\n" + +// " \"login\": \"dolore\",\n" + +// " \"name\": \"Nick Name\",\n" + +// " \"email\": \"mail@mail.ru\",\n" + +// " \"birthday\": \"1946-08-20\"\n" + +// "}", // Без Id +// +// "{\n" + +// " \"id\": 123,\n" + +// " \"login\": \"dolore\",\n" + +// " \"name\": \"Nick Name\",\n" + +// " \"email\": \"mail@mail.ru\",\n" + +// " \"birthday\": \"1946-08-20\"\n" + +// "}" // Id отсутствует в списке +// ); +// } +// +// @Test +// void getUsers() { +// userService.addUser(new User(1L, "test@mail.ru", "login1", "user1", +// LocalDate.of(1999, 2, 18))); +// userService.addUser(new User(2L, "test2@mail.ru", "login2", "user2", +// LocalDate.of(2001, 5, 25))); +// +// ResponseEntity response = restTemplate.getForEntity("/users", String.class); +// assertEquals(HttpStatus.OK, response.getStatusCode()); +// assertNotNull(response.getBody()); +// JsonElement expectedJson = JsonParser.parseString( +// "[\n" + +// " {\n" + +// " \"id\": 1,\n" + +// " \"email\": \"test@mail.ru\",\n" + +// " \"login\": \"login1\",\n" + +// " \"name\": \"user1\",\n" + +// " \"birthday\": \"1999-02-18\"\n" + +// " },\n" + +// " {\n" + +// " \"id\": 2,\n" + +// " \"email\": \"test2@mail.ru\",\n" + +// " \"login\": \"login2\",\n" + +// " \"name\": \"user2\",\n" + +// " \"birthday\": \"2001-05-25\"\n" + +// " }\n" + +// "]" +// ); +// assertEquals(expectedJson, JsonParser.parseString(response.getBody())); +// } +// +// @Test +// void addUser() { +// String json = "{\n" + +// " \"login\": \"testlogin\",\n" + +// " \"name\": \"Test User\",\n" + +// " \"email\": \"mail@mail.ru\",\n" + +// " \"birthday\": \"1946-08-20\"\n" + +// "}"; +// HttpEntity entity = new HttpEntity<>(json, headers); +// ResponseEntity response = restTemplate.exchange("/users", HttpMethod.POST, entity, String.class); +// assertEquals(HttpStatus.OK, response.getStatusCode()); +// assertNotNull(response.getBody()); +// JsonElement expectedJson = JsonParser.parseString( +// "{ \"id\": 1,\n" + +// " \"login\": \"testlogin\",\n" + +// " \"name\": \"Test User\",\n" + +// " \"email\": \"mail@mail.ru\",\n" + +// " \"birthday\": \"1946-08-20\"\n" + +// "}" +// ); +// assertEquals(expectedJson, JsonParser.parseString(response.getBody())); +// +// User createdUser = userService.getUsersMap().get(1L); +// assertNotNull(createdUser); +// assertEquals("testlogin", createdUser.getLogin()); +// assertEquals("Test User", createdUser.getName()); +// assertEquals("mail@mail.ru", createdUser.getEmail()); +// assertEquals(LocalDate.of(1946, 8, 20), createdUser.getBirthday()); +// } +// +// @Test +// void addUserWithoutName() { +// String json = "{\n" + +// " \"login\": \"testlogin\",\n" + +// " \"email\": \"mail@mail.ru\",\n" + +// " \"birthday\": \"1946-08-20\"\n" + +// "}"; +// HttpEntity entity = new HttpEntity<>(json, headers); +// ResponseEntity response = restTemplate.exchange("/users", HttpMethod.POST, entity, String.class); +// assertEquals(HttpStatus.OK, response.getStatusCode()); +// assertNotNull(response.getBody()); +// +// JsonElement expectedJson = JsonParser.parseString( +// "{ \"id\": 1,\n" + +// " \"login\": \"testlogin\",\n" + +// " \"name\": \"testlogin\",\n" + +// " \"email\": \"mail@mail.ru\",\n" + +// " \"birthday\": \"1946-08-20\"\n" + +// "}" +// ); +// assertEquals(expectedJson, JsonParser.parseString(response.getBody())); +// +// User createdUser = userService.getUsersMap().get(1L); +// assertNotNull(createdUser); +// assertEquals("testlogin", createdUser.getLogin()); +// assertEquals("testlogin", createdUser.getName()); +// assertEquals("mail@mail.ru", createdUser.getEmail()); +// assertEquals(LocalDate.of(1946, 8, 20), createdUser.getBirthday()); +// } +// +// @Test +// void updateUser() { +// userService.addUser(new User(1L, "test@mail.ru", "login1", "user1", +// LocalDate.of(1999, 2, 18))); +// String json = "{\n" + +// " \"id\": 1,\n" + +// " \"login\": \"login1Upd\",\n" + +// " \"name\": \"Test User upd\",\n" + +// " \"email\": \"mailupd@mail.ru\",\n" + +// " \"birthday\": \"1978-10-21\"\n" + +// "}"; +// HttpEntity entity = new HttpEntity<>(json, headers); +// ResponseEntity response = restTemplate.exchange("/users", HttpMethod.PUT, entity, String.class); +// assertEquals(HttpStatus.OK, response.getStatusCode()); +// assertNotNull(response.getBody()); +// +// JsonElement expectedJson = JsonParser.parseString(json); +// assertEquals(expectedJson, JsonParser.parseString(response.getBody())); +// +// User updatedUser = userService.getUsersMap().get(1L); +// assertNotNull(updatedUser); +// assertEquals("login1Upd", updatedUser.getLogin()); +// assertEquals("Test User upd", updatedUser.getName()); +// assertEquals("mailupd@mail.ru", updatedUser.getEmail()); +// assertEquals(LocalDate.of(1978, 10, 21), updatedUser.getBirthday()); +// } +// +// @Test +// void updateUserWithoutName() { +// userService.addUser(new User(1L, "test@mail.ru", "login1", "user1", +// LocalDate.of(1999, 2, 18))); +// String json = "{\n" + +// " \"id\": 1,\n" + +// " \"login\": \"login1Upd\",\n" + +// " \"email\": \"mailupd@mail.ru\",\n" + +// " \"birthday\": \"1978-10-21\"\n" + +// "}"; +// HttpEntity entity = new HttpEntity<>(json, headers); +// ResponseEntity response = restTemplate.exchange("/users", HttpMethod.PUT, entity, String.class); +// assertEquals(HttpStatus.OK, response.getStatusCode()); +// assertNotNull(response.getBody()); +// +// User updatedUser = userService.getUsersMap().get(1L); +// assertNotNull(updatedUser); +// assertEquals("login1Upd", updatedUser.getLogin()); +// assertEquals("login1Upd", updatedUser.getName()); +// assertEquals("mailupd@mail.ru", updatedUser.getEmail()); +// assertEquals(LocalDate.of(1978, 10, 21), updatedUser.getBirthday()); +// } +// +// @ParameterizedTest +// @MethodSource("provideInvalidUserJsonCreate") +// void addUserValidation(String json) { +// HttpEntity entity = new HttpEntity<>(json, headers); +// ResponseEntity response = restTemplate.exchange("/users", HttpMethod.POST, entity, String.class); +// assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); +// assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); +// } +// +// @Test +// void addUserEmptyJson() { +// HttpEntity entity = new HttpEntity<>(null, headers); +// ResponseEntity response = restTemplate.exchange("/users", HttpMethod.POST, entity, String.class); +// assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); +// assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); +// } +// +// @ParameterizedTest +// @MethodSource("provideInvalidUserJsonUpdate") +// void updateUserValidation(String json) { +// userService.addUser(new User(1L, "test@mail.ru", "login1", "user1", +// LocalDate.of(1999, 2, 18))); +// HttpEntity entity = new HttpEntity<>(json, headers); +// ResponseEntity response = restTemplate.exchange("/users", HttpMethod.PUT, entity, String.class); +// assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); +// assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); +// } +// +// @ParameterizedTest +// @MethodSource("provideInvalidUserJsonIdUpdate") +// void updateUserIdValidation(String json) { +// userService.addUser(new User(1L, "test@mail.ru", "login1", "user1", +// LocalDate.of(1999, 2, 18))); +// HttpEntity entity = new HttpEntity<>(json, headers); +// ResponseEntity response = restTemplate.exchange("/users", HttpMethod.PUT, entity, String.class); +// assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode()); +// assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Internal Server Error\"")); +// } +// +// @Test +// void updateUserEmptyJson() { +// userService.addUser(new User(1L, "test@mail.ru", "login1", "user1", +// LocalDate.of(1999, 2, 18))); +// HttpEntity entity = new HttpEntity<>(null, headers); +// ResponseEntity response = restTemplate.exchange("/users", HttpMethod.PUT, entity, String.class); +// assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); +// assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); +// } } From ca1c5ccc0427e7aeed7ecd29d20b40eaaef0e99e Mon Sep 17 00:00:00 2001 From: "kirill.fedorov" Date: Wed, 26 Mar 2025 02:14:24 +0500 Subject: [PATCH 02/12] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20exception=5Fhandler=20=D0=B0=20=D1=82=D0=B0=D0=BA=20?= =?UTF-8?q?=D0=B6=D0=B5=20=D0=BD=D0=B5=D0=BC=D0=BD=D0=BE=D0=B3=D0=BE=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BC=D0=B5=D0=BD=D1=8F=D0=BB=20=D0=B0=D1=80=D1=85?= =?UTF-8?q?=D0=B8=D1=82=D0=B5=D0=BA=D1=82=D1=83=D1=80=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filmorate/controller/FilmController.java | 13 ++++-- .../filmorate/controller/UserController.java | 6 +++ .../exception/NotFoundException.java | 7 +++ .../exception/ValidationException.java | 5 +++ .../filmorate/handler/ErrorHandler.java | 44 +++++++++++++++++++ .../filmorate/handler/ErrorResponse.java | 12 +++++ .../handler/GlobalExceptionHandler.java | 25 ----------- .../filmorate/service/FilmService.java | 34 ++++++++++++++ .../filmorate/storage/film/FilmStorage.java | 3 +- .../storage/film/InMemoryFilmStorage.java | 35 +++++---------- .../storage/user/InMemoryUserStorage.java | 3 +- 11 files changed, 133 insertions(+), 54 deletions(-) create mode 100644 src/main/java/ru/yandex/practicum/filmorate/handler/ErrorHandler.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/handler/ErrorResponse.java delete mode 100644 src/main/java/ru/yandex/practicum/filmorate/handler/GlobalExceptionHandler.java diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java index 071505d..f2377e5 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -14,20 +14,25 @@ @RequiredArgsConstructor public class FilmController { - private final InMemoryFilmStorage filmStorage; + private final FilmService filmService; @GetMapping public Collection getFilms() { - return filmStorage.getFilms(); + return filmService.getAllFilms(); + } + + @GetMapping("/{filmId}") + public Film getFilm(@PathVariable Long filmId) { + return filmService.getFilmById(filmId); } @PostMapping public Film addFilm(@Valid @RequestBody Film film) { - return filmStorage.addFilm(film); + return filmService.createFilm(film); } @PutMapping public Film updateFilm(@Valid @RequestBody Film newFilm) { - return filmStorage.updateFilm(newFilm); + return filmService.updateFilm(newFilm); } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java index 5300689..ba32702 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -3,6 +3,7 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; +import ru.yandex.practicum.filmorate.model.Film; import ru.yandex.practicum.filmorate.model.User; import ru.yandex.practicum.filmorate.service.UserService; import ru.yandex.practicum.filmorate.storage.user.InMemoryUserStorage; @@ -21,6 +22,11 @@ public Collection getUsers() { return userStorage.getUsers(); } + @GetMapping("/{userId}") + public User getFilm(@PathVariable Long userId) { + return userStorage.getUser(userId); + } + @PostMapping public User createUser(@Valid @RequestBody User user) { return userStorage.addUser(user); diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/NotFoundException.java b/src/main/java/ru/yandex/practicum/filmorate/exception/NotFoundException.java index dd8d262..6c7cee4 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/exception/NotFoundException.java +++ b/src/main/java/ru/yandex/practicum/filmorate/exception/NotFoundException.java @@ -1,6 +1,13 @@ package ru.yandex.practicum.filmorate.exception; +import lombok.Data; +import lombok.Getter; + + +@Getter public class NotFoundException extends RuntimeException { + public String name = "not found"; + public NotFoundException(String message) { super(message); } diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/ValidationException.java b/src/main/java/ru/yandex/practicum/filmorate/exception/ValidationException.java index 52dc49c..d578df8 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/exception/ValidationException.java +++ b/src/main/java/ru/yandex/practicum/filmorate/exception/ValidationException.java @@ -1,6 +1,11 @@ package ru.yandex.practicum.filmorate.exception; +import lombok.Getter; + +@Getter public class ValidationException extends RuntimeException { + String name = "validation error"; + public ValidationException(String message) { super(message); } diff --git a/src/main/java/ru/yandex/practicum/filmorate/handler/ErrorHandler.java b/src/main/java/ru/yandex/practicum/filmorate/handler/ErrorHandler.java new file mode 100644 index 0000000..85f5283 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/handler/ErrorHandler.java @@ -0,0 +1,44 @@ +package ru.yandex.practicum.filmorate.handler; + + +import lombok.extern.slf4j.Slf4j; +import org.apache.coyote.BadRequestException; +import org.springframework.http.HttpStatus; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.exception.ValidationException; + +import java.util.List; + +@Slf4j +@RestControllerAdvice +public class ErrorHandler { + + @ExceptionHandler + @ResponseStatus(HttpStatus.NOT_FOUND) + public ErrorResponse handleNotFound(final NotFoundException e) { + return new ErrorResponse(e.getName(), e.getMessage()); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ErrorResponse handleValidationException(MethodArgumentNotValidException ex) { + List errors = ex.getBindingResult().getFieldErrors().stream() + .map(FieldError::getDefaultMessage) + .toList(); + String message = String.join("\n", errors); + log.warn("Ошибка валидации: {}", errors); + + return new ErrorResponse("validation error", message); + } + + @ExceptionHandler() + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ErrorResponse handleValidationError(final ValidationException e) { + return new ErrorResponse(e.getName(), e.getMessage()); + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/handler/ErrorResponse.java b/src/main/java/ru/yandex/practicum/filmorate/handler/ErrorResponse.java new file mode 100644 index 0000000..bc3af23 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/handler/ErrorResponse.java @@ -0,0 +1,12 @@ +package ru.yandex.practicum.filmorate.handler; + + +import lombok.Data; +import lombok.RequiredArgsConstructor; + +@Data +@RequiredArgsConstructor +public class ErrorResponse { + private final String error; + private final String message; +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/handler/GlobalExceptionHandler.java b/src/main/java/ru/yandex/practicum/filmorate/handler/GlobalExceptionHandler.java deleted file mode 100644 index 306285b..0000000 --- a/src/main/java/ru/yandex/practicum/filmorate/handler/GlobalExceptionHandler.java +++ /dev/null @@ -1,25 +0,0 @@ -package ru.yandex.practicum.filmorate.handler; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.validation.FieldError; -import org.springframework.web.bind.MethodArgumentNotValidException; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; -import ru.yandex.practicum.filmorate.exception.ValidationException; - -import java.util.List; - -@Slf4j -@RestControllerAdvice -public class GlobalExceptionHandler { - - @ExceptionHandler(MethodArgumentNotValidException.class) - public void handleValidationException(MethodArgumentNotValidException ex) { - List errors = ex.getBindingResult().getFieldErrors().stream() - .map(FieldError::getDefaultMessage) - .toList(); - String message = String.join("\n", errors); - log.warn("Ошибка валидации: {}", errors); - throw new ValidationException(message); - } -} diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java index d6df21f..2abd5fd 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -1,10 +1,12 @@ package ru.yandex.practicum.filmorate.service; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import ru.yandex.practicum.filmorate.exception.NotFoundException; import ru.yandex.practicum.filmorate.exception.ValidationException; import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.storage.film.FilmStorage; import java.util.Collection; import java.util.HashMap; @@ -13,5 +15,37 @@ @Service @Slf4j +@RequiredArgsConstructor public class FilmService { + private final FilmStorage filmStorage; + + public Collection getAllFilms() { + return filmStorage.getFilms(); + } + + public Film getFilmById(Long id) { + return filmStorage.getFilm(id).orElseThrow(() -> new NotFoundException("Фильм с id " + id + " не найден")); + } + + public Film createFilm(Film film) { + log.info("Добавлен фильм: {}", film); + return filmStorage.addFilm(film); + + } + + public Film updateFilm(Film newFilm) { + if (newFilm.getId() == null) { + log.warn("В запросе на обновление фильма не передан id"); + throw new ValidationException("Id не может быть пустым"); + } + + filmStorage.getFilm(newFilm.getId()) + .orElseThrow(() -> { + log.warn("В запросе на обновление фильма передан неизвестный id - {}", newFilm.getId()); + return new NotFoundException("Фильм с id " + newFilm.getId() + " не найден"); + }); + + log.info("Обновлен фильм: {}", newFilm); + return filmStorage.updateFilm(newFilm); + } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java index c2b699e..244d6d1 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java @@ -3,6 +3,7 @@ import ru.yandex.practicum.filmorate.model.Film; import java.util.Collection; +import java.util.Optional; public interface FilmStorage { @@ -12,7 +13,7 @@ public interface FilmStorage { Collection getFilms(); - Film getFilm(Long id); + Optional getFilm(Long id); } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java index 0979a8c..9a2b87a 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java @@ -1,6 +1,7 @@ package ru.yandex.practicum.filmorate.storage.film; import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller; import ru.yandex.practicum.filmorate.exception.NotFoundException; import ru.yandex.practicum.filmorate.exception.ValidationException; @@ -11,7 +12,7 @@ import java.util.Map; import java.util.Optional; -@Controller +@Component @Slf4j public class InMemoryFilmStorage implements FilmStorage { @@ -21,37 +22,25 @@ public Collection getFilms() { return films.values(); } - public Film getFilm(Long id) { - if (!films.containsKey(id)) { - throw new NotFoundException("Фильм с id " + id + " не найден"); - } - return films.get(id); + public Optional getFilm(Long id) { + return films.values().stream() + .filter(film -> film.getId().equals(id)) + .findFirst(); } public Film addFilm(Film film) { film.setId(getNextId()); films.put(film.getId(), film); - log.info("Добавлен фильм: {}", film); return film; } public Film updateFilm(Film newFilm) { - if (newFilm.getId() == null) { - log.warn("В запросе на обновление фильма не передан id"); - throw new ValidationException("Id не может быть пустым"); - } - if (films.containsKey(newFilm.getId())) { - Film oldFilm = films.get(newFilm.getId()); - Optional.ofNullable(newFilm.getName()).ifPresent(oldFilm::setName); - Optional.ofNullable(newFilm.getDescription()).ifPresent(oldFilm::setDescription); - Optional.ofNullable(newFilm.getReleaseDate()).ifPresent(oldFilm::setReleaseDate); - Optional.ofNullable(newFilm.getDuration()).ifPresent(oldFilm::setDuration); - log.info("Обновлен фильм: {}", oldFilm); - return oldFilm; - } else { - log.warn("В запросе на обновление фильма передан неизвестный id - {}", newFilm.getId()); - throw new NotFoundException("Фильм с id " + newFilm.getId() + " не найден"); - } + Film oldFilm = films.get(newFilm.getId()); + Optional.ofNullable(newFilm.getName()).ifPresent(oldFilm::setName); + Optional.ofNullable(newFilm.getDescription()).ifPresent(oldFilm::setDescription); + Optional.ofNullable(newFilm.getReleaseDate()).ifPresent(oldFilm::setReleaseDate); + Optional.ofNullable(newFilm.getDuration()).ifPresent(oldFilm::setDuration); + return oldFilm; } private long getNextId() { diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java index 3ab947d..daeefea 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java @@ -1,6 +1,7 @@ package ru.yandex.practicum.filmorate.storage.user; import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller; import ru.yandex.practicum.filmorate.exception.NotFoundException; import ru.yandex.practicum.filmorate.exception.ValidationException; @@ -11,7 +12,7 @@ import java.util.Map; import java.util.Optional; -@Controller +@Component @Slf4j public class InMemoryUserStorage implements UserStorage { private final Map users = new HashMap<>(); From a4ce4a6df431465fafab00aa6de99ca9e663d19d Mon Sep 17 00:00:00 2001 From: "kirill.fedorov" Date: Wed, 26 Mar 2025 20:57:42 +0500 Subject: [PATCH 03/12] =?UTF-8?q?=D0=B2=D1=8B=D0=BD=D0=B5=D1=81=20=D0=BB?= =?UTF-8?q?=D0=BE=D0=B3=D0=B8=D0=BA=D1=83=20=D0=BF=D0=BE=20=D1=81=D0=BE?= =?UTF-8?q?=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8=D1=8E/=D0=BE=D0=B1=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8E=20=D0=B2=20UserService?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filmorate/controller/UserController.java | 10 ++--- .../filmorate/service/FilmService.java | 1 - .../filmorate/service/UserService.java | 45 +++++++++++++++++++ .../storage/film/InMemoryFilmStorage.java | 2 + .../storage/user/InMemoryUserStorage.java | 44 +++++------------- .../filmorate/storage/user/UserStorage.java | 3 +- 6 files changed, 66 insertions(+), 39 deletions(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java index ba32702..240bb26 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -15,25 +15,25 @@ @RequiredArgsConstructor public class UserController { - private final InMemoryUserStorage userStorage; + private final UserService userService; @GetMapping public Collection getUsers() { - return userStorage.getUsers(); + return userService.getAllUsers(); } @GetMapping("/{userId}") public User getFilm(@PathVariable Long userId) { - return userStorage.getUser(userId); + return userService.getUserById(userId); } @PostMapping public User createUser(@Valid @RequestBody User user) { - return userStorage.addUser(user); + return userService.createUser(user); } @PutMapping public User updateUser(@Valid @RequestBody User newUser) { - return userStorage.updateUser(newUser); + return userService.updateUser(newUser); } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java index 2abd5fd..acb0619 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -45,7 +45,6 @@ public Film updateFilm(Film newFilm) { return new NotFoundException("Фильм с id " + newFilm.getId() + " не найден"); }); - log.info("Обновлен фильм: {}", newFilm); return filmStorage.updateFilm(newFilm); } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java index 987f2f0..09cbfb9 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -1,10 +1,13 @@ package ru.yandex.practicum.filmorate.service; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import ru.yandex.practicum.filmorate.exception.NotFoundException; import ru.yandex.practicum.filmorate.exception.ValidationException; import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.storage.film.FilmStorage; +import ru.yandex.practicum.filmorate.storage.user.UserStorage; import java.util.Collection; import java.util.HashMap; @@ -13,6 +16,48 @@ @Service @Slf4j +@RequiredArgsConstructor public class UserService { + private final UserStorage userStorage; + public Collection getAllUsers() { + return userStorage.getUsers(); + } + + public User getUserById(Long id) { + return userStorage.getUser(id).orElseThrow(() -> new NotFoundException("Юзер с id " + id + " не найден")); + } + + public User createUser(User user) { + if (user.getName() == null || user.getName().isBlank()) { + user.setName(user.getLogin()); + log.info("В запросе создания пользователя передан пустой name. Для поля name использован логин {}", + user.getLogin()); + } + + return userStorage.addUser(user); + } + + public User updateUser(User newUser) { + if (newUser.getId() == null) { + log.warn("В запросе на обновление юзера не передан id"); + throw new ValidationException("Id не может быть пустым"); + } + + userStorage.getUser(newUser.getId()) + .orElseThrow(() -> { + log.warn("В запросе на обновление пользователя передан неизвестный id - {}", newUser.getId()); + return new NotFoundException("Пользователь с id " + newUser.getId() + " не найден"); + }); + + if (newUser.getName() == null || newUser.getName().isBlank()) { + newUser.setName(newUser.getLogin()); + log.info("В запросе обновления пользователя передан пустой name. Для поля name использован логин {}", + newUser.getLogin()); + } + + return userStorage.updateUser(newUser); + + + } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java index 9a2b87a..bb4cd39 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java @@ -31,6 +31,7 @@ public Optional getFilm(Long id) { public Film addFilm(Film film) { film.setId(getNextId()); films.put(film.getId(), film); + log.info("Добавлен фильм: {}", film); return film; } @@ -40,6 +41,7 @@ public Film updateFilm(Film newFilm) { Optional.ofNullable(newFilm.getDescription()).ifPresent(oldFilm::setDescription); Optional.ofNullable(newFilm.getReleaseDate()).ifPresent(oldFilm::setReleaseDate); Optional.ofNullable(newFilm.getDuration()).ifPresent(oldFilm::setDuration); + log.info("Обновлен фильм: {}", newFilm); return oldFilm; } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java index daeefea..d8da095 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java @@ -15,54 +15,34 @@ @Component @Slf4j public class InMemoryUserStorage implements UserStorage { + private final Map users = new HashMap<>(); public Collection getUsers() { return users.values(); } - public User getUser(Long id) { - if (!users.containsKey(id)) { - throw new NotFoundException("Юзер с id " + id + " не найден"); - } - return users.get(id); + public Optional getUser(Long id) { + return users.values().stream() + .filter(user -> user.getId().equals(id)) + .findFirst(); } public User addUser(User user) { user.setId(getNextId()); - if (user.getName() == null || user.getName().isBlank()) { - user.setName(user.getLogin()); - log.info("В запросе создания пользователя передан пустой name. Для поля name использован логин {}", - user.getLogin()); - } users.put(user.getId(), user); log.info("Добавлен пользователь: {}", user); return user; } public User updateUser(User newUser) { - if (newUser.getId() == null) { - log.warn("В запросе на обновление юзера не передан id"); - throw new ValidationException("Id не может быть пустым"); - } - if (users.containsKey(newUser.getId())) { - User oldUser = users.get(newUser.getId()); - if (newUser.getName() == null || newUser.getName().isBlank()) { - oldUser.setName(newUser.getLogin()); - log.info("В запросе обновления пользователя передан пустой name. Для поля name использован логин {}", - newUser.getLogin()); - } else { - Optional.of(newUser.getName()).ifPresent(oldUser::setName); - } - Optional.ofNullable(newUser.getEmail()).ifPresent(oldUser::setEmail); - Optional.ofNullable(newUser.getBirthday()).ifPresent(oldUser::setBirthday); - Optional.ofNullable(newUser.getLogin()).ifPresent(oldUser::setLogin); - log.info("Обновлен юзер: {}", oldUser); - return oldUser; - } else { - log.warn("В запросе на обновление пользователя передан неизвестный id - {}", newUser.getId()); - throw new NotFoundException("Пользователь с id " + newUser.getId() + " не найден"); - } + User oldUser = users.get(newUser.getId()); + Optional.of(newUser.getName()).ifPresent(oldUser::setName); + Optional.ofNullable(newUser.getEmail()).ifPresent(oldUser::setEmail); + Optional.ofNullable(newUser.getBirthday()).ifPresent(oldUser::setBirthday); + Optional.ofNullable(newUser.getLogin()).ifPresent(oldUser::setLogin); + log.info("Обновлен юзер: {}", newUser); + return oldUser; } public void clearData() { diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java index a73ddd1..112a34c 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java @@ -3,6 +3,7 @@ import ru.yandex.practicum.filmorate.model.User; import java.util.Collection; +import java.util.Optional; public interface UserStorage { @@ -12,5 +13,5 @@ public interface UserStorage { Collection getUsers(); - User getUser(Long id); + Optional getUser(Long id); } From 375849f12bc366a1bf365e4dc5d64c11c2fbd802 Mon Sep 17 00:00:00 2001 From: "kirill.fedorov" Date: Thu, 27 Mar 2025 03:05:50 +0500 Subject: [PATCH 04/12] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D1=8B=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F/=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=B2=20=D0=B4=D1=80=D1=83=D0=B7=D1=8C=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filmorate/controller/UserController.java | 19 ++++++++++-- .../filmorate/exception/OtherException.java | 11 +++++++ .../filmorate/handler/ErrorHandler.java | 12 ++++++-- .../practicum/filmorate/model/Film.java | 2 ++ .../practicum/filmorate/model/User.java | 7 +++-- .../{handler => response}/ErrorResponse.java | 2 +- .../filmorate/response/SuccessResponse.java | 10 +++++++ .../filmorate/service/UserService.java | 29 ++++++++++++++++--- 8 files changed, 81 insertions(+), 11 deletions(-) create mode 100644 src/main/java/ru/yandex/practicum/filmorate/exception/OtherException.java rename src/main/java/ru/yandex/practicum/filmorate/{handler => response}/ErrorResponse.java (79%) create mode 100644 src/main/java/ru/yandex/practicum/filmorate/response/SuccessResponse.java diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java index 240bb26..e7787d7 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -2,11 +2,11 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; -import ru.yandex.practicum.filmorate.model.Film; import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.response.SuccessResponse; import ru.yandex.practicum.filmorate.service.UserService; -import ru.yandex.practicum.filmorate.storage.user.InMemoryUserStorage; import java.util.Collection; @@ -28,6 +28,7 @@ public User getFilm(@PathVariable Long userId) { } @PostMapping + @ResponseStatus(HttpStatus.CREATED) public User createUser(@Valid @RequestBody User user) { return userService.createUser(user); } @@ -36,4 +37,18 @@ public User createUser(@Valid @RequestBody User user) { public User updateUser(@Valid @RequestBody User newUser) { return userService.updateUser(newUser); } + + @PutMapping("/{id}/friends/{friendId}") + public SuccessResponse addFriend(@PathVariable Long id, @PathVariable Long friendId) { + userService.addFriend(id, friendId); + return new SuccessResponse(); + } + + @DeleteMapping("/{id}/friends/{friendId}") + public SuccessResponse removeFriend(@PathVariable Long id, @PathVariable Long friendId) { + userService.removeFriend(id, friendId); + return new SuccessResponse(); + } + + } diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/OtherException.java b/src/main/java/ru/yandex/practicum/filmorate/exception/OtherException.java new file mode 100644 index 0000000..eeb2b1c --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/exception/OtherException.java @@ -0,0 +1,11 @@ +package ru.yandex.practicum.filmorate.exception; + +import lombok.Getter; + +@Getter +public class OtherException extends RuntimeException { + String name = "server error"; + public OtherException(String message) { + super(message); + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/handler/ErrorHandler.java b/src/main/java/ru/yandex/practicum/filmorate/handler/ErrorHandler.java index 85f5283..85b72a5 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/handler/ErrorHandler.java +++ b/src/main/java/ru/yandex/practicum/filmorate/handler/ErrorHandler.java @@ -2,7 +2,6 @@ import lombok.extern.slf4j.Slf4j; -import org.apache.coyote.BadRequestException; import org.springframework.http.HttpStatus; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; @@ -10,7 +9,9 @@ import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.exception.OtherException; import ru.yandex.practicum.filmorate.exception.ValidationException; +import ru.yandex.practicum.filmorate.response.ErrorResponse; import java.util.List; @@ -36,9 +37,16 @@ public ErrorResponse handleValidationException(MethodArgumentNotValidException e return new ErrorResponse("validation error", message); } - @ExceptionHandler() + @ExceptionHandler @ResponseStatus(HttpStatus.BAD_REQUEST) public ErrorResponse handleValidationError(final ValidationException e) { return new ErrorResponse(e.getName(), e.getMessage()); } + + @ExceptionHandler + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public ErrorResponse handleInternalServerError(final OtherException e) { + return new ErrorResponse(e.getName(), e.getMessage()); + } + } diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java index 6283263..4237d13 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java @@ -6,6 +6,7 @@ import lombok.Data; import java.time.LocalDate; +import java.util.Set; /** * Film. @@ -15,6 +16,7 @@ @AllArgsConstructor public class Film { private Long id; + private Set usersLikes; @NotBlank(message = "Название фильма не может быть пустым") private String name; diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/User.java b/src/main/java/ru/yandex/practicum/filmorate/model/User.java index 9eee6fb..f736834 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/User.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java @@ -4,19 +4,22 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.PastOrPresent; import jakarta.validation.constraints.Pattern; -import lombok.AllArgsConstructor; import lombok.Data; +import lombok.RequiredArgsConstructor; import java.time.LocalDate; +import java.util.HashSet; +import java.util.Set; /** * User. */ @Data -@AllArgsConstructor +@RequiredArgsConstructor public class User { private Long id; + private Set friends = new HashSet<>(); @Email(message = "Электронная почта пользователя должна соответствовать формату электронного адреса") @NotBlank(message = "Электронная почта пользователя не может быть пустой") diff --git a/src/main/java/ru/yandex/practicum/filmorate/handler/ErrorResponse.java b/src/main/java/ru/yandex/practicum/filmorate/response/ErrorResponse.java similarity index 79% rename from src/main/java/ru/yandex/practicum/filmorate/handler/ErrorResponse.java rename to src/main/java/ru/yandex/practicum/filmorate/response/ErrorResponse.java index bc3af23..1707772 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/handler/ErrorResponse.java +++ b/src/main/java/ru/yandex/practicum/filmorate/response/ErrorResponse.java @@ -1,4 +1,4 @@ -package ru.yandex.practicum.filmorate.handler; +package ru.yandex.practicum.filmorate.response; import lombok.Data; diff --git a/src/main/java/ru/yandex/practicum/filmorate/response/SuccessResponse.java b/src/main/java/ru/yandex/practicum/filmorate/response/SuccessResponse.java new file mode 100644 index 0000000..be025ad --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/response/SuccessResponse.java @@ -0,0 +1,10 @@ +package ru.yandex.practicum.filmorate.response; + +import lombok.Data; +import lombok.RequiredArgsConstructor; + +@Data +@RequiredArgsConstructor +public class SuccessResponse { + private final String status = "success"; +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java index 09cbfb9..5823b67 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -4,15 +4,12 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.exception.OtherException; import ru.yandex.practicum.filmorate.exception.ValidationException; import ru.yandex.practicum.filmorate.model.User; -import ru.yandex.practicum.filmorate.storage.film.FilmStorage; import ru.yandex.practicum.filmorate.storage.user.UserStorage; import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; @Service @Slf4j @@ -60,4 +57,28 @@ public User updateUser(User newUser) { } + + public void addFriend(Long id, Long friendId) { + User user = getUserById(id); + User friend = getUserById(friendId); + + if (!user.getFriends().add(friendId) || !friend.getFriends().add(id)) { + log.warn("Пользователи с id {} и id {} уже являются друзьями", id, friendId); + throw new OtherException("Пользователи уже являются друзьями"); + } + + log.info("Пользователь с id {} добавил в друзья пользователя с id {}", id, friendId); + } + + public void removeFriend(Long id, Long friendId) { + User user = getUserById(id); + User friend = getUserById(friendId); + + if (!user.getFriends().remove(friendId) || !friend.getFriends().remove(id)) { + log.warn("У пользователя с id {} не найден друг с id {}", id, friendId); + throw new NotFoundException("Пользователь не найден в друзьях"); + } + + log.info("Пользователь с id {} удалил из друзей пользователя с id {}", id, friendId); + } } From e438016fc103d74107b54bb315f12c33e325bef6 Mon Sep 17 00:00:00 2001 From: "kirill.fedorov" Date: Fri, 28 Mar 2025 02:48:05 +0500 Subject: [PATCH 05/12] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D1=8B=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=B2=D0=BE=D0=B7=D0=B2=D1=80=D0=B0=D1=82=D0=B0=20?= =?UTF-8?q?=D1=81=D0=BF=D0=B8=D1=81=D0=BA=D0=B0=20=D0=B4=D1=80=D1=83=D0=B7?= =?UTF-8?q?=D0=B5=D0=B9=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D1=82=D0=B5=D0=BB=D1=8F=20=D0=B8=20=D0=B2=D0=BE=D0=B7=D0=B2?= =?UTF-8?q?=D1=80=D0=B0=D1=82=D0=B0=20=D1=81=D0=BF=D0=B8=D1=81=D0=BA=D0=B0?= =?UTF-8?q?=20=D0=BE=D0=B1=D1=89=D0=B8=D1=85=20=D0=B4=D1=80=D1=83=D0=B7?= =?UTF-8?q?=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filmorate/controller/UserController.java | 12 ++++++++++++ .../practicum/filmorate/service/UserService.java | 16 ++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java index e7787d7..847c3c5 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -50,5 +50,17 @@ public SuccessResponse removeFriend(@PathVariable Long id, @PathVariable Long fr return new SuccessResponse(); } + @GetMapping("/{id}/friends") + public Collection getFriends(@PathVariable Long id) { + return userService.getUserFriends(id); + } + + @GetMapping("/{id}/friends/common/{otherId}") + public Collection getCommonFriends(@PathVariable Long id, @PathVariable Long otherId) { + return userService.getCommonUserFriends(id, otherId); + } + + + } diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java index 5823b67..7f302ef 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -62,6 +62,11 @@ public void addFriend(Long id, Long friendId) { User user = getUserById(id); User friend = getUserById(friendId); + if (id.equals(friendId)) { + log.warn("Пользователь не может добавить сам себя в друзья"); + throw new OtherException("Пользователь не может добавить сам себя в друзья"); + } + if (!user.getFriends().add(friendId) || !friend.getFriends().add(id)) { log.warn("Пользователи с id {} и id {} уже являются друзьями", id, friendId); throw new OtherException("Пользователи уже являются друзьями"); @@ -81,4 +86,15 @@ public void removeFriend(Long id, Long friendId) { log.info("Пользователь с id {} удалил из друзей пользователя с id {}", id, friendId); } + + public Collection getUserFriends(Long id) { + return getUserById(id).getFriends().stream() + .map(this::getUserById).toList(); + } + + public Collection getCommonUserFriends(Long id, Long otherId) { + return getUserById(id).getFriends().stream() + .filter(getUserById(otherId).getFriends()::contains) + .map(this::getUserById).toList(); + } } From 93ed0bc6da19439c68dc93178469d1c7cdafc566 Mon Sep 17 00:00:00 2001 From: "kirill.fedorov" Date: Fri, 28 Mar 2025 03:22:13 +0500 Subject: [PATCH 06/12] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D0=B2=D1=8B=D1=81=D1=82=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=BB=D0=B0=D0=B9=D0=BA=D0=B0=20=D1=84=D0=B8=D0=BB?= =?UTF-8?q?=D1=8C=D0=BC=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filmorate/controller/FilmController.java | 8 +++++++- .../ru/yandex/practicum/filmorate/model/Film.java | 7 ++++--- .../practicum/filmorate/service/FilmService.java | 15 ++++++++++++--- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java index f2377e5..f4322da 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -4,8 +4,8 @@ import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.response.SuccessResponse; import ru.yandex.practicum.filmorate.service.FilmService; -import ru.yandex.practicum.filmorate.storage.film.InMemoryFilmStorage; import java.util.Collection; @@ -35,4 +35,10 @@ public Film addFilm(@Valid @RequestBody Film film) { public Film updateFilm(@Valid @RequestBody Film newFilm) { return filmService.updateFilm(newFilm); } + + @PutMapping("/{id}/like/{userId}") + public SuccessResponse likeFilm(@PathVariable Long id, @PathVariable Long userId) { + filmService.likeFilm(id, userId); + return new SuccessResponse(); + } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java index 4237d13..0e0cda0 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java @@ -2,10 +2,11 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.validation.constraints.*; -import lombok.AllArgsConstructor; import lombok.Data; +import lombok.RequiredArgsConstructor; import java.time.LocalDate; +import java.util.HashSet; import java.util.Set; /** @@ -13,10 +14,10 @@ */ @Data -@AllArgsConstructor +@RequiredArgsConstructor public class Film { private Long id; - private Set usersLikes; + private Set usersLikes = new HashSet<>(); @NotBlank(message = "Название фильма не может быть пустым") private String name; diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java index acb0619..1e9f13c 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -4,20 +4,20 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.exception.OtherException; import ru.yandex.practicum.filmorate.exception.ValidationException; import ru.yandex.practicum.filmorate.model.Film; import ru.yandex.practicum.filmorate.storage.film.FilmStorage; import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; @Service @Slf4j @RequiredArgsConstructor public class FilmService { private final FilmStorage filmStorage; + private final UserService userService; + public Collection getAllFilms() { return filmStorage.getFilms(); @@ -47,4 +47,13 @@ public Film updateFilm(Film newFilm) { return filmStorage.updateFilm(newFilm); } + + public void likeFilm(Long filmId, Long userId) { + if (!getFilmById(filmId).getUsersLikes().add(userService.getUserById(userId).getId())) { + log.warn("Пользователь с id {} уже ставил лайк фильму с id {}", userId, filmId); + throw new OtherException("Пользователь уже ставил лайк фильму"); + } + + log.info("Пользователь с id {} поставил лайк фильму с id {}", userId, filmId); + } } From ff14c04b8165dc31c1d6adb5e0e3c8a7d7527102 Mon Sep 17 00:00:00 2001 From: "kirill.fedorov" Date: Fri, 28 Mar 2025 19:51:10 +0500 Subject: [PATCH 07/12] =?UTF-8?q?=D0=97=D0=B0=D0=BA=D0=BE=D0=BD=D1=87?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=B2=D1=81=D0=B5=20endpoint=D1=8B=20=D1=81=20?= =?UTF-8?q?=D1=84=D0=B8=D0=BB=D1=8C=D0=BC=D0=B0=D0=BC=D0=B8=20=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5?= =?UTF-8?q?=D0=BB=D1=8F=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filmorate/controller/FilmController.java | 11 +++++++++++ .../practicum/filmorate/service/FilmService.java | 15 +++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java index f4322da..8df87d7 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -41,4 +41,15 @@ public SuccessResponse likeFilm(@PathVariable Long id, @PathVariable Long userId filmService.likeFilm(id, userId); return new SuccessResponse(); } + + @DeleteMapping("/{id}/like/{userId}") + public SuccessResponse removeLikeFilm(@PathVariable Long id, @PathVariable Long userId) { + filmService.removeLikeFilm(id, userId); + return new SuccessResponse(); + } + + @GetMapping("/popular") + public Collection getPopularFilms(@RequestParam(defaultValue = "10") int count) { + return filmService.getPopularFilms(count); + } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java index 1e9f13c..d8e7cbb 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -10,6 +10,7 @@ import ru.yandex.practicum.filmorate.storage.film.FilmStorage; import java.util.Collection; +import java.util.Comparator; @Service @Slf4j @@ -17,6 +18,7 @@ public class FilmService { private final FilmStorage filmStorage; private final UserService userService; + private final Comparator filmComparator = Comparator.comparing((Film film) -> film.getUsersLikes().size()).reversed(); public Collection getAllFilms() { @@ -56,4 +58,17 @@ public void likeFilm(Long filmId, Long userId) { log.info("Пользователь с id {} поставил лайк фильму с id {}", userId, filmId); } + + public void removeLikeFilm(Long filmId, Long userId) { + if (!getFilmById(filmId).getUsersLikes().remove(userService.getUserById(userId).getId())) { + log.warn("Пользователь с id {} не ставил лайк фильму id {}", userId, filmId); + throw new OtherException("Пользователь не ставил лайк фильму"); + } + + log.info("Пользователь с id {} удалил свой лайк у фильма с id {}", userId, filmId); + } + + public Collection getPopularFilms(int count) { + return filmStorage.getFilms().stream().sorted(filmComparator).limit(count).toList(); + } } From 06b92ae7d18c87a3234392a82fd8ea10fee011c9 Mon Sep 17 00:00:00 2001 From: "kirill.fedorov" Date: Sat, 29 Mar 2025 01:23:10 +0500 Subject: [PATCH 08/12] =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B0=D0=BB=20=D0=B2=D1=81=D0=B5=20=D1=82=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D1=8B=20=D1=81=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=D0=BC=20=D0=BC=D0=BE?= =?UTF-8?q?=D0=BA=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filmorate/controller/FilmController.java | 2 + .../practicum/filmorate/model/Film.java | 12 +- .../filmorate/service/FilmService.java | 4 + .../filmorate/storage/film/FilmStorage.java | 2 + .../storage/film/InMemoryFilmStorage.java | 8 +- .../filmorate/FilmControllerTest.java | 530 +++++++++--------- 6 files changed, 276 insertions(+), 282 deletions(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java index 8df87d7..901f812 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -2,6 +2,7 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; import ru.yandex.practicum.filmorate.model.Film; import ru.yandex.practicum.filmorate.response.SuccessResponse; @@ -27,6 +28,7 @@ public Film getFilm(@PathVariable Long filmId) { } @PostMapping + @ResponseStatus(HttpStatus.CREATED) public Film addFilm(@Valid @RequestBody Film film) { return filmService.createFilm(film); } diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java index 0e0cda0..660004b 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java @@ -3,7 +3,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.validation.constraints.*; import lombok.Data; -import lombok.RequiredArgsConstructor; +import lombok.NoArgsConstructor; import java.time.LocalDate; import java.util.HashSet; @@ -14,7 +14,7 @@ */ @Data -@RequiredArgsConstructor +@NoArgsConstructor public class Film { private Long id; private Set usersLikes = new HashSet<>(); @@ -30,6 +30,14 @@ public class Film { @Positive(message = "Продолжительность фильма должна быть положительным числом") private Integer duration; + public Film(Long id, String name, String description, LocalDate releaseDate, Integer duration) { + this.id = id; + this.name = name; + this.description = description; + this.releaseDate = releaseDate; + this.duration = duration; + } + @AssertTrue(message = "Дата релиза фильма должна быть не раньше 28 декабря 1895 года") @JsonIgnore public boolean isReleaseDateValid() { diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java index d8e7cbb..29d74d1 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -71,4 +71,8 @@ public void removeLikeFilm(Long filmId, Long userId) { public Collection getPopularFilms(int count) { return filmStorage.getFilms().stream().sorted(filmComparator).limit(count).toList(); } + + public void clearFilmsData() { + filmStorage.clearData(); + } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java index 244d6d1..1880bcb 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmStorage.java @@ -15,5 +15,7 @@ public interface FilmStorage { Optional getFilm(Long id); + void clearData(); + } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java index bb4cd39..a91d713 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/InMemoryFilmStorage.java @@ -2,9 +2,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import org.springframework.stereotype.Controller; -import ru.yandex.practicum.filmorate.exception.NotFoundException; -import ru.yandex.practicum.filmorate.exception.ValidationException; + import ru.yandex.practicum.filmorate.model.Film; import java.util.Collection; @@ -53,4 +51,8 @@ private long getNextId() { .orElse(0); return ++currentMaxId; } + + public void clearData() { + films.clear(); + } } diff --git a/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java b/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java index abf2bd6..f84fd2f 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java +++ b/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java @@ -1,295 +1,271 @@ package ru.yandex.practicum.filmorate; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; +import org.springframework.http.*; +import org.springframework.test.web.servlet.MockMvc; import ru.yandex.practicum.filmorate.model.Film; import ru.yandex.practicum.filmorate.service.FilmService; import java.time.LocalDate; -import java.util.Objects; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@SpringBootTest +@AutoConfigureMockMvc class FilmControllerTest { -// -// @Autowired -// private TestRestTemplate restTemplate; -// -// @Autowired -// private FilmService filmService; -// -// private final HttpHeaders headers = new HttpHeaders(); -// -// static Stream provideInvalidFilmJsonCreate() { -// return Stream.of( -// "{\n" + -// " \"name\": \"\",\n" + -// " \"description\": \"Sci-fi action\",\n" + -// " \"releaseDate\": \"1900-12-25\",\n" + -// " \"duration\": 10\n" + -// "}", // Пустое название -// -// "{\n" + -// " \"name\": \"The Matrix\",\n" + -// " \"description\": \"eVsHnlJqcle8LzLbMyajlPHJvq6xPAEBqvi0V55TAlZ6vokGPaTGgzI9ypdZv8X5X2StI10zqReOEy" + -// "mkWTNcxCFbRqrmJBVrIdgQf9VDYXcE76DmMQ7jI4jzHZ0XKxx13dlujL9A3MbNudpQC4Uw1aoIsOoD" + -// "cHS1JAHFXAEduHxtxNuo3Iq6tGj0xXZqDczZX2UqqTfmt\",\n" + -// " \"releaseDate\": \"1900-12-25\",\n" + -// " \"duration\": 10\n" + -// "}", // Описание длиной 201 символ -// -// "{\n" + -// " \"name\": \"The Matrix\",\n" + -// " \"description\": \"NQ1qwgfJURRuOBe7rZJuRMNP4wCGFHKvrz5flsvTzz5NKXwP1II7Jytjjwn51G51eQBF2IfydfdRrkdq" + -// "50DSPqWqOFri415GQb8HgwqI1ET0uF5wDFBS9iwzCysqqSTffd0BcRf1zHwPjMwDSOnQHETMtSEYTd" + -// "V7PLRlZw4mgreyXaFpSjVXB4149KfTyeFL9YFXSANQbCly2IwtFAftdPKSTHrLzNFk2AEwInZGATHu" + -// "q73LwzP5qmx89M\",\n" + -// " \"releaseDate\": \"1900-12-25\",\n" + -// " \"duration\": 10\n" + -// "}", // Описание длиной 300 символов -// -// "{\n" + -// " \"name\": \"The Matrix\",\n" + -// " \"description\": \"Sci-fi action\",\n" + -// " \"releaseDate\": \"1800-12-25\",\n" + -// " \"duration\": 10\n" + -// "}", // Дата раньше 1895 -// -// "{\n" + -// " \"name\": \"The Matrix\",\n" + -// " \"description\": \"Sci-fi action\",\n" + -// " \"releaseDate\": \"1900-12-25\",\n" + -// " \"duration\": -5\n" + -// "}" // Отрицательная длительность -// ); -// } -// -// static Stream provideInvalidFilmJsonUpdate() { -// return Stream.of( -// "{\n" + -// " \"id\": 1,\n" + -// " \"name\": \"\",\n" + -// " \"description\": \"Sci-fi action\",\n" + -// " \"releaseDate\": \"1900-12-25\",\n" + -// " \"duration\": 10\n" + -// "}", // Пустое название -// -// "{\n" + -// " \"id\": 1,\n" + -// " \"name\": \"The Matrix\",\n" + -// " \"description\": \"eVsHnlJqcle8LzLbMyajlPHJvq6xPAEBqvi0V55TAlZ6vokGPaTGgzI9ypdZv8X5X2StI10zqReOEy" + -// "mkWTNcxCFbRqrmJBVrIdgQf9VDYXcE76DmMQ7jI4jzHZ0XKxx13dlujL9A3MbNudpQC4Uw1aoIsOoD" + -// "cHS1JAHFXAEduHxtxNuo3Iq6tGj0xXZqDczZX2UqqTfmt\",\n" + -// " \"releaseDate\": \"1900-12-25\",\n" + -// " \"duration\": 10\n" + -// "}", // Описание длиной 201 символ -// -// "{\n" + -// " \"id\": 1,\n" + -// " \"name\": \"The Matrix\",\n" + -// " \"description\": \"NQ1qwgfJURRuOBe7rZJuRMNP4wCGFHKvrz5flsvTzz5NKXwP1II7Jytjjwn51G51eQBF2IfydfdRrkdq" + -// "50DSPqWqOFri415GQb8HgwqI1ET0uF5wDFBS9iwzCysqqSTffd0BcRf1zHwPjMwDSOnQHETMtSEYTd" + -// "V7PLRlZw4mgreyXaFpSjVXB4149KfTyeFL9YFXSANQbCly2IwtFAftdPKSTHrLzNFk2AEwInZGATHu" + -// "q73LwzP5qmx89M\",\n" + -// " \"releaseDate\": \"1900-12-25\",\n" + -// " \"duration\": 10\n" + -// "}", // Описание длиной 300 символов -// -// "{\n" + -// " \"id\": 1,\n" + -// " \"name\": \"The Matrix\",\n" + -// " \"description\": \"Sci-fi action\",\n" + -// " \"releaseDate\": \"1800-12-25\",\n" + -// " \"duration\": 10\n" + -// "}", // Дата раньше 1895 -// -// "{\n" + -// " \"id\": 1,\n" + -// " \"name\": \"The Matrix\",\n" + -// " \"description\": \"Sci-fi action\",\n" + -// " \"releaseDate\": \"1900-12-25\",\n" + -// " \"duration\": -5\n" + -// "}" // Отрицательная длительность -// ); -// } -// -// static Stream provideInvalidFilmJsonIdUpdate() { -// return Stream.of( -// "{\n" + -// " \"name\": \"The Matrix\",\n" + -// " \"description\": \"Sci-fi action\",\n" + -// " \"releaseDate\": \"1900-12-25\",\n" + -// " \"duration\": 10\n" + -// "}", // Без id -// -// "{\n" + -// " \"id\": 125,\n" + -// " \"name\": \"The Matrix\",\n" + -// " \"description\": \"Sci-fi action\",\n" + -// " \"releaseDate\": \"1900-12-25\",\n" + -// " \"duration\": 10\n" + -// "}" // Id нет в списке -// ); -// } -// -// @Test -// void contextLoads() { -// } -// -// @BeforeEach -// void setUp() { -// headers.set("Content-Type", "application/json"); -// filmService.clearData(); -// } -// -// @Test -// void getFilms() { -// filmService.addFilm(new Film(1L, "The Matrix", "Sci-fi action", -// LocalDate.of(1900, 12, 25), 10)); -// filmService.addFilm(new Film(2L, "The Dark Knight", "Superhero thriller", -// LocalDate.of(1900, 12, 25), 10)); -// ResponseEntity response = restTemplate.getForEntity("/films", String.class); -// assertEquals(HttpStatus.OK, response.getStatusCode()); -// assertNotNull(response.getBody()); -// JsonElement expectedJson = JsonParser.parseString( -// "[\n" + -// " {\n" + -// " \"id\": 1,\n" + -// " \"name\": \"The Matrix\",\n" + -// " \"description\": \"Sci-fi action\",\n" + -// " \"releaseDate\": \"1900-12-25\",\n" + -// " \"duration\": 10\n" + -// " },\n" + -// " {\n" + -// " \"id\": 2,\n" + -// " \"name\": \"The Dark Knight\",\n" + -// " \"description\": \"Superhero thriller\",\n" + -// " \"releaseDate\": \"1900-12-25\",\n" + -// " \"duration\": 10\n" + -// " }\n" + -// "]" -// ); -// assertEquals(expectedJson, JsonParser.parseString(response.getBody())); -// } -// -// @Test -// void addFilm() { -// String json = "{\n" + -// " \"name\": \"The Matrix\",\n" + -// " \"description\": \"Sci-fi action\",\n" + -// " \"releaseDate\": \"1967-03-25\",\n" + -// " \"duration\": 100\n" + -// "}"; -// HttpEntity entity = new HttpEntity<>(json, headers); -// ResponseEntity response = restTemplate.exchange("/films", HttpMethod.POST, entity, String.class); -// assertEquals(HttpStatus.OK, response.getStatusCode()); -// -// assertNotNull(response.getBody()); -// JsonElement expectedJson = JsonParser.parseString( -// "{\n" + -// " \"id\": 1,\n" + -// " \"name\": \"The Matrix\",\n" + -// " \"description\": \"Sci-fi action\",\n" + -// " \"releaseDate\": \"1967-03-25\",\n" + -// " \"duration\": 100\n" + -// "}" -// ); -// Film createdFilm = filmService.getFilmsMap().get(1L); -// assertNotNull(createdFilm); -// assertEquals(expectedJson, JsonParser.parseString(response.getBody())); -// assertEquals(1L, createdFilm.getId()); -// assertEquals("The Matrix", createdFilm.getName()); -// assertEquals("Sci-fi action", createdFilm.getDescription()); -// assertEquals(LocalDate.of(1967, 3, 25), createdFilm.getReleaseDate()); -// assertEquals(100, createdFilm.getDuration()); -// } -// -// @Test -// void updateFilm() { -// filmService.addFilm(new Film(1L, "The Matrix", "Sci-fi action", -// LocalDate.of(1900, 12, 25), 10)); -// String json = "{\n" + -// " \"id\": 1,\n" + -// " \"name\": \"The Matrix updated\",\n" + -// " \"description\": \"Sci-fi action updated\",\n" + -// " \"releaseDate\": \"1967-03-25\",\n" + -// " \"duration\": 100\n" + -// "}"; -// HttpEntity entity = new HttpEntity<>(json, headers); -// ResponseEntity response = restTemplate.exchange("/films", HttpMethod.PUT, entity, String.class); -// assertEquals(HttpStatus.OK, response.getStatusCode()); -// assertNotNull(response.getBody()); -// JsonElement expectedJson = JsonParser.parseString(json); -// assertEquals(expectedJson, JsonParser.parseString(response.getBody())); -// Film updatedFilm = filmService.getFilmsMap().get(1L); -// assertNotNull(updatedFilm); -// assertEquals(1L, updatedFilm.getId()); -// assertEquals("The Matrix updated", updatedFilm.getName()); -// assertEquals("Sci-fi action updated", updatedFilm.getDescription()); -// assertEquals(LocalDate.of(1967, 3, 25), updatedFilm.getReleaseDate()); -// assertEquals(100, updatedFilm.getDuration()); -// } -// -// @ParameterizedTest -// @MethodSource("provideInvalidFilmJsonCreate") -// void addFilmValidation(String json) { -// HttpEntity entity = new HttpEntity<>(json, headers); -// ResponseEntity response = restTemplate.exchange("/films", HttpMethod.POST, entity, String.class); -// assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); -// assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); -// } -// -// @Test -// void addFilmEmptyJson() { -// HttpEntity entity = new HttpEntity<>(null, headers); -// ResponseEntity response = restTemplate.exchange("/films", HttpMethod.POST, entity, String.class); -// assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); -// assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); -// } -// -// @ParameterizedTest -// @MethodSource("provideInvalidFilmJsonUpdate") -// void updateFilmValidation(String json) { -// filmService.addFilm(new Film(1L, "The Matrix", "Sci-fi action", -// LocalDate.of(1900, 12, 25), 10)); -// HttpEntity entity = new HttpEntity<>(json, headers); -// ResponseEntity response = restTemplate.exchange("/films", HttpMethod.PUT, entity, String.class); -// assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); -// assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); -// } -// -// @ParameterizedTest -// @MethodSource("provideInvalidFilmJsonIdUpdate") -// void updateFilmIdValidation(String json) { -// filmService.addFilm(new Film(1L, "The Matrix", "Sci-fi action", -// LocalDate.of(1900, 12, 25), 10)); -// HttpEntity entity = new HttpEntity<>(json, headers); -// ResponseEntity response = restTemplate.exchange("/films", HttpMethod.PUT, entity, String.class); -// assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode()); -// assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Internal Server Error\"")); -// } -// -// @Test -// void updateFilmEmptyJson() { -// filmService.addFilm(new Film(1L, "The Matrix", "Sci-fi action", -// LocalDate.of(1900, 12, 25), 10)); -// HttpEntity entity = new HttpEntity<>(null, headers); -// ResponseEntity response = restTemplate.exchange("/films", HttpMethod.PUT, entity, String.class); -// assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); -// assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); -// } + + @Autowired + private MockMvc mockMvc; + + @Autowired + private FilmService filmService; + + @BeforeEach + void setUp() { + filmService.createFilm(new Film(1L, "test1", "test_descr1", LocalDate.of(1900, 12, 25), 10)); + filmService.createFilm(new Film(2L, "test2", "test_descr2", LocalDate.of(1900, 12, 25), 10)); + } + + @AfterEach + void tearDown() { + filmService.clearFilmsData(); + } + + static Stream provideInvalidFilmJsonCreate() { + return Stream.of( + "{\n" + + " \"name\": \"\",\n" + + " \"description\": \"Sci-fi action\",\n" + + " \"releaseDate\": \"1900-12-25\",\n" + + " \"duration\": 10\n" + + "}", // Пустое название + + "{\n" + + " \"name\": \"The Matrix\",\n" + + " \"description\": \"eVsHnlJqcle8LzLbMyajlPHJvq6xPAEBqvi0V55TAlZ6vokGPaTGgzI9ypdZv8X5X2StI10zqReOEy" + + "mkWTNcxCFbRqrmJBVrIdgQf9VDYXcE76DmMQ7jI4jzHZ0XKxx13dlujL9A3MbNudpQC4Uw1aoIsOoD" + + "cHS1JAHFXAEduHxtxNuo3Iq6tGj0xXZqDczZX2UqqTfmt\",\n" + + " \"releaseDate\": \"1900-12-25\",\n" + + " \"duration\": 10\n" + + "}", // Описание длиной 201 символ + + "{\n" + + " \"name\": \"The Matrix\",\n" + + " \"description\": \"NQ1qwgfJURRuOBe7rZJuRMNP4wCGFHKvrz5flsvTzz5NKXwP1II7Jytjjwn51G51eQBF2IfydfdRrkdq" + + "50DSPqWqOFri415GQb8HgwqI1ET0uF5wDFBS9iwzCysqqSTffd0BcRf1zHwPjMwDSOnQHETMtSEYTd" + + "V7PLRlZw4mgreyXaFpSjVXB4149KfTyeFL9YFXSANQbCly2IwtFAftdPKSTHrLzNFk2AEwInZGATHu" + + "q73LwzP5qmx89M\",\n" + + " \"releaseDate\": \"1900-12-25\",\n" + + " \"duration\": 10\n" + + "}", // Описание длиной 300 символов + + "{\n" + + " \"name\": \"The Matrix\",\n" + + " \"description\": \"Sci-fi action\",\n" + + " \"releaseDate\": \"1800-12-25\",\n" + + " \"duration\": 10\n" + + "}", // Дата раньше 1895 + + "{\n" + + " \"name\": \"The Matrix\",\n" + + " \"description\": \"Sci-fi action\",\n" + + " \"releaseDate\": \"1900-12-25\",\n" + + " \"duration\": -5\n" + + "}" // Отрицательная длительность + ); + } + + static Stream provideInvalidFilmJsonUpdate() { + return Stream.of( + "{\n" + + " \"id\": 1,\n" + + " \"name\": \"\",\n" + + " \"description\": \"Sci-fi action\",\n" + + " \"releaseDate\": \"1900-12-25\",\n" + + " \"duration\": 10\n" + + "}", // Пустое название + + "{\n" + + " \"id\": 1,\n" + + " \"name\": \"The Matrix\",\n" + + " \"description\": \"eVsHnlJqcle8LzLbMyajlPHJvq6xPAEBqvi0V55TAlZ6vokGPaTGgzI9ypdZv8X5X2StI10zqReOEy" + + "mkWTNcxCFbRqrmJBVrIdgQf9VDYXcE76DmMQ7jI4jzHZ0XKxx13dlujL9A3MbNudpQC4Uw1aoIsOoD" + + "cHS1JAHFXAEduHxtxNuo3Iq6tGj0xXZqDczZX2UqqTfmt\",\n" + + " \"releaseDate\": \"1900-12-25\",\n" + + " \"duration\": 10\n" + + "}", // Описание длиной 201 символ + + "{\n" + + " \"id\": 1,\n" + + " \"name\": \"The Matrix\",\n" + + " \"description\": \"NQ1qwgfJURRuOBe7rZJuRMNP4wCGFHKvrz5flsvTzz5NKXwP1II7Jytjjwn51G51eQBF2IfydfdRrkdq" + + "50DSPqWqOFri415GQb8HgwqI1ET0uF5wDFBS9iwzCysqqSTffd0BcRf1zHwPjMwDSOnQHETMtSEYTd" + + "V7PLRlZw4mgreyXaFpSjVXB4149KfTyeFL9YFXSANQbCly2IwtFAftdPKSTHrLzNFk2AEwInZGATHu" + + "q73LwzP5qmx89M\",\n" + + " \"releaseDate\": \"1900-12-25\",\n" + + " \"duration\": 10\n" + + "}", // Описание длиной 300 символов + + "{\n" + + " \"id\": 1,\n" + + " \"name\": \"The Matrix\",\n" + + " \"description\": \"Sci-fi action\",\n" + + " \"releaseDate\": \"1800-12-25\",\n" + + " \"duration\": 10\n" + + "}", // Дата раньше 1895 + + "{\n" + + " \"id\": 1,\n" + + " \"name\": \"The Matrix\",\n" + + " \"description\": \"Sci-fi action\",\n" + + " \"releaseDate\": \"1900-12-25\",\n" + + " \"duration\": -5\n" + + "}", // Отрицательная длительность + + "{\n" + + " \"id\": 135,\n" + + " \"name\": \"The Matrix\",\n" + + " \"description\": \"Sci-fi action\",\n" + + " \"releaseDate\": \"1900-12-25\",\n" + + " \"duration\": -5\n" + + "}" // неизвестный ид + ); + } + + @Test + void getFilms() throws Exception { + mockMvc.perform(get("/films")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id").value(1)) + .andExpect(jsonPath("$[0].name").value("test1")) + .andExpect(jsonPath("$[1].id").value(2)) + .andExpect(jsonPath("$[1].name").value("test2")); + } + + @Test + void getFilmById() throws Exception { + mockMvc.perform(get("/films/1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").value(1)) + .andExpect(jsonPath("$.name").value("test1")); + } + + @Test + void getUnknownFilmById() throws Exception { + mockMvc.perform(get("/films/5")) + .andExpect(status().isNotFound()) + .andExpect(jsonPath("$.error").value("not found")) + .andExpect(jsonPath("$.message").value("Фильм с id 5 не найден")); + } + + @Test + void addFilms() throws Exception { + String json = "{\n" + + " \"name\": \"The Matrix\",\n" + + " \"description\": \"Sci-fi action\",\n" + + " \"releaseDate\": \"1967-03-25\",\n" + + " \"duration\": 100\n" + + "}"; + mockMvc.perform(post("/films") + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.id").value(3)) + .andExpect(jsonPath("$.name").value("The Matrix")); + + assertEquals(filmService.getFilmById(3L).getName(), "The Matrix"); + } + + @Test + void updateFilms() throws Exception { + String json = "{\n" + + " \"id\": 1,\n" + + " \"name\": \"test1_upd\",\n" + + " \"description\": \"test_descr1_upd\",\n" + + " \"releaseDate\": \"1967-03-25\",\n" + + " \"duration\": 100\n" + + "}"; + + mockMvc.perform(put("/films") + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").value(1)) + .andExpect(jsonPath("$.name").value("test1_upd")); + + assertEquals(filmService.getFilmById(1L).getName(), "test1_upd"); + assertEquals(filmService.getFilmById(1L).getDescription(), "test_descr1_upd"); + assertEquals(filmService.getFilmById(1L).getReleaseDate().toString(), "1967-03-25"); + assertEquals(filmService.getFilmById(1L).getDuration(), 100); + } + + @ParameterizedTest + @MethodSource("provideInvalidFilmJsonCreate") + void addFilmValidation(String json) throws Exception { + mockMvc.perform(post("/films") + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.error").value("validation error")); + } + + @Test + void addFilmEmptyJson() throws Exception { + String json = "{}"; + + mockMvc.perform(post("/films") + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.error").value("validation error")); + } + + @ParameterizedTest + @MethodSource("provideInvalidFilmJsonUpdate") + void updateFilmValidation(String json) throws Exception { + mockMvc.perform(put("/films") + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.error").value("validation error")); + } + + @Test + void updateFilmWithoutId() throws Exception { + String json = "{\n" + + " \"name\": \"The Matrix\",\n" + + " \"description\": \"Sci-fi action\",\n" + + " \"releaseDate\": \"1900-12-25\",\n" + + " \"duration\": 10\n" + + "}"; + + mockMvc.perform(put("/films") + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.error").value("validation error")); + } + + @Test + void updateFilmEmptyJson() throws Exception { + String json = "{}"; + + mockMvc.perform(put("/films") + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.error").value("validation error")); + } + } From 0a6e1248accb9959edf87d4636929c5ed86fd862 Mon Sep 17 00:00:00 2001 From: "kirill.fedorov" Date: Sun, 30 Mar 2025 22:22:22 +0500 Subject: [PATCH 09/12] =?UTF-8?q?=D0=BD=D0=B0=D0=BF=D0=B8=D1=81=D0=B0?= =?UTF-8?q?=D0=BB=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?FilmController?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../practicum/filmorate/model/User.java | 19 +- .../filmorate/service/FilmService.java | 2 +- .../filmorate/service/UserService.java | 6 +- .../filmorate/storage/user/UserStorage.java | 2 + .../filmorate/FilmControllerTest.java | 173 +++++++++++++++++- 5 files changed, 193 insertions(+), 9 deletions(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/User.java b/src/main/java/ru/yandex/practicum/filmorate/model/User.java index f736834..4d60941 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/User.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java @@ -5,7 +5,7 @@ import jakarta.validation.constraints.PastOrPresent; import jakarta.validation.constraints.Pattern; import lombok.Data; -import lombok.RequiredArgsConstructor; +import lombok.NoArgsConstructor; import java.time.LocalDate; import java.util.HashSet; @@ -16,7 +16,7 @@ */ @Data -@RequiredArgsConstructor +@NoArgsConstructor public class User { private Long id; private Set friends = new HashSet<>(); @@ -32,4 +32,19 @@ public class User { @PastOrPresent(message = "Дата рождения пользователя не может быть в будущем") private LocalDate birthday; + + public User(Long id, String email, String login, String name, LocalDate birthday) { + this.id = id; + this.email = email; + this.login = login; + this.name = name; + this.birthday = birthday; + } + + public User(String email, String login, String name, LocalDate birthday) { + this.email = email; + this.login = login; + this.name = name; + this.birthday = birthday; + } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java index 29d74d1..6cfb0e6 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -26,7 +26,7 @@ public Collection getAllFilms() { } public Film getFilmById(Long id) { - return filmStorage.getFilm(id).orElseThrow(() -> new NotFoundException("Фильм с id " + id + " не найден")); + return filmStorage.getFilm(id).orElseThrow(() -> new NotFoundException("Фильм с id " + id + " не найден")); } public Film createFilm(Film film) { diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java index 7f302ef..ea5d370 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -22,7 +22,7 @@ public Collection getAllUsers() { } public User getUserById(Long id) { - return userStorage.getUser(id).orElseThrow(() -> new NotFoundException("Юзер с id " + id + " не найден")); + return userStorage.getUser(id).orElseThrow(() -> new NotFoundException("Юзер с id " + id + " не найден")); } public User createUser(User user) { @@ -97,4 +97,8 @@ public Collection getCommonUserFriends(Long id, Long otherId) { .filter(getUserById(otherId).getFriends()::contains) .map(this::getUserById).toList(); } + + public void clearUsersData() { + userStorage.clearData(); + } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java index 112a34c..11dd5fa 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/user/UserStorage.java @@ -14,4 +14,6 @@ public interface UserStorage { Collection getUsers(); Optional getUser(Long id); + + void clearData(); } diff --git a/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java b/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java index f84fd2f..0d234bf 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java +++ b/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java @@ -11,7 +11,9 @@ import org.springframework.http.*; import org.springframework.test.web.servlet.MockMvc; import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.model.User; import ru.yandex.practicum.filmorate.service.FilmService; +import ru.yandex.practicum.filmorate.service.UserService; import java.time.LocalDate; import java.util.stream.Stream; @@ -31,15 +33,21 @@ class FilmControllerTest { @Autowired private FilmService filmService; + @Autowired + private UserService userService; + @BeforeEach void setUp() { filmService.createFilm(new Film(1L, "test1", "test_descr1", LocalDate.of(1900, 12, 25), 10)); filmService.createFilm(new Film(2L, "test2", "test_descr2", LocalDate.of(1900, 12, 25), 10)); + userService.createUser(new User(1L, "test@mail.ru", "testlogin1", "testname1", LocalDate.of(1900, 12, 25))); + userService.createUser(new User(2L, "test2@mail.ru", "testlogin2", "testname2", LocalDate.of(1901, 10, 21))); } @AfterEach void tearDown() { filmService.clearFilmsData(); + userService.clearUsersData(); } static Stream provideInvalidFilmJsonCreate() { @@ -166,7 +174,7 @@ void getUnknownFilmById() throws Exception { mockMvc.perform(get("/films/5")) .andExpect(status().isNotFound()) .andExpect(jsonPath("$.error").value("not found")) - .andExpect(jsonPath("$.message").value("Фильм с id 5 не найден")); + .andExpect(jsonPath("$.message").value("Фильм с id 5 не найден")); } @Test @@ -204,10 +212,10 @@ void updateFilms() throws Exception { .andExpect(jsonPath("$.id").value(1)) .andExpect(jsonPath("$.name").value("test1_upd")); - assertEquals(filmService.getFilmById(1L).getName(), "test1_upd"); - assertEquals(filmService.getFilmById(1L).getDescription(), "test_descr1_upd"); - assertEquals(filmService.getFilmById(1L).getReleaseDate().toString(), "1967-03-25"); - assertEquals(filmService.getFilmById(1L).getDuration(), 100); + assertEquals("test1_upd", filmService.getFilmById(1L).getName()); + assertEquals("test_descr1_upd", filmService.getFilmById(1L).getDescription()); + assertEquals("1967-03-25", filmService.getFilmById(1L).getReleaseDate().toString()); + assertEquals(100, filmService.getFilmById(1L).getDuration()); } @ParameterizedTest @@ -268,4 +276,159 @@ void updateFilmEmptyJson() throws Exception { .andExpect(jsonPath("$.error").value("validation error")); } + @Test + void likeFilm() throws Exception { + + mockMvc.perform(put("/films/1/like/1")). + andExpect(status().isOk()) + .andExpect(jsonPath("$.status").value("success")); + + mockMvc.perform(put("/films/1/like/2")). + andExpect(status().isOk()) + .andExpect(jsonPath("$.status").value("success")); + + assertEquals(2, filmService.getFilmById(1L).getUsersLikes().size()); + } + + @Test + void deleteFilm() throws Exception { + filmService.likeFilm(1L, 1L); + filmService.likeFilm(1L, 2L); + mockMvc.perform(delete("/films/1/like/1")). + andExpect(status().isOk()) + .andExpect(jsonPath("$.status").value("success")); + + mockMvc.perform(delete("/films/1/like/2")). + andExpect(status().isOk()) + .andExpect(jsonPath("$.status").value("success")); + + assertEquals(0, filmService.getFilmById(1L).getUsersLikes().size()); + } + + @Test + void likeUnknownFilm() throws Exception { + mockMvc.perform(put("/films/4/like/1")). + andExpect(status().isNotFound()) + .andExpect(jsonPath("$.error").value("not found")) + .andExpect(jsonPath("$.message").value("Фильм с id 4 не найден")); + } + + @Test + void likeFilmUnkownUser() throws Exception { + mockMvc.perform(put("/films/1/like/4")) + .andExpect(status().isNotFound()) + .andExpect(jsonPath("$.error").value("not found")) + .andExpect(jsonPath("$.message").value("Юзер с id 4 не найден")); + } + + @Test + void deleteLikeFilm() throws Exception { + filmService.likeFilm(1L, 1L); + mockMvc.perform(delete("/films/1/like/1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.status").value("success")); + + assertEquals(0, filmService.getFilmById(1L).getUsersLikes().size()); + } + + @Test + void deleteUnknownLikeFilm() throws Exception { + mockMvc.perform(delete("/films/1/like/1")) + .andExpect(status().isInternalServerError()) + .andExpect(jsonPath("$.error").value("server error")) + .andExpect(jsonPath("$.message").value("Пользователь не ставил лайк фильму")); + } + + @Test + void deleteLikeFilmUnkownUser() throws Exception { + mockMvc.perform(delete("/films/1/like/4")) + .andExpect(status().isNotFound()) + .andExpect(jsonPath("$.error").value("not found")) + .andExpect(jsonPath("$.message").value("Юзер с id 4 не найден")); + } + + @Test + void deleteLikeFilmUnkownFilm() throws Exception { + mockMvc.perform(delete("/films/4/like/1")). + andExpect(status().isNotFound()) + .andExpect(jsonPath("$.error").value("not found")) + .andExpect(jsonPath("$.message").value("Фильм с id 4 не найден")); + } + + @Test + void get3PopularFilms() throws Exception { + filmService.createFilm(new Film(3L, "test3", "test_descr3", LocalDate.of(1900, 12, 25), 10)); + filmService.createFilm(new Film(4L, "test4", "test_descr4", LocalDate.of(1900, 12, 25), 10)); + userService.createUser(new User(3L, "test3@mail.ru", "testlogin3", "testname1", LocalDate.of(1900, 12, 25))); + userService.createUser(new User(4L, "test4@mail.ru", "testlogin4", "testname2", LocalDate.of(1901, 10, 21))); + filmService.createFilm(new Film(5L, "test5", "test_descr5", LocalDate.of(1900, 12, 25), 10)); + filmService.createFilm(new Film(6L, "test6", "test_descr6", LocalDate.of(1900, 12, 25), 10)); + userService.createUser(new User(5L, "test5@mail.ru", "testlogin5", "testname1", LocalDate.of(1900, 12, 25))); + userService.createUser(new User(6L, "test6@mail.ru", "testlogin6 ", "testname2", LocalDate.of(1901, 10, 21))); + filmService.likeFilm(3L, 1L); + filmService.likeFilm(3L, 2L); + filmService.likeFilm(3L, 3L); + filmService.likeFilm(3L, 4L); + filmService.likeFilm(1L, 5L); + filmService.likeFilm(1L, 6L); + filmService.likeFilm(4L, 6L); + filmService.likeFilm(2L, 1L); + filmService.likeFilm(2L, 2L); + mockMvc.perform(get("/films/popular?count=3")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.length()").value(3)) + .andExpect(jsonPath("$[0].id").value(3)) + .andExpect(jsonPath("$[1].name").value("test1")) + .andExpect(jsonPath("$[2].description").value("test_descr2")); + } + + @Test + void getDefaultPopularFilms() throws Exception { + filmService.createFilm(new Film(3L, "test3", "test_descr3", LocalDate.of(1900, 12, 25), 10)); + filmService.createFilm(new Film(4L, "test4", "test_descr4", LocalDate.of(1900, 12, 25), 10)); + userService.createUser(new User(3L, "test3@mail.ru", "testlogin3", "testname1", LocalDate.of(1900, 12, 25))); + userService.createUser(new User(4L, "test4@mail.ru", "testlogin4", "testname2", LocalDate.of(1901, 10, 21))); + filmService.createFilm(new Film(5L, "test5", "test_descr5", LocalDate.of(1900, 12, 25), 10)); + filmService.createFilm(new Film(6L, "test6", "test_descr6", LocalDate.of(1900, 12, 25), 10)); + userService.createUser(new User(5L, "test5@mail.ru", "testlogin5", "testname1", LocalDate.of(1900, 12, 25))); + userService.createUser(new User(6L, "test6@mail.ru", "testlogin6 ", "testname2", LocalDate.of(1901, 10, 21))); + filmService.createFilm(new Film(7L, "test7", "test_descr7", LocalDate.of(1900, 12, 25), 10)); + filmService.createFilm(new Film(8L, "test8", "test_descr8", LocalDate.of(1900, 12, 25), 10)); + userService.createUser(new User(7L, "test7@mail.ru", "testlogin7", "testname1", LocalDate.of(1900, 12, 25))); + userService.createUser(new User(8L, "test8@mail.ru", "testlogin8", "testname2", LocalDate.of(1901, 10, 21))); + filmService.createFilm(new Film(9L, "test9", "test_descr9", LocalDate.of(1900, 12, 25), 10)); + filmService.createFilm(new Film(10L, "test10", "test_descr10", LocalDate.of(1900, 12, 25), 10)); + userService.createUser(new User(9L, "test9@mail.ru", "testlogin9", "testname1", LocalDate.of(1900, 12, 25))); + userService.createUser(new User(10L, "test10@mail.ru", "testlogin10 ", "testname2", LocalDate.of(1901, 10, 21))); + filmService.createFilm(new Film(11L, "test11", "test_descr11", LocalDate.of(1900, 12, 25), 10)); + filmService.createFilm(new Film(12L, "test12", "test_descr12", LocalDate.of(1900, 12, 25), 10)); + userService.createUser(new User(11L, "test11@mail.ru", "testlogin11", "testname1", LocalDate.of(1900, 12, 25))); + userService.createUser(new User(12L, "test12@mail.ru", "testlogin12", "testname2", LocalDate.of(1901, 10, 21))); + filmService.createFilm(new Film(13L, "test13", "test_descr13", LocalDate.of(1900, 12, 25), 10)); + filmService.createFilm(new Film(14L, "test14", "test_descr14", LocalDate.of(1900, 12, 25), 10)); + userService.createUser(new User(13L, "test13@mail.ru", "testlogin13", "testname1", LocalDate.of(1900, 12, 25))); + userService.createUser(new User(14L, "test14@mail.ru", "testlogin14 ", "testname2", LocalDate.of(1901, 10, 21))); + filmService.likeFilm(3L, 1L); + filmService.likeFilm(3L, 2L); + filmService.likeFilm(3L, 3L); + filmService.likeFilm(3L, 4L); + filmService.likeFilm(1L, 5L); + filmService.likeFilm(1L, 6L); + filmService.likeFilm(4L, 6L); + filmService.likeFilm(5L, 1L); + filmService.likeFilm(5L, 2L); + filmService.likeFilm(6L, 1L); + filmService.likeFilm(7L, 2L); + filmService.likeFilm(8L, 3L); + filmService.likeFilm(6L, 4L); + filmService.likeFilm(10L, 5L); + filmService.likeFilm(11L, 6L); + filmService.likeFilm(12L, 6L); + filmService.likeFilm(10L, 1L); + filmService.likeFilm(10L, 2L); + mockMvc.perform(get("/films/popular")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.length()").value(10)); + } + } From e301329e6f709d03aba50a3ac77d352a2ed630fe Mon Sep 17 00:00:00 2001 From: "kirill.fedorov" Date: Mon, 31 Mar 2025 21:39:50 +0500 Subject: [PATCH 10/12] =?UTF-8?q?=D0=BD=D0=B0=D0=BF=D0=B8=D1=81=D0=B0?= =?UTF-8?q?=D0=BB=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?UserController?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../practicum/filmorate/model/User.java | 7 - .../filmorate/service/UserService.java | 1 - .../filmorate/FilmControllerTest.java | 4 +- .../filmorate/UserControllerTest.java | 704 ++++++++++-------- 4 files changed, 390 insertions(+), 326 deletions(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/User.java b/src/main/java/ru/yandex/practicum/filmorate/model/User.java index 4d60941..95c2eda 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/User.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java @@ -40,11 +40,4 @@ public User(Long id, String email, String login, String name, LocalDate birthday this.name = name; this.birthday = birthday; } - - public User(String email, String login, String name, LocalDate birthday) { - this.email = email; - this.login = login; - this.name = name; - this.birthday = birthday; - } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java index ea5d370..5d38853 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -81,7 +81,6 @@ public void removeFriend(Long id, Long friendId) { if (!user.getFriends().remove(friendId) || !friend.getFriends().remove(id)) { log.warn("У пользователя с id {} не найден друг с id {}", id, friendId); - throw new NotFoundException("Пользователь не найден в друзьях"); } log.info("Пользователь с id {} удалил из друзей пользователя с id {}", id, friendId); diff --git a/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java b/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java index 0d234bf..bfe9e13 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java +++ b/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java @@ -279,8 +279,8 @@ void updateFilmEmptyJson() throws Exception { @Test void likeFilm() throws Exception { - mockMvc.perform(put("/films/1/like/1")). - andExpect(status().isOk()) + mockMvc.perform(put("/films/1/like/1")) + .andExpect(status().isOk()) .andExpect(jsonPath("$.status").value("success")); mockMvc.perform(put("/films/1/like/2")). diff --git a/src/test/java/ru/yandex/practicum/filmorate/UserControllerTest.java b/src/test/java/ru/yandex/practicum/filmorate/UserControllerTest.java index f0bfd49..6518009 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/UserControllerTest.java +++ b/src/test/java/ru/yandex/practicum/filmorate/UserControllerTest.java @@ -1,335 +1,407 @@ package ru.yandex.practicum.filmorate; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; + import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.http.*; + +import static org.junit.jupiter.api.Assertions.*; + +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; import ru.yandex.practicum.filmorate.model.User; + import ru.yandex.practicum.filmorate.service.UserService; import java.time.LocalDate; -import java.util.Objects; +import java.util.Arrays; import java.util.stream.Stream; -import static org.junit.jupiter.api.Assertions.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@SpringBootTest +@AutoConfigureMockMvc public class UserControllerTest { -// @Autowired -// private TestRestTemplate restTemplate; -// -// @Autowired -// private UserService userService; -// -// private final HttpHeaders headers = new HttpHeaders(); -// -// @Test -// void contextLoads() { -// } -// -// @BeforeEach -// void setUp() { -// headers.set("Content-Type", "application/json"); -// userService.clearData(); -// } -// -// static Stream provideInvalidUserJsonCreate() { -// return Stream.of( -// "{\n" + -// " \"login\": \"doloreullamco\",\n" + -// " \"name\": \"test User\",\n" + -// " \"email\": \"mail.ru\",\n" + -// " \"birthday\": \"1980-08-20\"\n" + -// "}", // Не верный email -// -// "{\n" + -// " \"login\": \"doloreullamco\",\n" + -// " \"name\": \"test User\",\n" + -// " \"email\": \"\",\n" + -// " \"birthday\": \"1980-08-20\"\n" + -// "}", // пустой email -// -// "{\n" + -// " \"login\": \"dolore ullamco\",\n" + -// " \"name\": \"test User\",\n" + -// " \"email\": \"mail@mail.ru\",\n" + -// " \"birthday\": \"1980-08-20\"\n" + -// "}", // логин с пробелами -// -// "{\n" + -// " \"login\": \"\",\n" + -// " \"name\": \"Nick Name\",\n" + -// " \"email\": \"mail@mail.ru\",\n" + -// " \"birthday\": \"1946-08-20\"\n" + -// "}", // пустой логин -// -// "{\n" + -// " \"login\": \"dolore\",\n" + -// " \"name\": \"Nick Name\",\n" + -// " \"email\": \"mail@mail.ru\",\n" + -// " \"birthday\": \"2060-08-20\"\n" + -// "}" // Дата рождения в будущем -// ); -// } -// -// static Stream provideInvalidUserJsonUpdate() { -// return Stream.of( -// "{\n" + -// " \"id\": 1,\n" + -// " \"login\": \"doloreullamco\",\n" + -// " \"name\": \"test User\",\n" + -// " \"email\": \"mail.ru\",\n" + -// " \"birthday\": \"1980-08-20\"\n" + -// "}", // Не верный email -// -// "{\n" + -// " \"id\": 1,\n" + -// " \"login\": \"doloreullamco\",\n" + -// " \"name\": \"test User\",\n" + -// " \"email\": \"\",\n" + -// " \"birthday\": \"1980-08-20\"\n" + -// "}", // пустой email -// -// "{\n" + -// " \"id\": 1,\n" + -// " \"login\": \"dolore ullamco\",\n" + -// " \"name\": \"test User\",\n" + -// " \"email\": \"mail@mail.ru\",\n" + -// " \"birthday\": \"1980-08-20\"\n" + -// "}", // логин с пробелами -// -// "{\n" + -// " \"id\": 1,\n" + -// " \"login\": \"\",\n" + -// " \"name\": \"Nick Name\",\n" + -// " \"email\": \"mail@mail.ru\",\n" + -// " \"birthday\": \"1946-08-20\"\n" + -// "}", // пустой логин -// -// "{\n" + -// " \"id\": 1,\n" + -// " \"login\": \"dolore\",\n" + -// " \"name\": \"Nick Name\",\n" + -// " \"email\": \"mail@mail.ru\",\n" + -// " \"birthday\": \"2060-08-20\"\n" + -// "}" // Дата рождения в будущем -// ); -// } -// -// static Stream provideInvalidUserJsonIdUpdate() { -// return Stream.of( -// "{\n" + -// " \"login\": \"dolore\",\n" + -// " \"name\": \"Nick Name\",\n" + -// " \"email\": \"mail@mail.ru\",\n" + -// " \"birthday\": \"1946-08-20\"\n" + -// "}", // Без Id -// -// "{\n" + -// " \"id\": 123,\n" + -// " \"login\": \"dolore\",\n" + -// " \"name\": \"Nick Name\",\n" + -// " \"email\": \"mail@mail.ru\",\n" + -// " \"birthday\": \"1946-08-20\"\n" + -// "}" // Id отсутствует в списке -// ); -// } -// -// @Test -// void getUsers() { -// userService.addUser(new User(1L, "test@mail.ru", "login1", "user1", -// LocalDate.of(1999, 2, 18))); -// userService.addUser(new User(2L, "test2@mail.ru", "login2", "user2", -// LocalDate.of(2001, 5, 25))); -// -// ResponseEntity response = restTemplate.getForEntity("/users", String.class); -// assertEquals(HttpStatus.OK, response.getStatusCode()); -// assertNotNull(response.getBody()); -// JsonElement expectedJson = JsonParser.parseString( -// "[\n" + -// " {\n" + -// " \"id\": 1,\n" + -// " \"email\": \"test@mail.ru\",\n" + -// " \"login\": \"login1\",\n" + -// " \"name\": \"user1\",\n" + -// " \"birthday\": \"1999-02-18\"\n" + -// " },\n" + -// " {\n" + -// " \"id\": 2,\n" + -// " \"email\": \"test2@mail.ru\",\n" + -// " \"login\": \"login2\",\n" + -// " \"name\": \"user2\",\n" + -// " \"birthday\": \"2001-05-25\"\n" + -// " }\n" + -// "]" -// ); -// assertEquals(expectedJson, JsonParser.parseString(response.getBody())); -// } -// -// @Test -// void addUser() { -// String json = "{\n" + -// " \"login\": \"testlogin\",\n" + -// " \"name\": \"Test User\",\n" + -// " \"email\": \"mail@mail.ru\",\n" + -// " \"birthday\": \"1946-08-20\"\n" + -// "}"; -// HttpEntity entity = new HttpEntity<>(json, headers); -// ResponseEntity response = restTemplate.exchange("/users", HttpMethod.POST, entity, String.class); -// assertEquals(HttpStatus.OK, response.getStatusCode()); -// assertNotNull(response.getBody()); -// JsonElement expectedJson = JsonParser.parseString( -// "{ \"id\": 1,\n" + -// " \"login\": \"testlogin\",\n" + -// " \"name\": \"Test User\",\n" + -// " \"email\": \"mail@mail.ru\",\n" + -// " \"birthday\": \"1946-08-20\"\n" + -// "}" -// ); -// assertEquals(expectedJson, JsonParser.parseString(response.getBody())); -// -// User createdUser = userService.getUsersMap().get(1L); -// assertNotNull(createdUser); -// assertEquals("testlogin", createdUser.getLogin()); -// assertEquals("Test User", createdUser.getName()); -// assertEquals("mail@mail.ru", createdUser.getEmail()); -// assertEquals(LocalDate.of(1946, 8, 20), createdUser.getBirthday()); -// } -// -// @Test -// void addUserWithoutName() { -// String json = "{\n" + -// " \"login\": \"testlogin\",\n" + -// " \"email\": \"mail@mail.ru\",\n" + -// " \"birthday\": \"1946-08-20\"\n" + -// "}"; -// HttpEntity entity = new HttpEntity<>(json, headers); -// ResponseEntity response = restTemplate.exchange("/users", HttpMethod.POST, entity, String.class); -// assertEquals(HttpStatus.OK, response.getStatusCode()); -// assertNotNull(response.getBody()); -// -// JsonElement expectedJson = JsonParser.parseString( -// "{ \"id\": 1,\n" + -// " \"login\": \"testlogin\",\n" + -// " \"name\": \"testlogin\",\n" + -// " \"email\": \"mail@mail.ru\",\n" + -// " \"birthday\": \"1946-08-20\"\n" + -// "}" -// ); -// assertEquals(expectedJson, JsonParser.parseString(response.getBody())); -// -// User createdUser = userService.getUsersMap().get(1L); -// assertNotNull(createdUser); -// assertEquals("testlogin", createdUser.getLogin()); -// assertEquals("testlogin", createdUser.getName()); -// assertEquals("mail@mail.ru", createdUser.getEmail()); -// assertEquals(LocalDate.of(1946, 8, 20), createdUser.getBirthday()); -// } -// -// @Test -// void updateUser() { -// userService.addUser(new User(1L, "test@mail.ru", "login1", "user1", -// LocalDate.of(1999, 2, 18))); -// String json = "{\n" + -// " \"id\": 1,\n" + -// " \"login\": \"login1Upd\",\n" + -// " \"name\": \"Test User upd\",\n" + -// " \"email\": \"mailupd@mail.ru\",\n" + -// " \"birthday\": \"1978-10-21\"\n" + -// "}"; -// HttpEntity entity = new HttpEntity<>(json, headers); -// ResponseEntity response = restTemplate.exchange("/users", HttpMethod.PUT, entity, String.class); -// assertEquals(HttpStatus.OK, response.getStatusCode()); -// assertNotNull(response.getBody()); -// -// JsonElement expectedJson = JsonParser.parseString(json); -// assertEquals(expectedJson, JsonParser.parseString(response.getBody())); -// -// User updatedUser = userService.getUsersMap().get(1L); -// assertNotNull(updatedUser); -// assertEquals("login1Upd", updatedUser.getLogin()); -// assertEquals("Test User upd", updatedUser.getName()); -// assertEquals("mailupd@mail.ru", updatedUser.getEmail()); -// assertEquals(LocalDate.of(1978, 10, 21), updatedUser.getBirthday()); -// } -// -// @Test -// void updateUserWithoutName() { -// userService.addUser(new User(1L, "test@mail.ru", "login1", "user1", -// LocalDate.of(1999, 2, 18))); -// String json = "{\n" + -// " \"id\": 1,\n" + -// " \"login\": \"login1Upd\",\n" + -// " \"email\": \"mailupd@mail.ru\",\n" + -// " \"birthday\": \"1978-10-21\"\n" + -// "}"; -// HttpEntity entity = new HttpEntity<>(json, headers); -// ResponseEntity response = restTemplate.exchange("/users", HttpMethod.PUT, entity, String.class); -// assertEquals(HttpStatus.OK, response.getStatusCode()); -// assertNotNull(response.getBody()); -// -// User updatedUser = userService.getUsersMap().get(1L); -// assertNotNull(updatedUser); -// assertEquals("login1Upd", updatedUser.getLogin()); -// assertEquals("login1Upd", updatedUser.getName()); -// assertEquals("mailupd@mail.ru", updatedUser.getEmail()); -// assertEquals(LocalDate.of(1978, 10, 21), updatedUser.getBirthday()); -// } -// -// @ParameterizedTest -// @MethodSource("provideInvalidUserJsonCreate") -// void addUserValidation(String json) { -// HttpEntity entity = new HttpEntity<>(json, headers); -// ResponseEntity response = restTemplate.exchange("/users", HttpMethod.POST, entity, String.class); -// assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); -// assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); -// } -// -// @Test -// void addUserEmptyJson() { -// HttpEntity entity = new HttpEntity<>(null, headers); -// ResponseEntity response = restTemplate.exchange("/users", HttpMethod.POST, entity, String.class); -// assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); -// assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); -// } -// -// @ParameterizedTest -// @MethodSource("provideInvalidUserJsonUpdate") -// void updateUserValidation(String json) { -// userService.addUser(new User(1L, "test@mail.ru", "login1", "user1", -// LocalDate.of(1999, 2, 18))); -// HttpEntity entity = new HttpEntity<>(json, headers); -// ResponseEntity response = restTemplate.exchange("/users", HttpMethod.PUT, entity, String.class); -// assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); -// assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); -// } -// -// @ParameterizedTest -// @MethodSource("provideInvalidUserJsonIdUpdate") -// void updateUserIdValidation(String json) { -// userService.addUser(new User(1L, "test@mail.ru", "login1", "user1", -// LocalDate.of(1999, 2, 18))); -// HttpEntity entity = new HttpEntity<>(json, headers); -// ResponseEntity response = restTemplate.exchange("/users", HttpMethod.PUT, entity, String.class); -// assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode()); -// assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Internal Server Error\"")); -// } -// -// @Test -// void updateUserEmptyJson() { -// userService.addUser(new User(1L, "test@mail.ru", "login1", "user1", -// LocalDate.of(1999, 2, 18))); -// HttpEntity entity = new HttpEntity<>(null, headers); -// ResponseEntity response = restTemplate.exchange("/users", HttpMethod.PUT, entity, String.class); -// assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); -// assertTrue(Objects.requireNonNull(response.getBody()).contains("\"error\":\"Bad Request\"")); -// } + @Autowired + private MockMvc mockMvc; + + @Autowired + private UserService userService; + + static Stream provideInvalidUserJsonCreate() { + return Stream.of( + "{\n" + + " \"login\": \"doloreullamco\",\n" + + " \"name\": \"test User\",\n" + + " \"email\": \"mail.ru\",\n" + + " \"birthday\": \"1980-08-20\"\n" + + "}", // Не верный email + + "{\n" + + " \"login\": \"doloreullamco\",\n" + + " \"name\": \"test User\",\n" + + " \"email\": \"\",\n" + + " \"birthday\": \"1980-08-20\"\n" + + "}", // пустой email + + "{\n" + + " \"login\": \"dolore ullamco\",\n" + + " \"name\": \"test User\",\n" + + " \"email\": \"mail@mail.ru\",\n" + + " \"birthday\": \"1980-08-20\"\n" + + "}", // логин с пробелами + + "{\n" + + " \"login\": \"\",\n" + + " \"name\": \"Nick Name\",\n" + + " \"email\": \"mail@mail.ru\",\n" + + " \"birthday\": \"1946-08-20\"\n" + + "}", // пустой логин + + "{\n" + + " \"login\": \"dolore\",\n" + + " \"name\": \"Nick Name\",\n" + + " \"email\": \"mail@mail.ru\",\n" + + " \"birthday\": \"2060-08-20\"\n" + + "}" // Дата рождения в будущем + ); + } + + static Stream provideInvalidUserJsonUpdate() { + return Stream.of( + "{\n" + + " \"id\": 1,\n" + + " \"login\": \"doloreullamco\",\n" + + " \"name\": \"test User\",\n" + + " \"email\": \"mail.ru\",\n" + + " \"birthday\": \"1980-08-20\"\n" + + "}", // Не верный email + + "{\n" + + " \"id\": 1,\n" + + " \"login\": \"doloreullamco\",\n" + + " \"name\": \"test User\",\n" + + " \"email\": \"\",\n" + + " \"birthday\": \"1980-08-20\"\n" + + "}", // пустой email + + "{\n" + + " \"id\": 1,\n" + + " \"login\": \"dolore ullamco\",\n" + + " \"name\": \"test User\",\n" + + " \"email\": \"mail@mail.ru\",\n" + + " \"birthday\": \"1980-08-20\"\n" + + "}", // логин с пробелами + + "{\n" + + " \"id\": 1,\n" + + " \"login\": \"\",\n" + + " \"name\": \"Nick Name\",\n" + + " \"email\": \"mail@mail.ru\",\n" + + " \"birthday\": \"1946-08-20\"\n" + + "}", // пустой логин + + "{\n" + + " \"id\": 1,\n" + + " \"login\": \"dolore\",\n" + + " \"name\": \"Nick Name\",\n" + + " \"email\": \"mail@mail.ru\",\n" + + " \"birthday\": \"2060-08-20\"\n" + + "}" // Дата рождения в будущем + ); + } + + @BeforeEach + void setUp() { + userService.createUser(new User(1L, "test@mail.ru", "testlogin1", "testname1", LocalDate.of(1900, 12, 25))); + userService.createUser(new User(2L, "test2@mail.ru", "testlogin2", "testname2", LocalDate.of(1901, 10, 21))); + userService.createUser(new User(3L, "test3@mail.ru", "testlogin3", "testname3", LocalDate.of(1900, 12, 25))); + userService.createUser(new User(4L, "test4@mail.ru", "testlogin4", "testname4", LocalDate.of(1901, 10, 21))); + } + + @AfterEach + void tearDown() { + userService.clearUsersData(); + } + + @Test + void getAllUsers() throws Exception { + mockMvc.perform(get("/users")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id").value(1)) + .andExpect(jsonPath("$[1].name").value("testname2")) + .andExpect(jsonPath("$[2].email").value("test3@mail.ru")) + .andExpect(jsonPath("$[3].login").value("testlogin4")); + } + + @Test + void getUserById() throws Exception { + mockMvc.perform(get("/users/1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").value(1)) + .andExpect(jsonPath("$.name").value("testname1")); + } + + @Test + void getUnknownUserById() throws Exception { + mockMvc.perform(get("/users/200")) + .andExpect(status().isNotFound()) + .andExpect(jsonPath("$.error").value("not found")) + .andExpect(jsonPath("$.message").value("Юзер с id 200 не найден")); + } + + @Test + void addUser() throws Exception { + String json = "{\n" + + " \"login\": \"testlogin\",\n" + + " \"name\": \"Test User\",\n" + + " \"email\": \"mail@mail.ru\",\n" + + " \"birthday\": \"1946-08-20\"\n" + + "}"; + mockMvc.perform(post("/users") + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.id").value(5)) + .andExpect(jsonPath("$.name").value("Test User")); + + assertEquals(userService.getUserById(5L).getLogin(), "testlogin"); + } + + @Test + void addUserWithoutName() throws Exception { + String json = "{\n" + + " \"login\": \"testlogin\",\n" + + " \"email\": \"mail@mail.ru\",\n" + + " \"birthday\": \"1946-08-20\"\n" + + "}"; + + mockMvc.perform(post("/users") + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.id").value(5)) + .andExpect(jsonPath("$.name").value("testlogin")); + assertEquals(userService.getUserById(5L).getName(), "testlogin"); + } + + @Test + void updateUser() throws Exception { + String json = "{\n" + + " \"id\": 1,\n" + + " \"login\": \"testlogin1upd\",\n" + + " \"name\": \"testname1 upd\",\n" + + " \"email\": \"testupd@mail.ru\",\n" + + " \"birthday\": \"1978-10-21\"\n" + + "}"; + + mockMvc.perform(put("/users") + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").value(1)) + .andExpect(jsonPath("$.name").value("testname1 upd")) + .andExpect(jsonPath("$.email").value("testupd@mail.ru")) + .andExpect(jsonPath("$.login").value("testlogin1upd")) + .andExpect(jsonPath("$.birthday").value("1978-10-21")); + assertEquals("testlogin1upd", userService.getUserById(1L).getLogin()); + assertEquals("testname1 upd", userService.getUserById(1L).getName()); + assertEquals("testupd@mail.ru", userService.getUserById(1L).getEmail()); + assertEquals("1978-10-21", userService.getUserById(1L).getBirthday().toString()); + } + + @Test + void updateUserWithoutName() throws Exception { + String json = "{\n" + + " \"id\": 1,\n" + + " \"login\": \"testlogin1upd\",\n" + + " \"email\": \"testupd@mail.ru\",\n" + + " \"birthday\": \"1978-10-21\"\n" + + "}"; + + mockMvc.perform(put("/users") + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").value(1)) + .andExpect(jsonPath("$.name").value("testlogin1upd")) + .andExpect(jsonPath("$.email").value("testupd@mail.ru")) + .andExpect(jsonPath("$.login").value("testlogin1upd")) + .andExpect(jsonPath("$.birthday").value("1978-10-21")); + assertEquals("testlogin1upd", userService.getUserById(1L).getLogin()); + assertEquals("testlogin1upd", userService.getUserById(1L).getName()); + assertEquals("testupd@mail.ru", userService.getUserById(1L).getEmail()); + assertEquals("1978-10-21", userService.getUserById(1L).getBirthday().toString()); + } + + @ParameterizedTest + @MethodSource("provideInvalidUserJsonUpdate") + void updateUserValidation(String json) throws Exception { + mockMvc.perform(put("/users") + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.error").value("validation error")); + + } + + @ParameterizedTest + @MethodSource("provideInvalidUserJsonCreate") + void addUserValidation(String json) throws Exception { + mockMvc.perform(post("/users") + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.error").value("validation error")); + + } + + @Test + void addUserEmptyJson() throws Exception { + String json = "{}"; + + mockMvc.perform(post("/users") + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.error").value("validation error")); + } + + @Test + void updateUserWithoutId() throws Exception { + String json = "{\n" + + " \"login\": \"dolore\",\n" + + " \"name\": \"Nick Name\",\n" + + " \"email\": \"mail@mail.ru\",\n" + + " \"birthday\": \"1946-08-20\"\n" + + "}"; + + mockMvc.perform(put("/users") + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.error").value("validation error")); + } + + @Test + void updateUnknownUser() throws Exception { + String json = "{\n" + + " \"id\": 123,\n" + + " \"login\": \"dolore\",\n" + + " \"name\": \"Nick Name\",\n" + + " \"email\": \"mail@mail.ru\",\n" + + " \"birthday\": \"1946-08-20\"\n" + + "}"; + + mockMvc.perform(put("/users") + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andExpect(status().isNotFound()) + .andExpect(jsonPath("$.error").value("not found")) + .andExpect(jsonPath("$.message").value("Пользователь с id 123 не найден")); + } + + @Test + void updateUserEmptyJson() throws Exception { + String json = "{}"; + + mockMvc.perform(put("/users") + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.error").value("validation error")); + } + + @Test + void addFriend() throws Exception { + mockMvc.perform(put("/users/1/friends/2")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.status").value("success")); + + mockMvc.perform(put("/users/1/friends/3")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.status").value("success")); + + assertEquals(2, userService.getUserById(1L).getFriends().size()); + assertEquals(1, userService.getUserById(2L).getFriends().size()); + assertEquals(1, userService.getUserById(3L).getFriends().size()); + assertEquals(Arrays.toString(new int[]{2, 3}), userService.getUserById(1L).getFriends().toString()); + } + + @Test + void removeFriend() throws Exception { + userService.addFriend(1L, 2L); + userService.addFriend(1L, 3L); + + mockMvc.perform(delete("/users/1/friends/2")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.status").value("success")); + + mockMvc.perform(delete("/users/1/friends/3")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.status").value("success")); + + assertEquals(0, userService.getUserById(1L).getFriends().size()); + assertEquals(0, userService.getUserById(2L).getFriends().size()); + assertEquals(0, userService.getUserById(3L).getFriends().size()); + } + + @Test + void addUnknownFriend() throws Exception { + mockMvc.perform(put("/users/1/friends/10")) + .andExpect(status().isNotFound()) + .andExpect(jsonPath("$.message").value("Юзер с id 10 не найден")); + } + + @Test + void addFriendMyself() throws Exception { + mockMvc.perform(put("/users/1/friends/1")) + .andExpect(status().isInternalServerError()) + .andExpect(jsonPath("$.message").value("Пользователь не может " + + "добавить сам себя в друзья")); + } + + @Test + void addFriendUserFriend() throws Exception { + userService.addFriend(1L, 2L); + + mockMvc.perform(put("/users/1/friends/2")) + .andExpect(status().isInternalServerError()) + .andExpect(jsonPath("$.message").value("Пользователи уже являются друзьями")); + } + + @Test + void getUserFriends() throws Exception { + userService.addFriend(1L, 2L); + userService.addFriend(1L, 3L); + + mockMvc.perform(get("/users/1/friends")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.length()").value(2)) + .andExpect(jsonPath("$[0].id").value(2)) + .andExpect(jsonPath("$[1].name").value("testname3")); + } + + @Test + void getCommonUserFriends() throws Exception { + userService.addFriend(1L, 2L); + userService.addFriend(1L, 3L); + userService.addFriend(4L, 2L); + userService.addFriend(4L, 3L); + mockMvc.perform(get("/users/1/friends/common/4")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.length()").value(2)) + .andExpect(jsonPath("$[0].id").value(2)) + .andExpect(jsonPath("$[1].name").value("testname3")); + } + } From fcdb153708e883c8f3f449ccb603f610e75d947c Mon Sep 17 00:00:00 2001 From: "kirill.fedorov" Date: Mon, 31 Mar 2025 21:43:42 +0500 Subject: [PATCH 11/12] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BB=D0=BE=D0=B3=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=BF=D1=80=D0=BE=D1=81=D0=BE=D0=B2?= =?UTF-8?q?/=D0=BE=D1=82=D0=B2=D0=B5=D1=82=D0=BE=D0=B2=20=D0=B2=20=D1=84?= =?UTF-8?q?=D0=BE=D1=80=D0=BC=D0=B0=D1=82=D0=B5=20JSON?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 5 +++++ src/main/resources/application.properties | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 10fbe05..001dcbd 100644 --- a/pom.xml +++ b/pom.xml @@ -41,6 +41,11 @@ gson 2.8.9 + + org.zalando + logbook-spring-boot-starter + 3.7.2 + diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 4b49e8e..10f7117 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,2 @@ -logging.level.root=INFO \ No newline at end of file +logging.level.root=INFO +logging.level.org.zalando.logbook= TRACE \ No newline at end of file From ff8cd8ce91999434e4fa9543d8e62d6141fbae86 Mon Sep 17 00:00:00 2001 From: "kirill.fedorov" Date: Mon, 31 Mar 2025 21:47:50 +0500 Subject: [PATCH 12/12] fix codestyle --- .../exception/NotFoundException.java | 1 - .../filmorate/exception/OtherException.java | 1 + .../storage/user/InMemoryUserStorage.java | 3 --- .../filmorate/FilmControllerTest.java | 20 +++++++++---------- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/NotFoundException.java b/src/main/java/ru/yandex/practicum/filmorate/exception/NotFoundException.java index 6c7cee4..417433b 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/exception/NotFoundException.java +++ b/src/main/java/ru/yandex/practicum/filmorate/exception/NotFoundException.java @@ -1,6 +1,5 @@ package ru.yandex.practicum.filmorate.exception; -import lombok.Data; import lombok.Getter; diff --git a/src/main/java/ru/yandex/practicum/filmorate/exception/OtherException.java b/src/main/java/ru/yandex/practicum/filmorate/exception/OtherException.java index eeb2b1c..e9694c1 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/exception/OtherException.java +++ b/src/main/java/ru/yandex/practicum/filmorate/exception/OtherException.java @@ -5,6 +5,7 @@ @Getter public class OtherException extends RuntimeException { String name = "server error"; + public OtherException(String message) { super(message); } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java index d8da095..76fae6a 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/user/InMemoryUserStorage.java @@ -2,9 +2,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import org.springframework.stereotype.Controller; -import ru.yandex.practicum.filmorate.exception.NotFoundException; -import ru.yandex.practicum.filmorate.exception.ValidationException; import ru.yandex.practicum.filmorate.model.User; import java.util.Collection; diff --git a/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java b/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java index bfe9e13..1b93f1c 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java +++ b/src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java @@ -283,8 +283,8 @@ void likeFilm() throws Exception { .andExpect(status().isOk()) .andExpect(jsonPath("$.status").value("success")); - mockMvc.perform(put("/films/1/like/2")). - andExpect(status().isOk()) + mockMvc.perform(put("/films/1/like/2")) + .andExpect(status().isOk()) .andExpect(jsonPath("$.status").value("success")); assertEquals(2, filmService.getFilmById(1L).getUsersLikes().size()); @@ -294,12 +294,12 @@ void likeFilm() throws Exception { void deleteFilm() throws Exception { filmService.likeFilm(1L, 1L); filmService.likeFilm(1L, 2L); - mockMvc.perform(delete("/films/1/like/1")). - andExpect(status().isOk()) + mockMvc.perform(delete("/films/1/like/1")) + .andExpect(status().isOk()) .andExpect(jsonPath("$.status").value("success")); - mockMvc.perform(delete("/films/1/like/2")). - andExpect(status().isOk()) + mockMvc.perform(delete("/films/1/like/2")) + .andExpect(status().isOk()) .andExpect(jsonPath("$.status").value("success")); assertEquals(0, filmService.getFilmById(1L).getUsersLikes().size()); @@ -307,8 +307,8 @@ void deleteFilm() throws Exception { @Test void likeUnknownFilm() throws Exception { - mockMvc.perform(put("/films/4/like/1")). - andExpect(status().isNotFound()) + mockMvc.perform(put("/films/4/like/1")) + .andExpect(status().isNotFound()) .andExpect(jsonPath("$.error").value("not found")) .andExpect(jsonPath("$.message").value("Фильм с id 4 не найден")); } @@ -349,8 +349,8 @@ void deleteLikeFilmUnkownUser() throws Exception { @Test void deleteLikeFilmUnkownFilm() throws Exception { - mockMvc.perform(delete("/films/4/like/1")). - andExpect(status().isNotFound()) + mockMvc.perform(delete("/films/4/like/1")) + .andExpect(status().isNotFound()) .andExpect(jsonPath("$.error").value("not found")) .andExpect(jsonPath("$.message").value("Фильм с id 4 не найден")); }