Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@

@SpringBootApplication
public class FilmorateApplication {
public static void main(String[] args) {
SpringApplication.run(FilmorateApplication.class, args);
}

public static void main(String[] args) {
SpringApplication.run(FilmorateApplication.class, args);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,66 @@

import org.springframework.web.bind.annotation.RestController;

import ru.yandex.practicum.filmorate.exception.ValidationException;
import lombok.extern.slf4j.Slf4j;
import ru.yandex.practicum.filmorate.model.Film;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/films")
@Slf4j
public class FilmController {
private final Map<Long, Film> films = new HashMap<>();
private Long idCounter = 1L;

private void validateFilm(Film film) {
if (film.getName() == null || film.getName().isBlank()) {
log.warn("Название фильма не может быть пустым");
throw new ValidationException("Название фильма не может быть пустым");
}
if (film.getDescription() != null && film.getDescription().length() > 200) {
log.warn("Максимальная длина описания — 200 символов");
throw new ValidationException("Максимальная длина описания — 200 символов");
}
if (film.getReleaseDate() == null || film.getReleaseDate().isBefore(LocalDate.of(1895, 12, 28))) {
log.warn("Дата релиза должна быть не раньше 28 декабря 1895 года");
throw new ValidationException("Дата релиза должна быть не раньше 28 декабря 1895 года");
}
if (film.getDuration() <= 0) {
log.warn("Продолжительность фильма должна быть положительным числом");
throw new ValidationException("Продолжительность фильма должна быть положительным числом");
}
}

@PostMapping
public Film addFilm(@RequestBody Film film) {
validateFilm(film);
film.setId(idCounter++);
films.put(film.getId(), film);
log.info("Добавлен фильм с ID {}: {}", film.getId(), film);
return film;
}

@PutMapping
public Film updateFilm(@RequestBody Film film) {
if (film.getId() == null || !films.containsKey(film.getId())) {
log.warn("Фильм с ID {} не найден", film.getId());
throw new ValidationException("Фильм с указанным ID не существует");
}
validateFilm(film);
films.put(film.getId(), film);
log.info("Обновлен фильм с ID {}: {}", film.getId(), film);
return film;
}

@GetMapping
public List<Film> getAllFilms() {
log.info("Получен запрос всех фильмов. Текущее количество: {}", films.size());
return new ArrayList<>(films.values());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package ru.yandex.practicum.filmorate.controller;

import lombok.extern.slf4j.Slf4j;
import ru.yandex.practicum.filmorate.exception.ValidationException;
import ru.yandex.practicum.filmorate.model.User;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/users")
@Slf4j
public class UserController {
private final Map<Long, User> users = new HashMap<>();
private Long idCounter = 1L;

private void validateUser(User user) {
if (user.getEmail() == null || user.getEmail().isBlank() || !user.getEmail().contains("@")) {
log.warn("Электронная почта не может быть пустой и должна содержать символ @");
throw new ValidationException("Электронная почта не может быть пустой и должна содержать символ @");
}
if (user.getLogin() == null || user.getLogin().isBlank() || user.getLogin().contains(" ")) {
log.warn("Логин не может быть пустым и содержать пробелы");
throw new ValidationException("Логин не может быть пустым и содержать пробелы");
}
if (user.getName() == null || user.getName().isBlank()) {
user.setName(user.getLogin());
log.info("Для пользователя {} установлено имя из логина", user.getLogin());
}
if (user.getBirthday() == null || user.getBirthday().isAfter(LocalDate.now())) {
log.warn("Дата рождения не может быть в будущем");
throw new ValidationException("Дата рождения не может быть в будущем");
}
}

@PostMapping
public User createUser(@RequestBody User user) {
validateUser(user);
user.setId(idCounter++);
users.put(user.getId(), user);
log.info("Создан пользователь: {}", user);
return user;
}

@PutMapping
public User updateUser(@RequestBody User user) {
if (user.getId() == null || !users.containsKey(user.getId())) {
log.warn("Пользователь с id {} не найден", user.getId());
throw new ValidationException("Пользователь с указанным id не существует");
}
validateUser(user);
users.put(user.getId(), user);
log.info("Обновлен пользователь: {}", user);
return user;
}

@GetMapping
public List<User> getAllUsers() {
log.info("Получен запрос всех пользователей. Текущее количество: {}", users.size());
return new ArrayList<>(users.values());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ru.yandex.practicum.filmorate.exception;

public class ValidationException extends RuntimeException {
public ValidationException(String message) {
super(message);
}
}
16 changes: 9 additions & 7 deletions src/main/java/ru/yandex/practicum/filmorate/model/Film.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package ru.yandex.practicum.filmorate.model;

import lombok.Getter;
import lombok.Setter;

/**
* Film.
*/
@Getter
@Setter
import lombok.Data;
import java.time.LocalDate;

@Data
public class Film {
private Long id;
private String name;
private String description;
private LocalDate releaseDate;
private int duration;
}
13 changes: 13 additions & 0 deletions src/main/java/ru/yandex/practicum/filmorate/model/User.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ru.yandex.practicum.filmorate.model;

import lombok.Data;
import java.time.LocalDate;

@Data
public class User {
private Long id;
private String email;
private String login;
private String name;
private LocalDate birthday;
}
56 changes: 56 additions & 0 deletions src/test/java/ru/yandex/practicum/filmorate/BoundaryTests.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package ru.yandex.practicum.filmorate;

import ru.yandex.practicum.filmorate.controller.FilmController;
import ru.yandex.practicum.filmorate.controller.UserController;
import ru.yandex.practicum.filmorate.model.Film;
import ru.yandex.practicum.filmorate.model.User;
import org.junit.jupiter.api.Test;
import java.time.LocalDate;
import static org.junit.jupiter.api.Assertions.*;

class BoundaryTests {
private FilmController filmController = new FilmController();
private UserController userController = new UserController();

@Test
void filmValidation_BoundaryValues() {
// Проверка минимально допустимой даты релиза
Film film1 = new Film();
film1.setName("Boundary Film");
film1.setDescription("Desc");
film1.setReleaseDate(LocalDate.of(1895, 12, 28));
film1.setDuration(1);
assertDoesNotThrow(() -> filmController.addFilm(film1));

// Проверка максимальной длины описания
Film film2 = new Film();
film2.setName("Boundary Film");
film2.setDescription("a".repeat(200));
film2.setReleaseDate(LocalDate.of(2000, 1, 1));
film2.setDuration(1);
assertDoesNotThrow(() -> filmController.addFilm(film2));
}

@Test
void userValidation_BoundaryValues() {
// Проверка сегодняшней даты рождения
User user1 = new User();
user1.setEmail("test@example.com");
user1.setLogin("testlogin");
user1.setBirthday(LocalDate.now());
assertDoesNotThrow(() -> userController.createUser(user1));

// Проверка минимально допустимого логина
User user2 = new User();
user2.setEmail("test@example.com");
user2.setLogin("a"); // Минимальный логин
user2.setBirthday(LocalDate.of(1990, 1, 1));
assertDoesNotThrow(() -> userController.createUser(user2));
}

@Test
void nullRequest_ThrowsException() {
assertThrows(Exception.class, () -> filmController.addFilm(null));
assertThrows(Exception.class, () -> userController.createUser(null));
}
}
113 changes: 113 additions & 0 deletions src/test/java/ru/yandex/practicum/filmorate/FilmControllerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package ru.yandex.practicum.filmorate;

import ru.yandex.practicum.filmorate.controller.FilmController;
import ru.yandex.practicum.filmorate.exception.ValidationException;
import ru.yandex.practicum.filmorate.model.Film;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.time.LocalDate;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;

class FilmControllerTest {
private FilmController filmController;

@BeforeEach
void setUp() {
filmController = new FilmController();
}

@Test
void addFilm_ValidFilm_ReturnsFilmWithId() {
Film film = new Film();
film.setName("Valid Film");
film.setDescription("Valid description");
film.setReleaseDate(LocalDate.of(2000, 1, 1));
film.setDuration(120);

Film result = filmController.addFilm(film);

assertNotNull(result.getId());
assertEquals(film.getName(), result.getName());
}

@Test
void addFilm_EmptyName_ThrowsValidationException() {
Film film = new Film();
film.setName("");
film.setDescription("Valid description");
film.setReleaseDate(LocalDate.of(2000, 1, 1));
film.setDuration(120);

assertThrows(ValidationException.class, () -> filmController.addFilm(film));
}

@Test
void addFilm_TooLongDescription_ThrowsValidationException() {
Film film = new Film();
film.setName("Valid Film");
film.setDescription("a".repeat(201));
film.setReleaseDate(LocalDate.of(2000, 1, 1));
film.setDuration(120);

assertThrows(ValidationException.class, () -> filmController.addFilm(film));
}

@Test
void addFilm_TooEarlyReleaseDate_ThrowsValidationException() {
Film film = new Film();
film.setName("Valid Film");
film.setDescription("Valid description");
film.setReleaseDate(LocalDate.of(1895, 12, 27));
film.setDuration(120);

assertThrows(ValidationException.class, () -> filmController.addFilm(film));
}

@Test
void addFilm_NegativeDuration_ThrowsValidationException() {
Film film = new Film();
film.setName("Valid Film");
film.setDescription("Valid description");
film.setReleaseDate(LocalDate.of(2000, 1, 1));
film.setDuration(-1);

assertThrows(ValidationException.class, () -> filmController.addFilm(film));
}

@Test
void updateFilm_NonExistingId_ThrowsValidationException() {
Film film = new Film();
film.setId(999L);
film.setName("Valid Film");
film.setDescription("Valid description");
film.setReleaseDate(LocalDate.of(2000, 1, 1));
film.setDuration(120);

assertThrows(ValidationException.class, () -> filmController.updateFilm(film));
}

@Test
void getAllFilms_EmptyList_ReturnsEmptyList() {
List<Film> films = filmController.getAllFilms();
assertTrue(films.isEmpty());
}

@Test
void getAllFilms_WithFilms_ReturnsAllFilms() {
Film film1 = new Film();
film1.setName("Film 1");
film1.setReleaseDate(LocalDate.of(2000, 1, 1));
film1.setDuration(120);
filmController.addFilm(film1);

Film film2 = new Film();
film2.setName("Film 2");
film2.setReleaseDate(LocalDate.of(2001, 1, 1));
film2.setDuration(90);
filmController.addFilm(film2);

List<Film> films = filmController.getAllFilms();
assertEquals(2, films.size());
}
}
Loading
Loading