From 2b6a9060e1f3459fb50462d1160ed14d6b8d0b55 Mon Sep 17 00:00:00 2001 From: Sergey Filippovskikh Date: Mon, 3 Feb 2025 06:25:06 +0300 Subject: [PATCH 01/17] =?UTF-8?q?=D0=A1=D0=BF=D1=80=D0=B8=D0=BD=D1=82=2012?= =?UTF-8?q?-1.=20=D0=A0=D0=B5=D0=B9=D1=82=D0=B8=D0=BD=D0=B3=20=D0=A4=D0=B8?= =?UTF-8?q?=D0=BB=D1=8C=D0=BC=D0=BE=D0=B2.=20=D0=9F=D1=80=D0=BE=D0=BC?= =?UTF-8?q?=D0=B5=D0=B6=D1=83=D1=82=D0=BE=D1=87=D0=BD=D0=BE=D0=B5=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=2012=20=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=D0=BD=D1=82=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 20 ++++++++++++++++++-- er_diagram_filmrate.png | Bin 0 -> 37449 bytes 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 er_diagram_filmrate.png diff --git a/README.md b/README.md index 9f00859..a116f5d 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,25 @@ _java-filmorate_ # Рейтинг фильмов -### Согласно задания спринта № 11 +### Согласно задания спринта № 12 (добавление Базы данных) ## выполнено Филипповских Сергеем _**Когорта-53**_ -в файле PostmanSprint11_add-friends-likes.json находится скрипт для проверки API +![](/er_diagram_filmrate.png) + +Примеры запросов: +1. Получение пользователя с ID = 1: \ + SELECT * + FROM users + WHERE user_id = 1; + +2. Получение фильма с ID = 10: \ + SELECT * + FROM films + WHERE film_id = 10. + +3. Получение списка фильмов, понравившихся пользователю с ID = 5: \ + SELECT title + FROM films + WHERE film_id IN (SELECT film_id FROM likes WHERE user_id = 5); diff --git a/er_diagram_filmrate.png b/er_diagram_filmrate.png new file mode 100644 index 0000000000000000000000000000000000000000..e312c2109865446716f92a58e0b81f40fccf81c7 GIT binary patch literal 37449 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 Date: Mon, 3 Feb 2025 15:02:47 +0300 Subject: [PATCH 02/17] =?UTF-8?q?=D0=A1=D0=BF=D1=80=D0=B8=D0=BD=D1=82=2012?= =?UTF-8?q?-1.=20=D0=A0=D0=B5=D0=B9=D1=82=D0=B8=D0=BD=D0=B3=20=D0=A4=D0=B8?= =?UTF-8?q?=D0=BB=D1=8C=D0=BC=D0=BE=D0=B2.=20=D0=9F=D1=80=D0=BE=D0=BC?= =?UTF-8?q?=D0=B5=D0=B6=D1=83=D1=82=D0=BE=D1=87=D0=BD=D0=BE=D0=B5=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=2012=20=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=D0=BD=D1=82=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- er_diagram_filmrate.png | Bin 37449 -> 45841 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/er_diagram_filmrate.png b/er_diagram_filmrate.png index e312c2109865446716f92a58e0b81f40fccf81c7..c12be5b00b84968105920af0c76ac81efef790d5 100644 GIT binary patch literal 45841 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 JF6*2UngB$^KwSU; literal 37449 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 Date: Mon, 3 Feb 2025 15:09:17 +0300 Subject: [PATCH 03/17] =?UTF-8?q?=D0=A1=D0=BF=D1=80=D0=B8=D0=BD=D1=82=2012?= =?UTF-8?q?-1.=20=D0=A0=D0=B5=D0=B9=D1=82=D0=B8=D0=BD=D0=B3=20=D0=A4=D0=B8?= =?UTF-8?q?=D0=BB=D1=8C=D0=BC=D0=BE=D0=B2.=20=D0=9F=D1=80=D0=BE=D0=BC?= =?UTF-8?q?=D0=B5=D0=B6=D1=83=D1=82=D0=BE=D1=87=D0=BD=D0=BE=D0=B5=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=2012=20=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=D0=BD=D1=82=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- er_diagram_filmrate.png | Bin 45841 -> 54303 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/er_diagram_filmrate.png b/er_diagram_filmrate.png index c12be5b00b84968105920af0c76ac81efef790d5..f7b53e5a70adc5ec8cf6c4f9c3666a9b854fedba 100644 GIT binary patch literal 54303 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 (#aF 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 literal 45841 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 JF6*2UngB$^KwSU; From 8bfbf558ccf710193cf91e9e1d8708a1876c0a18 Mon Sep 17 00:00:00 2001 From: Sergey Filippovskikh Date: Mon, 17 Feb 2025 13:18:44 +0300 Subject: [PATCH 04/17] =?UTF-8?q?=D0=A1=D0=BF=D1=80=D0=B8=D0=BD=D1=82=2012?= =?UTF-8?q?.=20=D0=A0=D0=B5=D0=B9=D1=82=D0=B8=D0=BD=D0=B3=20=D0=A4=D0=B8?= =?UTF-8?q?=D0=BB=D1=8C=D0=BC=D0=BE=D0=B2.=20=D0=9F=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B2=D0=BE=D0=B4=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B2=20=D0=B1?= =?UTF-8?q?=D0=B0=D0=B7=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20H2.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 39 ++++++- .../filmorate/controller/ErrorHandler.java | 10 +- .../filmorate/controller/GenreController.java | 29 +++++ .../controller/RatingController.java | 32 +++++ .../practicum/filmorate/model/Film.java | 22 ++-- .../practicum/filmorate/model/Genre.java | 11 ++ .../filmorate/model/MinimumDate.java | 2 + .../filmorate/model/MinimumDateValidator.java | 12 +- .../practicum/filmorate/model/Rating.java | 11 ++ .../practicum/filmorate/model/User.java | 20 ++-- .../filmorate/service/FilmService.java | 16 +-- .../filmorate/service/GenreService.java | 24 ++++ .../filmorate/service/RatingService.java | 24 ++++ .../filmorate/service/UserService.java | 21 ++-- .../filmorate/storage/FilmDbStorage.java | 110 ++++++++++++++++++ .../filmorate/storage/FriendDbStorage.java | 37 ++++++ .../filmorate/storage/GenreDbStorage.java | 50 ++++++++ .../storage/InMemoryFilmStorage.java | 4 +- .../storage/InMemoryUserStorage.java | 3 +- .../filmorate/storage/LikeDbStorage.java | 37 ++++++ .../filmorate/storage/RatingDbStorage.java | 41 +++++++ .../filmorate/storage/UserDbStorage.java | 76 ++++++++++++ .../storage/dbmapper/FilmRowMapper.java | 37 ++++++ .../storage/dbmapper/GenreRowMapper.java | 23 ++++ .../storage/dbmapper/RatingRowMapper.java | 23 ++++ .../storage/dbmapper/UserRowMapper.java | 33 ++++++ src/main/resources/application.properties | 6 + src/main/resources/data.sql | 14 +++ src/main/resources/schema.sql | 54 +++++++++ 29 files changed, 764 insertions(+), 57 deletions(-) create mode 100644 src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/controller/RatingController.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/model/Genre.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/model/Rating.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/service/GenreService.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/service/RatingService.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/FilmDbStorage.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/FriendDbStorage.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/GenreDbStorage.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/LikeDbStorage.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/RatingDbStorage.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/UserDbStorage.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/FilmRowMapper.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/GenreRowMapper.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/RatingRowMapper.java create mode 100644 src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/UserRowMapper.java create mode 100644 src/main/resources/data.sql create mode 100644 src/main/resources/schema.sql diff --git a/pom.xml b/pom.xml index 57fafc4..b1b25b2 100644 --- a/pom.xml +++ b/pom.xml @@ -2,20 +2,24 @@ 4.0.0 + org.springframework.boot spring-boot-starter-parent - 3.2.4 + 3.4.1 + ru.yandex.practicum filmorate 0.0.1-SNAPSHOT filmorate filmorate + - 21 + 23 + org.springframework.boot @@ -38,9 +42,17 @@ org.zalando logbook-spring-boot-starter - 3.9.0 + 3.9.0 + + + org.springframework.boot + spring-boot-starter-jdbc + + + com.h2database + h2 + runtime - @@ -49,6 +61,25 @@ org.springframework.boot spring-boot-maven-plugin + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.6.0 + + checkstyle.xml + true + true + true + + + + + check + + compile + + + diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/ErrorHandler.java b/src/main/java/ru/yandex/practicum/filmorate/controller/ErrorHandler.java index 5694d83..94882a8 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/ErrorHandler.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/ErrorHandler.java @@ -22,7 +22,7 @@ public class ErrorHandler { @ExceptionHandler @ResponseStatus(HttpStatus.BAD_REQUEST) public ErrorResponse handleValidationException(final ValidationException e) { - log.error(HttpStatus.BAD_REQUEST + " - " + e.getMessage()); + log.error("{} - {}", HttpStatus.BAD_REQUEST, e.getMessage()); return new ErrorResponse(e.getMessage()); } @@ -34,26 +34,26 @@ public ErrorResponse handleMethodArgumentNotValidException(final MethodArgumentN String defaultMessage = allErrors.stream() .map(error -> Objects.requireNonNull(error.getDefaultMessage())) .collect(Collectors.joining(", ")); - log.error(HttpStatus.BAD_REQUEST + " - " + defaultMessage); + log.error("{} - {}", HttpStatus.BAD_REQUEST, defaultMessage); return new ErrorResponse(defaultMessage); } @ExceptionHandler @ResponseStatus(HttpStatus.NOT_FOUND) public ErrorResponse handleNotFoundException(final NotFoundException e) { - log.error(HttpStatus.NOT_FOUND + " - " + e.getMessage()); + log.error("{} - {}", HttpStatus.NOT_FOUND, e.getMessage()); return new ErrorResponse(e.getMessage()); } @ExceptionHandler @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public ErrorResponse handleRunTimeException(final RuntimeException e) { - log.error(HttpStatus.INTERNAL_SERVER_ERROR + " - " + e.getMessage()); + log.error("{} - {}", HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage()); return new ErrorResponse(e.getMessage()); } @Getter - private static class ErrorResponse { + public static class ErrorResponse { private final String error; public ErrorResponse(String error) { diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java new file mode 100644 index 0000000..2a70238 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java @@ -0,0 +1,29 @@ +package ru.yandex.practicum.filmorate.controller; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; +import ru.yandex.practicum.filmorate.model.Genre; +import ru.yandex.practicum.filmorate.service.GenreService; + +import java.util.List; + +@Slf4j +@RestController +@RequestMapping("/genres") +@RequiredArgsConstructor +public class GenreController { + private final GenreService genreService; + + // получаем список жанров + @GetMapping + public List findAll() { + return genreService.findAll(); + } + + // Получаем жанр по id + @GetMapping("/{Id}") + public Genre getById(@PathVariable Integer Id) { + return genreService.getById(Id); + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/RatingController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/RatingController.java new file mode 100644 index 0000000..42734cb --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/RatingController.java @@ -0,0 +1,32 @@ +package ru.yandex.practicum.filmorate.controller; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import ru.yandex.practicum.filmorate.model.Rating; +import ru.yandex.practicum.filmorate.service.RatingService; + +import java.util.List; + +@Slf4j +@RestController +@RequestMapping("/mpa") +@RequiredArgsConstructor +public class RatingController { + private final RatingService ratingService; + + // получаем список рейтингов + @GetMapping + public List findAll() { + return ratingService.findAll(); + } + + // Получаем рейтинг по id + @GetMapping("/{Id}") + public Rating getById(@PathVariable Integer Id) { + return ratingService.getById(Id); + } +} 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 1c5b382..3ba3aec 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java @@ -1,6 +1,5 @@ package ru.yandex.practicum.filmorate.model; - import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; @@ -8,16 +7,18 @@ import lombok.Data; import lombok.extern.slf4j.Slf4j; -import java.time.LocalDate; -import java.util.HashSet; -import java.util.Set; +import java.sql.Date; +import java.util.ArrayList; +import java.util.List; @Data @Slf4j public class Film { private Integer id; - private Set likes = new HashSet<>(); + private List likes = new ArrayList<>(); + + private List genres = new ArrayList<>(); @NotNull(message = "Необходимо указать название фильма") @NotBlank(message = "Название фильма не может быть пустым") @@ -26,12 +27,14 @@ public class Film { @Size(min = 1, max = 200, message = "Описание фильма должно быть от 1 до 200 символов") private String description; - @MinimumDate(message = "Фильм не может выйти в прокат ранее 28.12.1895") - private LocalDate releaseDate; - @NotNull(message = "Необходимо указать продолжительность фильма") @Min(value = 1, message = "Продолжительность фильма должна быть не меньше 1 секунды") - private int duration; + private Integer duration; + + @MinimumDate(message = "Фильм не может выйти в прокат ранее 28.12.1895") + private Date releaseDate; + + private Rating mpa; public void addLike(Integer id) { likes.add(id); @@ -40,4 +43,5 @@ public void addLike(Integer id) { public void removeLike(Integer id) { likes.remove(id); } + } diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Genre.java b/src/main/java/ru/yandex/practicum/filmorate/model/Genre.java new file mode 100644 index 0000000..64dfb12 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Genre.java @@ -0,0 +1,11 @@ +package ru.yandex.practicum.filmorate.model; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class Genre { + private Integer id; + private String name; +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/MinimumDate.java b/src/main/java/ru/yandex/practicum/filmorate/model/MinimumDate.java index 404a22a..9bf0130 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/MinimumDate.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/MinimumDate.java @@ -11,7 +11,9 @@ @Past public @interface MinimumDate { String message() default "Минимальная дата выхода фильма {value}"; + Class[] groups() default {}; + Class[] payload() default {}; String value() default "1895-12-28"; diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/MinimumDateValidator.java b/src/main/java/ru/yandex/practicum/filmorate/model/MinimumDateValidator.java index 625440f..dad323b 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/MinimumDateValidator.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/MinimumDateValidator.java @@ -3,18 +3,18 @@ import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; -import java.time.LocalDate; +import java.sql.Date; -public class MinimumDateValidator implements ConstraintValidator { - private LocalDate minimumDate; +public class MinimumDateValidator implements ConstraintValidator { + private Date minimumDate; @Override public void initialize(MinimumDate constraintAnnotation) { - minimumDate = LocalDate.parse(constraintAnnotation.value()); + minimumDate = Date.valueOf(constraintAnnotation.value()); } @Override - public boolean isValid(LocalDate value, ConstraintValidatorContext context) { - return value == null || !value.isBefore(minimumDate); + public boolean isValid(Date value, ConstraintValidatorContext constraintValidatorContext) { + return value != null && !value.before(minimumDate); } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Rating.java b/src/main/java/ru/yandex/practicum/filmorate/model/Rating.java new file mode 100644 index 0000000..421ad1d --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Rating.java @@ -0,0 +1,11 @@ +package ru.yandex.practicum.filmorate.model; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +@Data +@Slf4j +public class Rating { + private Integer id; + private String name; +} \ No newline at end of file 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 71c1c8c..ebfde78 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/User.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java @@ -4,31 +4,31 @@ import lombok.Data; import lombok.extern.slf4j.Slf4j; -import java.time.LocalDate; -import java.util.HashSet; -import java.util.Set; +import java.sql.Date; +import java.util.ArrayList; +import java.util.List; @Data @Slf4j public class User { private Integer id; - private Set friends = new HashSet<>(); - - @Email(message = "Укажите корректный email") - @NotNull(message = "Необходимо указать email") - @NotBlank(message = "Email не может быть пустым") - private String email; + private List friends = new ArrayList<>(); @NotNull(message = "Необходимо указать логин") @NotBlank(message = "Логин не может быть пустым") @Pattern(regexp = "^[A-Za-z0-9]+$", message = "Логин может содержать только буквы и цифры без пробелов и спецсимволов") private String login; + @Email(message = "Укажите корректный email") + @NotNull(message = "Необходимо указать email") + @NotBlank(message = "Email не может быть пустым") + private String email; + private String name; @PastOrPresent(message = "Дата рождения не должна находиться в будущем") - private LocalDate birthday; + private Date birthday; public void addFriend(Integer id) { friends.add(id); 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 a925140..3587427 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -6,7 +6,8 @@ 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.FilmStorage; +import ru.yandex.practicum.filmorate.storage.FilmDbStorage; +import ru.yandex.practicum.filmorate.storage.LikeDbStorage; import ru.yandex.practicum.filmorate.storage.UserStorage; import java.util.List; @@ -16,8 +17,9 @@ @Service @RequiredArgsConstructor public class FilmService { - private final FilmStorage filmStorage; + private final FilmDbStorage filmStorage; private final UserStorage userStorage; + private final LikeDbStorage likeStorage; public Film create(Film film) { return filmStorage.create(film); @@ -38,21 +40,21 @@ public List findAll() { // Ставим лайк фильму public void addLike(Integer idFilm, Integer idUser) { checkForLike(idFilm, idUser); - filmStorage.getById(idFilm).addLike(idUser); + likeStorage.addLike(idFilm, idUser); } // Убираем лайк фильму public void deleteLike(Integer idFilm, Integer idUser) { checkForLike(idFilm, idUser); - filmStorage.getById(idFilm).removeLike(idUser); + likeStorage.deleteLike(idFilm, idUser); } // Получаем список лучших фильмов public List listBestFilms(int count) { return filmStorage.findAll().stream() - .sorted((f1, f2) -> f2.getLikes().size() - f1.getLikes().size()) - .limit(count) - .collect(Collectors.toList()); + .sorted((f1, f2) -> f2.getLikes().size() - f1.getLikes().size()) + .limit(count) + .collect(Collectors.toList()); } // проверка условий для установки и удаления лайка diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/GenreService.java b/src/main/java/ru/yandex/practicum/filmorate/service/GenreService.java new file mode 100644 index 0000000..2a171be --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/service/GenreService.java @@ -0,0 +1,24 @@ +package ru.yandex.practicum.filmorate.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.model.Genre; +import ru.yandex.practicum.filmorate.storage.GenreDbStorage; + +import java.util.List; + +@Slf4j +@Service +@RequiredArgsConstructor +public class GenreService { + private final GenreDbStorage genreStorage; + + public Genre getById(Integer id) { + return genreStorage.getById(id); + } + + public List findAll() { + return genreStorage.findAll(); + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/RatingService.java b/src/main/java/ru/yandex/practicum/filmorate/service/RatingService.java new file mode 100644 index 0000000..a18956a --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/service/RatingService.java @@ -0,0 +1,24 @@ +package ru.yandex.practicum.filmorate.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import ru.yandex.practicum.filmorate.model.Rating; +import ru.yandex.practicum.filmorate.storage.RatingDbStorage; + +import java.util.List; + +@Slf4j +@Service +@RequiredArgsConstructor +public class RatingService { + private final RatingDbStorage ratingStorage; + + public Rating getById(Integer id) { + return ratingStorage.getById(id); + } + + public List findAll() { + return ratingStorage.findAll(); + } +} \ No newline at end of file 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 d30b7bb..935cb81 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -6,7 +6,8 @@ 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.UserStorage; +import ru.yandex.practicum.filmorate.storage.FriendDbStorage; +import ru.yandex.practicum.filmorate.storage.UserDbStorage; import java.util.HashSet; import java.util.List; @@ -17,8 +18,8 @@ @Service @RequiredArgsConstructor public class UserService { - - private final UserStorage userStorage; + private final UserDbStorage userStorage; + private final FriendDbStorage friendStorage; public User create(User user) { return userStorage.create(user); @@ -42,23 +43,21 @@ public void addFriend(Integer idUser, Integer idFriend) { throw new ValidationException("Нельзя добавить себя в друзья"); } checkForFriend(idUser, idFriend); - userStorage.getById(idUser).addFriend(idFriend); - userStorage.getById(idFriend).addFriend(idUser); + friendStorage.addFriend(idUser, idFriend); } // Удаляем друга из списка друзей public void deleteFriend(Integer idUser, Integer idFriend) { checkForFriend(idUser, idFriend); - userStorage.getById(idUser).removeFriend(idFriend); - userStorage.getById(idFriend).removeFriend(idUser); + friendStorage.deleteFriend(idUser, idFriend); } // Получаем список друзей public List userFriends(Integer idUser) { - User user = userStorage.getById(idUser); - return userStorage.findAll().stream() - .filter(u -> user.getFriends().contains(u.getId())) - .collect(Collectors.toList()); + if (userStorage.getById(idUser) == null) { + throw new NotFoundException("Пользователь с id = " + idUser + " не найден"); + } + return userStorage.getFriends(idUser); } // Получаем общий список друзей diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDbStorage.java new file mode 100644 index 0000000..1b367b5 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDbStorage.java @@ -0,0 +1,110 @@ +package ru.yandex.practicum.filmorate.storage; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Primary; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Repository; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.model.Genre; +import ru.yandex.practicum.filmorate.storage.dbmapper.FilmRowMapper; + +import java.sql.PreparedStatement; +import java.sql.Statement; +import java.util.List; +import java.util.stream.Collectors; + +@Slf4j +@Primary +@Repository +@RequiredArgsConstructor +public class FilmDbStorage implements FilmStorage { + private final JdbcTemplate jdbc; + private final FilmRowMapper filmRowMapper; + + // Добавление фильма + @Override + public Film create(Film film) { + List ratings = jdbc.queryForList("SELECT id FROM mpa", Integer.class); + List genres = jdbc.queryForList("SELECT id FROM genres", Integer.class); + + if (!ratings.contains(film.getMpa().getId())) { + throw new NotFoundException("Рейтинг MPA с id " + film.getMpa().getId() + " не найден"); + } + + List notFoundGenres = film.getGenres().stream() + .filter(genre -> !genres.contains(genre.getId())) + .map(Genre::getId) + .collect(Collectors.toList()); + + if (!notFoundGenres.isEmpty()) { + throw new NotFoundException("Жанры с id " + notFoundGenres + " не найдены"); + } + + KeyHolder keyHolder = new GeneratedKeyHolder(); + jdbc.update(connection -> { + PreparedStatement ps = connection + .prepareStatement("INSERT INTO films (name, description, duration, release_date, mpa) VALUES (?, ?, ?, ?, ?)", + Statement.RETURN_GENERATED_KEYS); + ps.setString(1, film.getName()); + ps.setString(2, film.getDescription()); + ps.setInt(3, film.getDuration()); + ps.setDate(4, film.getReleaseDate()); + ps.setObject(5, film.getMpa().getId()); + return ps; + }, keyHolder); + film.setId(keyHolder.getKey().intValue()); + for (Genre genre : film.getGenres()) { + try { + jdbc.update("INSERT INTO film_genres (film_id, genre_id) VALUES (?, ?)", + keyHolder.getKey().intValue(), genre.getId()); + } catch (DuplicateKeyException e) { + } + } + return film; + } + + // Обновление фильма + @Override + public Film update(Film film) { + int count = jdbc.update("UPDATE films SET name = ?, description = ?, duration = ?, release_date = ?, mpa = ? WHERE id = ?", + film.getName(), film.getDescription(), film.getDuration(), film.getReleaseDate(), film.getMpa().getId(), film.getId()); + if (count == 0) { + throw new NotFoundException("Фильм с id " + film.getId() + " не найден"); + } + jdbc.update("DELETE FROM film_genres WHERE film_id = ?", film.getId()); + for (Genre genre : film.getGenres()) { + try { + jdbc.update("INSERT INTO film_genres (film_id, genre_id) VALUES (?, ?)", + film.getId(), genre.getId()); + } catch (DuplicateKeyException e) { + } + } + return film; + } + + // Выборка всех фильмов + @Override + public List findAll() { + try { + return jdbc.query("SELECT * FROM films", filmRowMapper); + } catch (EmptyResultDataAccessException e) { + throw new NotFoundException("Список фильмов пуст"); + } + } + + // Получение фильма по id + @Override + public Film getById(Integer id) { + try { + return jdbc.queryForObject("SELECT * FROM films WHERE id = ?", filmRowMapper, id); + } catch (EmptyResultDataAccessException e) { + throw new NotFoundException("Фильм с id " + id + " не найден"); + } + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/FriendDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/FriendDbStorage.java new file mode 100644 index 0000000..584b042 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/FriendDbStorage.java @@ -0,0 +1,37 @@ +package ru.yandex.practicum.filmorate.storage; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Primary; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Slf4j +@Primary +@Repository +@RequiredArgsConstructor +public class FriendDbStorage { + private final JdbcTemplate jdbc; + + // Отправка заявки на добавление в друзья + public void addFriend(Integer userId, Integer friendId) { + try { + jdbc.update("INSERT INTO friends (user_id, friend_id) VALUES (?, ?)", userId, friendId); + } catch (DuplicateKeyException e) { + } + } + + // отзыв заявки на дружбу + public void deleteFriend(Integer userId, Integer friendId) { + jdbc.update("DELETE FROM friends WHERE user_id = ? AND friend_id = ?", userId, friendId); + } + + // Получение id всех друзей по id пользователя + public List getFriends(Integer userId) { + return jdbc.queryForList("SELECT friend_id FROM friends WHERE user_id = ?", + Integer.class, userId); + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/GenreDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/GenreDbStorage.java new file mode 100644 index 0000000..b442647 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/GenreDbStorage.java @@ -0,0 +1,50 @@ +package ru.yandex.practicum.filmorate.storage; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Primary; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.model.Genre; +import ru.yandex.practicum.filmorate.storage.dbmapper.GenreRowMapper; + +import java.util.List; + +@Slf4j +@Primary +@Repository +@RequiredArgsConstructor +public class GenreDbStorage { + private final JdbcTemplate jdbc; + private final GenreRowMapper genreRowMapper; + + // Получение всех жанров + public List findAll() { + try { + return jdbc.query("SELECT * FROM genres", genreRowMapper); + } catch (EmptyResultDataAccessException e) { + throw new NotFoundException("Список жанров пуст"); + } + } + + // Получение жанра по id + public Genre getById(Integer id) { + try { + return jdbc.queryForObject("SELECT * FROM genres WHERE id = ?", genreRowMapper, id); + } catch (EmptyResultDataAccessException e) { + throw new NotFoundException("Жанр с id " + id + " не найден"); + } + } + + // Получение жанров по id фильма + public List getByFilmId(Integer filmId) { + try { + return jdbc.query("SELECT * FROM genres WHERE id IN (SELECT genre_id FROM film_genres WHERE film_id = ?)", + genreRowMapper, filmId); + } catch (EmptyResultDataAccessException e) { + throw new NotFoundException("Жанры для фильма с id " + filmId + " не найдены"); + } + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java index f20811e..3a8397a 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryFilmStorage.java @@ -1,7 +1,6 @@ package ru.yandex.practicum.filmorate.storage; import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Repository; import ru.yandex.practicum.filmorate.exception.NotFoundException; import ru.yandex.practicum.filmorate.exception.ValidationException; @@ -12,8 +11,7 @@ import java.util.Map; @Slf4j -@Repository("inMemoryFilmStorage") -@Primary +@Repository public class InMemoryFilmStorage implements FilmStorage { private final Map films = new HashMap<>(); diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java index de24788..990e245 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java @@ -12,8 +12,7 @@ import java.util.Map; @Slf4j -@Repository("inMemoryUserStorage") -@Primary +@Repository public class InMemoryUserStorage implements UserStorage { private final Map users = new HashMap<>(); diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/LikeDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/LikeDbStorage.java new file mode 100644 index 0000000..cad5647 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/LikeDbStorage.java @@ -0,0 +1,37 @@ +package ru.yandex.practicum.filmorate.storage; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Primary; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Slf4j +@Primary +@Repository +@RequiredArgsConstructor +public class LikeDbStorage { + private final JdbcTemplate jdbc; + + // Ставим лайк фильму + public void addLike(Integer filmId, Integer userId) { + try { + jdbc.update("INSERT INTO likes (film_id, user_id) VALUES (?, ?)", filmId, userId); + } catch (DuplicateKeyException e) { + } + } + + // Удаляем лайк фильма + public void deleteLike(Integer filmId, Integer userId) { + jdbc.update("DELETE FROM likes WHERE film_id = ? AND user_id = ?", filmId, userId); + } + + // Получаем список id пользователей, которые лайкнули фильм + public List getLikes(Integer filmId) { + return jdbc.queryForList("SELECT user_id FROM likes WHERE film_id = ?", + Integer.class, filmId); + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/RatingDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/RatingDbStorage.java new file mode 100644 index 0000000..ed13937 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/RatingDbStorage.java @@ -0,0 +1,41 @@ +package ru.yandex.practicum.filmorate.storage; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Primary; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.model.Rating; +import ru.yandex.practicum.filmorate.storage.dbmapper.RatingRowMapper; + +import java.util.List; + +@Slf4j +@Primary +@Repository +@RequiredArgsConstructor +public class RatingDbStorage { + private final JdbcTemplate jdbc; + private final RatingRowMapper ratingRowMapper; + + public List findAll() { + try { + return jdbc.query("SELECT * FROM mpa", ratingRowMapper); + } catch (EmptyResultDataAccessException e) { + throw new NotFoundException("Список жанров пуст"); + } + } + + public Rating getById(Integer id) { + try { + return jdbc.queryForObject("SELECT * FROM mpa WHERE id = ?", ratingRowMapper, id); + } catch (EmptyResultDataAccessException e) { + throw new NotFoundException("Рейтинг с id " + id + " не найден"); + } + } + + + +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/UserDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/UserDbStorage.java new file mode 100644 index 0000000..5ac3763 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/UserDbStorage.java @@ -0,0 +1,76 @@ +package ru.yandex.practicum.filmorate.storage; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Primary; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Repository; +import ru.yandex.practicum.filmorate.exception.NotFoundException; +import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.storage.dbmapper.UserRowMapper; + +import java.sql.PreparedStatement; +import java.sql.Statement; +import java.util.List; + +@Slf4j +@Primary +@Repository +@RequiredArgsConstructor +public class UserDbStorage implements UserStorage { + private final JdbcTemplate jdbc; + private final UserRowMapper userRowMapper; + + @Override + public User create(User user) { + KeyHolder keyHolder = new GeneratedKeyHolder(); + jdbc.update(connection -> { + PreparedStatement ps = connection + .prepareStatement("INSERT INTO users (login, email, name, birthday) VALUES (?, ?, ?, ?)", + Statement.RETURN_GENERATED_KEYS); + ps.setString(3, user.getLogin()); + ps.setString(2, user.getEmail()); + ps.setString(1, user.getName()); + ps.setDate(4, user.getBirthday()); + return ps; + }, keyHolder); + user.setId(keyHolder.getKey().intValue()); + return user; + } + + @Override + public User update(User user) { + int count = jdbc.update("UPDATE users SET login = ?, email = ?, name = ?, birthday = ? WHERE id = ?", + user.getLogin(), user.getEmail(), user.getName(), user.getBirthday(), user.getId()); + if (count == 0) { + throw new NotFoundException("Пользователь с id " + user.getId() + " не найден"); + } + return user; + } + + @Override + public List findAll() { + try { + return jdbc.query("SELECT * FROM users", userRowMapper); + } catch (EmptyResultDataAccessException e) { + throw new NotFoundException("Список пользователей пуст"); + } + } + + @Override + public User getById(Integer id) { + try { + return jdbc.queryForObject("SELECT * FROM users WHERE id = ?", userRowMapper, id); + } catch (EmptyResultDataAccessException e) { + throw new NotFoundException("Пользователь с id " + id + " не найден"); + } + } + + public List getFriends(Integer id) { + return jdbc.query("SELECT * FROM users WHERE id IN (SELECT friend_id FROM friends WHERE user_id = ?)", + userRowMapper, id); + } +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/FilmRowMapper.java b/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/FilmRowMapper.java new file mode 100644 index 0000000..719c1b3 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/FilmRowMapper.java @@ -0,0 +1,37 @@ +package ru.yandex.practicum.filmorate.storage.dbmapper; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Component; +import ru.yandex.practicum.filmorate.model.Film; +import ru.yandex.practicum.filmorate.storage.GenreDbStorage; +import ru.yandex.practicum.filmorate.storage.LikeDbStorage; +import ru.yandex.practicum.filmorate.storage.RatingDbStorage; + +import java.sql.ResultSet; +import java.sql.SQLException; + +@Slf4j +@Component +@RequiredArgsConstructor +public class FilmRowMapper implements RowMapper { + private final RatingDbStorage ratingDbStorage; + private final LikeDbStorage likeDbStorage; + private final GenreDbStorage genreDbStorage; + + // Маппер для Film + @Override + public Film mapRow(ResultSet resultSet, int rowNum) throws SQLException { + Film film = new Film(); + film.setId(resultSet.getInt("id")); + film.setName(resultSet.getString("name")); + film.setDescription(resultSet.getString("description")); + film.setDuration(resultSet.getInt("duration")); + film.setReleaseDate(resultSet.getDate("release_date")); + film.setMpa(ratingDbStorage.getById(resultSet.getInt("mpa"))); + film.setLikes(likeDbStorage.getLikes(resultSet.getInt("id"))); + film.setGenres(genreDbStorage.getByFilmId(resultSet.getInt("id"))); + return film; + } +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/GenreRowMapper.java b/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/GenreRowMapper.java new file mode 100644 index 0000000..a69ab1e --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/GenreRowMapper.java @@ -0,0 +1,23 @@ +package ru.yandex.practicum.filmorate.storage.dbmapper; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Component; +import ru.yandex.practicum.filmorate.model.Genre; + +import java.sql.ResultSet; +import java.sql.SQLException; + +@Slf4j +@Component +public class GenreRowMapper implements RowMapper { + + // Маппер для Genre + @Override + public Genre mapRow(ResultSet resultSet, int rowNum) throws SQLException { + Genre genre = new Genre(); + genre.setId(resultSet.getInt("id")); + genre.setName(resultSet.getString("name")); + return genre; + } +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/RatingRowMapper.java b/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/RatingRowMapper.java new file mode 100644 index 0000000..727a1f2 --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/RatingRowMapper.java @@ -0,0 +1,23 @@ +package ru.yandex.practicum.filmorate.storage.dbmapper; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Component; +import ru.yandex.practicum.filmorate.model.Rating; + +import java.sql.ResultSet; +import java.sql.SQLException; + +@Slf4j +@Component +public class RatingRowMapper implements RowMapper { + + // Маппер для Rating + @Override + public Rating mapRow(ResultSet resultSet, int rowNum) throws SQLException { + Rating rating = new Rating(); + rating.setId(resultSet.getInt("id")); + rating.setName(resultSet.getString("name")); + return rating; + } +} \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/UserRowMapper.java b/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/UserRowMapper.java new file mode 100644 index 0000000..124679a --- /dev/null +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/UserRowMapper.java @@ -0,0 +1,33 @@ +package ru.yandex.practicum.filmorate.storage.dbmapper; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Component; +import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.storage.FriendDbStorage; + +import java.sql.ResultSet; +import java.sql.SQLException; + +@Slf4j +@Component +@RequiredArgsConstructor +public class UserRowMapper implements RowMapper { + private final FriendDbStorage friendDbStorage; + + // Маппер для User + @Override + public User mapRow(ResultSet resultSet, int rowNum) throws SQLException { + User user = new User(); + user.setId(resultSet.getInt("id")); + user.setName(resultSet.getString("name")); + user.setLogin(resultSet.getString("login")); + user.setEmail(resultSet.getString("email")); + user.setBirthday(resultSet.getDate("birthday")); + user.setFriends(friendDbStorage.getFriends(resultSet.getInt("id"))); + return user; + } + + +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 92ee3fc..3cf419c 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,7 @@ logging.level.org.zalando.logbook= ERROR +spring.sql.init.mode=always +spring.datasource.url=jdbc:h2:file:./db/filmorate +spring.datasource.driverClassName=org.h2.Driver +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect +spring.datasource.username=sa +spring.datasource.password=password \ No newline at end of file diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql new file mode 100644 index 0000000..6e666b5 --- /dev/null +++ b/src/main/resources/data.sql @@ -0,0 +1,14 @@ +MERGE INTO genres (id, name) + VALUES (1, 'Комедия'), + (2, 'Драма'), + (3, 'Мультфильм'), + (4, 'Триллер'), + (5, 'Документальный'), + (6, 'Боевик'); + +MERGE INTO mpa (id, name) + VALUES (1, 'G'), + (2, 'PG'), + (3, 'PG-13'), + (4, 'R'), + (5, 'NC-17'); \ No newline at end of file diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql new file mode 100644 index 0000000..6ed3a5d --- /dev/null +++ b/src/main/resources/schema.sql @@ -0,0 +1,54 @@ +DROP TABLE IF EXISTS film_genres; +DROP TABLE IF EXISTS friends; +DROP TABLE IF EXISTS likes; +DROP TABLE IF EXISTS genres; +DROP TABLE IF EXISTS users; +DROP TABLE IF EXISTS films; +DROP TABLE IF EXISTS mpa; + + + +CREATE TABLE IF NOT EXISTS genres ( + id INT NOT NULL GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(50) NOT NULL +); + +CREATE TABLE IF NOT EXISTS mpa ( + id INT NOT NULL GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(10) NOT NULL +); + +CREATE TABLE IF NOT EXISTS films ( + id INT NOT NULL GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(100) NOT NULL, + description VARCHAR(255), + duration INT NOT NULL, + release_date DATE NOT NULL, + mpa INT REFERENCES mpa(id) ON DELETE RESTRICT ON UPDATE CASCADE +); + +CREATE TABLE IF NOT EXISTS users ( + id INT NOT NULL GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + login VARCHAR(50) NOT NULL, + email VARCHAR(100) NOT NULL, + name VARCHAR(100), + birthday DATE +); + +CREATE TABLE IF NOT EXISTS film_genres ( + film_id INT NOT NULL REFERENCES films (id) ON DELETE CASCADE ON UPDATE CASCADE, + genre_id INT NOT NULL REFERENCES genres (id) ON DELETE CASCADE ON UPDATE CASCADE, + PRIMARY KEY (film_id, genre_id) +); + +CREATE TABLE IF NOT EXISTS likes ( + film_id INT NOT NULL REFERENCES films (id) ON DELETE CASCADE ON UPDATE CASCADE, + user_id INT NOT NULL REFERENCES users (id) ON DELETE RESTRICT ON UPDATE CASCADE, + PRIMARY KEY (film_id, user_id) +); + +CREATE TABLE IF NOT EXISTS friends ( + user_id INT NOT NULL REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE, + friend_id INT NOT NULL REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE, + PRIMARY KEY (user_id, friend_id) +); \ No newline at end of file From 272b6b4362ee6345fca7e1d6e1a9d2e324eab626 Mon Sep 17 00:00:00 2001 From: Sergey Filippovskikh Date: Mon, 17 Feb 2025 13:22:36 +0300 Subject: [PATCH 05/17] =?UTF-8?q?=D0=A1=D0=BF=D1=80=D0=B8=D0=BD=D1=82=2012?= =?UTF-8?q?.=20=D0=A0=D0=B5=D0=B9=D1=82=D0=B8=D0=BD=D0=B3=20=D0=A4=D0=B8?= =?UTF-8?q?=D0=BB=D1=8C=D0=BC=D0=BE=D0=B2.=20=D0=9F=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B2=D0=BE=D0=B4=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B2=20=D0=B1?= =?UTF-8?q?=D0=B0=D0=B7=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20H2.?= =?UTF-8?q?=20=D0=9A=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D1=81=D1=82=D0=B8=D0=BB=D1=8F=20=D0=BF?= =?UTF-8?q?=D0=BE=20GitHub.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../practicum/filmorate/controller/GenreController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java index 2a70238..d5cc548 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java @@ -23,7 +23,7 @@ public List findAll() { // Получаем жанр по id @GetMapping("/{Id}") - public Genre getById(@PathVariable Integer Id) { - return genreService.getById(Id); + public Genre getById(@PathVariable Integer id) { + return genreService.getById(id); } } From e596d6100bcf4a61f998b5fd2ff5645c6448cb0b Mon Sep 17 00:00:00 2001 From: Sergey Filippovskikh Date: Mon, 17 Feb 2025 13:23:54 +0300 Subject: [PATCH 06/17] =?UTF-8?q?=D0=A1=D0=BF=D1=80=D0=B8=D0=BD=D1=82=2012?= =?UTF-8?q?.=20=D0=A0=D0=B5=D0=B9=D1=82=D0=B8=D0=BD=D0=B3=20=D0=A4=D0=B8?= =?UTF-8?q?=D0=BB=D1=8C=D0=BC=D0=BE=D0=B2.=20=D0=9F=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B2=D0=BE=D0=B4=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B2=20=D0=B1?= =?UTF-8?q?=D0=B0=D0=B7=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20H2.?= =?UTF-8?q?=20=D0=9A=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D1=81=D1=82=D0=B8=D0=BB=D1=8F=20=D0=BF?= =?UTF-8?q?=D0=BE=20GitHub.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../practicum/filmorate/controller/RatingController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/RatingController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/RatingController.java index 42734cb..177b62d 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/RatingController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/RatingController.java @@ -26,7 +26,7 @@ public List findAll() { // Получаем рейтинг по id @GetMapping("/{Id}") - public Rating getById(@PathVariable Integer Id) { - return ratingService.getById(Id); + public Rating getById(@PathVariable Integer id) { + return ratingService.getById(id); } } From 9609fea8868bae3c44c904e9b07678b9c81733db Mon Sep 17 00:00:00 2001 From: Sergey Filippovskikh Date: Mon, 17 Feb 2025 13:50:39 +0300 Subject: [PATCH 07/17] =?UTF-8?q?=D0=A1=D0=BF=D1=80=D0=B8=D0=BD=D1=82=2012?= =?UTF-8?q?.=20=D0=A0=D0=B5=D0=B9=D1=82=D0=B8=D0=BD=D0=B3=20=D0=A4=D0=B8?= =?UTF-8?q?=D0=BB=D1=8C=D0=BC=D0=BE=D0=B2.=20=D0=9F=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B2=D0=BE=D0=B4=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B2=20=D0=B1?= =?UTF-8?q?=D0=B0=D0=B7=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20H2.?= =?UTF-8?q?=20=D0=9A=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D1=81=D1=82=D0=B8=D0=BB=D1=8F=20=D0=BF?= =?UTF-8?q?=D0=BE=20GitHub.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ru/yandex/practicum/filmorate/storage/FilmDbStorage.java | 2 ++ .../ru/yandex/practicum/filmorate/storage/FriendDbStorage.java | 1 + .../ru/yandex/practicum/filmorate/storage/LikeDbStorage.java | 1 + 3 files changed, 4 insertions(+) diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDbStorage.java index 1b367b5..60610af 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDbStorage.java @@ -64,6 +64,7 @@ public Film create(Film film) { jdbc.update("INSERT INTO film_genres (film_id, genre_id) VALUES (?, ?)", keyHolder.getKey().intValue(), genre.getId()); } catch (DuplicateKeyException e) { + log.error("DuplicateKeyException", e); } } return film; @@ -83,6 +84,7 @@ public Film update(Film film) { jdbc.update("INSERT INTO film_genres (film_id, genre_id) VALUES (?, ?)", film.getId(), genre.getId()); } catch (DuplicateKeyException e) { + log.error("DuplicateKeyException", e); } } return film; diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/FriendDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/FriendDbStorage.java index 584b042..ca17c84 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/FriendDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/FriendDbStorage.java @@ -21,6 +21,7 @@ public void addFriend(Integer userId, Integer friendId) { try { jdbc.update("INSERT INTO friends (user_id, friend_id) VALUES (?, ?)", userId, friendId); } catch (DuplicateKeyException e) { + log.error("DuplicateKeyException", e); } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/LikeDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/LikeDbStorage.java index cad5647..01d55bf 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/LikeDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/LikeDbStorage.java @@ -21,6 +21,7 @@ public void addLike(Integer filmId, Integer userId) { try { jdbc.update("INSERT INTO likes (film_id, user_id) VALUES (?, ?)", filmId, userId); } catch (DuplicateKeyException e) { + log.error("DuplicateKeyException", e); } } From 3c583585d8a5ff8b1fcd91c1ff16328588936b13 Mon Sep 17 00:00:00 2001 From: Sergey Filippovskikh Date: Mon, 17 Feb 2025 14:05:36 +0300 Subject: [PATCH 08/17] =?UTF-8?q?=D0=A1=D0=BF=D1=80=D0=B8=D0=BD=D1=82=2012?= =?UTF-8?q?.=20=D0=A0=D0=B5=D0=B9=D1=82=D0=B8=D0=BD=D0=B3=20=D0=A4=D0=B8?= =?UTF-8?q?=D0=BB=D1=8C=D0=BC=D0=BE=D0=B2.=20=D0=9F=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B2=D0=BE=D0=B4=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B2=20=D0=B1?= =?UTF-8?q?=D0=B0=D0=B7=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20H2.?= =?UTF-8?q?=20=D0=9A=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D1=81=D1=82=D0=B8=D0=BB=D1=8F=20=D0=BF?= =?UTF-8?q?=D0=BE=20GitHub.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../practicum/filmorate/controller/GenreController.java | 2 +- .../practicum/filmorate/controller/RatingController.java | 2 +- .../ru/yandex/practicum/filmorate/storage/FilmDbStorage.java | 4 ++-- .../yandex/practicum/filmorate/storage/FriendDbStorage.java | 2 +- .../ru/yandex/practicum/filmorate/storage/LikeDbStorage.java | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java index d5cc548..51bda0f 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java @@ -22,7 +22,7 @@ public List findAll() { } // Получаем жанр по id - @GetMapping("/{Id}") + @GetMapping("/{id}") public Genre getById(@PathVariable Integer id) { return genreService.getById(id); } diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/RatingController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/RatingController.java index 177b62d..c9d3119 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/RatingController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/RatingController.java @@ -25,7 +25,7 @@ public List findAll() { } // Получаем рейтинг по id - @GetMapping("/{Id}") + @GetMapping("/{id}") public Rating getById(@PathVariable Integer id) { return ratingService.getById(id); } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDbStorage.java index 60610af..da7d9b9 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDbStorage.java @@ -64,7 +64,7 @@ public Film create(Film film) { jdbc.update("INSERT INTO film_genres (film_id, genre_id) VALUES (?, ?)", keyHolder.getKey().intValue(), genre.getId()); } catch (DuplicateKeyException e) { - log.error("DuplicateKeyException", e); + log.error("Duplicate key exception"); } } return film; @@ -84,7 +84,7 @@ public Film update(Film film) { jdbc.update("INSERT INTO film_genres (film_id, genre_id) VALUES (?, ?)", film.getId(), genre.getId()); } catch (DuplicateKeyException e) { - log.error("DuplicateKeyException", e); + log.error("Duplicate key exception"); } } return film; diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/FriendDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/FriendDbStorage.java index ca17c84..a1d9754 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/FriendDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/FriendDbStorage.java @@ -21,7 +21,7 @@ public void addFriend(Integer userId, Integer friendId) { try { jdbc.update("INSERT INTO friends (user_id, friend_id) VALUES (?, ?)", userId, friendId); } catch (DuplicateKeyException e) { - log.error("DuplicateKeyException", e); + log.error("DuplicateKeyException"); } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/LikeDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/LikeDbStorage.java index 01d55bf..bd02fc2 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/LikeDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/LikeDbStorage.java @@ -21,7 +21,7 @@ public void addLike(Integer filmId, Integer userId) { try { jdbc.update("INSERT INTO likes (film_id, user_id) VALUES (?, ?)", filmId, userId); } catch (DuplicateKeyException e) { - log.error("DuplicateKeyException", e); + log.error("DuplicateKeyException"); } } From d57f5abc85c18dd7e6aa47158f668b47785fb22a Mon Sep 17 00:00:00 2001 From: Sergey Filippovskikh Date: Mon, 17 Feb 2025 14:07:23 +0300 Subject: [PATCH 09/17] =?UTF-8?q?=D0=A1=D0=BF=D1=80=D0=B8=D0=BD=D1=82=2012?= =?UTF-8?q?.=20=D0=A0=D0=B5=D0=B9=D1=82=D0=B8=D0=BD=D0=B3=20=D0=A4=D0=B8?= =?UTF-8?q?=D0=BB=D1=8C=D0=BC=D0=BE=D0=B2.=20=D0=9F=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B2=D0=BE=D0=B4=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B2=20=D0=B1?= =?UTF-8?q?=D0=B0=D0=B7=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20H2.?= =?UTF-8?q?=20=D0=9A=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D1=81=D1=82=D0=B8=D0=BB=D1=8F=20=D0=BF?= =?UTF-8?q?=D0=BE=20GitHub.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yandex/practicum/filmorate/storage/InMemoryUserStorage.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java index 990e245..8b92e94 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/InMemoryUserStorage.java @@ -1,7 +1,6 @@ package ru.yandex.practicum.filmorate.storage; import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Repository; import ru.yandex.practicum.filmorate.exception.NotFoundException; import ru.yandex.practicum.filmorate.exception.ValidationException; From 001546b28688af427658133aa50f7d0649af0a90 Mon Sep 17 00:00:00 2001 From: Sergey Filippovskikh Date: Mon, 17 Feb 2025 14:15:14 +0300 Subject: [PATCH 10/17] =?UTF-8?q?=D0=A1=D0=BF=D1=80=D0=B8=D0=BD=D1=82=2012?= =?UTF-8?q?.=20=D0=A0=D0=B5=D0=B9=D1=82=D0=B8=D0=BD=D0=B3=20=D0=A4=D0=B8?= =?UTF-8?q?=D0=BB=D1=8C=D0=BC=D0=BE=D0=B2.=20=D0=9F=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B2=D0=BE=D0=B4=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B2=20=D0=B1?= =?UTF-8?q?=D0=B0=D0=B7=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20H2.?= =?UTF-8?q?=20=D0=9A=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D1=81=D1=82=D0=B8=D0=BB=D1=8F=20=D0=BF?= =?UTF-8?q?=D0=BE=20GitHub.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pom.xml b/pom.xml index b1b25b2..cf9ceb6 100644 --- a/pom.xml +++ b/pom.xml @@ -61,6 +61,10 @@ org.springframework.boot spring-boot-maven-plugin + + org.apache.maven.plugins + maven-compiler-plugin + org.apache.maven.plugins maven-checkstyle-plugin From 909dbc1ef9ade0d669a54b9eb97160c21cd00d63 Mon Sep 17 00:00:00 2001 From: Sergey Filippovskikh Date: Mon, 17 Feb 2025 14:18:39 +0300 Subject: [PATCH 11/17] =?UTF-8?q?=D0=A1=D0=BF=D1=80=D0=B8=D0=BD=D1=82=2012?= =?UTF-8?q?.=20=D0=A0=D0=B5=D0=B9=D1=82=D0=B8=D0=BD=D0=B3=20=D0=A4=D0=B8?= =?UTF-8?q?=D0=BB=D1=8C=D0=BC=D0=BE=D0=B2.=20=D0=9F=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B2=D0=BE=D0=B4=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B2=20=D0=B1?= =?UTF-8?q?=D0=B0=D0=B7=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20H2.?= =?UTF-8?q?=20=D0=9A=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D1=81=D1=82=D0=B8=D0=BB=D1=8F=20=D0=BF?= =?UTF-8?q?=D0=BE=20GitHub.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index cf9ceb6..f07847f 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ org.springframework.boot spring-boot-starter-parent 3.4.1 - + ru.yandex.practicum @@ -17,7 +17,7 @@ filmorate - 23 + 22 @@ -61,10 +61,6 @@ org.springframework.boot spring-boot-maven-plugin - - org.apache.maven.plugins - maven-compiler-plugin - org.apache.maven.plugins maven-checkstyle-plugin From 137c44c151f1f42a81ffcce17b7839fa87c42945 Mon Sep 17 00:00:00 2001 From: Sergey Filippovskikh Date: Mon, 17 Feb 2025 14:28:41 +0300 Subject: [PATCH 12/17] =?UTF-8?q?=D0=A1=D0=BF=D1=80=D0=B8=D0=BD=D1=82=2012?= =?UTF-8?q?.=20=D0=A0=D0=B5=D0=B9=D1=82=D0=B8=D0=BD=D0=B3=20=D0=A4=D0=B8?= =?UTF-8?q?=D0=BB=D1=8C=D0=BC=D0=BE=D0=B2.=20=D0=9F=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B2=D0=BE=D0=B4=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B2=20=D0=B1?= =?UTF-8?q?=D0=B0=D0=B7=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20H2.?= =?UTF-8?q?=20=D0=9A=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D1=81=D1=82=D0=B8=D0=BB=D1=8F=20=D0=BF?= =?UTF-8?q?=D0=BE=20GitHub.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f07847f..c53c203 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ filmorate - 22 + 23 @@ -61,6 +61,11 @@ org.springframework.boot spring-boot-maven-plugin + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + org.apache.maven.plugins maven-checkstyle-plugin From 404c7bb75a6dbd5ad3a5617a438e4b7501bf638a Mon Sep 17 00:00:00 2001 From: Sergey Filippovskikh Date: Mon, 17 Feb 2025 14:31:27 +0300 Subject: [PATCH 13/17] =?UTF-8?q?=D0=A1=D0=BF=D1=80=D0=B8=D0=BD=D1=82=2012?= =?UTF-8?q?.=20=D0=A0=D0=B5=D0=B9=D1=82=D0=B8=D0=BD=D0=B3=20=D0=A4=D0=B8?= =?UTF-8?q?=D0=BB=D1=8C=D0=BC=D0=BE=D0=B2.=20=D0=9F=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B2=D0=BE=D0=B4=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B2=20=D0=B1?= =?UTF-8?q?=D0=B0=D0=B7=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20H2.?= =?UTF-8?q?=20=D0=9A=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D1=81=D1=82=D0=B8=D0=BB=D1=8F=20=D0=BF?= =?UTF-8?q?=D0=BE=20GitHub.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index c53c203..60c5890 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ filmorate - 23 + 17 @@ -64,7 +64,6 @@ org.apache.maven.plugins maven-compiler-plugin - 3.13.0 org.apache.maven.plugins From eccacf894a5f585ab74f898e659bf45a9d52ec69 Mon Sep 17 00:00:00 2001 From: Sergey Filippovskikh Date: Mon, 17 Feb 2025 14:55:29 +0300 Subject: [PATCH 14/17] =?UTF-8?q?=D0=A1=D0=BF=D1=80=D0=B8=D0=BD=D1=82=2012?= =?UTF-8?q?.=20=D0=A0=D0=B5=D0=B9=D1=82=D0=B8=D0=BD=D0=B3=20=D0=A4=D0=B8?= =?UTF-8?q?=D0=BB=D1=8C=D0=BC=D0=BE=D0=B2.=20=D0=9F=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B2=D0=BE=D0=B4=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B2=20=D0=B1?= =?UTF-8?q?=D0=B0=D0=B7=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20H2.?= =?UTF-8?q?=20=D0=9A=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D1=81=D1=82=D0=B8=D0=BB=D1=8F=20=D0=BF?= =?UTF-8?q?=D0=BE=20GitHub.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PostmanSprint12_add-database.json | 5181 +++++++++++++++++ README.md | 9 +- .../filmorate/FilmorateApplicationTests.java | 30 +- 3 files changed, 5213 insertions(+), 7 deletions(-) create mode 100644 PostmanSprint12_add-database.json diff --git a/PostmanSprint12_add-database.json b/PostmanSprint12_add-database.json new file mode 100644 index 0000000..0140080 --- /dev/null +++ b/PostmanSprint12_add-database.json @@ -0,0 +1,5181 @@ +{ + "info": { + "_postman_id": "8ed6b8f0-1e77-445f-8736-87dd5f364b51", + "name": "add-database", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "23073145", + "_collection_link": "https://universal-shadow-295426.postman.co/workspace/My-Workspace~4200f6aa-0504-44b1-8a1d-707d0dcbd5ce/collection/23073145-8ed6b8f0-1e77-445f-8736-87dd5f364b51?action=share&source=collection_link&creator=23073145" + }, + "item": [ + { + "name": "users", + "item": [ + { + "name": "User create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const source = JSON.parse(pm.request.body.raw)\r", + "\r", + "pm.test(\"Status code is 200 or 201\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,201]);\r", + "});\r", + "pm.test(\"Has user create response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "pm.test(\"Test user 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('id');\r", + "});\r", + "pm.test(\"Test user 'email' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('email');\r", + " pm.expect(jsonData.email, `\"email\" must be \"${source.mail}\"`).to.eql(source.email);\r", + "});\r", + "pm.test(\"Test user 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('name');\r", + " pm.expect(jsonData.name, `\"name\" must be \"${source.name}\"`).to.eql(source.name);\r", + "});\r", + "pm.test(\"Test user 'login' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('login');\r", + " pm.expect(jsonData.login, `\"login\" field must be \"${source.login}\"`).to.eql(source.login); \r", + "});\r", + "pm.test(\"Test user 'birthday' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('birthday');\r", + " pm.expect(jsonData.birthday, `\"birthday\" field must be \"${source.birthday}\"`).to.eql(source.birthday);\r", + "});" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user;\r", + " try {\r", + " user = rnd.getUser();\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + " pm.request.body.update({\r", + " mode: 'raw',\r", + " raw: JSON.stringify(user),\r", + " options: { raw: { language: 'json' } }\r", + " });\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"login\": \"dolore\",\n \"name\": \"Nick Name\",\n \"email\": \"mail@mail.ru\",\n \"birthday\": \"1946-08-20\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users" + ] + } + }, + "response": [] + }, + { + "name": "User create Fail login", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(400);\r", + "});\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"login\": \"dolore ullamco\",\n \"email\": \"yandex@mail.ru\",\n \"birthday\": \"2446-08-20\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users" + ] + } + }, + "response": [] + }, + { + "name": "User create Fail email", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(400);\r", + "});\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"login\": \"dolore ullamco\",\n \"name\": \"\",\n \"email\": \"mail.ru\",\n \"birthday\": \"1980-08-20\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users" + ] + } + }, + "response": [] + }, + { + "name": "User create Fail birthday", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(400);\r", + "});\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"login\": \"dolore\",\n \"name\": \"\",\n \"email\": \"test@mail.ru\",\n \"birthday\": \"2446-08-20\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users" + ] + } + }, + "response": [] + }, + { + "name": "User update", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const source = pm.collectionVariables.get(\"user\")\r", + "const new_user_info = pm.collectionVariables.get(\"new_user_info\");\r", + "\r", + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Has user update response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "pm.test(\"Test user 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('id');\r", + " pm.expect(jsonData.id, `\"id\" must be ${source.id}`).to.eql(source.id);\r", + "});\r", + "pm.test(\"Test user 'email' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('email');\r", + " pm.expect(jsonData.email, `\"email\" must be \"${new_user_info.email}\"`).to.eql(new_user_info.email);\r", + "});\r", + "pm.test(\"Test user 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('name');\r", + " pm.expect(jsonData.name, `\"name\" must be \"${new_user_info.name}\"`).to.eql(new_user_info.name);\r", + "});\r", + "pm.test(\"Test user 'login' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('login');\r", + " pm.expect(jsonData.login, `\"login\" field must be \"${new_user_info.login}\"`).to.eql(new_user_info.login); \r", + "});\r", + "pm.test(\"Test user 'birthday' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('birthday');\r", + " pm.expect(jsonData.birthday, `\"birthday\" field must be \"${new_user_info.birthday}\"`).to.eql(new_user_info.birthday);\r", + "});" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user;\r", + " try {\r", + " user = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user\", user);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + " let new_user_info = rnd.getUser();\r", + " pm.collectionVariables.set(\"new_user_info\", new_user_info);\r", + " new_user_info[\"id\"] = user.id;\r", + "\r", + " pm.request.body.update({\r", + " mode: 'raw',\r", + " raw: JSON.stringify(new_user_info),\r", + " options: { raw: { language: 'json' } }\r", + " });\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users" + ] + } + }, + "response": [] + }, + { + "name": "User update unknown", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(404);\r", + "});\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user;\r", + " try {\r", + " user = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user\", user);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + " pm.request.body.update({\r", + " mode: 'raw',\r", + " raw: JSON.stringify({\r", + " \"login\": \"doloreUpdate\",\r", + " \"name\": \"est adipisicing\",\r", + " \"id\": user.id+1,\r", + " \"email\": \"mail@yandex.ru\",\r", + " \"birthday\": \"1976-09-20\"\r", + " }),\r", + " options: { raw: { language: 'json' } }\r", + " });\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"login\": \"doloreUpdate\",\n \"name\": \"est adipisicing\",\n \"id\": 9999,\n \"email\": \"mail@yandex.ru\",\n \"birthday\": \"1976-09-20\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users" + ] + } + }, + "response": [] + }, + { + "name": "User get All", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Test list user response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "pm.test(\"Test user[0] 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[0]).to.have.property('id');\r", + " pm.expect(jsonData[0].id, '\"id\" must be 1').to.eql(1);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "*/*" + } + ], + "url": { + "raw": "{{baseUrl}}/users", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "friends", + "item": [ + { + "name": "Friend add", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const user1_id = pm.collectionVariables.get(\"id\");\r", + "const user2_id = pm.collectionVariables.get(\"friend_id\");\r", + "\r", + "pm.test(\"Status code is 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,204]);\r", + "});\r", + "\r", + "pm.sendRequest({\r", + " url : \"http://localhost:8080/users/\" + user1_id + '/friends',\r", + " method : \"GET\",\r", + " header: { \"Content-Type\": \"application/json\" }\r", + "}, (error, response) => {\r", + " pm.test(\"user1 has user2 friend\", function () {\r", + " pm.expect(response.json()[0].id).to.be.equal(user2_id);\r", + " });\r", + "});\r", + "\r", + "pm.sendRequest({\r", + " url : \"http://localhost:8080/users/\" + user2_id + '/friends',\r", + " method : \"GET\",\r", + " header: { \"Content-Type\": \"application/json\" }\r", + "}, (error, response) => {\r", + " pm.test(\"user2 doesn't have user1 friend\", function () {\r", + " pm.expect(response.json().length).to.be.equal(0);\r", + " });\r", + "});\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user1, user2;\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"id\", user1.id);\r", + " pm.collectionVariables.set(\"friend_id\", user2.id);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users/{{id}}/friends/{{friend_id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{id}}", + "friends", + "{{friend_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Friend add unknown id", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(404);\r", + "});\r", + "\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user1, user2;\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"id\", user1.id);\r", + " pm.collectionVariables.set(\"friend_id\", user2.id+1);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users/{{id}}/friends/{{friend_id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{id}}", + "friends", + "{{friend_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Friend get", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const user_friends = pm.collectionVariables.get(\"user_friends\");\r", + "\r", + "pm.test(\"Status code is 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,204]);\r", + "});\r", + "\r", + "pm.test(\"initially user1 should have 0 friends\", function () {\r", + " pm.expect(user_friends.length).to.be.equal(0);\r", + "});\r", + "\r", + "pm.test(\"finally user1 should have 1 friend\", function () {\r", + " pm.expect(pm.response.json().length).to.be.equal(1);\r", + "});" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user1, user2, user1_friends;\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " user1_friends = await api.getFriends(user1.id);\r", + " await api.addFriend(user1.id, user2.id);\r", + " pm.collectionVariables.set(\"id\", user1.id);\r", + " pm.collectionVariables.set(\"user_friends\", user1_friends);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users/{{id}}/friends", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{id}}", + "friends" + ] + } + }, + "response": [] + }, + { + "name": "Friend get unknown id", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(404);\r", + "});\r", + "\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user;\r", + " try {\r", + " user = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"id\", user.id+1);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users/{{id}}/friends", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{id}}", + "friends" + ] + } + }, + "response": [] + }, + { + "name": "Friend remove", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const user1_id = pm.collectionVariables.get(\"id\");\r", + "const user2_id = pm.collectionVariables.get(\"friend_id\");\r", + "\r", + "pm.test(\"Status code is 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,204]);\r", + "});\r", + "\r", + "pm.sendRequest({\r", + " url : \"http://localhost:8080/users/\" + user1_id + '/friends',\r", + " method : \"GET\",\r", + " header: { \"Content-Type\": \"application/json\" }\r", + "}, (error, response) => {\r", + " pm.test(\"user1 should have 0 friends\", function () {\r", + " pm.expect(response.json().length).to.be.equal(0);\r", + " });\r", + "});\r", + "\r", + "pm.sendRequest({\r", + " url : \"http://localhost:8080/users/\" + user2_id + '/friends',\r", + " method : \"GET\",\r", + " header: { \"Content-Type\": \"application/json\" }\r", + "}, (error, response) => {\r", + " pm.test(\"user2 should have 0 friends\", function () {\r", + " pm.expect(response.json().length).to.be.equal(0);\r", + " });\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user1, user2;\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " await api.addFriend(user1.id, user2.id);\r", + " pm.collectionVariables.set(\"id\", user1.id);\r", + " pm.collectionVariables.set(\"friend_id\", user2.id);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users/{{id}}/friends/{{friend_id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{id}}", + "friends", + "{{friend_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Not friend remove", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const user1_id = pm.collectionVariables.get(\"id\");\r", + "const user2_id = pm.collectionVariables.get(\"friend_id\");\r", + "\r", + "pm.test(\"Status code is 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,204]);\r", + "});\r", + "\r", + "pm.sendRequest({\r", + " url : \"http://localhost:8080/users/\" + user1_id + '/friends',\r", + " method : \"GET\",\r", + " header: { \"Content-Type\": \"application/json\" }\r", + "}, (error, response) => {\r", + " pm.test(\"user1 should have 0 friends\", function () {\r", + " pm.expect(response.json().length).to.be.equal(0);\r", + " });\r", + "});\r", + "\r", + "pm.sendRequest({\r", + " url : \"http://localhost:8080/users/\" + user2_id + '/friends',\r", + " method : \"GET\",\r", + " header: { \"Content-Type\": \"application/json\" }\r", + "}, (error, response) => {\r", + " pm.test(\"user2 should have 0 friends\", function () {\r", + " pm.expect(response.json().length).to.be.equal(0);\r", + " });\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user1, user2;\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"id\", user1.id);\r", + " pm.collectionVariables.set(\"friend_id\", user2.id);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users/{{id}}/friends/{{friend_id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{id}}", + "friends", + "{{friend_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Friend reciprocity", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const user1_id = pm.collectionVariables.get(\"id\");\r", + "const user2_id = pm.collectionVariables.get(\"friend_id\");\r", + "\r", + "pm.test(\"Status code is 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,204]);\r", + "});\r", + "\r", + "pm.sendRequest({\r", + " url : \"http://localhost:8080/users/\" + user1_id + '/friends',\r", + " method : \"GET\",\r", + " header: { \"Content-Type\": \"application/json\" }\r", + "}, (error, response) => {\r", + " pm.test(\"user1 should have 0 friends\", function () {\r", + " pm.expect(response.json().length).to.be.equal(0);\r", + " });\r", + "});\r", + "\r", + "pm.sendRequest({\r", + " url : \"http://localhost:8080/users/\" + user2_id + '/friends',\r", + " method : \"GET\",\r", + " header: { \"Content-Type\": \"application/json\" }\r", + "}, (error, response) => {\r", + " pm.test(\"user2 should have 1 friends\", function () {\r", + " pm.expect(response.json().length).to.be.equal(1);\r", + " });\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user1, user2;\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " await api.addFriend(user1.id, user2.id);\r", + " pm.collectionVariables.set(\"id\", user2.id);\r", + " pm.collectionVariables.set(\"friend_id\", user1.id);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users/{{id}}/friends/{{friend_id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{id}}", + "friends", + "{{friend_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Friend remove unknown id", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(404);\r", + "});\r", + "\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user1, user2;\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " await api.addFriend(user1.id, user2.id);\r", + " pm.collectionVariables.set(\"id\", user1.id + 4);\r", + " pm.collectionVariables.set(\"friend_id\", user2.id);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users/{{id}}/friends/{{friend_id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{id}}", + "friends", + "{{friend_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Friend remove unknown friend id", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(404);\r", + "});\r", + "\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user1, user2;\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " await api.addFriend(user1.id, user2.id);\r", + " pm.collectionVariables.set(\"id\", user1.id);\r", + " pm.collectionVariables.set(\"friend_id\", user2.id+1);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users/{{id}}/friends/{{friend_id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{id}}", + "friends", + "{{friend_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Get common friends", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const user3_id = pm.collectionVariables.get(\"user3_id\");\r", + "\r", + "pm.test(\"Status code is 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,204]);\r", + "});\r", + "\r", + "pm.test(\"user1 should have 1 common friend with user2\", function () {\r", + " pm.expect(pm.response.json().length).to.be.equal(1);\r", + " pm.expect(pm.response.json()[0].id).to.be.equal(user3_id);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user1, user2, user3;\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " user3 = await api.addUser(rnd.getUser());\r", + " await api.addFriend(user1.id, user3.id);\r", + " await api.addFriend(user1.id, user2.id);\r", + " await api.addFriend(user2.id, user3.id);\r", + " pm.collectionVariables.set(\"id\", user1.id);\r", + " pm.collectionVariables.set(\"friend_id\", user2.id);\r", + " pm.collectionVariables.set(\"user3_id\", user3.id);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/users/{{id}}/friends/common/{{friend_id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{id}}", + "friends", + "common", + "{{friend_id}}" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "films", + "item": [ + { + "name": "Film create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const source = JSON.parse(pm.request.body.raw)\r", + "\r", + "pm.test(\"Status code is 200 or 201\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,201]);\r", + "});\r", + "pm.test(\"Has film create response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "pm.test(\"Test film 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('id');\r", + "});\r", + "pm.test(\"Test film 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('name');\r", + " pm.expect(jsonData.name, `\"name\" must be \"${source.name}\"`).to.eql(source.name);\r", + "});\r", + "pm.test(\"Test film 'description' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('description');\r", + " pm.expect(jsonData.description, `\"description\" must be \"${source.description}\"`).to.eql(source.description);\r", + "});\r", + "pm.test(\"Test film 'releaseDate' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('releaseDate');\r", + " pm.expect(jsonData.releaseDate, `\"releaseDate\" field must be \"${source.releaseDate}\"`).to.eql(source.releaseDate);\r", + "});\r", + "pm.test(\"Test film 'duration' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('duration');\r", + " pm.expect(jsonData.duration, `\"duration\" field must be %{source.duration}`).to.eql(source.duration); \r", + "});\r", + "pm.test(\"Test film 'mpa' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('mpa');\r", + " pm.expect(jsonData.mpa.id, `\"mpa.id\" field must be %{source.mpa.id}`).to.eql(source.mpa.id); \r", + "});\r", + "pm.test(\"Test film 'genres' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " let responseGenres = [];\r", + " let requestGenres = [];\r", + " source.genres.forEach((element) => requestGenres.push(element.id));\r", + " jsonData.genres.forEach((element) => responseGenres.push(element.id));\r", + " pm.expect(jsonData).to.have.property('genres');\r", + " pm.expect(responseGenres, `\"genres\" field must be %{requestGenres}`).to.eql(requestGenres); \r", + "});\r", + "\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let film;\r", + " try {\r", + " film = rnd.getFilm();\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + " pm.request.body.update({\r", + " mode: 'raw',\r", + " raw: JSON.stringify(film),\r", + " options: { raw: { language: 'json' } }\r", + " });\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"nisi eiusmod\",\n \"description\": \"adipisicing\",\n \"releaseDate\": \"1967-03-25\",\n \"duration\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films" + ] + } + }, + "response": [] + }, + { + "name": "Film create several genres", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const source = JSON.parse(pm.request.body.raw)\r", + "\r", + "pm.test(\"Status code is 200 or 201\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,201]);\r", + "});\r", + "pm.test(\"Has film create response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "pm.test(\"Test film 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('id');\r", + "});\r", + "pm.test(\"Test film 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('name');\r", + " pm.expect(jsonData.name, `\"name\" must be \"${source.name}\"`).to.eql(source.name);\r", + "});\r", + "pm.test(\"Test film 'description' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('description');\r", + " pm.expect(jsonData.description, `\"description\" must be \"${source.description}\"`).to.eql(source.description);\r", + "});\r", + "pm.test(\"Test film 'releaseDate' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('releaseDate');\r", + " pm.expect(jsonData.releaseDate, `\"releaseDate\" field must be \"${source.releaseDate}\"`).to.eql(source.releaseDate);\r", + "});\r", + "pm.test(\"Test film 'duration' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('duration');\r", + " pm.expect(jsonData.duration, `\"duration\" field must be %{source.duration}`).to.eql(source.duration); \r", + "});\r", + "pm.test(\"Test film 'mpa' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('mpa');\r", + " pm.expect(jsonData.mpa.id, `\"mpa.id\" field must be %{source.mpa.id}`).to.eql(source.mpa.id); \r", + "});\r", + "pm.test(\"Test film 'genres' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " let responseGenres = [];\r", + " let requestGenres = [];\r", + " source.genres.forEach((element) => requestGenres.push(element.id));\r", + " jsonData.genres.forEach((element) => responseGenres.push(element.id));\r", + " pm.expect(jsonData).to.have.property('genres');\r", + " pm.expect(responseGenres, `\"genres\" field must be %{requestGenres}`).to.eql(requestGenres); \r", + "});\r", + "\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let film;\r", + " try {\r", + " film = rnd.getFilm();\r", + " film.genres = [\r", + " {\"id\": 3},\r", + " {\"id\": 5}\r", + " ]\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + " pm.request.body.update({\r", + " mode: 'raw',\r", + " raw: JSON.stringify(film),\r", + " options: { raw: { language: 'json' } }\r", + " });\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"nisi eiusmod\",\n \"description\": \"adipisicing\",\n \"releaseDate\": \"1967-03-25\",\n \"duration\": 100\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films" + ] + } + }, + "response": [] + }, + { + "name": "Film create Fail name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(400);\r", + "});\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"\",\n \"description\": \"Description\",\n \"releaseDate\": \"1900-03-25\",\n \"duration\": 200,\n \"mpa\": { \"id\": 1}\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films" + ] + } + }, + "response": [] + }, + { + "name": "Film create Fail description", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(400);\r", + "});\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Film name\",\n \"description\": \"Пятеро друзей ( комик-группа «Шарло»), приезжают в город Бризуль. Здесь они хотят разыскать господина Огюста Куглова, который задолжал им деньги, а именно 20 миллионов. о Куглов, который за время «своего отсутствия», стал кандидатом Коломбани.\",\n \"releaseDate\": \"1900-03-25\",\n \"duration\": 200,\n \"mpa\": { \"id\": 1}\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films" + ] + } + }, + "response": [] + }, + { + "name": "Film create Fail releaseDate", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(400);\r", + "});\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Name\",\n \"description\": \"Description\",\n \"releaseDate\": \"1890-03-25\",\n \"duration\": 200,\n \"mpa\": { \"id\": 1}\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films" + ] + } + }, + "response": [] + }, + { + "name": "Film create Fail duration", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(400);\r", + "});\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Name\",\n \"description\": \"Descrition\",\n \"releaseDate\": \"1980-03-25\",\n \"duration\": -200,\n \"mpa\": { \"id\": 1}\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films" + ] + } + }, + "response": [] + }, + { + "name": "Film create Fail MPA", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(404);\r", + "});\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Name\",\n \"description\": \"Descrition\",\n \"releaseDate\": \"1980-03-25\",\n \"duration\": 200,\n \"mpa\": { \"id\": 10}\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films" + ] + } + }, + "response": [] + }, + { + "name": "Film create Fail Genre", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {\r", + " pm.expect(pm.response.code).to.be.equal(404);\r", + "});\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Name\",\n \"description\": \"Descrition\",\n \"releaseDate\": \"1980-03-25\",\n \"duration\": 200,\n \"mpa\": { \"id\": 5},\n \"genres\": [\n {\"id\": 500}\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films" + ] + } + }, + "response": [] + }, + { + "name": "Film update", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const source = pm.collectionVariables.get(\"film\")\r", + "\r", + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Has film update response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "\r", + "pm.test(\"Test film 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('id');\r", + " pm.expect(jsonData.id, `\"id\" must be ${source.id}`).to.eql(source.id);\r", + "});\r", + "pm.test(\"Test film 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('name');\r", + " pm.expect(jsonData.name, '\"name\" must be \"Film Updated\"').to.eql('Film Updated');\r", + "});\r", + "pm.test(\"Test film 'description' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('description');\r", + " pm.expect(jsonData.description, '\"description\" must be \"New film update decription\"').to.eql('New film update decription');\r", + "});\r", + "pm.test(\"Test film 'releaseDate' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('releaseDate');\r", + " pm.expect(jsonData.releaseDate, '\"releaseDate\" field must be \"1989-04-17\"').to.eql('1989-04-17');\r", + "});\r", + "pm.test(\"Test film 'duration' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('duration');\r", + " pm.expect(jsonData.duration, '\"duration\" field must be 190').to.eql(190); \r", + "});\r", + "\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user;\r", + " try {\r", + " film = await api.addFilm(rnd.getFilm());\r", + " pm.collectionVariables.set(\"film\", film);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + " pm.request.body.update({\r", + " mode: 'raw',\r", + " raw: JSON.stringify({\r", + " \"id\": film.id,\r", + " \"name\": \"Film Updated\",\r", + " \"releaseDate\": \"1989-04-17\",\r", + " \"description\": \"New film update decription\",\r", + " \"duration\": 190,\r", + " \"rate\": 4,\r", + " \"mpa\": { \"id\": 3}\r", + " }),\r", + " options: { raw: { language: 'json' } }\r", + " });\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films" + ] + } + }, + "response": [] + }, + { + "name": "Film update unknown", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 500\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([500, 404]);\r", + "});\r", + "pm.test(\"Has error response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user;\r", + " try {\r", + " film = await api.addFilm(rnd.getFilm());\r", + " pm.collectionVariables.set(\"film\", film);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + " pm.request.body.update({\r", + " mode: 'raw',\r", + " raw: JSON.stringify({\r", + " \"id\": film.id+1,\r", + " \"name\": \"Film Updated\",\r", + " \"releaseDate\": \"1989-04-17\",\r", + " \"description\": \"New film update decription\",\r", + " \"duration\": 190,\r", + " \"rate\": 4,\r", + " \"mpa\": { \"id\": 3}\r", + " }),\r", + " options: { raw: { language: 'json' } }\r", + " });\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films" + ] + } + }, + "response": [] + }, + { + "name": "Film get All", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Test list film response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "pm.test(\"Test film[0] 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[0]).to.have.property('id');\r", + " pm.expect(jsonData[0].id, '\"id\" must be 1').to.eql(1);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "*/*" + } + ], + "url": { + "raw": "{{baseUrl}}/films", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films" + ] + } + }, + "response": [] + }, + { + "name": "Film get Popular", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const film1_id = pm.collectionVariables.get(\"film1_id\");\r", + "const film2_id = pm.collectionVariables.get(\"film2_id\");\r", + "const film3_id = pm.collectionVariables.get(\"film3_id\");\r", + "\r", + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Test list popular film response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "\r", + "const index1 = pm.response.json().findIndex(x => x.id == film1_id);\r", + "const index2 = pm.response.json().findIndex(x => x.id == film2_id);\r", + "const index3 = pm.response.json().findIndex(x => x.id == film3_id);\r", + "\r", + "pm.test(\"Test films сonsistency\", function () {\r", + " pm.expect(index1).to.be.above(index2);\r", + " pm.expect(index1).to.be.above(index3);\r", + " pm.expect(index3).to.be.above(index2);\r", + "});\r", + "\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user1, user2, user3, film1, film2, film3;\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " user3 = await api.addUser(rnd.getUser());\r", + " film1 = await api.addFilm(rnd.getFilm());\r", + " film2 = await api.addFilm(rnd.getFilm());\r", + " film3 = await api.addFilm(rnd.getFilm());\r", + " await api.addLike(film2.id, user1.id);\r", + " await api.addLike(film2.id, user2.id);\r", + " await api.addLike(film2.id, user3.id);\r", + " await api.addLike(film3.id, user1.id);\r", + " await api.addLike(film3.id, user2.id);\r", + " await api.addLike(film1.id, user1.id);\r", + " pm.collectionVariables.set(\"film1_id\", film1.id);\r", + " pm.collectionVariables.set(\"film2_id\", film2.id);\r", + " pm.collectionVariables.set(\"film3_id\", film3.id);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "*/*" + } + ], + "url": { + "raw": "{{baseUrl}}/films/popular?count=1000", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + "popular" + ], + "query": [ + { + "key": "count", + "value": "1000" + } + ] + } + }, + "response": [] + } + ] + }, + { + "name": "like", + "item": [ + { + "name": "Add like", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,204]);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user, film;\r", + " try {\r", + " user = await api.addUser(rnd.getUser());\r", + " film = await api.addFilm(rnd.getFilm());\r", + " pm.collectionVariables.set(\"id\", user.id);\r", + " pm.collectionVariables.set(\"film_id\", film.id);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films/{{film_id}}/like/{{id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + "{{film_id}}", + "like", + "{{id}}" + ] + } + }, + "response": [] + }, + { + "name": "Remove like", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,204]);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " let user, film;\r", + " try {\r", + " user = await api.addUser(rnd.getUser());\r", + " film = await api.addFilm(rnd.getFilm());\r", + " await api.addLike(film.id, user.id);\r", + " pm.collectionVariables.set(\"id\", user.id);\r", + " pm.collectionVariables.set(\"film_id\", film.id);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "*/*" + } + ], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/films/{{film_id}}/like/{{id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + "{{film_id}}", + "like", + "{{id}}" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "MPA", + "item": [ + { + "name": "Get MPA name by id", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Get MPA response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "\r", + "const source = pm.collectionVariables.get(\"source\");\r", + "\r", + "pm.test(\"Test MPA 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('id');\r", + " pm.expect(jsonData.id, `\"id\" must be ${source}`).to.eql(source);\r", + "});\r", + "\r", + "const MPAS = {\r", + " 1: \"G\",\r", + " 2: \"PG\",\r", + " 3: \"PG-13\",\r", + " 4: \"R\",\r", + " 5: \"NC-17\"\r", + "}\r", + "\r", + "pm.test(\"Test MPA 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('name');\r", + " pm.expect(jsonData.name, `\"name\" must be \"${MPAS[source]}\"`).to.eql(MPAS[source]);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const mpa = Math.floor(Math.random() * (5 - 1 + 1) + 1);\r", + "pm.collectionVariables.set(\"id\", mpa);\r", + "pm.collectionVariables.set(\"source\", mpa)" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "*/*" + } + ], + "url": { + "raw": "{{baseUrl}}/mpa/{{id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "mpa", + "{{id}}" + ] + } + }, + "response": [ + { + "name": "OK", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/users/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Not Found", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/users/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Conflict", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/users/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Conflict", + "code": 409, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Internal Server Error", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/users/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Internal Server Error", + "code": 500, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + } + ] + }, + { + "name": "MPA id=9999 get not found", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {\r", + " pm.response.to.have.status(404);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "*/*" + } + ], + "url": { + "raw": "{{baseUrl}}/mpa/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "mpa", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "9999", + "description": "(Required) " + } + ] + } + }, + "response": [ + { + "name": "OK", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/users/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Not Found", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/users/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Conflict", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/users/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Conflict", + "code": 409, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Internal Server Error", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/users/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Internal Server Error", + "code": 500, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + } + ] + }, + { + "name": "MPA get All", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Test list MPA response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData.length, 'List length must be 5').to.eql(5);\r", + "});\r", + "pm.test(\"Test MPA[0] 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[0]).to.have.property('id');\r", + " pm.expect(jsonData[0].id, '\"id\" must be 1').to.eql(1);\r", + "});\r", + "pm.test(\"Test MPA[0] 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[0]).to.have.property('name');\r", + " pm.expect(jsonData[0].name, '\"name\" must be \"G\"').to.eql('G');\r", + "});\r", + "pm.test(\"Test MPA[1] 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[1]).to.have.property('id');\r", + " pm.expect(jsonData[1].id, '\"id\" must be 2').to.eql(2);\r", + "});\r", + "pm.test(\"Test MPA[1] 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[1]).to.have.property('name');\r", + " pm.expect(jsonData[1].name, '\"name\" must be \"PG\"').to.eql('PG');\r", + "});\r", + "pm.test(\"Test MPA[2] 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[2]).to.have.property('id');\r", + " pm.expect(jsonData[2].id, '\"id\" must be 3').to.eql(3);\r", + "});\r", + "pm.test(\"Test MPA[2] 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[2]).to.have.property('name');\r", + " pm.expect(jsonData[2].name, '\"name\" must be \"PG-13\"').to.eql('PG-13');\r", + "});\r", + "pm.test(\"Test MPA[3] 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[3]).to.have.property('id');\r", + " pm.expect(jsonData[3].id, '\"id\" must be 4').to.eql(4);\r", + "});\r", + "pm.test(\"Test MPA[3] 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[3]).to.have.property('name');\r", + " pm.expect(jsonData[3].name, '\"name\" must be \"R\"').to.eql('R');\r", + "});\r", + "pm.test(\"Test MPA[4] 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[4]).to.have.property('id');\r", + " pm.expect(jsonData[4].id, '\"id\" must be 5').to.eql(5);\r", + "});\r", + "pm.test(\"Test MPA[4] 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[4]).to.have.property('name');\r", + " pm.expect(jsonData[4].name, '\"name\" must be \"NC-17\"').to.eql('NC-17');\r", + "});\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "*/*" + } + ], + "url": { + "raw": "{{baseUrl}}/mpa", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "mpa" + ] + } + }, + "response": [ + { + "name": "OK", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/users", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + } + ] + } + ] + }, + { + "name": "Genre", + "item": [ + { + "name": "Get Genre name by id", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Get MPA response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "\r", + "const source = pm.collectionVariables.get(\"source\");\r", + "\r", + "pm.test(\"Test MPA 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('id');\r", + " pm.expect(jsonData.id, `\"id\" must be ${source}`).to.eql(source);\r", + "});\r", + "\r", + "const MPAS = {\r", + " 1: \"Комедия\",\r", + " 2: \"Драма\",\r", + " 3: \"Мультфильм\",\r", + " 4: \"Триллер\",\r", + " 5: \"Документальный\",\r", + " 6: \"Боевик\"\r", + "}\r", + "\r", + "pm.test(\"Test MPA 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('name');\r", + " pm.expect(jsonData.name, `\"name\" must be \"${MPAS[source]}\"`).to.eql(MPAS[source]);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const mpa = Math.floor(Math.random() * (6 - 1 + 1) + 1);\r", + "pm.collectionVariables.set(\"id\", mpa);\r", + "pm.collectionVariables.set(\"source\", mpa)" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "*/*" + } + ], + "url": { + "raw": "{{baseUrl}}/genres/{{id}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "genres", + "{{id}}" + ] + } + }, + "response": [ + { + "name": "OK", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/users/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Not Found", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/users/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Conflict", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/users/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Conflict", + "code": 409, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Internal Server Error", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/users/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Internal Server Error", + "code": 500, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + } + ] + }, + { + "name": "Genre id=9999 get not found", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {\r", + " pm.response.to.have.status(404);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "*/*" + } + ], + "url": { + "raw": "{{baseUrl}}/genres/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "genres", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "9999", + "description": "(Required) " + } + ] + } + }, + "response": [ + { + "name": "OK", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/users/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Not Found", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/users/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Conflict", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/users/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Conflict", + "code": 409, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Internal Server Error", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/users/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Internal Server Error", + "code": 500, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + } + ] + }, + { + "name": "Genre get All", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Test list genre response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData.length, 'List length must be 6').to.eql(6);\r", + "});\r", + "pm.test(\"Test genre[0] 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[0]).to.have.property('id');\r", + " pm.expect(jsonData[0].id, '\"id\" must be 1').to.eql(1);\r", + "});\r", + "pm.test(\"Test genre[0] 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[0]).to.have.property('name');\r", + " pm.expect(jsonData[0].name, '\"name\" must be \"Комедия\"').to.eql('Комедия');\r", + "});\r", + "pm.test(\"Test genre[1] 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[1]).to.have.property('id');\r", + " pm.expect(jsonData[1].id, '\"id\" must be 2').to.eql(2);\r", + "});\r", + "pm.test(\"Test genre[1] 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[1]).to.have.property('name');\r", + " pm.expect(jsonData[1].name, '\"name\" must be \"Драма\"').to.eql('Драма');\r", + "});\r", + "pm.test(\"Test genre[2] 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[2]).to.have.property('id');\r", + " pm.expect(jsonData[2].id, '\"id\" must be 3').to.eql(3);\r", + "});\r", + "pm.test(\"Test genre[2] 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[2]).to.have.property('name');\r", + " pm.expect(jsonData[2].name, '\"name\" must be \"Мультфильм\"').to.eql('Мультфильм');\r", + "});\r", + "pm.test(\"Test genre[3] 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[3]).to.have.property('id');\r", + " pm.expect(jsonData[3].id, '\"id\" must be 4').to.eql(4);\r", + "});\r", + "pm.test(\"Test genre[3] 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[3]).to.have.property('name');\r", + " pm.expect(jsonData[3].name, '\"name\" must be \"Триллер\"').to.eql('Триллер');\r", + "});\r", + "pm.test(\"Test genre[4] 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[4]).to.have.property('id');\r", + " pm.expect(jsonData[4].id, '\"id\" must be 5').to.eql(5);\r", + "});\r", + "pm.test(\"Test genre[4] 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[4]).to.have.property('name');\r", + " pm.expect(jsonData[4].name, '\"name\" must be \"Документальный\"').to.eql('Документальный');\r", + "});\r", + "pm.test(\"Test genre[5] 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[5]).to.have.property('id');\r", + " pm.expect(jsonData[5].id, '\"id\" must be 6').to.eql(6);\r", + "});\r", + "pm.test(\"Test genre[5] 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData[5]).to.have.property('name');\r", + " pm.expect(jsonData[5].name, '\"name\" must be \"Боевик\"').to.eql('Боевик');\r", + "});\r", + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "*/*" + } + ], + "url": { + "raw": "{{baseUrl}}/genres", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "genres" + ] + } + }, + "response": [ + { + "name": "OK", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/users", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + } + ] + }, + { + "name": "Film get with genre", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Get film response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "pm.test(\"Test film 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('id');\r", + " var filmId = pm.collectionVariables.get(\"id\");\r", + " pm.expect(jsonData.id, `\"id\" must be ${filmId}`).to.eql(filmId);\r", + "});\r", + "pm.test(\"Test film 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('name');\r", + " pm.expect(jsonData.name, '\"name\" must be \"Film Updated\"').to.eql('Film Updated');\r", + "});\r", + "pm.test(\"Test film 'description' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('description');\r", + " pm.expect(jsonData.description, '\"description\" must be \"New film update decription\"').to.eql('New film update decription');\r", + "});\r", + "pm.test(\"Test film 'releaseDate' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('releaseDate');\r", + " pm.expect(jsonData.releaseDate, '\"releaseDate\" field must be \"1989-04-17\"').to.eql('1989-04-17');\r", + "});\r", + "pm.test(\"Test film 'duration' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('duration');\r", + " pm.expect(jsonData.duration, '\"duration\" field must be 190').to.eql(190); \r", + "});\r", + "pm.test(\"Test film 'mpa' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('mpa');\r", + " pm.expect(jsonData.mpa).to.have.property('id');\r", + " pm.expect(jsonData.mpa.id, '\"mpa.id\" field must be 5').to.eql(5); \r", + " pm.expect(jsonData.mpa).to.have.property('name');\r", + " pm.expect(jsonData.mpa.name, '\"mpa.name\" field must be \"PG\"').to.eql(\"NC-17\"); \r", + "});\r", + "\r", + "pm.test(\"Test film 'genres' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('genres');\r", + " pm.expect(jsonData.genres.length, '\"genres\" field must be have 1 genre').to.eql(1);\r", + " pm.expect(jsonData.genres[0]).to.have.property('id');\r", + " pm.expect(jsonData.genres[0].id, '\"genres[0].id\" field must be 2').to.eql(2); \r", + " pm.expect(jsonData.genres[0]).to.have.property('name');\r", + " pm.expect(jsonData.genres[0].name, '\"genres[0].name\" field must be \"Драма\"').to.eql('Драма');\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " film = await api.addFilm({\r", + " \"name\": \"Film Updated\",\r", + " \"releaseDate\": \"1989-04-17\",\r", + " \"description\": \"New film update decription\",\r", + " \"duration\": 190,\r", + " \"rate\": 4,\r", + " \"mpa\": { \"id\": 5},\r", + " \"genres\": [{ \"id\": 2}]\r", + " });\r", + " pm.collectionVariables.set(\"id\", film.id);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "*/*" + } + ], + "url": { + "raw": "{{baseUrl}}/films/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "{{id}}", + "description": "(Required) " + } + ] + } + }, + "response": [ + { + "name": "OK", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/films/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Not Found", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/films/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Conflict", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/films/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Conflict", + "code": 409, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Internal Server Error", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/films/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Internal Server Error", + "code": 500, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + } + ] + }, + { + "name": "Film get without genre", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Get film response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "pm.test(\"Test film 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('id');\r", + " var filmId = pm.collectionVariables.get(\"id\");\r", + " pm.expect(jsonData.id, `\"id\" must be ${filmId}`).to.eql(filmId);\r", + "});\r", + "pm.test(\"Test film 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('name');\r", + " pm.expect(jsonData.name, '\"name\" must be \"New film\"').to.eql('New film');\r", + "});\r", + "pm.test(\"Test film 'description' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('description');\r", + " pm.expect(jsonData.description, '\"description\" must be \"New film about friends\"').to.eql('New film about friends');\r", + "});\r", + "pm.test(\"Test film 'releaseDate' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('releaseDate');\r", + " pm.expect(jsonData.releaseDate, '\"releaseDate\" field must be \"1999-04-30\"').to.eql('1999-04-30');\r", + "});\r", + "pm.test(\"Test film 'duration' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('duration');\r", + " pm.expect(jsonData.duration, '\"duration\" field must be 120').to.eql(120); \r", + "});\r", + "pm.test(\"Test film 'mpa' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('mpa');\r", + " pm.expect(jsonData.mpa).to.have.property('id');\r", + " pm.expect(jsonData.mpa.id, '\"mpa.id\" field must be 3').to.eql(3); \r", + " pm.expect(jsonData.mpa).to.have.property('name');\r", + " pm.expect(jsonData.mpa.name, '\"mpa.name\" field must be \"PG-13\"').to.eql(\"PG-13\"); \r", + "});\r", + "\r", + "pm.test(\"Test film 'genres' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('genres');\r", + " if (jsonData.genres != null) {\r", + " pm.expect(jsonData.genres.length, '\"genres\" field must be have 0 genre').to.eql(0);\r", + " }\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " film = await api.addFilm({\r", + " \"name\": \"New film\",\r", + " \"releaseDate\": \"1999-04-30\",\r", + " \"description\": \"New film about friends\",\r", + " \"duration\": 120,\r", + " \"mpa\": { \"id\": 3}\r", + " });\r", + " pm.collectionVariables.set(\"id\", film.id);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "*/*" + } + ], + "url": { + "raw": "{{baseUrl}}/films/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "{{id}}", + "description": "(Required) " + } + ] + } + }, + "response": [ + { + "name": "OK", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/films/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Not Found", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/films/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Conflict", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/films/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Conflict", + "code": 409, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Internal Server Error", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/films/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Internal Server Error", + "code": 500, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + } + ] + }, + { + "name": "Film get with genres", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Get film response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "pm.test(\"Test film 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('id');\r", + " var filmId = pm.collectionVariables.get(\"id\");\r", + " pm.expect(jsonData.id, `\"id\" must be ${filmId}`).to.eql(filmId);\r", + "});\r", + "pm.test(\"Test film 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('name');\r", + " pm.expect(jsonData.name, '\"name\" must be \"New film\"').to.eql('New film');\r", + "});\r", + "pm.test(\"Test film 'description' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('description');\r", + " pm.expect(jsonData.description, '\"description\" must be \"New film about friends\"').to.eql('New film about friends');\r", + "});\r", + "pm.test(\"Test film 'releaseDate' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('releaseDate');\r", + " pm.expect(jsonData.releaseDate, '\"releaseDate\" field must be \"1999-04-30\"').to.eql('1999-04-30');\r", + "});\r", + "pm.test(\"Test film 'duration' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('duration');\r", + " pm.expect(jsonData.duration, '\"duration\" field must be 100').to.eql(120); \r", + "});\r", + "\r", + "pm.test(\"Test film 'mpa.id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('mpa');\r", + " pm.expect(jsonData.mpa).to.have.property('id');\r", + " pm.expect(jsonData.mpa.id, '\"mpa.id\" field must be 3').to.eql(3);\r", + " pm.expect(jsonData.mpa).to.have.property('name');\r", + " pm.expect(jsonData.mpa.name, '\"mpa.name\" field must be \"PG-13\"').to.eql(\"PG-13\");\r", + "});\r", + "\r", + "pm.test(\"Test film 'genres' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('genres');\r", + " pm.expect(jsonData.genres.length, '\"genres\" field must be have 3 genres').to.eql(3);\r", + " pm.expect(jsonData.genres[0]).to.have.property('id');\r", + " pm.expect(jsonData.genres[0].id, '\"genres[0].id\" field must be 1').to.eql(1); \r", + " pm.expect(jsonData.genres[0]).to.have.property('name');\r", + " pm.expect(jsonData.genres[0].name, '\"genres[0].name\" field must be \"Комедия\"').to.eql('Комедия');\r", + " pm.expect(jsonData.genres[1]).to.have.property('id');\r", + " pm.expect(jsonData.genres[1].id, '\"genres[1].id\" field must be 2').to.eql(2);\r", + " pm.expect(jsonData.genres[1]).to.have.property('name');\r", + " pm.expect(jsonData.genres[1].name, '\"genres[1].name\" field must be \"Драма\"').to.eql('Драма');\r", + " pm.expect(jsonData.genres[2]).to.have.property('id');\r", + " pm.expect(jsonData.genres[2].id, '\"genres[2].id\" field must be 3').to.eql(3);\r", + " pm.expect(jsonData.genres[2]).to.have.property('name');\r", + " pm.expect(jsonData.genres[2].name, '\"genres[2].name\" field must be \"Мультфильм\"').to.eql('Мультфильм');\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " film = await api.addFilm({\r", + " \"name\": \"New film\",\r", + " \"releaseDate\": \"1999-04-30\",\r", + " \"description\": \"New film about friends\",\r", + " \"duration\": 120,\r", + " \"mpa\": { \"id\": 3},\r", + " \"genres\": [{ \"id\": 1}, { \"id\": 2}, { \"id\": 3}]\r", + " });\r", + " pm.collectionVariables.set(\"id\", film.id);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "*/*" + } + ], + "url": { + "raw": "{{baseUrl}}/films/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "{{id}}", + "description": "(Required) " + } + ] + } + }, + "response": [ + { + "name": "OK", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/films/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Not Found", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/films/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Conflict", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/films/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Conflict", + "code": 409, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Internal Server Error", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/films/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Internal Server Error", + "code": 500, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + } + ] + }, + { + "name": "Film get with genre without duplicate", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Get film response\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "pm.test(\"Test film 'id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('id');\r", + " var filmId = pm.collectionVariables.get(\"id\");\r", + " pm.expect(jsonData.id, `\"id\" must be ${filmId}`).to.eql(filmId);\r", + "});\r", + "pm.test(\"Test film 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('name');\r", + " pm.expect(jsonData.name, '\"name\" must be \"New film\"').to.eql('New film');\r", + "});\r", + "pm.test(\"Test film 'description' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('description');\r", + " pm.expect(jsonData.description, '\"description\" must be \"New film about friends\"').to.eql('New film about friends');\r", + "});\r", + "pm.test(\"Test film 'releaseDate' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('releaseDate');\r", + " pm.expect(jsonData.releaseDate, '\"releaseDate\" field must be \"1999-04-30\"').to.eql('1999-04-30');\r", + "});\r", + "pm.test(\"Test film 'duration' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('duration');\r", + " pm.expect(jsonData.duration, '\"duration\" field must be 100').to.eql(120); \r", + "});\r", + "\r", + "pm.test(\"Test film 'mpa.id' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('mpa');\r", + " pm.expect(jsonData.mpa).to.have.property('id');\r", + " pm.expect(jsonData.mpa.id, '\"mpa.id\" field must be 3').to.eql(3);\r", + " pm.expect(jsonData.mpa).to.have.property('name');\r", + " pm.expect(jsonData.mpa.name, '\"mpa.name\" field must be \"PG-13\"').to.eql(\"PG-13\");\r", + "});\r", + "\r", + "pm.test(\"Test film 'genres' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('genres');\r", + " pm.expect(jsonData.genres.length, '\"genres\" field must be have 2 genres').to.eql(2);\r", + " pm.expect(jsonData.genres[0]).to.have.property('id');\r", + " pm.expect(jsonData.genres[0].id, '\"genres[0].id\" field must be 1').to.eql(1); \r", + " pm.expect(jsonData.genres[0]).to.have.property('name');\r", + " pm.expect(jsonData.genres[0].name, '\"genres[0].name\" field must be \"Комедия\"').to.eql('Комедия');\r", + " pm.expect(jsonData.genres[1]).to.have.property('id');\r", + " pm.expect(jsonData.genres[1].id, '\"genres[1].id\" field must be 2').to.eql(2);\r", + " pm.expect(jsonData.genres[1]).to.have.property('name');\r", + " pm.expect(jsonData.genres[1].name, '\"genres[1].name\" field must be \"Драма\"').to.eql('Драма');\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " film = await api.addFilm({\r", + " \"name\": \"New film\",\r", + " \"releaseDate\": \"1999-04-30\",\r", + " \"description\": \"New film about friends\",\r", + " \"duration\": 120,\r", + " \"mpa\": { \"id\": 3},\r", + " \"genres\": [{ \"id\": 1}, { \"id\": 2}, { \"id\": 1}]\r", + " });\r", + " pm.collectionVariables.set(\"id\", film.id);\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "\r", + "setTimeout(async () => \r", + " {\r", + " try {\r", + " await main();\r", + " } catch (e) {\r", + " console.error(e);\r", + " } finally {\r", + " clearInterval(interval);\r", + " }\r", + " }, \r", + " 100 \r", + ");" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Accept", + "value": "*/*" + } + ], + "url": { + "raw": "{{baseUrl}}/films/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "{{id}}", + "description": "(Required) " + } + ] + } + }, + "response": [ + { + "name": "OK", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/films/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Not Found", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/films/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Conflict", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/films/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Conflict", + "code": 409, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Internal Server Error", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/films/:id", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "films", + ":id" + ], + "variable": [ + { + "key": "id", + "value": "-29029902", + "description": "(Required) " + } + ] + } + }, + "status": "Internal Server Error", + "code": 500, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "*/*" + } + ], + "cookie": [], + "body": "" + } + ] + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "API = class {", + " constructor(postman, verbose = false, baseUrl = \"http://localhost:8080\") {", + " this.baseUrl = baseUrl;", + " this.pm = postman;", + " this._verbose = verbose;", + " }", + "", + " async addUser(user, verbose=null) {", + " return this.post(\"/users\", user, \"Ошибка при добавлении нового пользователя: \", verbose);", + " }", + "", + " async addFilm(film, verbose=null) {", + " return this.post(\"/films\", film, \"Ошибка при добавлении нового фильма: \", verbose);", + " }", + "", + " async addFriend(userId, friendId, verbose=null) {", + " return this.put(\"/users/\" + userId + '/friends/' + friendId, null, \"Ошибка при добавлении нового фильма: \", verbose);", + " }", + "", + " async addLike(filmId, userId, verbose=null) {", + " return this.put(\"/films/\" + filmId + '/like/' + userId, null, \"Ошибка при добавлении лайка на фильм: \", verbose);", + " }", + "", + " async getFriends(userId, verbose=null) {", + " return this.get('/users/' + userId + '/friends', null, \"Ошибка при поиске друзей по id пользователя\", verbose);", + " }", + "", + " async post(path, body, errorText = \"Ошибка при выполнении post-запроса: \", verbose=null) {", + " return this.sendRequest(\"POST\", path, body, errorText, verbose);", + " }", + "", + " async patch(path, body = null, errorText = \"Ошибка при выполнении patch-запроса: \", verbose=null) {", + " return this.sendRequest(\"PATCH\", path, body, errorText, verbose);", + " }", + "", + " async get(path, body = null, errorText = \"Ошибка при выполнении get-запроса: \", verbose=null) {", + " return this.sendRequest(\"GET\", path, body, errorText, verbose);", + " }", + "", + " async put(path, body = null, errorText = \"Ошибка при выполнении put-запроса: \", verbose=null) {", + " return this.sendRequest(\"PUT\", path, body, errorText, verbose);", + " }", + "", + " async sendRequest(method, path, body=null, errorText = \"Ошибка при выполнении запроса: \", verbose=null) {", + " return new Promise((resolve, reject) => {", + " verbose = verbose == null ? this._verbose : verbose;", + " const request = {", + " url: this.baseUrl + path,", + " method: method,", + " body: body == null ? \"\" : JSON.stringify(body),", + " header: { \"Content-Type\": \"application/json\" },", + " };", + " if(verbose) {", + " console.log(\"Отправляю запрос: \", request);", + " }", + "", + " try {", + " this.pm.sendRequest(request, (error, response) => {", + " if(error || (response.code >= 400 && response.code <= 599)) {", + " let err = error ? error : JSON.stringify(response.json());", + " console.error(\"При выполнении запроса к серверу возникла ошика.\\n\", err,", + " \"\\nДля отладки проблемы повторите такой же запрос к вашей программе \" + ", + " \"на локальном компьютере. Данные запроса:\\n\", JSON.stringify(request));", + "", + " reject(new Error(errorText + err));", + " }", + " if(verbose) {", + " console.log(\"Результат обработки запроса: код состояния - \", response.code, \", тело: \", response.json());", + " }", + " if (response.stream.length === 0){", + " resolve(null);", + " }else{", + " resolve(response.json());", + " }", + " });", + " ", + " } catch(err) {", + " if(verbose) {", + " console.error(errorText, err);", + " }", + " return Promise.reject(err);", + " }", + " });", + " }", + "};", + "", + "RandomUtils = class {", + " constructor() {}", + "", + " getUser() {", + " let date = new Date(new Date(1960, 0, 1).getTime() + Math.random() * (new Date(2010, 0, 1).getTime() - new Date(1960, 0, 1).getTime()));", + " return {", + " name: pm.variables.replaceIn('{{$randomFullName}}'),", + " login: this.getWord(10),", + " email: pm.variables.replaceIn('{{$randomEmail}}'),", + " birthday: date.toISOString().slice(0,10)", + " };", + " }", + "", + " getFilm() {", + " let date = new Date(new Date(1960, 0, 1).getTime() + Math.random() * (new Date(2010, 0, 1).getTime() - new Date(1960, 0, 1).getTime()));", + " return {", + " name: this.getWord(15),", + " description: this.getWord(50),", + " releaseDate: date.toISOString().slice(0,10),", + " duration: Math.floor(Math.random() * (180 - 60 + 1) + 60),", + " mpa: { id: Math.floor(Math.random() * (5 - 1 + 1) + 1)},", + " genres: [{ id: Math.floor(Math.random() * (6 - 1 + 1) + 1)}]", + " };", + " }", + "", + " getWord(length = 1) {", + " let result = '';", + " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';", + " const charactersLength = characters.length;", + " let counter = 0;", + " while (counter < length) {", + " result += characters.charAt(Math.floor(Math.random() * charactersLength));", + " counter += 1;", + " }", + " return result;", + " }", + "", + "}" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "key": "baseUrl", + "value": "http://localhost:8080", + "type": "string" + }, + { + "key": "id", + "value": "" + }, + { + "key": "friend_id", + "value": "" + }, + { + "key": "user_friends", + "value": "" + }, + { + "key": "user3_id", + "value": "" + }, + { + "key": "film", + "value": "" + }, + { + "key": "film1_id", + "value": "" + }, + { + "key": "film2_id", + "value": "" + }, + { + "key": "film3_id", + "value": "" + }, + { + "key": "source", + "value": "" + }, + { + "key": "user", + "value": "" + }, + { + "key": "film_id", + "value": "" + }, + { + "key": "new_user_info", + "value": "" + } + ] +} diff --git a/README.md b/README.md index a116f5d..c8ab348 100644 --- a/README.md +++ b/README.md @@ -9,17 +9,20 @@ _**Когорта-53**_ ![](/er_diagram_filmrate.png) Примеры запросов: -1. Получение пользователя с ID = 1: \ +1. Получение пользователя с ID = 1: SELECT * FROM users WHERE user_id = 1; -2. Получение фильма с ID = 10: \ +2. Получение фильма с ID = 10: SELECT * FROM films WHERE film_id = 10. -3. Получение списка фильмов, понравившихся пользователю с ID = 5: \ +3. Получение списка фильмов, понравившихся пользователю с ID = 5: SELECT title FROM films WHERE film_id IN (SELECT film_id FROM likes WHERE user_id = 5); + +_**Для 12 спринта есть файла для проверки через postman: +PostmanSprint12_add-database.json**_ \ No newline at end of file diff --git a/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java b/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java index 7f2b8d9..df2138c 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java +++ b/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java @@ -1,10 +1,32 @@ package ru.yandex.practicum.filmorate; -import org.springframework.boot.test.context.SpringBootTest; +import lombok.RequiredArgsConstructor; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; +import ru.yandex.practicum.filmorate.model.User; +import ru.yandex.practicum.filmorate.storage.UserDbStorage; -@SpringBootTest -public class FilmorateApplicationTests { +import java.util.Optional; -} +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +@JdbcTest +@AutoConfigureTestDatabase +@RequiredArgsConstructor(onConstructor_ = @Autowired) +class FilmorateApplicationTests { + private final UserDbStorage userStorage; + @Test + public void testFindUserById() { + + Optional userOptional = Optional.ofNullable(userStorage.getById(1)); + + assertThat(userOptional) + .isPresent() + .hasValueSatisfying(user -> + assertThat(user).hasFieldOrPropertyWithValue("id", 1) + ); + } +} \ No newline at end of file From 9faafaf4256ba799fad3c0a6fc34b388ad34d3dc Mon Sep 17 00:00:00 2001 From: Sergey Filippovskikh Date: Mon, 17 Feb 2025 14:58:33 +0300 Subject: [PATCH 15/17] =?UTF-8?q?=D0=A1=D0=BF=D1=80=D0=B8=D0=BD=D1=82=2012?= =?UTF-8?q?.=20=D0=A0=D0=B5=D0=B9=D1=82=D0=B8=D0=BD=D0=B3=20=D0=A4=D0=B8?= =?UTF-8?q?=D0=BB=D1=8C=D0=BC=D0=BE=D0=B2.=20=D0=9F=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B2=D0=BE=D0=B4=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B2=20=D0=B1?= =?UTF-8?q?=D0=B0=D0=B7=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20H2.?= =?UTF-8?q?=20=D0=9A=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D1=81=D1=82=D0=B8=D0=BB=D1=8F=20=D0=BF?= =?UTF-8?q?=D0=BE=20GitHub.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filmorate/FilmorateApplicationTests.java | 32 +++---------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java b/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java index df2138c..e1aa6f8 100644 --- a/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java +++ b/src/test/java/ru/yandex/practicum/filmorate/FilmorateApplicationTests.java @@ -1,32 +1,8 @@ package ru.yandex.practicum.filmorate; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; -import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; -import ru.yandex.practicum.filmorate.model.User; -import ru.yandex.practicum.filmorate.storage.UserDbStorage; +import org.springframework.boot.test.context.SpringBootTest; -import java.util.Optional; +@SpringBootTest +public class FilmorateApplicationTests { -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -@JdbcTest -@AutoConfigureTestDatabase -@RequiredArgsConstructor(onConstructor_ = @Autowired) -class FilmorateApplicationTests { - private final UserDbStorage userStorage; - - @Test - public void testFindUserById() { - - Optional userOptional = Optional.ofNullable(userStorage.getById(1)); - - assertThat(userOptional) - .isPresent() - .hasValueSatisfying(user -> - assertThat(user).hasFieldOrPropertyWithValue("id", 1) - ); - } -} \ No newline at end of file +} From a0d8ecee0be60ffae51d740c3a0193ee55c0e3f1 Mon Sep 17 00:00:00 2001 From: Sergey Filippovskikh Date: Tue, 18 Feb 2025 10:07:31 +0300 Subject: [PATCH 16/17] =?UTF-8?q?=D0=A1=D0=BF=D1=80=D0=B8=D0=BD=D1=82=2012?= =?UTF-8?q?.=20=D0=A0=D0=B5=D0=B9=D1=82=D0=B8=D0=BD=D0=B3=20=D0=A4=D0=B8?= =?UTF-8?q?=D0=BB=D1=8C=D0=BC=D0=BE=D0=B2.=20=D0=9F=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B2=D0=BE=D0=B4=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B2=20=D0=B1?= =?UTF-8?q?=D0=B0=D0=B7=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20H2.?= =?UTF-8?q?=20=D0=9A=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D0=BF=D0=BE=20=D0=B7=D0=B0=D0=BC=D0=B5?= =?UTF-8?q?=D1=87=D0=B0=D0=BD=D0=B8=D1=8F=D0=BC=20=D1=80=D0=B5=D0=B2=D1=8C?= =?UTF-8?q?=D1=8E=D0=B2=D0=B5=D1=80=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- er_diagram_filmrate.png | Bin 54303 -> 55804 bytes .../filmorate/controller/FilmController.java | 9 --------- .../filmorate/controller/GenreController.java | 4 ---- .../controller/RatingController.java | 4 ---- .../filmorate/controller/UserController.java | 10 ---------- .../practicum/filmorate/model/Film.java | 2 -- .../practicum/filmorate/model/Genre.java | 2 -- .../practicum/filmorate/model/Rating.java | 2 -- .../practicum/filmorate/model/User.java | 2 -- .../filmorate/service/FilmService.java | 11 +++++++---- .../filmorate/service/GenreService.java | 2 ++ .../filmorate/service/RatingService.java | 2 ++ .../filmorate/service/UserService.java | 13 ++++++++----- .../filmorate/storage/FilmDbStorage.java | 17 +++++------------ .../filmorate/storage/FriendDbStorage.java | 3 --- .../filmorate/storage/GenreDbStorage.java | 17 ++--------------- .../filmorate/storage/LikeDbStorage.java | 3 --- .../filmorate/storage/RatingDbStorage.java | 9 +-------- .../filmorate/storage/UserDbStorage.java | 11 +++-------- .../storage/dbmapper/FilmRowMapper.java | 3 --- .../storage/dbmapper/GenreRowMapper.java | 3 --- .../storage/dbmapper/RatingRowMapper.java | 3 --- .../storage/dbmapper/UserRowMapper.java | 3 --- 23 files changed, 30 insertions(+), 105 deletions(-) diff --git a/er_diagram_filmrate.png b/er_diagram_filmrate.png index f7b53e5a70adc5ec8cf6c4f9c3666a9b854fedba..d502bdafa7ce64dd9002020c81449f6f13b1a0dd 100644 GIT binary patch literal 55804 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
    YG@$4@P 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 literal 54303 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 (#aF zgj)Rcu>#L4eZ>}{NHc}Uj}LapGUL*8J5f|6JU@pVxB2}@tH!3i8#SuY9BAMzEcc`` z^{uB3O*Re4G(!@*(O`=xVfW8i-lALN%B>-gk63!2(?KyPQ(q>8@rkf%e3o9&d zX?A#mt@v*)02Cha2U^;H<0E>EA>!0sU0uqmM=(MRoz@TkK2G*ibE{sT?en&7dRO&r z%eb4Ww)8)MzO<48O}ezT?_mmB)@*@-4HtqRUq^E+drQ=fppK1#$D86q`)TF zDRbIy`C$aPCXFdv>5!J3*ys@9U%1~w_#FEZ5LtxQuZa^4q%Us#Z2Dd38bE4g=w`Zr z$e}qvN2Ln6%f+A?G`23S0jxrePHW-+c*IMe!uiwV0IX;|UZr!OXQq|3+R|P+>h|+` z+%=g$JY7`_y$(}T{uw!Eg(dgQO(a-UQV${>k8K4*8d}O+9X$f29U}&3atQ0;F9LmY z_ugC!mM;=9dE_OXlpM!+cH zhU8gAgX@hKgd_pm_3T|Ghs6M`e0`_ggA1ic)qD^KrG7;f!kt^@O-=#jjr%);YMnzM zYh2D55cK7&%tgrb3lIZA0nQXN2W3u3cVl%=&kB%UvY?%2`RqId(evg{yWYGj;jtPL zxxA{3VySx>mg`f|H=b=`d(qsn+WCBc3fw7zoGt zS+42%DzomdSi`l>UG)nis897*u1E!Yp|iNPX5F!g;>`jxH@1hIu3WCRr3T#y+cu7T z`P76>bBVP20BQ8(v2jPv<|tMxC9b1@{8Yl`S2kna{OSPBX!|Np$W>#r2Ed>daFflI z35iS?q2v!YnScs&^71KY3pS+V(zA|Re-;u*V;AvVMqX0Wv(;JvJtM8ht#P2@d9B}I0&6u zZgIk0!e6(*5xzE+Kmvo8rL&MG?*Hde)Yh(L$x9Kc6ASaPrKx`3UcXV|y!6t%t6}rL zE1@(OZCi=usFs8(PifOrfNqJrT8eh4k22_%Z(kl?SF4ue!EWEYs+b-0^5_NIAH7m3 zz8p{bfq?LKW#N(&gjqKVt&B zUg(Zuezu1R1eV+TeiRKTewL$AW0tF(M7A+Y+Vq$tv*$;ia~@JQ51V)^kn9I=d>F@S zC_+?>(zR+w(V#;Zk4ll+Q){95SXtMrTRehh7CM^_u<=y$J9Vg#mOd*d0$6g{Zwyst zW~%Ga_UGB;g4&O)b5M4OgcA95d3mZCzB&Mx=e)%D1(-j2bYgP1T243C^=!L6OxNN} z3;Bqm+KqUSm$(SP@BefZ5-ehr@Yw8kd23_AyZ3yXuNp6EIytINXxN>ZQ2>jsRQ3G> zG!lmzzb1%KztvW#5}6+~MZ+$LO-dr`;JW;h&S?b+j7)d;x^4VXpDoXc7uL*zBtVf~ zfzP6#^~cwNX(hG-L_J!ewlhG^u`O1~j$L{@Izhfn%4X_NfJ{d);sc&UVfR1*(E~_O z5z5;0sBZQtFEi2||GN_ENRiDGnr3NZ+6&5^ z*70phZ!kPcz~r}$_*Xw>_C&SddkS1`aN!tw2Ya?q=r#F*VE+*Qeu3(n7jO;ysS&jX z8=KlfatXMfq?ga`HdWEsLY>f|6zILocI?6)3|Aj~zvMuW?%`;Zpg`b0Q7&)>cUwvv zqUJ)$Qn9k`&kUfPdy{OG#6B3UUM1Dm@1Xr`4>1(|2n3W$WEHYB;XbE<>%^p10={pA zO4==YsG%~n{}KiKY#H{>^Y_QEe;Uklp7WgZea`tVpU>yS?V|Qa z9P{BXLK3uR5d4v+@UE6S0G+tKceWKlYF_g1rw5V-B!&3ielR7Wjv=(T(~hEW#HI#Z zxT18=Y7=15@Q1<=wH>4-Vo|g~AX<_!8%KKhO@WcS>uh0h9P= z+xLf1;s>*g9TW6N_-O)d1X_oW6l!1v9l$VJo`T^%4>RVsgC^SVC$3&2T&N(Bk*0^j z@QI~i(!b1%jEHrAEB_N-4k8dqQ7j_p6gowzCVvE#sQx~uXX%Eg=$0=aHSgzm50$xer&}7 zaxlGHrA~qKhia67p44uCBl{EVFu+fa6JrZtQ4&N$%8+54m#x{h`_M6vFE6FkT%R$H z2YK4+YecTZ~RBm zvWU_??Vkv7`7%>OZwe8)K!ojMYy(R9YDp(9sHmuzLH)5aU4afcxa*L#rxqe74rIMp z(BWUm^=yduKK*MgP0=VLf4rw5^9f2^33bRoqLpH-byCnMAATgHHg)cWLu~0vpX0a~S zt+kezeCJq&O#@FH4AM~4%BrQRr3v(P3nl*g5)RSd+( z);rnEN;8O#uUec?+8}l}%c*0CHWm`v_$$s6{=GYO6r1 z*ldeHO;WWsb}aK^i@KHMNJ7<+U5i=H`tjbri6pIH5Vm@?$1&az$RSo8$A97iJ8{0p zLkj&)0&$wmo!55+RBHI1-=f#3?r8NuyKM5K1+!NWddRmO_FT0m8c>wK3X(HA7Lgzz z&6=teEV&iWfc5N6YZfWte>0a!^};O6!}xOJ!CqP24o0@AtkVgt0&Q9=Z>ThfKEwzNNcU9dx$_uP zYb86$3AOez9$`Y**lm7)`5ds8QPVC0Ub{vyCseQk>ev{yl4l|wuNeJ=G7SBj$esDo z76)TI7I37>X1Zx3BunF&r zIe}L5ZCPv4x|-K?uJqJ7$Xs}r4#&gOoU?x5paW;y-Mwrl7<6!alaL2(2HQQ1+Ip74 z?Xs^$#-AD8oD*x}ib`G=%`z@S&HhNaNwIm95jgxJPGors1gSyco85>Y3d!n=isEa zxsUc%K;~(-(@*SLG9vXME-tuq@P$BY0%XumSgWodd)>m_Dl(vgx!}Wc4w8Nm)DY_j zCha#>NCnEveO6N)ckmWMxqw3&EbgZk5a(aKKU4gL)j&X8AGsMc?ew!`VNfTzP64jF zQ|hA^l!FOUP25C!>(Ko(ob{~>b8j5hw2aqHDjvqQB)!dykAdS?9?ssb@j0l92oee$ z4@HH1d*0ZIJ`YEu6WHY}&w?uvN`w9jnFOU5Lxc;d#^tvCL4%&nHoU#;YrF0C{(NtC z3QJg9yd>5>9C*6rFb$QxxHf>n+BK_y5o@uMVK3PcvXgM)lz1KkRR?TmA?Ns>m+uMC z?Ph=JT>>S`me@lJu;WFtMdYL2yhzlHMM@TpVkNwKL2*R#LqJLxcd2G}K~Ve2GoXq| zRh!|Sow#Wr9f0cOc5NhL;c8=8e1VpxE(8CQPRGdHJPS)${X-!x7|YAZSd#rqrB0V@ z?WE;%-jR_al8s-|AJVdloM~=WiI;NCnNJvNNfNOh4~S>vD|7I%LymbisOvxXK+J%f zZd-^S+xg2>JoU(#8*l`jvS)LK0Ry%qu+uCwo{L`0E#2H*f37>}LG!^N~QWA|1td&o>p#Se1f|)UFDzFh>xMNXC^heQMs*bZG z!_Pe>pTH8>;LIv411-Di4LLt}wjI<7SHRENn3^}6TBM)Z+0xbP=Qx$LuX_4K!@>9bk`utg#bxfxP zAEd_7FGWFvf|h`dwCu+qesRKyPcX)Qh+nLAB5vn~L;=&6uR@YQeS^C=p?9_Uqp)e) z_c6A8_YC@Xe&_(?!zzie>JV&3I6RVB<^4kFp_8cnU}hOeE%M3%7%amA<+k_Qtf?zl{4uF%_b9sR_BW* zL0B6(2Gj=!QV<|FG2@?ZK)?n9AcAAU@lF1#7Ay*De5_;JkNE^c2c9Y4AxCU1%tQ(; zfEwCUqTUJQt{!#%+!_f@wtzCJIc0STlJe2+h-lS@XoQWA50Yc*TD~>! zzm+bpwsnns)E!U;z# zhOK6sc_I75f@_&GQHo~t`PWEyM1r6i3jP?q&@)vHo>=2H* z0=r$&$2@X$(e|upbZBCwc+6}9ruZqy?7(3t95V&9t1^Ru6E7hJvwb_ zU86@Q+LoOCP$9DpJBYB{e_x5-!XA~*bb$!D7PB+JOpjG@kKZXgAdsbJV2{azQw51` z(w4+{0gOU|^i9>RU4LN~DCf4C_ zszLFS0wt|3@n;lWvhNmK#!7D0vuI0&8d4y>;vV+U>Ux7)!nrv_@#v|g}>UaIJG!GZf>e~T}Ce;Rjq znrDo>7Qo^j_LBoZvYxz}LQqq&Q!W~knxz3QPK?-uj!Zl;y^~Mm@to&$)#x~=9T+}H z?$NQ{Zw=}sK_5XTX)CqZ$CQ;giLulTIE zDcIrFg2&txqn9%6Lg$Jd99?+76#DeOh?SOaO{ua-z3+U`Jn!cE(~nc>iY4L*taFju*BhTX@hEJlD&hPt4KyojnN>TLNddeZ09N4wa-ZpWLHt48+Jp5O2sX zPMMr<=pT-}t;chFBs5p_W;1uENE^zTsYj!$&PS%neXLwFpW*XelOCW{>ak+@re)VQ z)NwX^f)mIdExC-yE;Qz%RN;snqs#GAvHGH|wogj|w~bvUvo9Zz@j3_u(a(34oevzv zYU?Hw(PM!qRl)kwKqH;8F2oQS8RuOktUvFyQ?!lOJX}V< zPXo%*nQ?ahpX(LuY|cf!#T`_(EN4sLkMYDEH{jIPjnCs1eE=}D!qs$(G!><#cA`*Yq$70R6Cq66a0M?J<+CKc(BixWvg#DHIL%J|5j^c*&%4-Loj0r;+p}LDVD3qh3@B+z;|D;8(fDM$LIJCQK2B)Dx3oP0Z$+o`?sLc zhMhh|cvZfkacFqA5FLe6&oXUj&xC>#fZc2^`PVJ$5&xU`!SWmYVng{0^%c?Df%M8h zqx2Qr7=Km{3nXQPIL_hM#tu+1ASokVIlbL~Sp)$*;t`dolVKM%`o*|hA>|tLf$XWwYXd85-5QfEAxdRe+ z8v_6dWJGmlQ5YKp&I}8DokWW-K%<1A`QWX0M>d)PQ~f6^2nu(?DbW7^ZJ?VBfa<#ar2Mf{oBX>yF=f5PNu%vZW3iTVwpk4F3Tj8Sw+@H28&%~ z>&$w7l-qhTTQZC-;s11z6J76xIwn8`!yTeXH@K*}yzN7>+}ahv!~&UrAfpvq zo@}s10_|ob5jpXw%VF)yfd#bh@fw|FSD>BeZn~z4fVWw8{B1%%Rv+ka=bqP(uIS71 zB?6hO+A$cWU{+vd+xy?$t5AR)*<%NO!7BKC=3N^TU+ zXZ(DxoBb}}GM7B3%*!kke9mWZY}vCidttx%XC(%#-qst5;}9QxJO9^I{nHC*1mS4i zoLy)sxG7G0T)0q7tjW&P_pM%xP-E@VnLg0N$sgjf%ecq;qHoDukvEyhJMsX{|3-Xt zp8eRhoo1UhF-9t%IjseAx^J_TJm$AcRBHKkra6LLK1Hi?N>YnseJPMda)Fh+ zdv`J_zOEq6>cRWr%`cjk<%0v)xUrO92WOKXBp_9T2RxD+@eb!?J{;RY@R>=)Zy)Nn z=U=X??UuJ^?#t#LAt=EsipMokaWw@VWGH4SR3>n6LRE#d4^J1 z;dg4*LcZ$J+R>%fFtgx&9NR(>VUAzM>IMx}6)mCZxqi!a%lW9>-r&_MC5^ahzRvr} zjf=kXG;X{P3-ed^Vy~~?Q!9_fRhm03C320-u2)^E_0-^6@~1c8++T2tonEHg#8)Uc zxAl*%_AN#UdlMj{-QdjrVm_PvPB4Ar8D|sj=Jh-IW8u7udT-z46StDZ70P% zKG_mK%P#AqH~hk`hhN43O`fJ4kaQyXi&?RexYqP_Z)UZia!r5+2+lFrlVh8?A8 zJFAv=Xb3Inq(lRYPTz)LlDLo*DJs4{)A9Z`kyCAzow#hE06WJ zP7mA}$Bj&%yXf^TYIQEYS&DJ3zoFo+L%#tod41kCb9E)^k=?wR^1gtfl>uLmFO=Nj zTKYTV>tnL9O^J_XTUFj{PSLxr=3BfNF)8aLBb;)lz(Hds>ex#Mur1r5G+@qwZ1=-v`o9hH6 zk7zdt9(l=Mlb*KvKKfGAVO*!wH|c%1cvdNnWNp%v(!%XK;=o9-=c!w5VR8EU#iJwt z9uI2%QF=z&>fG#rx&N(bafdZ)Q)Z`kN0;zkHWNiDj~}I-s`}>SBkUaZ_;Zx^$|u)8 z^YtS}wNQxQJw1&mgZ{LVz{mOs|l}Z|-Z4Xv2XT@wSTV-9*>th!$8GlgMXMej8zG2fO=@2N zNok_b!X{g#a%Nqx>r9^ki}xir*1X8XLL2V7)!dZZGwTD@KBW5b`=klM`McY@9{d@j z8Jtb4i9Vj!aC9l_@r1=qYX-^;pY@S9N``ke!pT{*vY6I4;d{bdfN=j#QQjVEwzUV%zvJHQaD&roLLRn zSiK5Yd-saooQ6zxyJ&M&5Q?42$^M{i+ch!06TgX)Rf$qVH`yu@} z=ar0BibI2SPi2XIyHTZ?d6e{{RiF4-!fw*M*U5JbSV79y17q*T{Y;giuX3Rz>; zS26TeuHCnU^;VaKm->`=hP`k^ZHg^s{5f?JW>QH|Eb5Y*SOhLnhj+_k!yJiGFWkHC z9IoRF(G=Tc;I1rRNN4!n)&{9X_F)BU95I|mL(M$L*9RJShQF!fCp65xKnBx(ar`9l z_>&4>nb)qB%0q)!-aU8PL8z-Ox$iwz(9&~(Jn=%EE6>xcgtHu9m)fI1nHrNP&93J= zwRLx{s0HbRAWT`cOGt)_R87#lb;?5zi-2zML!2gV&JY=l$yGHtlK&S^NGv>B`__RU z!Z%PJTuP=|{4A3^gj;jSEZcXnaKcLhFX3iXQ1+R#ekYgn`gL4|iErJkuD`I)if&^?g-(><56PmdHxN7PXsoxenPuxXHE*D$@wYSFY_`Kzcw zKuZU*Ed1`vU@=eBgRRrZTy;KSF1DIom#wDqy;wajNtN2Oudj|xJE?bBkcN1}TV(k? zWNq{zA_ITp%DaJH((GxSFuqaoahn-kgMG=ENzLfKmWt`z)Nk`|6HG~ALps6S1%(Cz zt`j5IWjo&G(tNo~AZC5x$;bh$exI66l4M{^twlym%K7YBR?_KY z5z#;Qqhs^d4FkHnQf-eUE{GS2Jn<~gO+}NNlmr}jeI_+&33<5SN`~K@PB=M}wsO0$ zptMzTeyVrDEpJ=*gC0H&%uD1?+QsWupD%I%ZmFDa+)Z(SXjNz2eGNld#*Yvyz&o|^ z;9q+x-kGy>tE{XvSrSdEt9=b_7*T~->#T3#!&Z{wc$O#sRVK5MCzUA=n*24IW~58- zQ2CAzHmALvt)DKh_?GgbK`-d@jT>Bb@3_!KYF->!lYP>f+d=s_p*J-&)wcZ(LpRVN>k(X&w|T<9`HZz;?%m^A96OqYEkJxk1*Xgk4( zE-zaRJsLT;+>vTxo=laEZx+g5b0xK!XMfbu!qtoO=k*%t2OHCkC_*`VE z$xSa~wCqaAw9XYTXX}G)VtqxkPE-8OV@+WdxYDwtITyDRIJg8G8z>YbNzWXe0;}Hh zE}{8euXGi@;+70!`X$QqUF)jE64geM)~*f}6IQ=c3P^$LJPUmFTAl;snq(bPjH8&i)hOY`GF z#S_;C>>J>#jCAJe~UWF;Q1*zwv%y-;>_ z$Wd>lojZ41?=DtrG*3sAQ9@=W^OcqGB>chUiind+<&g_H?M-(o&Na7nRop!-T~K8I zj%xW)Sf_ER$>_ZveTV6S@__E)wEVnhKwAJ8P=AzKX-a;@=+URkRG^lUHnp9~ob2%ztj6H@i9}8k1i3Laa}% zFtCt?P&}MOv+KwNuA#O>hbhH=^E=lsu3rLlF=`rr9wL5vJ}EH3o{e|*%CNXoQ(Ti~ zEB#td<$zJtX(I*7@OVh)vWVi4KtP`y{quR0j~)l6b$_S}@JIi7fj2$|ABTMBw~x7<6Jz2H!v=3o zs@f<$#c8%oX3xwKid!qIAvE^*bcXlW>);3j$jsc?Pw`^qiEi_1*JXSijlMN+CjgPn zsX9vKq}O`2_Fa>ZS!WMORn4~Ffy&e`9ETZ_(j{iM*M1phB0@=&MHGZkA2rz$^MZ@^IIcJySUCwxWubYxJV0S-q%(Q zKbV=S4qU!wE$z=+jwzlux3hx1%Hq&0upbbmH?#v z<;I&fYf$fIkru4*amWHyzxlU=V$BM{WwylgvEKP1E>{PR-50jr`9q=n_ls%WIlq#< zEJqqb=$ms5&Uw^w8K93pz=FI`CIut;4WbcJ+( zvxSX`{f-~}cgVA0Y;uV96Lz0H6Wwpthm03ej{j}kzS|~}P0M@MhDB5kf3aJ*VxxNc zpH~t9B>?C~J-**OwvD91_f+VAT*;;bjS_Z9garO#s^4$_qwxD56IFi)GL||YEC~Pc zH|Y5H^yDuI4dfPZoE9W|dHVU7{=;_QkpTtqpO4Ol0=+JRZeZez-`y}|@_uAi|6|aw e|Jx^Vaot6o?`CY_#hFd;Pg&vInF7pZ|NjH>23hF< 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 313431c..ff883bc 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -2,7 +2,6 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; import ru.yandex.practicum.filmorate.model.Film; @@ -10,7 +9,6 @@ import java.util.List; -@Slf4j @RestController @RequestMapping("/films") @RequiredArgsConstructor @@ -18,7 +16,6 @@ public class FilmController { private final FilmService filmService; - // добавляем фильм @ResponseStatus(HttpStatus.CREATED) @PostMapping public Film create(@RequestBody @Valid Film film) { @@ -26,33 +23,28 @@ public Film create(@RequestBody @Valid Film film) { return film; } - // обновляем данные о фильме @PutMapping public Film update(@RequestBody @Valid Film film) { filmService.update(film); return film; } - // получаем список фильмов @GetMapping public List findAll() { return filmService.findAll(); } - // Получаем фильм по id @GetMapping("/{filmId}") public Film getFilmById(@PathVariable Integer filmId) { return filmService.getById(filmId); } - // Добавляем like пользователя userId к фильму filmId @PutMapping("/{filmId}/like/{userId}") public Film addLike(@PathVariable Integer filmId, @PathVariable Integer userId) { filmService.addLike(filmId, userId); return filmService.getById(filmId); } - // Удаляем like пользователя userId к фильму filmId @DeleteMapping("/{filmId}/like/{userId}") public Film deleteLike(@PathVariable Integer filmId, @PathVariable Integer userId) { filmService.deleteLike(filmId, userId); @@ -63,5 +55,4 @@ public Film deleteLike(@PathVariable Integer filmId, @PathVariable Integer userI public List getListBestFilms(@RequestParam(defaultValue = "10") Integer count) { return filmService.listBestFilms(count); } - } diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java index 51bda0f..faf8ec4 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/GenreController.java @@ -1,27 +1,23 @@ package ru.yandex.practicum.filmorate.controller; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; import ru.yandex.practicum.filmorate.model.Genre; import ru.yandex.practicum.filmorate.service.GenreService; import java.util.List; -@Slf4j @RestController @RequestMapping("/genres") @RequiredArgsConstructor public class GenreController { private final GenreService genreService; - // получаем список жанров @GetMapping public List findAll() { return genreService.findAll(); } - // Получаем жанр по id @GetMapping("/{id}") public Genre getById(@PathVariable Integer id) { return genreService.getById(id); diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/RatingController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/RatingController.java index c9d3119..7e4f481 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/RatingController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/RatingController.java @@ -1,7 +1,6 @@ package ru.yandex.practicum.filmorate.controller; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -11,20 +10,17 @@ import java.util.List; -@Slf4j @RestController @RequestMapping("/mpa") @RequiredArgsConstructor public class RatingController { private final RatingService ratingService; - // получаем список рейтингов @GetMapping public List findAll() { return ratingService.findAll(); } - // Получаем рейтинг по id @GetMapping("/{id}") public Rating getById(@PathVariable Integer id) { return ratingService.getById(id); 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 e63da94..97e15f3 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/UserController.java @@ -2,7 +2,6 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; import ru.yandex.practicum.filmorate.model.User; @@ -10,7 +9,6 @@ import java.util.List; -@Slf4j @RestController @RequestMapping("/users") @RequiredArgsConstructor @@ -18,7 +16,6 @@ public class UserController { private final UserService userService; - // Добавляем пользователя @ResponseStatus(HttpStatus.CREATED) @PostMapping public User create(@RequestBody @Valid User user) { @@ -26,46 +23,39 @@ public User create(@RequestBody @Valid User user) { return user; } - // Обновляем данные пользователя @PutMapping public User update(@RequestBody @Valid User user) { userService.update(user); return user; } - // Получаем список всех пользователей @GetMapping public List findAll() { return userService.findAll(); } - // Получаем пользователя по id @GetMapping("/{userId}") public User getUserById(@PathVariable Integer userId) { return userService.getById(userId); } - // Добавляем друга friendId для пользователя userId @PutMapping("/{userId}/friends/{friendId}") public User addFriend(@PathVariable Integer userId, @PathVariable Integer friendId) { userService.addFriend(userId, friendId); return userService.getById(userId); } - // Удаляем друга friendId у пользователя userId @DeleteMapping("/{userId}/friends/{friendId}") public User deleteFriend(@PathVariable Integer userId, @PathVariable Integer friendId) { userService.deleteFriend(userId, friendId); return userService.getById(userId); } - // Получаем список друзей пользователя userId @GetMapping("/{userId}/friends") public List getUserFriends(@PathVariable Integer userId) { return userService.userFriends(userId); } - // Получаем общий список друзей пользователя userId и и пользователя otherUserId @GetMapping("/{userId}/friends/common/{otherUserId}") public List getCrossingFriends(@PathVariable Integer userId, @PathVariable Integer otherUserId) { return userService.crossingFriends(userId, otherUserId); 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 3ba3aec..9b069ff 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Film.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Film.java @@ -5,14 +5,12 @@ import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import lombok.Data; -import lombok.extern.slf4j.Slf4j; import java.sql.Date; import java.util.ArrayList; import java.util.List; @Data -@Slf4j public class Film { private Integer id; diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Genre.java b/src/main/java/ru/yandex/practicum/filmorate/model/Genre.java index 64dfb12..e40c936 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Genre.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Genre.java @@ -1,10 +1,8 @@ package ru.yandex.practicum.filmorate.model; import lombok.Data; -import lombok.extern.slf4j.Slf4j; @Data -@Slf4j public class Genre { private Integer id; private String name; diff --git a/src/main/java/ru/yandex/practicum/filmorate/model/Rating.java b/src/main/java/ru/yandex/practicum/filmorate/model/Rating.java index 421ad1d..b47d472 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/Rating.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/Rating.java @@ -1,10 +1,8 @@ package ru.yandex.practicum.filmorate.model; import lombok.Data; -import lombok.extern.slf4j.Slf4j; @Data -@Slf4j public class Rating { private Integer id; 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 ebfde78..7c05712 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/model/User.java +++ b/src/main/java/ru/yandex/practicum/filmorate/model/User.java @@ -2,14 +2,12 @@ import jakarta.validation.constraints.*; import lombok.Data; -import lombok.extern.slf4j.Slf4j; import java.sql.Date; import java.util.ArrayList; import java.util.List; @Data -@Slf4j public class User { private Integer id; 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 3587427..190cbdf 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/FilmService.java @@ -22,42 +22,45 @@ public class FilmService { private final LikeDbStorage likeStorage; public Film create(Film film) { + log.info("create film with id: {}", film.getId()); return filmStorage.create(film); } public Film update(Film film) { + log.info("update film with id: {}", film.getId()); return filmStorage.update(film); } public Film getById(Integer id) { + log.info("get film by id: {}", id); return filmStorage.getById(id); } public List findAll() { + log.info("get all films"); return filmStorage.findAll(); } - // Ставим лайк фильму public void addLike(Integer idFilm, Integer idUser) { checkForLike(idFilm, idUser); + log.info("add like film with id: {} and user with id: {}", idFilm, idUser); likeStorage.addLike(idFilm, idUser); } - // Убираем лайк фильму public void deleteLike(Integer idFilm, Integer idUser) { checkForLike(idFilm, idUser); + log.info("delete like film with id: {} and user with id: {}", idFilm, idUser); likeStorage.deleteLike(idFilm, idUser); } - // Получаем список лучших фильмов public List listBestFilms(int count) { + log.info("list best films"); return filmStorage.findAll().stream() .sorted((f1, f2) -> f2.getLikes().size() - f1.getLikes().size()) .limit(count) .collect(Collectors.toList()); } - // проверка условий для установки и удаления лайка private void checkForLike(Integer idFilm, Integer idUser) { if (idFilm == null) { throw new ValidationException("Не указан id фильма"); diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/GenreService.java b/src/main/java/ru/yandex/practicum/filmorate/service/GenreService.java index 2a171be..4a3418a 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/GenreService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/GenreService.java @@ -15,10 +15,12 @@ public class GenreService { private final GenreDbStorage genreStorage; public Genre getById(Integer id) { + log.info("get genre by id: {}", id); return genreStorage.getById(id); } public List findAll() { + log.info("get all genres"); return genreStorage.findAll(); } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/RatingService.java b/src/main/java/ru/yandex/practicum/filmorate/service/RatingService.java index a18956a..50c64b4 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/RatingService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/RatingService.java @@ -15,10 +15,12 @@ public class RatingService { private final RatingDbStorage ratingStorage; public Rating getById(Integer id) { + log.info("get rating by id: {}", id); return ratingStorage.getById(id); } public List findAll() { + log.info("get all ratings"); return ratingStorage.findAll(); } } \ No newline at end of file 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 935cb81..734dde4 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/UserService.java @@ -22,56 +22,59 @@ public class UserService { private final FriendDbStorage friendStorage; public User create(User user) { + log.info("create user with id: {}", user.getId()); return userStorage.create(user); } public User update(User user) { + log.info("update user with id: {}", user.getId()); return userStorage.update(user); } public User getById(Integer id) { + log.info("get user by id: {}", id); return userStorage.getById(id); } public List findAll() { + log.info("get all users"); return userStorage.findAll(); } - // Добавляем друга в список друзей public void addFriend(Integer idUser, Integer idFriend) { if (idUser.equals(idFriend)) { throw new ValidationException("Нельзя добавить себя в друзья"); } checkForFriend(idUser, idFriend); + log.info("add friend with idUser: {}, idFriend: {}", idUser, idFriend); friendStorage.addFriend(idUser, idFriend); } - // Удаляем друга из списка друзей public void deleteFriend(Integer idUser, Integer idFriend) { checkForFriend(idUser, idFriend); + log.info("delete friend with idUser: {}, idFriend: {}", idUser, idFriend); friendStorage.deleteFriend(idUser, idFriend); } - // Получаем список друзей public List userFriends(Integer idUser) { if (userStorage.getById(idUser) == null) { throw new NotFoundException("Пользователь с id = " + idUser + " не найден"); } + log.info("get user friends with idUser: {}", idUser); return userStorage.getFriends(idUser); } - // Получаем общий список друзей public List crossingFriends(Integer idUser, Integer idFriend) { User user = userStorage.getById(idUser); User friend = userStorage.getById(idFriend); Set commonFriends = new HashSet<>(user.getFriends()); commonFriends.retainAll(friend.getFriends()); + log.info("get common friends with idUser: {}, idFriend: {}", idUser, idFriend); return userStorage.findAll().stream() .filter(u -> commonFriends.contains(u.getId())) .collect(Collectors.toList()); } - // Проверка для установки или удаления друзей private void checkForFriend(Integer idUser, Integer idFriend) { if (idUser == null || idFriend == null) { throw new ValidationException("Не указаны id пользователя или его друга"); diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDbStorage.java index da7d9b9..5fa6b3c 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDbStorage.java @@ -17,6 +17,7 @@ import java.sql.PreparedStatement; import java.sql.Statement; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; @Slf4j @@ -27,7 +28,6 @@ public class FilmDbStorage implements FilmStorage { private final JdbcTemplate jdbc; private final FilmRowMapper filmRowMapper; - // Добавление фильма @Override public Film create(Film film) { List ratings = jdbc.queryForList("SELECT id FROM mpa", Integer.class); @@ -38,9 +38,9 @@ public Film create(Film film) { } List notFoundGenres = film.getGenres().stream() - .filter(genre -> !genres.contains(genre.getId())) .map(Genre::getId) - .collect(Collectors.toList()); + .filter(id -> !genres.contains(id)) + .toList(); if (!notFoundGenres.isEmpty()) { throw new NotFoundException("Жанры с id " + notFoundGenres + " не найдены"); @@ -58,7 +58,7 @@ public Film create(Film film) { ps.setObject(5, film.getMpa().getId()); return ps; }, keyHolder); - film.setId(keyHolder.getKey().intValue()); + film.setId(Objects.requireNonNull(keyHolder.getKey()).intValue()); for (Genre genre : film.getGenres()) { try { jdbc.update("INSERT INTO film_genres (film_id, genre_id) VALUES (?, ?)", @@ -70,7 +70,6 @@ public Film create(Film film) { return film; } - // Обновление фильма @Override public Film update(Film film) { int count = jdbc.update("UPDATE films SET name = ?, description = ?, duration = ?, release_date = ?, mpa = ? WHERE id = ?", @@ -90,17 +89,11 @@ public Film update(Film film) { return film; } - // Выборка всех фильмов @Override public List findAll() { - try { - return jdbc.query("SELECT * FROM films", filmRowMapper); - } catch (EmptyResultDataAccessException e) { - throw new NotFoundException("Список фильмов пуст"); - } + return jdbc.query("SELECT * FROM films", filmRowMapper); } - // Получение фильма по id @Override public Film getById(Integer id) { try { diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/FriendDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/FriendDbStorage.java index a1d9754..2cdf657 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/FriendDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/FriendDbStorage.java @@ -16,7 +16,6 @@ public class FriendDbStorage { private final JdbcTemplate jdbc; - // Отправка заявки на добавление в друзья public void addFriend(Integer userId, Integer friendId) { try { jdbc.update("INSERT INTO friends (user_id, friend_id) VALUES (?, ?)", userId, friendId); @@ -25,12 +24,10 @@ public void addFriend(Integer userId, Integer friendId) { } } - // отзыв заявки на дружбу public void deleteFriend(Integer userId, Integer friendId) { jdbc.update("DELETE FROM friends WHERE user_id = ? AND friend_id = ?", userId, friendId); } - // Получение id всех друзей по id пользователя public List getFriends(Integer userId) { return jdbc.queryForList("SELECT friend_id FROM friends WHERE user_id = ?", Integer.class, userId); diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/GenreDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/GenreDbStorage.java index b442647..f0504ab 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/GenreDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/GenreDbStorage.java @@ -1,7 +1,6 @@ package ru.yandex.practicum.filmorate.storage; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Primary; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; @@ -12,7 +11,6 @@ import java.util.List; -@Slf4j @Primary @Repository @RequiredArgsConstructor @@ -20,16 +18,10 @@ public class GenreDbStorage { private final JdbcTemplate jdbc; private final GenreRowMapper genreRowMapper; - // Получение всех жанров public List findAll() { - try { - return jdbc.query("SELECT * FROM genres", genreRowMapper); - } catch (EmptyResultDataAccessException e) { - throw new NotFoundException("Список жанров пуст"); - } + return jdbc.query("SELECT * FROM genres", genreRowMapper); } - // Получение жанра по id public Genre getById(Integer id) { try { return jdbc.queryForObject("SELECT * FROM genres WHERE id = ?", genreRowMapper, id); @@ -38,13 +30,8 @@ public Genre getById(Integer id) { } } - // Получение жанров по id фильма public List getByFilmId(Integer filmId) { - try { - return jdbc.query("SELECT * FROM genres WHERE id IN (SELECT genre_id FROM film_genres WHERE film_id = ?)", + return jdbc.query("SELECT * FROM genres WHERE id IN (SELECT genre_id FROM film_genres WHERE film_id = ?)", genreRowMapper, filmId); - } catch (EmptyResultDataAccessException e) { - throw new NotFoundException("Жанры для фильма с id " + filmId + " не найдены"); - } } } diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/LikeDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/LikeDbStorage.java index bd02fc2..608ef87 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/LikeDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/LikeDbStorage.java @@ -16,7 +16,6 @@ public class LikeDbStorage { private final JdbcTemplate jdbc; - // Ставим лайк фильму public void addLike(Integer filmId, Integer userId) { try { jdbc.update("INSERT INTO likes (film_id, user_id) VALUES (?, ?)", filmId, userId); @@ -25,12 +24,10 @@ public void addLike(Integer filmId, Integer userId) { } } - // Удаляем лайк фильма public void deleteLike(Integer filmId, Integer userId) { jdbc.update("DELETE FROM likes WHERE film_id = ? AND user_id = ?", filmId, userId); } - // Получаем список id пользователей, которые лайкнули фильм public List getLikes(Integer filmId) { return jdbc.queryForList("SELECT user_id FROM likes WHERE film_id = ?", Integer.class, filmId); diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/RatingDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/RatingDbStorage.java index ed13937..a8af3b4 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/RatingDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/RatingDbStorage.java @@ -21,11 +21,7 @@ public class RatingDbStorage { private final RatingRowMapper ratingRowMapper; public List findAll() { - try { - return jdbc.query("SELECT * FROM mpa", ratingRowMapper); - } catch (EmptyResultDataAccessException e) { - throw new NotFoundException("Список жанров пуст"); - } + return jdbc.query("SELECT * FROM mpa", ratingRowMapper); } public Rating getById(Integer id) { @@ -35,7 +31,4 @@ public Rating getById(Integer id) { throw new NotFoundException("Рейтинг с id " + id + " не найден"); } } - - - } \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/UserDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/UserDbStorage.java index 5ac3763..7ccfd21 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/UserDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/UserDbStorage.java @@ -1,7 +1,6 @@ package ru.yandex.practicum.filmorate.storage; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Primary; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; @@ -15,8 +14,8 @@ import java.sql.PreparedStatement; import java.sql.Statement; import java.util.List; +import java.util.Objects; -@Slf4j @Primary @Repository @RequiredArgsConstructor @@ -37,7 +36,7 @@ public User create(User user) { ps.setDate(4, user.getBirthday()); return ps; }, keyHolder); - user.setId(keyHolder.getKey().intValue()); + user.setId(Objects.requireNonNull(keyHolder.getKey()).intValue()); return user; } @@ -53,11 +52,7 @@ public User update(User user) { @Override public List findAll() { - try { - return jdbc.query("SELECT * FROM users", userRowMapper); - } catch (EmptyResultDataAccessException e) { - throw new NotFoundException("Список пользователей пуст"); - } + return jdbc.query("SELECT * FROM users", userRowMapper); } @Override diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/FilmRowMapper.java b/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/FilmRowMapper.java index 719c1b3..32abdd7 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/FilmRowMapper.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/FilmRowMapper.java @@ -1,7 +1,6 @@ package ru.yandex.practicum.filmorate.storage.dbmapper; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Component; import ru.yandex.practicum.filmorate.model.Film; @@ -12,7 +11,6 @@ import java.sql.ResultSet; import java.sql.SQLException; -@Slf4j @Component @RequiredArgsConstructor public class FilmRowMapper implements RowMapper { @@ -20,7 +18,6 @@ public class FilmRowMapper implements RowMapper { private final LikeDbStorage likeDbStorage; private final GenreDbStorage genreDbStorage; - // Маппер для Film @Override public Film mapRow(ResultSet resultSet, int rowNum) throws SQLException { Film film = new Film(); diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/GenreRowMapper.java b/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/GenreRowMapper.java index a69ab1e..6947168 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/GenreRowMapper.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/GenreRowMapper.java @@ -1,6 +1,5 @@ package ru.yandex.practicum.filmorate.storage.dbmapper; -import lombok.extern.slf4j.Slf4j; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Component; import ru.yandex.practicum.filmorate.model.Genre; @@ -8,11 +7,9 @@ import java.sql.ResultSet; import java.sql.SQLException; -@Slf4j @Component public class GenreRowMapper implements RowMapper { - // Маппер для Genre @Override public Genre mapRow(ResultSet resultSet, int rowNum) throws SQLException { Genre genre = new Genre(); diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/RatingRowMapper.java b/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/RatingRowMapper.java index 727a1f2..09bd489 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/RatingRowMapper.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/RatingRowMapper.java @@ -1,6 +1,5 @@ package ru.yandex.practicum.filmorate.storage.dbmapper; -import lombok.extern.slf4j.Slf4j; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Component; import ru.yandex.practicum.filmorate.model.Rating; @@ -8,11 +7,9 @@ import java.sql.ResultSet; import java.sql.SQLException; -@Slf4j @Component public class RatingRowMapper implements RowMapper { - // Маппер для Rating @Override public Rating mapRow(ResultSet resultSet, int rowNum) throws SQLException { Rating rating = new Rating(); diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/UserRowMapper.java b/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/UserRowMapper.java index 124679a..c622d66 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/UserRowMapper.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/dbmapper/UserRowMapper.java @@ -1,7 +1,6 @@ package ru.yandex.practicum.filmorate.storage.dbmapper; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Component; import ru.yandex.practicum.filmorate.model.User; @@ -10,13 +9,11 @@ import java.sql.ResultSet; import java.sql.SQLException; -@Slf4j @Component @RequiredArgsConstructor public class UserRowMapper implements RowMapper { private final FriendDbStorage friendDbStorage; - // Маппер для User @Override public User mapRow(ResultSet resultSet, int rowNum) throws SQLException { User user = new User(); From 29adde641a0a355817c87bd3578f5c12d3daf214 Mon Sep 17 00:00:00 2001 From: Sergey Filippovskikh Date: Tue, 18 Feb 2025 10:08:23 +0300 Subject: [PATCH 17/17] =?UTF-8?q?=D0=A1=D0=BF=D1=80=D0=B8=D0=BD=D1=82=2012?= =?UTF-8?q?.=20=D0=A0=D0=B5=D0=B9=D1=82=D0=B8=D0=BD=D0=B3=20=D0=A4=D0=B8?= =?UTF-8?q?=D0=BB=D1=8C=D0=BC=D0=BE=D0=B2.=20=D0=9F=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B2=D0=BE=D0=B4=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B2=20=D0=B1?= =?UTF-8?q?=D0=B0=D0=B7=D0=B5=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20H2.?= =?UTF-8?q?=20=D0=9A=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D0=BF=D0=BE=20=D0=B7=D0=B0=D0=BC=D0=B5?= =?UTF-8?q?=D1=87=D0=B0=D0=BD=D0=B8=D1=8F=D0=BC=20=D1=80=D0=B5=D0=B2=D1=8C?= =?UTF-8?q?=D1=8E=D0=B2=D0=B5=D1=80=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ru/yandex/practicum/filmorate/storage/FilmDbStorage.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDbStorage.java index 5fa6b3c..67bdf64 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/FilmDbStorage.java @@ -18,7 +18,6 @@ import java.sql.Statement; import java.util.List; import java.util.Objects; -import java.util.stream.Collectors; @Slf4j @Primary