From ec39ed93d2af47cf399b2254226e5b97328495e5 Mon Sep 17 00:00:00 2001 From: aKorishev Date: Mon, 18 Nov 2024 18:43:06 +0300 Subject: [PATCH 01/11] =?UTF-8?q?[add-item-requests-and-gateway]=20=D0=94?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BB=D0=BE=D0=B3=D0=B8?= =?UTF-8?q?=D0=BA=D1=83=20Request...=20=D0=A0=D0=B5=D1=84=D0=B0=D0=BA?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20=D0=BC=D0=B0=D0=BF=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=BE=D0=B2=20=D0=BD=D0=B0=20static=20=D0=BC=D0=B5?= =?UTF-8?q?=D1=82=D0=BE=D0=B4=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shareit/booking/BookingMapper.java | 6 +- .../shareit/booking/BookingService.java | 35 ++++++------ .../item/{storage => }/CommentMapper.java | 8 ++- .../ru/practicum/shareit/item/ItemMapper.java | 12 ++-- .../practicum/shareit/item/ItemService.java | 27 ++++----- .../shareit/item/storage/ItemStorageInDb.java | 1 + .../shareit/request/AnswerMapper.java | 18 ++++++ .../shareit/request/ItemRequest.java | 7 --- .../request/ItemRequestController.java | 12 ---- .../shareit/request/RequestController.java | 37 +++++++++++++ .../shareit/request/RequestMapper.java | 34 ++++++++++++ .../shareit/request/RequestService.java | 55 +++++++++++++++++++ .../shareit/request/RequestStorage.java | 14 +++++ .../shareit/request/dto/AnswerDto.java | 11 ++++ .../shareit/request/dto/ItemRequestDto.java | 12 ---- .../shareit/request/dto/RequestDto.java | 19 +++++++ .../shareit/request/storage/AnswerEntity.java | 27 +++++++++ .../request/storage/RequestEntity.java | 36 ++++++++++++ .../request/storage/RequestRepository.java | 11 ++++ .../request/storage/RequestStorageInDb.java | 35 ++++++++++++ .../ru/practicum/shareit/user/UserMapper.java | 4 +- .../practicum/shareit/user/UserService.java | 11 ++-- src/main/resources/schema.sql | 26 +++++++-- 23 files changed, 367 insertions(+), 91 deletions(-) rename src/main/java/ru/practicum/shareit/item/{storage => }/CommentMapper.java (69%) create mode 100644 src/main/java/ru/practicum/shareit/request/AnswerMapper.java delete mode 100644 src/main/java/ru/practicum/shareit/request/ItemRequest.java delete mode 100644 src/main/java/ru/practicum/shareit/request/ItemRequestController.java create mode 100644 src/main/java/ru/practicum/shareit/request/RequestController.java create mode 100644 src/main/java/ru/practicum/shareit/request/RequestMapper.java create mode 100644 src/main/java/ru/practicum/shareit/request/RequestService.java create mode 100644 src/main/java/ru/practicum/shareit/request/RequestStorage.java create mode 100644 src/main/java/ru/practicum/shareit/request/dto/AnswerDto.java delete mode 100644 src/main/java/ru/practicum/shareit/request/dto/ItemRequestDto.java create mode 100644 src/main/java/ru/practicum/shareit/request/dto/RequestDto.java create mode 100644 src/main/java/ru/practicum/shareit/request/storage/AnswerEntity.java create mode 100644 src/main/java/ru/practicum/shareit/request/storage/RequestEntity.java create mode 100644 src/main/java/ru/practicum/shareit/request/storage/RequestRepository.java create mode 100644 src/main/java/ru/practicum/shareit/request/storage/RequestStorageInDb.java diff --git a/src/main/java/ru/practicum/shareit/booking/BookingMapper.java b/src/main/java/ru/practicum/shareit/booking/BookingMapper.java index 7d59f31..b645522 100644 --- a/src/main/java/ru/practicum/shareit/booking/BookingMapper.java +++ b/src/main/java/ru/practicum/shareit/booking/BookingMapper.java @@ -12,9 +12,9 @@ import java.text.SimpleDateFormat; public class BookingMapper { - private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + private static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); - public BookingDto toDto(BookingEntity entity, UserDto userDto, ItemDto itemDto) { + public static BookingDto toDto(BookingEntity entity, UserDto userDto, ItemDto itemDto) { return BookingDto .builder() .id(entity.getId()) @@ -27,7 +27,7 @@ public BookingDto toDto(BookingEntity entity, UserDto userDto, ItemDto itemDto) .build(); } - public BookingEntity toEntity(BookingDto dto, UserEntity user, ItemEntity item) throws ParseException { + public static BookingEntity toEntity(BookingDto dto, UserEntity user, ItemEntity item) throws ParseException { var entity = new BookingEntity(); entity.setId(dto.id()); entity.setBooker(user); diff --git a/src/main/java/ru/practicum/shareit/booking/BookingService.java b/src/main/java/ru/practicum/shareit/booking/BookingService.java index e2bb74b..bfe9eb0 100644 --- a/src/main/java/ru/practicum/shareit/booking/BookingService.java +++ b/src/main/java/ru/practicum/shareit/booking/BookingService.java @@ -21,9 +21,6 @@ public class BookingService { private final ItemStorage itemStorage; private final UserStorage userStorage; private final BookingStorage bookingStorage; - private final BookingMapper bookingMapper = new BookingMapper(); - private final UserMapper userMapper = new UserMapper(); - private final ItemMapper itemMapper = new ItemMapper(); public BookingDto getBooking(long bookingId, long userId) { var userEntity = userStorage.getUser(userId) @@ -36,10 +33,10 @@ public BookingDto getBooking(long bookingId, long userId) { throw new NotValidException("Данные о бронировании может получить заказчик или владелец"); } - return bookingMapper.toDto( + return BookingMapper.toDto( bookingEntity, - userMapper.toDto(userEntity), - itemMapper.toDto(bookingEntity.getItem())); + UserMapper.toDto(userEntity), + ItemMapper.toDto(bookingEntity.getItem())); } public List getItemsForUserId(long userId) { @@ -60,10 +57,10 @@ public List getItemsForUserId(BookingStatusRequestDto state, long us return bookingEntities .stream() - .map(i -> bookingMapper.toDto( + .map(i -> BookingMapper.toDto( i, - userMapper.toDto(userEntity), - itemMapper.toDto(i.getItem()))) + UserMapper.toDto(userEntity), + ItemMapper.toDto(i.getItem()))) .toList(); } @@ -86,10 +83,10 @@ public List getItemsForItemOwnerId(BookingStatusRequestDto state, lo return bookingEntities .stream() - .map(i -> bookingMapper.toDto( + .map(i -> BookingMapper.toDto( i, - userMapper.toDto(i.getBooker()), - itemMapper.toDto(i.getItem()))) + UserMapper.toDto(i.getBooker()), + ItemMapper.toDto(i.getItem()))) .toList(); } @@ -104,15 +101,15 @@ public BookingDto createBooking(BookingDto bookingDto, long userId) { } try { - var bookingEntity = bookingMapper.toEntity(bookingDto, userEntity, itemEntity); + var bookingEntity = BookingMapper.toEntity(bookingDto, userEntity, itemEntity); bookingEntity.setStatus(BookingStatus.WAITING); bookingStorage.updateBooking(bookingEntity); - return bookingMapper.toDto( + return BookingMapper.toDto( bookingEntity, - userMapper.toDto(userEntity), - itemMapper.toDto(itemEntity)); + UserMapper.toDto(userEntity), + ItemMapper.toDto(itemEntity)); } catch (ParseException e) { throw new NotValidException("Произошла ошибка чтения данных"); } @@ -139,9 +136,9 @@ public BookingDto setBookingStatus(long id, boolean approved, long userId) { bookingStorage.updateBooking(bookingEntity); - return bookingMapper.toDto( + return BookingMapper.toDto( bookingEntity, - userMapper.toDto(bookingEntity.getBooker()), - itemMapper.toDto(itemEntity)); + UserMapper.toDto(bookingEntity.getBooker()), + ItemMapper.toDto(itemEntity)); } } diff --git a/src/main/java/ru/practicum/shareit/item/storage/CommentMapper.java b/src/main/java/ru/practicum/shareit/item/CommentMapper.java similarity index 69% rename from src/main/java/ru/practicum/shareit/item/storage/CommentMapper.java rename to src/main/java/ru/practicum/shareit/item/CommentMapper.java index 14ac1ba..ba5abe3 100644 --- a/src/main/java/ru/practicum/shareit/item/storage/CommentMapper.java +++ b/src/main/java/ru/practicum/shareit/item/CommentMapper.java @@ -1,10 +1,12 @@ -package ru.practicum.shareit.item.storage; +package ru.practicum.shareit.item; import ru.practicum.shareit.item.dto.CommentDto; +import ru.practicum.shareit.item.storage.CommentEntity; +import ru.practicum.shareit.item.storage.ItemEntity; import ru.practicum.shareit.user.storage.UserEntity; public class CommentMapper { - public CommentDto toDto( + public static CommentDto toDto( CommentEntity entity) { var build = CommentDto .builder() @@ -16,7 +18,7 @@ public CommentDto toDto( return build.build(); } - public CommentEntity toEntity(CommentDto dto, UserEntity userEntity, ItemEntity itemEntity) { + public static CommentEntity toEntity(CommentDto dto, UserEntity userEntity, ItemEntity itemEntity) { var entity = new CommentEntity(); entity.setId(dto.id()); entity.setText(dto.text()); diff --git a/src/main/java/ru/practicum/shareit/item/ItemMapper.java b/src/main/java/ru/practicum/shareit/item/ItemMapper.java index 320794c..8e74e81 100644 --- a/src/main/java/ru/practicum/shareit/item/ItemMapper.java +++ b/src/main/java/ru/practicum/shareit/item/ItemMapper.java @@ -12,7 +12,7 @@ import java.util.Optional; public class ItemMapper { - public ItemDto toDto(ItemWithDateOfBookings entity) { + public static ItemDto toDto(ItemWithDateOfBookings entity) { return toDto( entity.getItemEntity(), Optional.ofNullable(entity.getLastDateBooking()), @@ -20,7 +20,7 @@ public ItemDto toDto(ItemWithDateOfBookings entity) { List.of()); } - public ItemDto toDto(ItemWithDateOfBookings entity, List comments) { + public static ItemDto toDto(ItemWithDateOfBookings entity, List comments) { return toDto( entity.getItemEntity(), Optional.ofNullable(entity.getLastDateBooking()), @@ -28,15 +28,15 @@ public ItemDto toDto(ItemWithDateOfBookings entity, List comments) { comments); } - public ItemDto toDto(ItemEntity itemEntity) { + public static ItemDto toDto(ItemEntity itemEntity) { return toDto(itemEntity, Optional.empty(),Optional.empty(), List.of()); } - public ItemDto toDto(ItemEntity itemEntity, List comments) { + public static ItemDto toDto(ItemEntity itemEntity, List comments) { return toDto(itemEntity, Optional.empty(),Optional.empty(), comments); } - public ItemDto toDto( + public static ItemDto toDto( ItemEntity itemEntity, @NotNull Optional lastBooking, @NotNull Optional nextBooking, @@ -55,7 +55,7 @@ public ItemDto toDto( return build.build(); } - public ItemEntity toEntity(ItemDto itemDto, UserEntity userEntity) { + public static ItemEntity toEntity(ItemDto itemDto, UserEntity userEntity) { var entity = new ItemEntity(); entity.setId(itemDto.id()); entity.setOwner(userEntity); diff --git a/src/main/java/ru/practicum/shareit/item/ItemService.java b/src/main/java/ru/practicum/shareit/item/ItemService.java index cc9957b..80c68ce 100644 --- a/src/main/java/ru/practicum/shareit/item/ItemService.java +++ b/src/main/java/ru/practicum/shareit/item/ItemService.java @@ -9,7 +9,6 @@ import ru.practicum.shareit.item.dto.CommentDto; import ru.practicum.shareit.item.dto.ItemDto; import ru.practicum.shareit.item.dto.ItemToUpdateDto; -import ru.practicum.shareit.item.storage.CommentMapper; import ru.practicum.shareit.user.UserStorage; import java.sql.Timestamp; @@ -23,8 +22,6 @@ public class ItemService { private final ItemStorage itemStorage; private final UserStorage userStorage; private final BookingStorage bookingStorage; - private final ItemMapper itemMapper = new ItemMapper(); - private final CommentMapper commentMapper = new CommentMapper(); public ItemDto getItem(long itemId) { var itemEntity = itemStorage.getItem(itemId) @@ -32,21 +29,21 @@ public ItemDto getItem(long itemId) { var comments = itemEntity.getComments() .stream() - .map(commentMapper::toDto) + .map(CommentMapper::toDto) .toList(); - return itemMapper.toDto(itemEntity, comments); + return ItemMapper.toDto(itemEntity, comments); } public ItemDto createItem(ItemDto item, long userId) { var userEntity = userStorage.getUser(userId) .orElseThrow(() -> new NotFoundException("Пользователь не найден")); - var itemEntity = itemMapper.toEntity(item, userEntity); + var itemEntity = ItemMapper.toEntity(item, userEntity); itemStorage.updateItem(itemEntity); - return itemMapper.toDto(itemEntity); + return ItemMapper.toDto(itemEntity); } public ItemDto updateItem(ItemDto item, long userId) { @@ -59,11 +56,11 @@ public ItemDto updateItem(ItemDto item, long userId) { throw new NotFoundException("Вещь не доступна"); } - var itemEntity = itemMapper.toEntity(item, owner); + var itemEntity = ItemMapper.toEntity(item, owner); itemStorage.updateItem(itemEntity); - return itemMapper.toDto(itemEntity); + return ItemMapper.toDto(itemEntity); } public ItemDto updateItem(long itemId, ItemToUpdateDto item, long userId) { @@ -85,7 +82,7 @@ public ItemDto updateItem(long itemId, ItemToUpdateDto item, long userId) { itemStorage.updateItem(itemEntity); - return itemMapper.toDto(itemEntity); + return ItemMapper.toDto(itemEntity); } public ItemDto deleteItem(long itemId, long userId) { @@ -100,7 +97,7 @@ public ItemDto deleteItem(long itemId, long userId) { itemStorage.deleteItem(itemId); - return itemMapper.toDto(itemEntityOld); + return ItemMapper.toDto(itemEntityOld); } public List getItems(long userId) { @@ -111,7 +108,7 @@ public List getItems(long userId) { return itemEntities .stream() - .map(itemMapper::toDto) + .map(ItemMapper::toDto) .toList(); } @@ -123,7 +120,7 @@ public List findFreeItemsByText(String text, boolean available) { return itemEntities .stream() - .map(itemMapper::toDto) + .map(ItemMapper::toDto) .toList(); } @@ -142,12 +139,12 @@ public CommentDto addComment(CommentDto commentDto, long itemId, long userId) { throw new NotValidException("Пользователь не брал вещь, не может оставить комментарий"); } - var commentEntity = commentMapper.toEntity(commentDto, userEntity, itemEntity); + var commentEntity = CommentMapper.toEntity(commentDto, userEntity, itemEntity); commentEntity.setCreated(Timestamp.valueOf(LocalDateTime.now())); itemStorage.updateComment(commentEntity); - return commentMapper.toDto(commentEntity); + return CommentMapper.toDto(commentEntity); } } diff --git a/src/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java b/src/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java index e96b71a..7a9aff8 100644 --- a/src/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java +++ b/src/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java @@ -5,6 +5,7 @@ import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; import ru.practicum.shareit.booking.storage.BookingRepository; +import ru.practicum.shareit.item.CommentMapper; import ru.practicum.shareit.item.ItemMapper; import ru.practicum.shareit.item.ItemStorage; import ru.practicum.shareit.user.storage.UserRepository; diff --git a/src/main/java/ru/practicum/shareit/request/AnswerMapper.java b/src/main/java/ru/practicum/shareit/request/AnswerMapper.java new file mode 100644 index 0000000..5f7cb9e --- /dev/null +++ b/src/main/java/ru/practicum/shareit/request/AnswerMapper.java @@ -0,0 +1,18 @@ +package ru.practicum.shareit.request; + +import ru.practicum.shareit.request.dto.AnswerDto; +import ru.practicum.shareit.request.storage.AnswerEntity; + +public class AnswerMapper { + public static AnswerDto toDto(AnswerEntity entity) { + var itemEntity = entity.getItem(); + + var build = AnswerDto + .builder() + .itemId(itemEntity.getId()) + .name(itemEntity.getName()) + .userId(itemEntity.getOwner().getId()); + + return build.build(); + } +} diff --git a/src/main/java/ru/practicum/shareit/request/ItemRequest.java b/src/main/java/ru/practicum/shareit/request/ItemRequest.java deleted file mode 100644 index 95d6f23..0000000 --- a/src/main/java/ru/practicum/shareit/request/ItemRequest.java +++ /dev/null @@ -1,7 +0,0 @@ -package ru.practicum.shareit.request; - -/** - * TODO Sprint add-item-requests. - */ -public class ItemRequest { -} diff --git a/src/main/java/ru/practicum/shareit/request/ItemRequestController.java b/src/main/java/ru/practicum/shareit/request/ItemRequestController.java deleted file mode 100644 index 064e2e9..0000000 --- a/src/main/java/ru/practicum/shareit/request/ItemRequestController.java +++ /dev/null @@ -1,12 +0,0 @@ -package ru.practicum.shareit.request; - -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -/** - * TODO Sprint add-item-requests. - */ -@RestController -@RequestMapping(path = "/requests") -public class ItemRequestController { -} diff --git a/src/main/java/ru/practicum/shareit/request/RequestController.java b/src/main/java/ru/practicum/shareit/request/RequestController.java new file mode 100644 index 0000000..2058da5 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/request/RequestController.java @@ -0,0 +1,37 @@ +package ru.practicum.shareit.request; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; +import ru.practicum.shareit.request.dto.RequestDto; + +import java.util.List; + +@RestController +@RequestMapping(path = "/requests") +@RequiredArgsConstructor +public class RequestController { + private final RequestService requestService; + + @GetMapping + public List getSelfRequests(@RequestHeader("X-Sharer-User-Id") long userId) { + return requestService.getRequestsByUserId(userId, true); + } + + @GetMapping("/{id}") + public RequestDto getRequestById(@PathVariable long id) { + return requestService.getRequestById(id); + } + + @GetMapping("/all") + public List getOtherUserRequests(@RequestHeader("X-Sharer-User-Id") long userId) { + return requestService.getRequestsByUserId(userId, false); + } + + @PostMapping + public RequestDto postRequestDto( + @Valid @RequestBody RequestDto requestDto, + @RequestHeader("X-Sharer-User-Id") long userId) { + return requestService.createItem(requestDto, userId); + } +} diff --git a/src/main/java/ru/practicum/shareit/request/RequestMapper.java b/src/main/java/ru/practicum/shareit/request/RequestMapper.java new file mode 100644 index 0000000..7a35d0a --- /dev/null +++ b/src/main/java/ru/practicum/shareit/request/RequestMapper.java @@ -0,0 +1,34 @@ +package ru.practicum.shareit.request; + +import ru.practicum.shareit.request.dto.AnswerDto; +import ru.practicum.shareit.request.dto.RequestDto; +import ru.practicum.shareit.request.storage.RequestEntity; +import ru.practicum.shareit.user.storage.UserEntity; + +import java.util.List; + +public class RequestMapper { + public static RequestDto toDto(RequestEntity entity, List answers) { + var build = RequestDto + .builder() + .id(entity.getId()) + .text(entity.getText()) + .description(entity.getDescription()) + .date(entity.getDate()) + .answers(answers); + + return build.build(); + } + + public static RequestEntity toEntity( + RequestDto requestDto, + UserEntity userEntity) { + var entity = new RequestEntity(); + entity.setId(requestDto.id()); + entity.setUser(userEntity); + entity.setText(requestDto.text()); + entity.setDescription(requestDto.description()); + + return entity; + } +} diff --git a/src/main/java/ru/practicum/shareit/request/RequestService.java b/src/main/java/ru/practicum/shareit/request/RequestService.java new file mode 100644 index 0000000..f93dd2e --- /dev/null +++ b/src/main/java/ru/practicum/shareit/request/RequestService.java @@ -0,0 +1,55 @@ +package ru.practicum.shareit.request; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import ru.practicum.shareit.exceptions.NotFoundException; +import ru.practicum.shareit.request.dto.RequestDto; +import ru.practicum.shareit.request.storage.RequestEntity; +import ru.practicum.shareit.user.UserStorage; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class RequestService { + private final RequestStorage requestStorage; + private final UserStorage userStorage; + + public RequestDto createItem(@Valid RequestDto requestDto, long userId) { + var userEntity = userStorage.getUser(userId) + .orElseThrow(() -> new NotFoundException("Пользователь не найден")); + + var requestEntity = RequestMapper.toEntity(requestDto, userEntity); + + requestStorage.updateRequest(requestEntity); + + return mapToDto(requestEntity); + } + + public List getRequestsByUserId(long userId, boolean findByUserId) { + if (findByUserId && !userStorage.existsById(userId)) + throw new NotFoundException("Пользователь не найден"); + + return requestStorage.getRequestsByUserId(userId, findByUserId) + .stream() + .map(this::mapToDto) + .toList(); + } + + public RequestDto getRequestById(long id) { + var requestEntity = requestStorage.findRequestById(id) + .orElseThrow(() -> new NotFoundException("Запрос не найден")); + + return mapToDto(requestEntity); + } + + private RequestDto mapToDto(RequestEntity requestEntity) { + var answers = requestEntity.getAnswers() + .stream() + .map(AnswerMapper::toDto) + .toList(); + + return RequestMapper.toDto(requestEntity, answers); + } +} diff --git a/src/main/java/ru/practicum/shareit/request/RequestStorage.java b/src/main/java/ru/practicum/shareit/request/RequestStorage.java new file mode 100644 index 0000000..de99a42 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/request/RequestStorage.java @@ -0,0 +1,14 @@ +package ru.practicum.shareit.request; + +import ru.practicum.shareit.request.storage.RequestEntity; + +import java.util.List; +import java.util.Optional; + +public interface RequestStorage { + void updateRequest(RequestEntity requestEntity); + + List getRequestsByUserId(long userId, boolean findByUserId); + + Optional findRequestById(long id); +} diff --git a/src/main/java/ru/practicum/shareit/request/dto/AnswerDto.java b/src/main/java/ru/practicum/shareit/request/dto/AnswerDto.java new file mode 100644 index 0000000..2e7a3d8 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/request/dto/AnswerDto.java @@ -0,0 +1,11 @@ +package ru.practicum.shareit.request.dto; + +import lombok.Builder; + +@Builder(toBuilder = true) +public record AnswerDto( + long itemId, + String name, + long userId +) { +}; diff --git a/src/main/java/ru/practicum/shareit/request/dto/ItemRequestDto.java b/src/main/java/ru/practicum/shareit/request/dto/ItemRequestDto.java deleted file mode 100644 index e8e0b13..0000000 --- a/src/main/java/ru/practicum/shareit/request/dto/ItemRequestDto.java +++ /dev/null @@ -1,12 +0,0 @@ -package ru.practicum.shareit.request.dto; - -import lombok.Builder; -import lombok.Value; - -@Value -@Builder(toBuilder = true) -public class ItemRequestDto { - Long id; - Long userId; - String text; -} diff --git a/src/main/java/ru/practicum/shareit/request/dto/RequestDto.java b/src/main/java/ru/practicum/shareit/request/dto/RequestDto.java new file mode 100644 index 0000000..dad4218 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/request/dto/RequestDto.java @@ -0,0 +1,19 @@ +package ru.practicum.shareit.request.dto; + +import jakarta.validation.constraints.NotBlank; +import lombok.Builder; + +import java.sql.Timestamp; +import java.util.List; + +@Builder(toBuilder = true) +public record RequestDto( + Long id, + @NotBlank + String text, + @NotBlank + String description, + Timestamp date, + List answers +) { +} diff --git a/src/main/java/ru/practicum/shareit/request/storage/AnswerEntity.java b/src/main/java/ru/practicum/shareit/request/storage/AnswerEntity.java new file mode 100644 index 0000000..e2213d3 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/request/storage/AnswerEntity.java @@ -0,0 +1,27 @@ +package ru.practicum.shareit.request.storage; + +import jakarta.persistence.*; +import lombok.Data; +import ru.practicum.shareit.item.storage.ItemEntity; + +@Entity +@Table(name = "Answers") +@Data +public class AnswerEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "answer_id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "request_id", nullable = false) + private RequestEntity request; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "item_id", nullable = false) + private ItemEntity item; + + public AnswerEntity() { + + } +} diff --git a/src/main/java/ru/practicum/shareit/request/storage/RequestEntity.java b/src/main/java/ru/practicum/shareit/request/storage/RequestEntity.java new file mode 100644 index 0000000..795b626 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/request/storage/RequestEntity.java @@ -0,0 +1,36 @@ +package ru.practicum.shareit.request.storage; + +import jakarta.persistence.*; +import lombok.Data; +import ru.practicum.shareit.user.storage.UserEntity; + +import java.sql.Timestamp; +import java.util.List; + +@Entity +@Table(name = "Request") +@Data +public class RequestEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "request_id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id", nullable = false) + private UserEntity user; + + @Column(nullable = false) + private String text; + @Column + private String description; + @Column + private Timestamp date; + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "request") + private List answers; + + public RequestEntity() { + + } +} diff --git a/src/main/java/ru/practicum/shareit/request/storage/RequestRepository.java b/src/main/java/ru/practicum/shareit/request/storage/RequestRepository.java new file mode 100644 index 0000000..357049b --- /dev/null +++ b/src/main/java/ru/practicum/shareit/request/storage/RequestRepository.java @@ -0,0 +1,11 @@ +package ru.practicum.shareit.request.storage; + +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface RequestRepository extends JpaRepository { + List findByUserId(long id); + + List findByUserIdNot(long id); +} diff --git a/src/main/java/ru/practicum/shareit/request/storage/RequestStorageInDb.java b/src/main/java/ru/practicum/shareit/request/storage/RequestStorageInDb.java new file mode 100644 index 0000000..5bf6e18 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/request/storage/RequestStorageInDb.java @@ -0,0 +1,35 @@ +package ru.practicum.shareit.request.storage; + +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; +import ru.practicum.shareit.request.RequestStorage; + +import java.util.List; +import java.util.Optional; + +@Component +@RequiredArgsConstructor +@Primary +public class RequestStorageInDb implements RequestStorage { + private final RequestRepository requestRepository; + + @Override + public void updateRequest(RequestEntity requestEntity) { + requestRepository.saveAndFlush(requestEntity); + } + + @Override + public List getRequestsByUserId(long userId, boolean findByUserId) { + if (findByUserId) { + return requestRepository.findByUserId(userId); + } else { + return requestRepository.findByUserIdNot(userId); + } + } + + @Override + public Optional findRequestById(long id) { + return requestRepository.findById(id); + } +} diff --git a/src/main/java/ru/practicum/shareit/user/UserMapper.java b/src/main/java/ru/practicum/shareit/user/UserMapper.java index d6e99e6..9b270c6 100644 --- a/src/main/java/ru/practicum/shareit/user/UserMapper.java +++ b/src/main/java/ru/practicum/shareit/user/UserMapper.java @@ -4,7 +4,7 @@ import ru.practicum.shareit.user.storage.UserEntity; public class UserMapper { - public UserEntity toEntity(UserDto user) { + public static UserEntity toEntity(UserDto user) { var entity = new UserEntity(); entity.setId(user.id()); entity.setName(user.name()); @@ -13,7 +13,7 @@ public UserEntity toEntity(UserDto user) { return entity; } - public UserDto toDto(UserEntity userEntity) { + public static UserDto toDto(UserEntity userEntity) { return UserDto .builder() .id(userEntity.getId()) diff --git a/src/main/java/ru/practicum/shareit/user/UserService.java b/src/main/java/ru/practicum/shareit/user/UserService.java index 1a36078..159e9a1 100644 --- a/src/main/java/ru/practicum/shareit/user/UserService.java +++ b/src/main/java/ru/practicum/shareit/user/UserService.java @@ -10,21 +10,20 @@ @RequiredArgsConstructor public class UserService { private final UserStorage userStorage; - private final UserMapper userMapper = new UserMapper(); public UserDto getUser(long userId) { var userEntity = userStorage.getUser(userId) .orElseThrow(() -> new NotFoundException("Не нашел userId в системе")); - return userMapper.toDto(userEntity); + return UserMapper.toDto(userEntity); } public UserDto updateUser(UserDto user) { - var userEntity = userMapper.toEntity(user); + var userEntity = UserMapper.toEntity(user); userStorage.updateUser(userEntity); - return userMapper.toDto(userEntity); + return UserMapper.toDto(userEntity); } public UserDto updateUser(long userId, UserToUpdateDto user) { @@ -38,7 +37,7 @@ public UserDto updateUser(long userId, UserToUpdateDto user) { userStorage.updateUser(userEntity); - return userMapper.toDto(userEntity); + return UserMapper.toDto(userEntity); } public UserDto deleteUser(long userId) { @@ -47,6 +46,6 @@ public UserDto deleteUser(long userId) { userStorage.deleteUser(userEntity); - return userMapper.toDto(userEntity); + return UserMapper.toDto(userEntity); } } diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 284dc0b..3a9812d 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -1,19 +1,19 @@ -CREATE TABLE if not exists Users( +CREATE TABLE if NOT EXISTS Users( user_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, name VARCHAR(100) NOT NULL, email VARCHAR(100) NOT NULL, CONSTRAINT uniqueEmails UNIQUE(email) ); -CREATE TABLE IF NOT exists Items( +CREATE TABLE IF NOT EXISTS Items( item_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, owner_id BIGINT REFERENCES Users(user_id), name VARCHAR(100) NOT NULL, - description VARCHAR(100) NOT NULL, + description VARCHAR(1000) NOT NULL, available boolean ); -CREATE TABLE IF NOT exists Comments( +CREATE TABLE IF NOT EXISTS Comments( comment_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, user_id BIGINT REFERENCES Users(user_id), item_id BIGINT REFERENCES Items(item_id), @@ -21,12 +21,26 @@ CREATE TABLE IF NOT exists Comments( created timestamp WITHOUT TIME ZONE NOT NULL ); -CREATE TABLE IF NOT exists Bookings( +CREATE TABLE IF NOT EXISTS Bookings( booking_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, booker_id BIGINT REFERENCES Users(user_id), item_id BIGINT REFERENCES Items(item_id), status VARCHAR(100) NOT NULL, - description VARCHAR(100), + description VARCHAR(1000), start timestamp WITHOUT TIME ZONE NOT NULL, finish timestamp WITHOUT TIME ZONE NOT NULL +); + +CREATE TABLE IF NOT EXISTS Requests( + request_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + user_id BIGINT REFERENCES Users(user_id), + text VARCHAR(1000), + description VARCHAR(1000), + date timestamp WITHOUT TIME ZONE NOT NULL +); + +CREATE TABLE IF NOT EXISTS Answers( + answer_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + request_id BIGINT REFERENCES Requests(request_id), + item_id BIGINT REFERENCES Items(item_id) ); \ No newline at end of file From f7eea75f1211a432da8cfd576ebace89315e4f04 Mon Sep 17 00:00:00 2001 From: aKorishev Date: Mon, 18 Nov 2024 19:12:12 +0300 Subject: [PATCH 02/11] =?UTF-8?q?[add-item-requests-and-gateway]=20=D0=94?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BF=D0=BE=D0=BB=D0=B5?= =?UTF-8?q?=20requestId=20=D0=B2=20item?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/ru/practicum/shareit/item/dto/ItemDto.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java b/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java index f208647..842bbd5 100644 --- a/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java +++ b/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java @@ -15,5 +15,6 @@ public record ItemDto( @NotNull Boolean available, Timestamp lastBooking, Timestamp nextBooking, - List comments + List comments, + Long requestId ) { } From 6c40b8848ba429fd64d06366a1654cedd4c2ba76 Mon Sep 17 00:00:00 2001 From: aKorishev Date: Thu, 21 Nov 2024 19:47:05 +0300 Subject: [PATCH 03/11] =?UTF-8?q?[add-item-requests-and-gateway]=20=D0=9E?= =?UTF-8?q?=D1=82=D0=BB=D0=B0=D0=B4=D0=BA=D0=B0=20=D0=BF=D0=BE=20=D0=B8?= =?UTF-8?q?=D1=82=D0=BE=D0=B3=D0=B0=D0=BC=20=D1=82=D0=B5=D1=81=D1=82=D0=BE?= =?UTF-8?q?=D0=B2=20postman?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ru/practicum/shareit/item/ItemMapper.java | 4 ++- .../practicum/shareit/item/ItemService.java | 21 ++++++++++++--- .../practicum/shareit/item/ItemStorage.java | 1 + .../shareit/item/storage/ItemEntity.java | 5 ++++ .../shareit/item/storage/ItemStorageInDb.java | 5 ++++ .../shareit/request/AnswerMapper.java | 18 ------------- .../shareit/request/RequestMapper.java | 13 ++++++--- .../shareit/request/RequestService.java | 12 ++++++--- .../shareit/request/dto/AnswerDto.java | 11 -------- .../shareit/request/dto/RequestDto.java | 6 ++--- .../shareit/request/storage/AnswerEntity.java | 27 ------------------- .../request/storage/RequestEntity.java | 7 ++--- src/main/resources/application-dev.yaml | 8 +++--- src/main/resources/schema.sql | 25 +++++++---------- 14 files changed, 71 insertions(+), 92 deletions(-) delete mode 100644 src/main/java/ru/practicum/shareit/request/AnswerMapper.java delete mode 100644 src/main/java/ru/practicum/shareit/request/dto/AnswerDto.java delete mode 100644 src/main/java/ru/practicum/shareit/request/storage/AnswerEntity.java diff --git a/src/main/java/ru/practicum/shareit/item/ItemMapper.java b/src/main/java/ru/practicum/shareit/item/ItemMapper.java index 8e74e81..9c4d244 100644 --- a/src/main/java/ru/practicum/shareit/item/ItemMapper.java +++ b/src/main/java/ru/practicum/shareit/item/ItemMapper.java @@ -5,6 +5,7 @@ import ru.practicum.shareit.item.dto.ItemDto; import ru.practicum.shareit.item.storage.ItemEntity; import ru.practicum.shareit.item.storage.ItemWithDateOfBookings; +import ru.practicum.shareit.request.storage.RequestEntity; import ru.practicum.shareit.user.storage.UserEntity; import java.sql.Timestamp; @@ -55,13 +56,14 @@ public static ItemDto toDto( return build.build(); } - public static ItemEntity toEntity(ItemDto itemDto, UserEntity userEntity) { + public static ItemEntity toEntity(ItemDto itemDto, UserEntity userEntity, RequestEntity requestEntity) { var entity = new ItemEntity(); entity.setId(itemDto.id()); entity.setOwner(userEntity); entity.setName(itemDto.name()); entity.setDescription(itemDto.description()); entity.setAvailable(itemDto.available()); + entity.setRequest(requestEntity); return entity; } diff --git a/src/main/java/ru/practicum/shareit/item/ItemService.java b/src/main/java/ru/practicum/shareit/item/ItemService.java index 80c68ce..e43e6aa 100644 --- a/src/main/java/ru/practicum/shareit/item/ItemService.java +++ b/src/main/java/ru/practicum/shareit/item/ItemService.java @@ -9,6 +9,8 @@ import ru.practicum.shareit.item.dto.CommentDto; import ru.practicum.shareit.item.dto.ItemDto; import ru.practicum.shareit.item.dto.ItemToUpdateDto; +import ru.practicum.shareit.request.RequestStorage; +import ru.practicum.shareit.request.storage.RequestEntity; import ru.practicum.shareit.user.UserStorage; import java.sql.Timestamp; @@ -22,6 +24,7 @@ public class ItemService { private final ItemStorage itemStorage; private final UserStorage userStorage; private final BookingStorage bookingStorage; + private final RequestStorage requestStorage; public ItemDto getItem(long itemId) { var itemEntity = itemStorage.getItem(itemId) @@ -39,7 +42,13 @@ public ItemDto createItem(ItemDto item, long userId) { var userEntity = userStorage.getUser(userId) .orElseThrow(() -> new NotFoundException("Пользователь не найден")); - var itemEntity = ItemMapper.toEntity(item, userEntity); + RequestEntity requestEntity = null; + + if (item.requestId() != null) + requestEntity = requestStorage.findRequestById(item.requestId()) + .orElseThrow(() -> new NotFoundException("Запрос не найден")); + + var itemEntity = ItemMapper.toEntity(item, userEntity, requestEntity); itemStorage.updateItem(itemEntity); @@ -53,10 +62,16 @@ public ItemDto updateItem(ItemDto item, long userId) { var owner = itemEntityOld.getOwner(); if (owner.getId() != userId) { - throw new NotFoundException("Вещь не доступна"); + throw new NotFoundException("Владелец не найден"); } - var itemEntity = ItemMapper.toEntity(item, owner); + RequestEntity requestEntity = null; + + if (item.requestId() != null) + requestEntity = requestStorage.findRequestById(item.requestId()) + .orElseThrow(() -> new NotFoundException("Запрос не найден")); + + var itemEntity = ItemMapper.toEntity(item, owner, requestEntity); itemStorage.updateItem(itemEntity); diff --git a/src/main/java/ru/practicum/shareit/item/ItemStorage.java b/src/main/java/ru/practicum/shareit/item/ItemStorage.java index 7cb4d79..25c0db6 100644 --- a/src/main/java/ru/practicum/shareit/item/ItemStorage.java +++ b/src/main/java/ru/practicum/shareit/item/ItemStorage.java @@ -21,4 +21,5 @@ public interface ItemStorage { List findItemsByTextAndStatus(String text, boolean available); + List getAllItems(); } diff --git a/src/main/java/ru/practicum/shareit/item/storage/ItemEntity.java b/src/main/java/ru/practicum/shareit/item/storage/ItemEntity.java index 55af6c1..d466979 100644 --- a/src/main/java/ru/practicum/shareit/item/storage/ItemEntity.java +++ b/src/main/java/ru/practicum/shareit/item/storage/ItemEntity.java @@ -2,6 +2,7 @@ import jakarta.persistence.*; import lombok.Data; +import ru.practicum.shareit.request.storage.RequestEntity; import ru.practicum.shareit.user.storage.UserEntity; import java.util.List; @@ -29,6 +30,10 @@ public class ItemEntity { @OneToMany(fetch = FetchType.LAZY, mappedBy = "item") private List comments; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "request_id") + private RequestEntity request; + public ItemEntity() { } diff --git a/src/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java b/src/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java index 7a9aff8..cabd26c 100644 --- a/src/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java +++ b/src/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java @@ -71,4 +71,9 @@ public List getItemsForOwner(long userId) { public List findItemsByTextAndStatus(String text, boolean available) { return itemRepository.findByTextAndAvailable(text, available); } + + @Override + public List getAllItems() { + return itemRepository.findAll(); + } } diff --git a/src/main/java/ru/practicum/shareit/request/AnswerMapper.java b/src/main/java/ru/practicum/shareit/request/AnswerMapper.java deleted file mode 100644 index 5f7cb9e..0000000 --- a/src/main/java/ru/practicum/shareit/request/AnswerMapper.java +++ /dev/null @@ -1,18 +0,0 @@ -package ru.practicum.shareit.request; - -import ru.practicum.shareit.request.dto.AnswerDto; -import ru.practicum.shareit.request.storage.AnswerEntity; - -public class AnswerMapper { - public static AnswerDto toDto(AnswerEntity entity) { - var itemEntity = entity.getItem(); - - var build = AnswerDto - .builder() - .itemId(itemEntity.getId()) - .name(itemEntity.getName()) - .userId(itemEntity.getOwner().getId()); - - return build.build(); - } -} diff --git a/src/main/java/ru/practicum/shareit/request/RequestMapper.java b/src/main/java/ru/practicum/shareit/request/RequestMapper.java index 7a35d0a..62ca50f 100644 --- a/src/main/java/ru/practicum/shareit/request/RequestMapper.java +++ b/src/main/java/ru/practicum/shareit/request/RequestMapper.java @@ -1,6 +1,6 @@ package ru.practicum.shareit.request; -import ru.practicum.shareit.request.dto.AnswerDto; +import ru.practicum.shareit.item.dto.ItemDto; import ru.practicum.shareit.request.dto.RequestDto; import ru.practicum.shareit.request.storage.RequestEntity; import ru.practicum.shareit.user.storage.UserEntity; @@ -8,14 +8,14 @@ import java.util.List; public class RequestMapper { - public static RequestDto toDto(RequestEntity entity, List answers) { + public static RequestDto toDto(RequestEntity entity, List items) { var build = RequestDto .builder() .id(entity.getId()) .text(entity.getText()) .description(entity.getDescription()) - .date(entity.getDate()) - .answers(answers); + .created(entity.getCreated()) + .items(items); return build.build(); } @@ -29,6 +29,11 @@ public static RequestEntity toEntity( entity.setText(requestDto.text()); entity.setDescription(requestDto.description()); + var created = requestDto.created(); + + if (created != null) + entity.setCreated(created); + return entity; } } diff --git a/src/main/java/ru/practicum/shareit/request/RequestService.java b/src/main/java/ru/practicum/shareit/request/RequestService.java index f93dd2e..52255ff 100644 --- a/src/main/java/ru/practicum/shareit/request/RequestService.java +++ b/src/main/java/ru/practicum/shareit/request/RequestService.java @@ -4,11 +4,15 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import ru.practicum.shareit.exceptions.NotFoundException; +import ru.practicum.shareit.item.ItemMapper; import ru.practicum.shareit.request.dto.RequestDto; import ru.practicum.shareit.request.storage.RequestEntity; import ru.practicum.shareit.user.UserStorage; +import java.sql.Timestamp; +import java.time.LocalDateTime; import java.util.List; +import java.util.Optional; @Service @RequiredArgsConstructor @@ -21,6 +25,7 @@ public RequestDto createItem(@Valid RequestDto requestDto, long userId) { .orElseThrow(() -> new NotFoundException("Пользователь не найден")); var requestEntity = RequestMapper.toEntity(requestDto, userEntity); + requestEntity.setCreated(Timestamp.valueOf(LocalDateTime.now())); requestStorage.updateRequest(requestEntity); @@ -45,11 +50,12 @@ public RequestDto getRequestById(long id) { } private RequestDto mapToDto(RequestEntity requestEntity) { - var answers = requestEntity.getAnswers() + var items = Optional.ofNullable(requestEntity.getItems()) + .orElse(List.of()) .stream() - .map(AnswerMapper::toDto) + .map(ItemMapper::toDto) .toList(); - return RequestMapper.toDto(requestEntity, answers); + return RequestMapper.toDto(requestEntity, items); } } diff --git a/src/main/java/ru/practicum/shareit/request/dto/AnswerDto.java b/src/main/java/ru/practicum/shareit/request/dto/AnswerDto.java deleted file mode 100644 index 2e7a3d8..0000000 --- a/src/main/java/ru/practicum/shareit/request/dto/AnswerDto.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.practicum.shareit.request.dto; - -import lombok.Builder; - -@Builder(toBuilder = true) -public record AnswerDto( - long itemId, - String name, - long userId -) { -}; diff --git a/src/main/java/ru/practicum/shareit/request/dto/RequestDto.java b/src/main/java/ru/practicum/shareit/request/dto/RequestDto.java index dad4218..7b74515 100644 --- a/src/main/java/ru/practicum/shareit/request/dto/RequestDto.java +++ b/src/main/java/ru/practicum/shareit/request/dto/RequestDto.java @@ -2,6 +2,7 @@ import jakarta.validation.constraints.NotBlank; import lombok.Builder; +import ru.practicum.shareit.item.dto.ItemDto; import java.sql.Timestamp; import java.util.List; @@ -9,11 +10,10 @@ @Builder(toBuilder = true) public record RequestDto( Long id, - @NotBlank String text, @NotBlank String description, - Timestamp date, - List answers + Timestamp created, + List items ) { } diff --git a/src/main/java/ru/practicum/shareit/request/storage/AnswerEntity.java b/src/main/java/ru/practicum/shareit/request/storage/AnswerEntity.java deleted file mode 100644 index e2213d3..0000000 --- a/src/main/java/ru/practicum/shareit/request/storage/AnswerEntity.java +++ /dev/null @@ -1,27 +0,0 @@ -package ru.practicum.shareit.request.storage; - -import jakarta.persistence.*; -import lombok.Data; -import ru.practicum.shareit.item.storage.ItemEntity; - -@Entity -@Table(name = "Answers") -@Data -public class AnswerEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "answer_id") - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "request_id", nullable = false) - private RequestEntity request; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "item_id", nullable = false) - private ItemEntity item; - - public AnswerEntity() { - - } -} diff --git a/src/main/java/ru/practicum/shareit/request/storage/RequestEntity.java b/src/main/java/ru/practicum/shareit/request/storage/RequestEntity.java index 795b626..9558642 100644 --- a/src/main/java/ru/practicum/shareit/request/storage/RequestEntity.java +++ b/src/main/java/ru/practicum/shareit/request/storage/RequestEntity.java @@ -2,13 +2,14 @@ import jakarta.persistence.*; import lombok.Data; +import ru.practicum.shareit.item.storage.ItemEntity; import ru.practicum.shareit.user.storage.UserEntity; import java.sql.Timestamp; import java.util.List; @Entity -@Table(name = "Request") +@Table(name = "Requests") @Data public class RequestEntity { @Id @@ -25,10 +26,10 @@ public class RequestEntity { @Column private String description; @Column - private Timestamp date; + private Timestamp created; @OneToMany(fetch = FetchType.LAZY, mappedBy = "request") - private List answers; + private List items; public RequestEntity() { diff --git a/src/main/resources/application-dev.yaml b/src/main/resources/application-dev.yaml index a93fcf0..39e9429 100644 --- a/src/main/resources/application-dev.yaml +++ b/src/main/resources/application-dev.yaml @@ -6,12 +6,12 @@ spring: driverClassName: org.h2.Driver url: jdbc:h2:mem:shareit jpa: - #show-sql: true + #show-sql: true show-sql: false logging.level: ru.practicum.shareit: TRACE org: zalando.logbook: TRACE - hibernate: - type.descriptor.sql.BasicBinder: TRACE - #orm.jdbc.bind: TRACE +# hibernate: +# type.descriptor.sql.BasicBinder: TRACE +# orm.jdbc.bind: TRACE diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 3a9812d..66ec3f6 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -5,12 +5,21 @@ CREATE TABLE if NOT EXISTS Users( CONSTRAINT uniqueEmails UNIQUE(email) ); +CREATE TABLE IF NOT EXISTS Requests( + request_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + user_id BIGINT REFERENCES Users(user_id), + text VARCHAR(1000), + description VARCHAR(1000), + created timestamp WITHOUT TIME ZONE NOT NULL +); + CREATE TABLE IF NOT EXISTS Items( item_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, owner_id BIGINT REFERENCES Users(user_id), name VARCHAR(100) NOT NULL, description VARCHAR(1000) NOT NULL, - available boolean + available boolean, + request_id BIGINT REFERENCES Requests(request_id) ); CREATE TABLE IF NOT EXISTS Comments( @@ -29,18 +38,4 @@ CREATE TABLE IF NOT EXISTS Bookings( description VARCHAR(1000), start timestamp WITHOUT TIME ZONE NOT NULL, finish timestamp WITHOUT TIME ZONE NOT NULL -); - -CREATE TABLE IF NOT EXISTS Requests( - request_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - user_id BIGINT REFERENCES Users(user_id), - text VARCHAR(1000), - description VARCHAR(1000), - date timestamp WITHOUT TIME ZONE NOT NULL -); - -CREATE TABLE IF NOT EXISTS Answers( - answer_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - request_id BIGINT REFERENCES Requests(request_id), - item_id BIGINT REFERENCES Items(item_id) ); \ No newline at end of file From 168be08f5e8c72cb9edd572044cb6b406c8ef7c7 Mon Sep 17 00:00:00 2001 From: aKorishev Date: Sun, 1 Dec 2024 12:26:41 +0300 Subject: [PATCH 04/11] =?UTF-8?q?[add-item-requests-and-gateway]=20=D0=94?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BC=D0=BE=D0=B4=D1=83?= =?UTF-8?q?=D0=BB=D0=B8=20server=20=D0=B8=20gateway.=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D1=82=D0=B5=D1=81=D1=82=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=BA=D0=BE=D0=BD=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=BB=D0=BB=D0=B5=D1=80=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gateway/Dockerfile | 5 + gateway/pom.xml | 70 + .../ru/practicum/shareit/ShareItGateway.java | 12 + .../shareit/booking/BookingController.java | 80 + .../shareit/booking/BookingService.java | 26 + .../shareit/booking/dto/BookingDto.java | 17 + .../shareit/booking/dto/BookingStatus.java | 8 + .../booking/dto/BookingStatusRequestDto.java | 0 .../shareit/booking/dto/ReviewDto.java | 0 .../shareit/item/ItemController.java | 120 + .../shareit/item/dto/CommentDto.java | 14 + .../practicum/shareit/item/dto/ItemDto.java | 20 + .../shareit/item/dto/ItemToUpdateDto.java | 10 + .../shareit/request/RequestController.java | 61 + .../shareit/request/RequestService.java | 26 + .../shareit/request/dto/RequestDto.java | 0 .../shareit/rest/RestQueryBuilder.java | 58 + .../practicum/shareit/rest/RestQueryDto.java | 20 + .../practicum/shareit/rest/RestQueryHead.java | 7 + .../practicum/shareit/rest/RestService.java | 64 + .../shareit/user/UserController.java | 72 + .../practicum/shareit/user/UserService.java | 26 + .../practicum/shareit/user/dto/UserDto.java | 0 .../shareit/user/dto/UserToUpdateDto.java | 0 .../src/main/resources/application.properties | 7 + gateway/src/test/ShareItTests.java | 13 + .../ru/practicum/shareit/ShareItTests.java | 13 + .../booking/BookingControllerTest.java | 277 ++ .../shareit/item/ItemControllerTest.java | 374 ++ .../request/RequestControllerTest.java | 206 + .../shareit/user/UserControllerTest.java | 221 + .../test/request/RequestControllerTest.java | 170 + gateway/src/test/shareit/ShareItTests.java | 13 + .../booking/BookingControllerTest.java | 277 ++ .../shareit/booking/BookingServiceTest.java | 271 ++ .../test/shareit/item/ItemControllerTest.java | 337 ++ .../request/RequestControllerTest.java | 170 + .../test/shareit/user/UserControllerTest.java | 179 + gateway/src/test/user/UserControllerTest.java | 179 + pom.xml | 9 +- postman/sprint.json | 4052 +++++++++++++++++ server/pom.xml | 86 + .../java/ru/practicum/shareit/ShareItApp.java | 13 + .../ru/practicum/shareit/booking/Booking.java | 0 .../shareit/booking/BookingController.java | 14 +- .../shareit/booking/BookingMapper.java | 0 .../shareit/booking/BookingService.java | 12 +- .../shareit/booking/BookingStatus.java | 0 .../shareit/booking/BookingStorage.java | 0 .../ru/practicum/shareit/booking/Review.java | 0 .../ru/practicum/shareit/booking/Status.java | 0 .../shareit/booking/dto/BookingDto.java | 0 .../booking/dto/BookingStatusRequestDto.java | 11 + .../shareit/booking/dto/ReviewDto.java | 13 + .../shareit/booking/dto/ReviewMapper.java | 0 .../booking/storage/BookingEntity.java | 0 .../booking/storage/BookingRepository.java | 0 .../booking/storage/BookingStorageInDb.java | 0 .../exceptions/IdIsAlreadyInUseException.java | 0 .../shareit/exceptions/NotFoundException.java | 0 .../shareit/exceptions/NotValidException.java | 0 .../practicum/shareit/item/CommentMapper.java | 0 .../shareit/item/ItemController.java | 70 + .../ru/practicum/shareit/item/ItemMapper.java | 0 .../practicum/shareit/item/ItemService.java | 2 +- .../practicum/shareit/item/ItemStorage.java | 0 .../shareit/item/dto/CommentDto.java | 14 + .../practicum/shareit/item/dto/ItemDto.java | 20 + .../shareit/item/dto/ItemToUpdateDto.java | 10 + .../shareit/item/storage/CommentEntity.java | 0 .../item/storage/CommentRepository.java | 0 .../shareit/item/storage/ItemEntity.java | 0 .../shareit/item/storage/ItemRepository.java | 0 .../shareit/item/storage/ItemStorageInDb.java | 0 .../item/storage/ItemWithDateOfBookings.java | 0 .../shareit/request/RequestController.java | 2 +- .../shareit/request/RequestMapper.java | 0 .../shareit/request/RequestService.java | 2 +- .../shareit/request/RequestStorage.java | 0 .../shareit/request/dto/RequestDto.java | 19 + .../request/storage/RequestEntity.java | 0 .../request/storage/RequestRepository.java | 0 .../request/storage/RequestStorageInDb.java | 0 .../practicum/shareit/tool/ErrorHandler.java | 0 .../practicum/shareit/tool/ErrorResponse.java | 0 .../shareit/user/UserController.java | 0 .../ru/practicum/shareit/user/UserMapper.java | 0 .../practicum/shareit/user/UserService.java | 0 .../practicum/shareit/user/UserStorage.java | 0 .../practicum/shareit/user/dto/UserDto.java | 18 + .../shareit/user/dto/UserToUpdateDto.java | 10 + .../shareit/user/storage/UserEntity.java | 0 .../shareit/user/storage/UserRepository.java | 0 .../shareit/user/storage/UserStorageInDB.java | 0 .../src/main/resources/application-dev.yaml | 17 + .../src/main/resources/application.properties | 1 + server/src/main/resources/application.yaml | 11 + server/src/main/resources/schema.sql | 41 + .../ru/practicum/shareit/ShareItTests.java | 13 + .../booking/BookingControllerTest.java | 277 ++ .../shareit/booking/BookingServiceTest.java | 271 ++ .../shareit/item/ItemControllerTest.java | 337 ++ .../request/RequestControllerTest.java | 170 + .../shareit/user/UserControllerTest.java | 179 + src/main/resources/application.properties | 1 + src/main/resources/application.yaml | 5 - .../booking/BookingControllerTest.java | 274 ++ .../shareit/booking/BookingServiceTest.java | 267 ++ .../shareit/item/ItemControllerTest.java | 335 ++ .../request/RequestControllerTest.java | 168 + .../shareit/user/UserControllerTest.java | 177 + 111 files changed, 10321 insertions(+), 23 deletions(-) create mode 100644 gateway/Dockerfile create mode 100644 gateway/pom.xml create mode 100644 gateway/src/main/java/ru/practicum/shareit/ShareItGateway.java create mode 100644 gateway/src/main/java/ru/practicum/shareit/booking/BookingController.java create mode 100644 gateway/src/main/java/ru/practicum/shareit/booking/BookingService.java create mode 100644 gateway/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java create mode 100644 gateway/src/main/java/ru/practicum/shareit/booking/dto/BookingStatus.java rename {src => gateway/src}/main/java/ru/practicum/shareit/booking/dto/BookingStatusRequestDto.java (100%) rename {src => gateway/src}/main/java/ru/practicum/shareit/booking/dto/ReviewDto.java (100%) create mode 100644 gateway/src/main/java/ru/practicum/shareit/item/ItemController.java create mode 100644 gateway/src/main/java/ru/practicum/shareit/item/dto/CommentDto.java create mode 100644 gateway/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java create mode 100644 gateway/src/main/java/ru/practicum/shareit/item/dto/ItemToUpdateDto.java create mode 100644 gateway/src/main/java/ru/practicum/shareit/request/RequestController.java create mode 100644 gateway/src/main/java/ru/practicum/shareit/request/RequestService.java rename {src => gateway/src}/main/java/ru/practicum/shareit/request/dto/RequestDto.java (100%) create mode 100644 gateway/src/main/java/ru/practicum/shareit/rest/RestQueryBuilder.java create mode 100644 gateway/src/main/java/ru/practicum/shareit/rest/RestQueryDto.java create mode 100644 gateway/src/main/java/ru/practicum/shareit/rest/RestQueryHead.java create mode 100644 gateway/src/main/java/ru/practicum/shareit/rest/RestService.java create mode 100644 gateway/src/main/java/ru/practicum/shareit/user/UserController.java create mode 100644 gateway/src/main/java/ru/practicum/shareit/user/UserService.java rename {src => gateway/src}/main/java/ru/practicum/shareit/user/dto/UserDto.java (100%) rename {src => gateway/src}/main/java/ru/practicum/shareit/user/dto/UserToUpdateDto.java (100%) create mode 100644 gateway/src/main/resources/application.properties create mode 100644 gateway/src/test/ShareItTests.java create mode 100644 gateway/src/test/java/ru/practicum/shareit/ShareItTests.java create mode 100644 gateway/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java create mode 100644 gateway/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java create mode 100644 gateway/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java create mode 100644 gateway/src/test/java/ru/practicum/shareit/user/UserControllerTest.java create mode 100644 gateway/src/test/request/RequestControllerTest.java create mode 100644 gateway/src/test/shareit/ShareItTests.java create mode 100644 gateway/src/test/shareit/booking/BookingControllerTest.java create mode 100644 gateway/src/test/shareit/booking/BookingServiceTest.java create mode 100644 gateway/src/test/shareit/item/ItemControllerTest.java create mode 100644 gateway/src/test/shareit/request/RequestControllerTest.java create mode 100644 gateway/src/test/shareit/user/UserControllerTest.java create mode 100644 gateway/src/test/user/UserControllerTest.java create mode 100644 postman/sprint.json create mode 100644 server/pom.xml create mode 100644 server/src/main/java/ru/practicum/shareit/ShareItApp.java rename {src => server/src}/main/java/ru/practicum/shareit/booking/Booking.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/booking/BookingController.java (78%) rename {src => server/src}/main/java/ru/practicum/shareit/booking/BookingMapper.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/booking/BookingService.java (92%) rename {src => server/src}/main/java/ru/practicum/shareit/booking/BookingStatus.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/booking/BookingStorage.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/booking/Review.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/booking/Status.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/booking/dto/BookingDto.java (100%) create mode 100644 server/src/main/java/ru/practicum/shareit/booking/dto/BookingStatusRequestDto.java create mode 100644 server/src/main/java/ru/practicum/shareit/booking/dto/ReviewDto.java rename {src => server/src}/main/java/ru/practicum/shareit/booking/dto/ReviewMapper.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/booking/storage/BookingEntity.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/booking/storage/BookingRepository.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/booking/storage/BookingStorageInDb.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/exceptions/IdIsAlreadyInUseException.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/exceptions/NotFoundException.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/exceptions/NotValidException.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/item/CommentMapper.java (100%) create mode 100644 server/src/main/java/ru/practicum/shareit/item/ItemController.java rename {src => server/src}/main/java/ru/practicum/shareit/item/ItemMapper.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/item/ItemService.java (99%) rename {src => server/src}/main/java/ru/practicum/shareit/item/ItemStorage.java (100%) create mode 100644 server/src/main/java/ru/practicum/shareit/item/dto/CommentDto.java create mode 100644 server/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java create mode 100644 server/src/main/java/ru/practicum/shareit/item/dto/ItemToUpdateDto.java rename {src => server/src}/main/java/ru/practicum/shareit/item/storage/CommentEntity.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/item/storage/CommentRepository.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/item/storage/ItemEntity.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/item/storage/ItemRepository.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/item/storage/ItemWithDateOfBookings.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/request/RequestController.java (94%) rename {src => server/src}/main/java/ru/practicum/shareit/request/RequestMapper.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/request/RequestService.java (96%) rename {src => server/src}/main/java/ru/practicum/shareit/request/RequestStorage.java (100%) create mode 100644 server/src/main/java/ru/practicum/shareit/request/dto/RequestDto.java rename {src => server/src}/main/java/ru/practicum/shareit/request/storage/RequestEntity.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/request/storage/RequestRepository.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/request/storage/RequestStorageInDb.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/tool/ErrorHandler.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/tool/ErrorResponse.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/user/UserController.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/user/UserMapper.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/user/UserService.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/user/UserStorage.java (100%) create mode 100644 server/src/main/java/ru/practicum/shareit/user/dto/UserDto.java create mode 100644 server/src/main/java/ru/practicum/shareit/user/dto/UserToUpdateDto.java rename {src => server/src}/main/java/ru/practicum/shareit/user/storage/UserEntity.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/user/storage/UserRepository.java (100%) rename {src => server/src}/main/java/ru/practicum/shareit/user/storage/UserStorageInDB.java (100%) create mode 100644 server/src/main/resources/application-dev.yaml create mode 100644 server/src/main/resources/application.properties create mode 100644 server/src/main/resources/application.yaml create mode 100644 server/src/main/resources/schema.sql create mode 100644 server/src/test/java/ru/practicum/shareit/ShareItTests.java create mode 100644 server/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java create mode 100644 server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java create mode 100644 server/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java create mode 100644 server/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java create mode 100644 server/src/test/java/ru/practicum/shareit/user/UserControllerTest.java create mode 100644 src/main/resources/application.properties create mode 100644 src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java create mode 100644 src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java create mode 100644 src/test/java/ru/practicum/shareit/item/ItemControllerTest.java create mode 100644 src/test/java/ru/practicum/shareit/request/RequestControllerTest.java create mode 100644 src/test/java/ru/practicum/shareit/user/UserControllerTest.java diff --git a/gateway/Dockerfile b/gateway/Dockerfile new file mode 100644 index 0000000..0ff1817 --- /dev/null +++ b/gateway/Dockerfile @@ -0,0 +1,5 @@ +FROM eclipse-temurin:21-jre-jammy +VOLUME /tmp +ARG JAR_FILE=target/*.jar +COPY ${JAR_FILE} app.jar +ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} -jar /app.jar"] \ No newline at end of file diff --git a/gateway/pom.xml b/gateway/pom.xml new file mode 100644 index 0000000..f3394c1 --- /dev/null +++ b/gateway/pom.xml @@ -0,0 +1,70 @@ + + + 4.0.0 + + ru.practicum + shareit + 0.0.1-SNAPSHOT + + + shareit-gateway + 0.0.1-SNAPSHOT + + ShareIt Gateway + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-validation + + + + org.springframework.boot + spring-boot-starter-actuator + + + + org.hibernate.validator + hibernate-validator + + + + org.apache.httpcomponents.client5 + httpclient5 + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + org.projectlombok + lombok + true + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/gateway/src/main/java/ru/practicum/shareit/ShareItGateway.java b/gateway/src/main/java/ru/practicum/shareit/ShareItGateway.java new file mode 100644 index 0000000..0aa75c3 --- /dev/null +++ b/gateway/src/main/java/ru/practicum/shareit/ShareItGateway.java @@ -0,0 +1,12 @@ +package ru.practicum.shareit; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ShareItGateway { + public static void main(String[] args) { + SpringApplication.run(ShareItGateway.class, args); + } + +} diff --git a/gateway/src/main/java/ru/practicum/shareit/booking/BookingController.java b/gateway/src/main/java/ru/practicum/shareit/booking/BookingController.java new file mode 100644 index 0000000..4a7b045 --- /dev/null +++ b/gateway/src/main/java/ru/practicum/shareit/booking/BookingController.java @@ -0,0 +1,80 @@ +package ru.practicum.shareit.booking; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import ru.practicum.shareit.rest.RestQueryBuilder; +import ru.practicum.shareit.rest.RestService; +import ru.practicum.shareit.booking.dto.BookingDto; + +@RestController +@RequestMapping(path = "/bookings") +@RequiredArgsConstructor +public class BookingController { + private final BookingService bookingService; + + @GetMapping("/{id}") + public ResponseEntity getBooking( + @PathVariable long id, + @RequestHeader("X-Sharer-User-Id") long userId) { + var request = RestQueryBuilder.builder() + .method(HttpMethod.GET) + .path("/" + id) + .requestHead("X-Sharer-User-Id", String.valueOf(userId)) + .build(); + + return bookingService.executeQuery(request); + } + + @GetMapping + public ResponseEntity getBookingForUserId( + @RequestHeader("X-Sharer-User-Id") long userId) { + var request = RestQueryBuilder.builder() + .method(HttpMethod.GET) + .requestHead("X-Sharer-User-Id", String.valueOf(userId)) + .build(); + + return bookingService.executeQuery(request); + } + + @GetMapping("/owner") + public ResponseEntity getBookingForItemOwnerId( + @RequestHeader("X-Sharer-User-Id") long ownerId) { + var request = RestQueryBuilder.builder() + .method(HttpMethod.GET) + .path("/owner") + .requestHead("X-Sharer-User-Id", String.valueOf(ownerId)) + .build(); + + return bookingService.executeQuery(request); + } + + @PostMapping + public ResponseEntity postBooking( + @RequestHeader("X-Sharer-User-Id") long userId, + @Valid @RequestBody BookingDto bookingDto) { + var request = RestQueryBuilder.builder() + .method(HttpMethod.POST) + .requestHead("X-Sharer-User-Id", String.valueOf(userId)) + .body(bookingDto) + .build(); + + return bookingService.executeQuery(request); + } + + @PatchMapping("/{id}") + public ResponseEntity patchBooking( + @PathVariable long id, + @RequestParam(name = "approved") boolean approved, + @RequestHeader("X-Sharer-User-Id") long userId) { + var request = RestQueryBuilder.builder() + .method(HttpMethod.PATCH) + .path("/" + id + "?approved=" + (approved ? "true" : "false")) + .requestHead("X-Sharer-User-Id", String.valueOf(userId)) + .build(); + + return bookingService.executeQuery(request); + } +} diff --git a/gateway/src/main/java/ru/practicum/shareit/booking/BookingService.java b/gateway/src/main/java/ru/practicum/shareit/booking/BookingService.java new file mode 100644 index 0000000..ccfde5a --- /dev/null +++ b/gateway/src/main/java/ru/practicum/shareit/booking/BookingService.java @@ -0,0 +1,26 @@ +package ru.practicum.shareit.booking; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.stereotype.Service; +import org.springframework.web.util.DefaultUriBuilderFactory; +import ru.practicum.shareit.rest.RestService; + +@Service +public class BookingService extends RestService { + private static final String API_PREFIX = "/bookings"; + + @Autowired + public BookingService( + @Value("${shareit-server.url}") String serverUrl, + RestTemplateBuilder builder) { + super( + builder + .uriTemplateHandler(new DefaultUriBuilderFactory(serverUrl + API_PREFIX)) + .requestFactory(() -> new HttpComponentsClientHttpRequestFactory()) + .build() + ); + } +} diff --git a/gateway/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java b/gateway/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java new file mode 100644 index 0000000..93e4e47 --- /dev/null +++ b/gateway/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java @@ -0,0 +1,17 @@ +package ru.practicum.shareit.booking.dto; + + +import lombok.Builder; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.user.dto.UserDto; + +@Builder(toBuilder = true) +public record BookingDto( + Long id, + Long itemId, + BookingStatus status, + String start, + String end, + UserDto booker, + ItemDto item +){ } diff --git a/gateway/src/main/java/ru/practicum/shareit/booking/dto/BookingStatus.java b/gateway/src/main/java/ru/practicum/shareit/booking/dto/BookingStatus.java new file mode 100644 index 0000000..3353e65 --- /dev/null +++ b/gateway/src/main/java/ru/practicum/shareit/booking/dto/BookingStatus.java @@ -0,0 +1,8 @@ +package ru.practicum.shareit.booking.dto; + +public enum BookingStatus { + WAITING, + APPROVED, + REJECTED, + CANCELED +} diff --git a/src/main/java/ru/practicum/shareit/booking/dto/BookingStatusRequestDto.java b/gateway/src/main/java/ru/practicum/shareit/booking/dto/BookingStatusRequestDto.java similarity index 100% rename from src/main/java/ru/practicum/shareit/booking/dto/BookingStatusRequestDto.java rename to gateway/src/main/java/ru/practicum/shareit/booking/dto/BookingStatusRequestDto.java diff --git a/src/main/java/ru/practicum/shareit/booking/dto/ReviewDto.java b/gateway/src/main/java/ru/practicum/shareit/booking/dto/ReviewDto.java similarity index 100% rename from src/main/java/ru/practicum/shareit/booking/dto/ReviewDto.java rename to gateway/src/main/java/ru/practicum/shareit/booking/dto/ReviewDto.java diff --git a/gateway/src/main/java/ru/practicum/shareit/item/ItemController.java b/gateway/src/main/java/ru/practicum/shareit/item/ItemController.java new file mode 100644 index 0000000..4d11657 --- /dev/null +++ b/gateway/src/main/java/ru/practicum/shareit/item/ItemController.java @@ -0,0 +1,120 @@ +package ru.practicum.shareit.item; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import ru.practicum.shareit.item.dto.CommentDto; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.dto.ItemToUpdateDto; +import ru.practicum.shareit.rest.RestQueryBuilder; + +import java.util.List; + + +@RestController +@RequestMapping("/items") +@RequiredArgsConstructor +public class ItemController { + private final ItemService itemService; + + @GetMapping + public ResponseEntity getItems(@RequestHeader("X-Sharer-User-Id") long userId) { + var restQuery = RestQueryBuilder.builder() + .method(HttpMethod.GET) + .requestHeadUserId(userId) + .build(); + + return itemService.executeQuery(restQuery); + } + + @GetMapping("/{id}") + public ResponseEntity getItem(@PathVariable long id) { + var restQuery = RestQueryBuilder.builder() + .method(HttpMethod.GET) + .path("/" + id) + .build(); + + return itemService.executeQuery(restQuery); + } + + @GetMapping("/search") + public ResponseEntity findItemsByText(@RequestParam String text) { + var restQuery = RestQueryBuilder.builder() + .method(HttpMethod.GET) + .path("/search?text=" + text) + .build(); + + return itemService.executeQuery(restQuery); + } + + @PostMapping + public ResponseEntity postItem( + @Valid @RequestBody ItemDto itemDto, + @RequestHeader("X-Sharer-User-Id") long userId) { + var restQuery = RestQueryBuilder.builder() + .method(HttpMethod.POST) + .requestHeadUserId(userId) + .body(itemDto) + .build(); + + return itemService.executeQuery(restQuery); + } + + @PostMapping("/{id}/comment") + public ResponseEntity postComment( + @PathVariable long id, + @RequestHeader("X-Sharer-User-Id") long userId, + @Valid @RequestBody CommentDto commentDto) { + var restQuery = RestQueryBuilder.builder() + .method(HttpMethod.POST) + .path("/" + id + "/comment") + .requestHeadUserId(userId) + .body(commentDto) + .build(); + + return itemService.executeQuery(restQuery); + } + + @PutMapping() + public ResponseEntity putItem( + @Valid @RequestBody ItemDto itemDto, + @RequestHeader("X-Sharer-User-Id") long userId) { + var restQuery = RestQueryBuilder.builder() + .method(HttpMethod.PUT) + .requestHeadUserId(userId) + .body(itemDto) + .build(); + + return itemService.executeQuery(restQuery); + } + + @PatchMapping("/{id}") + public ResponseEntity patchItem( + @PathVariable long id, + @Valid @RequestBody ItemToUpdateDto item, + @RequestHeader("X-Sharer-User-Id") long userId) { + var restQuery = RestQueryBuilder.builder() + .method(HttpMethod.PATCH) + .path("/" + id) + .requestHeadUserId(userId) + .body(item) + .build(); + + return itemService.executeQuery(restQuery); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteItem( + @PathVariable long id, + @RequestHeader("X-Sharer-User-Id") long userId) { + var restQuery = RestQueryBuilder.builder() + .method(HttpMethod.DELETE) + .path("/" + id) + .requestHeadUserId(userId) + .build(); + + return itemService.executeQuery(restQuery); + } +} diff --git a/gateway/src/main/java/ru/practicum/shareit/item/dto/CommentDto.java b/gateway/src/main/java/ru/practicum/shareit/item/dto/CommentDto.java new file mode 100644 index 0000000..6b72310 --- /dev/null +++ b/gateway/src/main/java/ru/practicum/shareit/item/dto/CommentDto.java @@ -0,0 +1,14 @@ +package ru.practicum.shareit.item.dto; + +import jakarta.validation.constraints.NotBlank; +import lombok.Builder; + +import java.sql.Timestamp; + +@Builder(toBuilder = true) +public record CommentDto( + Long id, + @NotBlank String text, + String authorName, + Timestamp created +) { } diff --git a/gateway/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java b/gateway/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java new file mode 100644 index 0000000..842bbd5 --- /dev/null +++ b/gateway/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java @@ -0,0 +1,20 @@ +package ru.practicum.shareit.item.dto; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Builder; + +import java.sql.Timestamp; +import java.util.List; + +@Builder(toBuilder = true) +public record ItemDto( + Long id, + @NotBlank String name, + @NotBlank String description, + @NotNull Boolean available, + Timestamp lastBooking, + Timestamp nextBooking, + List comments, + Long requestId +) { } diff --git a/gateway/src/main/java/ru/practicum/shareit/item/dto/ItemToUpdateDto.java b/gateway/src/main/java/ru/practicum/shareit/item/dto/ItemToUpdateDto.java new file mode 100644 index 0000000..af7523d --- /dev/null +++ b/gateway/src/main/java/ru/practicum/shareit/item/dto/ItemToUpdateDto.java @@ -0,0 +1,10 @@ +package ru.practicum.shareit.item.dto; + +import lombok.Builder; + +@Builder +public record ItemToUpdateDto( + String name, + String description, + Boolean available +) { } diff --git a/gateway/src/main/java/ru/practicum/shareit/request/RequestController.java b/gateway/src/main/java/ru/practicum/shareit/request/RequestController.java new file mode 100644 index 0000000..4ba16fb --- /dev/null +++ b/gateway/src/main/java/ru/practicum/shareit/request/RequestController.java @@ -0,0 +1,61 @@ +package ru.practicum.shareit.request; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import ru.practicum.shareit.request.dto.RequestDto; +import ru.practicum.shareit.rest.RestQueryBuilder; + +@RestController +@RequestMapping(path = "/requests") +@RequiredArgsConstructor +public class RequestController { + private final RequestService requestService; + + @GetMapping + public ResponseEntity getSelfRequests( + @RequestHeader("X-Sharer-User-Id") long userId) { + var query = RestQueryBuilder.builder() + .method(HttpMethod.GET) + .requestHead("X-Sharer-User-Id", String.valueOf(userId)) + .build(); + + return requestService.executeQuery(query); + } + + @GetMapping("/{id}") + public ResponseEntity getRequestById(@PathVariable long id) { + var query = RestQueryBuilder.builder() + .method(HttpMethod.GET) + .path("/" + id) + .build(); + + return requestService.executeQuery(query); + } + + @GetMapping("/all") + public ResponseEntity getOtherUserRequests(@RequestHeader("X-Sharer-User-Id") long userId) { + var query = RestQueryBuilder.builder() + .method(HttpMethod.GET) + .path("/all") + .requestHead("X-Sharer-User-Id", String.valueOf(userId)) + .build(); + + return requestService.executeQuery(query); + } + + @PostMapping + public ResponseEntity postRequestDto( + @Valid @RequestBody RequestDto requestDto, + @RequestHeader("X-Sharer-User-Id") long userId) { + var query = RestQueryBuilder.builder() + .method(HttpMethod.POST) + .requestHead("X-Sharer-User-Id", String.valueOf(userId)) + .body(requestDto) + .build(); + + return requestService.executeQuery(query); + } +} diff --git a/gateway/src/main/java/ru/practicum/shareit/request/RequestService.java b/gateway/src/main/java/ru/practicum/shareit/request/RequestService.java new file mode 100644 index 0000000..72d8b4b --- /dev/null +++ b/gateway/src/main/java/ru/practicum/shareit/request/RequestService.java @@ -0,0 +1,26 @@ +package ru.practicum.shareit.request; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.stereotype.Service; +import org.springframework.web.util.DefaultUriBuilderFactory; +import ru.practicum.shareit.rest.RestService; + +@Service +public class RequestService extends RestService { + private static final String API_PREFIX = "/requests"; + + @Autowired + public RequestService( + @Value("${shareit-server.url}") String serverUrl, + RestTemplateBuilder builder) { + super( + builder + .uriTemplateHandler(new DefaultUriBuilderFactory(serverUrl + API_PREFIX)) + .requestFactory(() -> new HttpComponentsClientHttpRequestFactory()) + .build() + ); + } +} diff --git a/src/main/java/ru/practicum/shareit/request/dto/RequestDto.java b/gateway/src/main/java/ru/practicum/shareit/request/dto/RequestDto.java similarity index 100% rename from src/main/java/ru/practicum/shareit/request/dto/RequestDto.java rename to gateway/src/main/java/ru/practicum/shareit/request/dto/RequestDto.java diff --git a/gateway/src/main/java/ru/practicum/shareit/rest/RestQueryBuilder.java b/gateway/src/main/java/ru/practicum/shareit/rest/RestQueryBuilder.java new file mode 100644 index 0000000..4892f5f --- /dev/null +++ b/gateway/src/main/java/ru/practicum/shareit/rest/RestQueryBuilder.java @@ -0,0 +1,58 @@ +package ru.practicum.shareit.rest; + +import lombok.Value; +import org.springframework.http.HttpMethod; + +import java.util.Optional; + +public class RestQueryBuilder { + private final RestQueryDto.RestQueryDtoBuilder builder; + + private RestQueryBuilder(RestQueryDto.RestQueryDtoBuilder builder) { + this.builder = builder; + } + + public static RestQueryBuilder builder() { + return new RestQueryBuilder(RestQueryDto.builder()); + } + + public RestQueryDto build() { + return builder.build(); + } + + public RestQueryBuilder method(HttpMethod method) { + builder.httpMethod(method); + + return this; + } + + public RestQueryBuilder path(String path) { + builder.path(path); + + return this; + } + + public RestQueryBuilder requestHead(RestQueryHead restQueryHead) { + builder.requestHead(Optional.of(restQueryHead)); + + return this; + } + + public RestQueryBuilder requestHead(String name, String value) { + builder.requestHead(Optional.of(new RestQueryHead(name, value))); + + return this; + } + + public RestQueryBuilder requestHeadUserId(long userId) { + builder.requestHead(Optional.of(new RestQueryHead("X-Sharer-User-Id", String.valueOf(userId)))); + + return this; + } + + public RestQueryBuilder body(Object body) { + builder.body(Optional.of(body)); + + return this; + } +} diff --git a/gateway/src/main/java/ru/practicum/shareit/rest/RestQueryDto.java b/gateway/src/main/java/ru/practicum/shareit/rest/RestQueryDto.java new file mode 100644 index 0000000..3644988 --- /dev/null +++ b/gateway/src/main/java/ru/practicum/shareit/rest/RestQueryDto.java @@ -0,0 +1,20 @@ +package ru.practicum.shareit.rest; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Value; +import org.springframework.http.HttpMethod; + +import java.util.Optional; + +@Builder(access = AccessLevel.PACKAGE) +@Value +public class RestQueryDto { + HttpMethod httpMethod; + @Builder.Default + String path = ""; + @Builder.Default + Optional requestHead = Optional.empty(); + @Builder.Default + Optional body = Optional.empty(); +} diff --git a/gateway/src/main/java/ru/practicum/shareit/rest/RestQueryHead.java b/gateway/src/main/java/ru/practicum/shareit/rest/RestQueryHead.java new file mode 100644 index 0000000..56076ba --- /dev/null +++ b/gateway/src/main/java/ru/practicum/shareit/rest/RestQueryHead.java @@ -0,0 +1,7 @@ +package ru.practicum.shareit.rest; + +public record RestQueryHead( + String name, + String value +) { +} diff --git a/gateway/src/main/java/ru/practicum/shareit/rest/RestService.java b/gateway/src/main/java/ru/practicum/shareit/rest/RestService.java new file mode 100644 index 0000000..ffecb63 --- /dev/null +++ b/gateway/src/main/java/ru/practicum/shareit/rest/RestService.java @@ -0,0 +1,64 @@ +package ru.practicum.shareit.rest; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.*; +import org.springframework.web.client.HttpStatusCodeException; +import org.springframework.web.client.RestTemplate; + +import java.util.List; +import java.util.Optional; + + +@Slf4j +@RequiredArgsConstructor +public abstract class RestService { + private final RestTemplate restTemplate; + + public ResponseEntity executeQuery(RestQueryDto restQueryDto) { + log.trace("try exchange " + restQueryDto); + + var headers = getHeaders(restQueryDto.getRequestHead()); + + HttpEntity restQueryEntity = restQueryDto.getBody() + .map(i -> new HttpEntity<>(i, headers)) + .orElse(new HttpEntity<>(headers)); + + try { + var response = restTemplate.exchange( + restQueryDto.getPath(), + restQueryDto.getHttpMethod(), + restQueryEntity, + Object.class); + + return prepareGatewayResponse(response); + } catch (HttpStatusCodeException e) { + return ResponseEntity.status(e.getStatusCode()).body(e.getResponseBodyAsByteArray()); + } + } + + private HttpHeaders getHeaders(Optional head) { + HttpHeaders headers = new HttpHeaders(); + + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(List.of(MediaType.APPLICATION_JSON)); + + head.ifPresent(i -> headers.set(i.name(), i.value())); + + return headers; + } + + private ResponseEntity prepareGatewayResponse(ResponseEntity response) { + if (response.getStatusCode().is2xxSuccessful()) { + return response; + } + + ResponseEntity.BodyBuilder responseBuilder = ResponseEntity.status(response.getStatusCode()); + + if (response.hasBody()) { + return responseBuilder.body(response.getBody()); + } + + return responseBuilder.build(); + } +} diff --git a/gateway/src/main/java/ru/practicum/shareit/user/UserController.java b/gateway/src/main/java/ru/practicum/shareit/user/UserController.java new file mode 100644 index 0000000..91bd234 --- /dev/null +++ b/gateway/src/main/java/ru/practicum/shareit/user/UserController.java @@ -0,0 +1,72 @@ +package ru.practicum.shareit.user; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import ru.practicum.shareit.rest.RestQueryBuilder; +import ru.practicum.shareit.rest.RestService; +import ru.practicum.shareit.user.dto.UserDto; +import ru.practicum.shareit.user.dto.UserToUpdateDto; + + +@RestController +@RequestMapping(path = "/users") +@RequiredArgsConstructor +public class UserController { + private final UserService userService; + + @GetMapping("/{id}") + public ResponseEntity getUser(@PathVariable long id) { + var query = RestQueryBuilder.builder() + .method(HttpMethod.GET) + .path("/" + id) + .build(); + + return userService.executeQuery(query); + } + + @PostMapping + public ResponseEntity postUser(@Valid @RequestBody UserDto user) { + var query = RestQueryBuilder.builder() + .method(HttpMethod.POST) + .body(user) + .build(); + + return userService.executeQuery(query); + } + + @PutMapping + public ResponseEntity putUser(@Valid @RequestBody UserDto user) { + var query = RestQueryBuilder.builder() + .method(HttpMethod.PUT) + .body(user) + .build(); + + return userService.executeQuery(query); + } + + @PatchMapping("/{id}") + public ResponseEntity patchUser( + @PathVariable long id, + @RequestBody @Valid UserToUpdateDto user) { + var query = RestQueryBuilder.builder() + .method(HttpMethod.PATCH) + .path("/" + id) + .body(user) + .build(); + + return userService.executeQuery(query); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteUser(@PathVariable long id) { + var query = RestQueryBuilder.builder() + .method(HttpMethod.DELETE) + .path("/" + id) + .build(); + + return userService.executeQuery(query); + } +} diff --git a/gateway/src/main/java/ru/practicum/shareit/user/UserService.java b/gateway/src/main/java/ru/practicum/shareit/user/UserService.java new file mode 100644 index 0000000..5adf826 --- /dev/null +++ b/gateway/src/main/java/ru/practicum/shareit/user/UserService.java @@ -0,0 +1,26 @@ +package ru.practicum.shareit.user; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.stereotype.Service; +import org.springframework.web.util.DefaultUriBuilderFactory; +import ru.practicum.shareit.rest.RestService; + +@Service +public class UserService extends RestService { + private static final String API_PREFIX = "/users"; + + @Autowired + public UserService( + @Value("${shareit-server.url}") String serverUrl, + RestTemplateBuilder builder) { + super( + builder + .uriTemplateHandler(new DefaultUriBuilderFactory(serverUrl + API_PREFIX)) + .requestFactory(() -> new HttpComponentsClientHttpRequestFactory()) + .build() + ); + } +} diff --git a/src/main/java/ru/practicum/shareit/user/dto/UserDto.java b/gateway/src/main/java/ru/practicum/shareit/user/dto/UserDto.java similarity index 100% rename from src/main/java/ru/practicum/shareit/user/dto/UserDto.java rename to gateway/src/main/java/ru/practicum/shareit/user/dto/UserDto.java diff --git a/src/main/java/ru/practicum/shareit/user/dto/UserToUpdateDto.java b/gateway/src/main/java/ru/practicum/shareit/user/dto/UserToUpdateDto.java similarity index 100% rename from src/main/java/ru/practicum/shareit/user/dto/UserToUpdateDto.java rename to gateway/src/main/java/ru/practicum/shareit/user/dto/UserToUpdateDto.java diff --git a/gateway/src/main/resources/application.properties b/gateway/src/main/resources/application.properties new file mode 100644 index 0000000..2ee0851 --- /dev/null +++ b/gateway/src/main/resources/application.properties @@ -0,0 +1,7 @@ +logging.level.org.springframework.web.client.RestTemplate=DEBUG +#logging.level.org.apache.http=DEBUG +#logging.level.httpclient.wire=DEBUG + +server.port=8080 + +shareit-server.url=http://localhost:9090 \ No newline at end of file diff --git a/gateway/src/test/ShareItTests.java b/gateway/src/test/ShareItTests.java new file mode 100644 index 0000000..4d79052 --- /dev/null +++ b/gateway/src/test/ShareItTests.java @@ -0,0 +1,13 @@ +package ru.practicum.shareit; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ShareItTests { + + @Test + void contextLoads() { + } + +} diff --git a/gateway/src/test/java/ru/practicum/shareit/ShareItTests.java b/gateway/src/test/java/ru/practicum/shareit/ShareItTests.java new file mode 100644 index 0000000..4d79052 --- /dev/null +++ b/gateway/src/test/java/ru/practicum/shareit/ShareItTests.java @@ -0,0 +1,13 @@ +package ru.practicum.shareit; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ShareItTests { + + @Test + void contextLoads() { + } + +} diff --git a/gateway/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java b/gateway/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java new file mode 100644 index 0000000..eb4343f --- /dev/null +++ b/gateway/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java @@ -0,0 +1,277 @@ +package ru.practicum.shareit.booking; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import ru.practicum.shareit.booking.dto.BookingDto; +import ru.practicum.shareit.booking.dto.BookingStatus; +import ru.practicum.shareit.rest.RestQueryBuilder; +import ru.practicum.shareit.rest.RestQueryDto; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +public class BookingControllerTest { + @Mock + BookingService bookingService; + + @InjectMocks + BookingController bookingController; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void requestPathWithoutUserIdInHead() throws Exception { + List needIdUserFromHeadRequest = + List.of(get("/bookings/1"), + get("/bookings"), + get("/bookings/owner"), + post("/bookings"), + patch("/bookings/1?approved=true")); + + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + for (var requestBuilder: needIdUserFromHeadRequest) { + var result = mockMvc.perform(requestBuilder) + .andReturn(); + + var status = result + .getResponse() + .getStatus(); + + var path = result.getRequest().getMethod() + " '" + result.getRequest().getRequestURI() + "'"; + + Assertions.assertEquals(400, status, path + " was needed userid as RequestHeader \"X-Sharer-User-Id\""); + } + } + + @Test + public void getBookingTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + var dto = BookingDto.builder() + .id(10L) + .build(); + + var response = new ResponseEntity<>( + (Object) dto, + HttpStatus.OK); + + Mockito.when(bookingService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + mockMvc.perform(get("/bookings/1") + .header("X-Sharer-User-Id", 1L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(10L), Long.class)); + + Mockito.verify(bookingService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.GET) + .path("/1") + .requestHeadUserId(1L) + .build()); + } + + @Test + void getItemsForUserIdTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + var expectedResult = List.of( + BookingDto.builder().id(1L).build(), + BookingDto.builder().id(2L).build(), + BookingDto.builder().id(3L).build()); + + var response = new ResponseEntity<>( + (Object) expectedResult, + HttpStatus.OK); + + Mockito.when(bookingService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + mockMvc.perform(get("/bookings") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.[0].id",is(1L), Long.class)) + .andExpect(jsonPath("$.[1].id",is(2L), Long.class)) + .andExpect(jsonPath("$.[2].id",is(3L), Long.class)); + + Mockito.verify(bookingService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.GET) + .requestHeadUserId(10L) + .build()); + } + + @Test + void getItemsForItemOwnerIdTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + var expectedResult = List.of( + BookingDto.builder().id(1L).build(), + BookingDto.builder().id(2L).build(), + BookingDto.builder().id(3L).build()); + + var response = new ResponseEntity<>( + (Object) expectedResult, + HttpStatus.OK); + + Mockito.when(bookingService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + mockMvc.perform(get("/bookings/owner") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.[0].id",is(1L), Long.class)) + .andExpect(jsonPath("$.[1].id",is(2L), Long.class)) + .andExpect(jsonPath("$.[2].id",is(3L), Long.class)); + + Mockito.verify(bookingService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.GET) + .path("/owner") + .requestHeadUserId(10L) + .build()); + } + + @Test + void postItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + var dto = BookingDto.builder() + .id(50L) + .build(); + + var response = new ResponseEntity<>( + (Object) BookingDto.builder().id(17L).build(), + HttpStatus.OK); + + Mockito.when(bookingService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + mockMvc.perform(post("/bookings") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(17L), Long.class)); + + Mockito.verify(bookingService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.POST) + .requestHeadUserId(10L) + .body(dto) + .build()); + } + + @Test + void postItemWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + mockMvc.perform(post("/bookings") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } + + @Test + void patchItemApprovedTrueTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + var dto = BookingDto.builder() + .id(15L) + .status(BookingStatus.APPROVED) + .build(); + + var response = new ResponseEntity<>( + (Object) dto, + HttpStatus.OK); + + Mockito.when(bookingService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + mockMvc.perform(patch("/bookings/10?approved=true") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.status",is(BookingStatus.APPROVED.name()), String.class)); + + Mockito.verify(bookingService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.PATCH) + .path("/10?approved=true") + .requestHeadUserId(10L) + .build()); + } + + @Test + void patchItemApprovedFalseTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + var dto = BookingDto.builder() + .id(10L) + .status(BookingStatus.REJECTED) + .build(); + + var response = new ResponseEntity<>( + (Object) dto, + HttpStatus.OK); + + Mockito.when(bookingService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + mockMvc.perform(patch("/bookings/10?approved=false") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.status",is(BookingStatus.REJECTED.name()), String.class)); + + Mockito.verify(bookingService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.PATCH) + .path("/10?approved=false") + .requestHeadUserId(10L) + .build()); + } + + @Test + void patchItemWithoutParamsTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + mockMvc.perform(patch("/bookings/100") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } +} diff --git a/gateway/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java b/gateway/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java new file mode 100644 index 0000000..558660a --- /dev/null +++ b/gateway/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java @@ -0,0 +1,374 @@ +package ru.practicum.shareit.item; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import ru.practicum.shareit.booking.dto.BookingDto; +import ru.practicum.shareit.item.ItemController; +import ru.practicum.shareit.item.ItemService; +import ru.practicum.shareit.item.dto.CommentDto; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.dto.ItemToUpdateDto; +import ru.practicum.shareit.rest.RestQueryBuilder; +import ru.practicum.shareit.rest.RestQueryDto; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +public class ItemControllerTest { + @Mock + ItemService itemService; + + @InjectMocks + ItemController itemController; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void requestPathWithoutUserIdInHead() throws Exception { + List needIdUserFromHeadRequest = + List.of(post("/items"), + post("/items/1/comment"), + put("/items"), + patch("/items/1"), + delete("/items/1")); + + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + for (var requestBuilder: needIdUserFromHeadRequest) { + var result = mockMvc.perform(requestBuilder) + .andReturn(); + + var status = result + .getResponse() + .getStatus(); + + var path = result.getRequest().getMethod() + " '" + result.getRequest().getRequestURI() + "'"; + + Assertions.assertEquals(400, status, path + " was needed userid as RequestHeader \"X-Sharer-User-Id\""); + } + } + + @Test + public void getItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var dto = ItemDto.builder() + .id(10L) + .build(); + + var response = new ResponseEntity<>( + (Object) dto, + HttpStatus.OK); + + Mockito.when(itemService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + mockMvc.perform(get("/items/1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(10L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.GET) + .path("/1") + .build()); + } + + @Test + void getItemsForUserIdTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var expectedResult = List.of( + ItemDto.builder().id(11L).build(), + ItemDto.builder().id(42L).build(), + ItemDto.builder().id(37L).build()); + + var response = new ResponseEntity<>( + (Object) expectedResult, + HttpStatus.OK); + + Mockito.when(itemService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + mockMvc.perform(get("/items") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.[0].id",is(11L), Long.class)) + .andExpect(jsonPath("$.[1].id",is(42L), Long.class)) + .andExpect(jsonPath("$.[2].id",is(37L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.GET) + .requestHeadUserId(10L) + .build()); + } + + @Test + void findItemsByTextTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var expectedResult = List.of( + ItemDto.builder().id(1L).build(), + ItemDto.builder().id(42L).build(), + ItemDto.builder().id(37L).build()); + + var response = new ResponseEntity<>( + (Object) expectedResult, + HttpStatus.OK); + + Mockito.when(itemService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + mockMvc.perform(get("/items/search?text=abc")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.[0].id",is(1L), Long.class)) + .andExpect(jsonPath("$.[1].id",is(42L), Long.class)) + .andExpect(jsonPath("$.[2].id",is(37L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.GET) + .path("/search?text=abc") + .build()); + } + + @Test + void postItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var response = new ResponseEntity<>( + (Object) ItemDto.builder().id(50L).build(), + HttpStatus.OK); + + Mockito.when(itemService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + var dto = ItemDto.builder() + .id(13L) + .name("la") + .available(true) + .description("ma") + .build(); + + mockMvc.perform(post("/items") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.POST) + .requestHeadUserId(10L) + .body(dto) + .build()); + } + + @Test + void postItemWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(post("/items") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } + + @Test + void postCommentTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var commentDto = CommentDto.builder() + .id(47L) + .text("la") + .build(); + + var response = new ResponseEntity<>( + (Object) commentDto, + HttpStatus.OK); + + Mockito.when(itemService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + mockMvc.perform(post("/items/13/comment") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(commentDto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(47L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.POST) + .path("/13/comment") + .requestHeadUserId(10L) + .body(commentDto) + .build()); + } + + @Test + void postCommentWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(post("/items/13/comment") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } + + @Test + void putItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var response = new ResponseEntity<>( + (Object) ItemDto.builder().id(50L).build(), + HttpStatus.OK); + + Mockito.when(itemService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + var dto = ItemDto.builder() + .id(13L) + .name("la") + .description("ma") + .available(true) + .build(); + + mockMvc.perform(put("/items") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.PUT) + .requestHeadUserId(10L) + .body(dto) + .build()); + } + + @Test + void putItemWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(put("/items") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } + + @Test + void patchItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var dto = ItemToUpdateDto.builder() + .build(); + + var response = new ResponseEntity<>( + (Object) ItemDto.builder().id(50L).build(), + HttpStatus.OK); + + Mockito.when(itemService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + mockMvc.perform(patch("/items/17") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.PATCH) + .path("/17") + .requestHeadUserId(10L) + .body(dto) + .build()); + } + + @Test + void patchItemWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(put("/items") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } + + @Test + void deleteItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var dto = ItemDto.builder() + .id(50L) + .build(); + + var response = new ResponseEntity<>( + (Object) dto, + HttpStatus.OK); + + Mockito.when(itemService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + mockMvc.perform(delete("/items/17") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.DELETE) + .path("/17") + .requestHeadUserId(10L) + .build()); + } +} diff --git a/gateway/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java b/gateway/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java new file mode 100644 index 0000000..3f14d2c --- /dev/null +++ b/gateway/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java @@ -0,0 +1,206 @@ +package ru.practicum.shareit.request; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import ru.practicum.shareit.booking.dto.BookingDto; +import ru.practicum.shareit.item.dto.CommentDto; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.dto.ItemToUpdateDto; +import ru.practicum.shareit.request.RequestController; +import ru.practicum.shareit.request.RequestService; +import ru.practicum.shareit.request.dto.RequestDto; +import ru.practicum.shareit.rest.RestQueryBuilder; +import ru.practicum.shareit.rest.RestQueryDto; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +public class RequestControllerTest { + @Mock + RequestService requestService; + + @InjectMocks + RequestController requestController; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void requestPathWithoutUserIdInHead() throws Exception { + List needIdUserFromHeadRequest = + List.of(get("/requests"), + get("/requests/all"), + post("/requests")); + + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + for (var requestBuilder: needIdUserFromHeadRequest) { + var result = mockMvc.perform(requestBuilder) + .andReturn(); + + var status = result + .getResponse() + .getStatus(); + + var path = result.getRequest().getMethod() + " '" + result.getRequest().getRequestURI() + "'"; + + Assertions.assertEquals(400, status, path + " was needed userid as RequestHeader \"X-Sharer-User-Id\""); + } + } + + @Test + public void getSelfRequestsTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + List expectedRequests = List.of( + RequestDto.builder().id(13L).build(), + RequestDto.builder().id(24L).build(), + RequestDto.builder().id(37L).build() + ); + + var response = new ResponseEntity<>( + (Object)expectedRequests, + HttpStatus.OK); + + Mockito.when(requestService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + mockMvc.perform(get("/requests") + .header("X-Sharer-User-Id", 7L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id", is(13L), Long.class)) + .andExpect(jsonPath("$[1].id", is(24L), Long.class)) + .andExpect(jsonPath("$[2].id", is(37L), Long.class)); + + Mockito.verify(requestService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.GET) + .requestHeadUserId(7L) + .build()); + } + + @Test + void getRequestByIdTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + var expectedResult = RequestDto.builder().id(13L).build(); + + var response = new ResponseEntity<>( + (Object) expectedResult, + HttpStatus.OK); + + Mockito.when(requestService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + mockMvc.perform(get("/requests/23")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(13L), Long.class)); + + Mockito.verify(requestService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.GET) + .path("/23") + .build()); + } + + @Test + void getOtherUserRequestsTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + List expectedRequests = List.of( + RequestDto.builder().id(13L).build(), + RequestDto.builder().id(24L).build(), + RequestDto.builder().id(37L).build() + ); + + var response = new ResponseEntity<>( + (Object) expectedRequests, + HttpStatus.OK); + + Mockito.when(requestService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + mockMvc.perform(get("/requests/all") + .header("X-Sharer-User-Id", 7L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id", is(13L), Long.class)) + .andExpect(jsonPath("$[1].id", is(24L), Long.class)) + .andExpect(jsonPath("$[2].id", is(37L), Long.class)); + + Mockito.verify(requestService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.GET) + .path("/all") + .requestHeadUserId(7L) + .build()); + } + + @Test + void postRequestDtoTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + var response = new ResponseEntity<>( + (Object) RequestDto.builder().id(50L).build(), + HttpStatus.OK); + + Mockito.when(requestService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + var dto = RequestDto.builder() + .id(13L) + .description("la") + .build(); + + mockMvc.perform(post("/requests") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(requestService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.POST) + .requestHeadUserId(10L) + .body(dto) + .build()); + } + + @Test + void postRequestWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + mockMvc.perform(post("/requests") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } +} diff --git a/gateway/src/test/java/ru/practicum/shareit/user/UserControllerTest.java b/gateway/src/test/java/ru/practicum/shareit/user/UserControllerTest.java new file mode 100644 index 0000000..1f72b5f --- /dev/null +++ b/gateway/src/test/java/ru/practicum/shareit/user/UserControllerTest.java @@ -0,0 +1,221 @@ +package ru.practicum.shareit.user; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.request.dto.RequestDto; +import ru.practicum.shareit.rest.RestQueryBuilder; +import ru.practicum.shareit.rest.RestQueryDto; +import ru.practicum.shareit.user.UserController; +import ru.practicum.shareit.user.UserService; +import ru.practicum.shareit.user.dto.UserDto; +import ru.practicum.shareit.user.dto.UserToUpdateDto; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +public class UserControllerTest { + @Mock + UserService userService; + + @InjectMocks + UserController userController; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void getUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + var dto = UserDto.builder() + .id(47L) + .name("la") + .email("email@mail.ru") + .build(); + + var response = new ResponseEntity<>( + (Object) dto, + HttpStatus.OK); + + Mockito.when(userService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + mockMvc.perform(get("/users/17")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(47L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.GET) + .path("/17") + .build()); + } + + @Test + void postUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + var response = new ResponseEntity<>( + (Object) ItemDto.builder().id(50L).build(), + HttpStatus.OK); + + Mockito.when(userService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + var dto = UserDto.builder() + .name("la") + .email("email@mail.ru") + .build(); + + mockMvc.perform(post("/users") + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.POST) + .body(dto) + .build()); + } + + @Test + void postUserWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + mockMvc.perform(post("/users")) + .andExpect(status().is(400)); + } + + @Test + void putUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + var response = new ResponseEntity<>( + (Object) ItemDto.builder().id(52L).build(), + HttpStatus.OK); + + Mockito.when(userService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + var dto = UserDto.builder() + .id(10L) + .name("la") + .email("email@mail.ru") + .build(); + + mockMvc.perform(put("/users") + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(52L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.PUT) + .body(dto) + .build()); + } + + @Test + void putUserWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + mockMvc.perform(put("/users")) + .andExpect(status().is(400)); + } + + @Test + void patchUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + var response = new ResponseEntity<>( + (Object) ItemDto.builder().id(542L).build(), + HttpStatus.OK); + + Mockito.when(userService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + var dto = UserToUpdateDto.builder().name("la").build(); + + mockMvc.perform(patch("/users/13") + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(542L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.PATCH) + .path("/13") + .body(dto) + .build()); + } + + @Test + void patchUserWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + mockMvc.perform(patch("/users/13")) + .andExpect(status().is(400)); + } + + @Test + void deleteUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + var response = new ResponseEntity<>( + (Object) ItemDto.builder().id(54L).build(), + HttpStatus.OK); + + Mockito.when(userService.executeQuery(Mockito.any(RestQueryDto.class))) + .thenReturn(response); + + mockMvc.perform(delete("/users/13")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(54L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .executeQuery(RestQueryBuilder.builder() + .method(HttpMethod.DELETE) + .path("/13") + .build()); + } +} diff --git a/gateway/src/test/request/RequestControllerTest.java b/gateway/src/test/request/RequestControllerTest.java new file mode 100644 index 0000000..7b76193 --- /dev/null +++ b/gateway/src/test/request/RequestControllerTest.java @@ -0,0 +1,170 @@ +package ru.practicum.shareit.request; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import ru.practicum.shareit.item.dto.CommentDto; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.dto.ItemToUpdateDto; +import ru.practicum.shareit.request.RequestController; +import ru.practicum.shareit.request.RequestService; +import ru.practicum.shareit.request.dto.RequestDto; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +public class RequestControllerTest { + @Mock + RequestService requestService; + + @InjectMocks + RequestController requestController; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void requestPathWithoutUserIdInHead() throws Exception { + List needIdUserFromHeadRequest = + List.of(get("/requests"), + get("/requests/all"), + post("/requests")); + + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + for (var requestBuilder: needIdUserFromHeadRequest) { + var result = mockMvc.perform(requestBuilder) + .andReturn(); + + var status = result + .getResponse() + .getStatus(); + + var path = result.getRequest().getMethod() + " '" + result.getRequest().getRequestURI() + "'"; + + Assertions.assertEquals(400, status, path + " was needed userid as RequestHeader \"X-Sharer-User-Id\""); + } + } + + @Test + public void getSelfRequestsTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + List expectedRequests = List.of( + RequestDto.builder().id(13L).build(), + RequestDto.builder().id(24L).build(), + RequestDto.builder().id(37L).build() + ); + + Mockito.when(requestService.getRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) + .thenReturn(expectedRequests); + + mockMvc.perform(get("/requests") + .header("X-Sharer-User-Id", 7L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id", is(13L), Long.class)) + .andExpect(jsonPath("$[1].id", is(24L), Long.class)) + .andExpect(jsonPath("$[2].id", is(37L), Long.class)); + + Mockito.verify(requestService, Mockito.times(1)) + .getRequestsByUserId(7L, true); + } + + @Test + void getRequestByIdTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + var expectedResult = RequestDto.builder().id(13L).build(); + + Mockito.when(requestService.getRequestById(Mockito.anyLong())) + .thenReturn(expectedResult); + + mockMvc.perform(get("/requests/23")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(13L), Long.class)); + + Mockito.verify(requestService, Mockito.times(1)) + .getRequestById(23L); + } + + @Test + void getOtherUserRequestsTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + List expectedRequests = List.of( + RequestDto.builder().id(13L).build(), + RequestDto.builder().id(24L).build(), + RequestDto.builder().id(37L).build() + ); + + Mockito.when(requestService.getRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) + .thenReturn(expectedRequests); + + mockMvc.perform(get("/requests/all") + .header("X-Sharer-User-Id", 7L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id", is(13L), Long.class)) + .andExpect(jsonPath("$[1].id", is(24L), Long.class)) + .andExpect(jsonPath("$[2].id", is(37L), Long.class)); + + Mockito.verify(requestService, Mockito.times(1)) + .getRequestsByUserId(7L, false); + } + + @Test + void postRequestDtoTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + Mockito.when(requestService.createRequest(Mockito.any(RequestDto.class), Mockito.anyLong())) + .thenReturn(RequestDto.builder().id(50L).build()); + + var dto = RequestDto.builder() + .id(13L) + .description("la") + .build(); + + mockMvc.perform(post("/requests") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(requestService, Mockito.times(1)) + .createRequest(dto, 10L); + } + + @Test + void postRequestWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + mockMvc.perform(post("/requests") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } +} diff --git a/gateway/src/test/shareit/ShareItTests.java b/gateway/src/test/shareit/ShareItTests.java new file mode 100644 index 0000000..4d79052 --- /dev/null +++ b/gateway/src/test/shareit/ShareItTests.java @@ -0,0 +1,13 @@ +package ru.practicum.shareit; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ShareItTests { + + @Test + void contextLoads() { + } + +} diff --git a/gateway/src/test/shareit/booking/BookingControllerTest.java b/gateway/src/test/shareit/booking/BookingControllerTest.java new file mode 100644 index 0000000..9aa62f4 --- /dev/null +++ b/gateway/src/test/shareit/booking/BookingControllerTest.java @@ -0,0 +1,277 @@ +package ru.practicum.shareit.booking; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import ru.practicum.shareit.booking.BookingController; +import ru.practicum.shareit.booking.BookingService; +import ru.practicum.shareit.booking.BookingStatus; +import ru.practicum.shareit.booking.dto.BookingDto; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.hamcrest.Matchers.is; + +@SpringBootTest +public class BookingControllerTest { + @Mock + BookingService bookingService; + + @InjectMocks + BookingController bookingController; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void requestPathWithoutUserIdInHead() throws Exception { + List needIdUserFromHeadRequest = + List.of(get("/bookings/1"), + get("/bookings"), + get("/bookings/owner"), + post("/bookings"), + patch("/bookings/1?approved=true")); + + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + for (var requestBuilder: needIdUserFromHeadRequest) { + var result = mockMvc.perform(requestBuilder) + .andReturn(); + + var status = result + .getResponse() + .getStatus(); + + var path = result.getRequest().getMethod() + " '" + result.getRequest().getRequestURI() + "'"; + + Assertions.assertEquals(400, status, path + " was needed userid as RequestHeader \"X-Sharer-User-Id\""); + } + } + + @Test + public void getBookingTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + var dto = BookingDto.builder() + .id(10L) + .build(); + + Mockito.when(bookingService.getBooking(Mockito.anyLong(), Mockito.anyLong())) + .thenReturn(dto); + + mockMvc.perform(get("/bookings/1") + .header("X-Sharer-User-Id", 1L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(10L), Long.class)); + } + + @Test + void getItemParsingRequestId() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + mockMvc.perform(get("/bookings/100") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()); + + Mockito.verify(bookingService, Mockito.times(1)) + .getBooking(100, 10); + } + + @Test + void getItemsForUserIdTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + var expectedResult = List.of( + BookingDto.builder().id(1L).build(), + BookingDto.builder().id(2L).build(), + BookingDto.builder().id(3L).build()); + + Mockito.when(bookingService.getBookingForUserId(Mockito.anyLong())) + .thenReturn(expectedResult); + + mockMvc.perform(get("/bookings") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.[0].id",is(1L), Long.class)) + .andExpect(jsonPath("$.[1].id",is(2L), Long.class)) + .andExpect(jsonPath("$.[2].id",is(3L), Long.class)); + } + + @Test + void getItemsForUserIdParsingRequestTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + mockMvc.perform(get("/bookings") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()); + + Mockito.verify(bookingService, Mockito.times(1)) + .getBookingForUserId(10); + } + + @Test + void getItemsForItemOwnerIdTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + var expectedResult = List.of( + BookingDto.builder().id(1L).build(), + BookingDto.builder().id(2L).build(), + BookingDto.builder().id(3L).build()); + + Mockito.when(bookingService.getBookingsForItemOwnerId(Mockito.anyLong())) + .thenReturn(expectedResult); + + mockMvc.perform(get("/bookings/owner") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.[0].id",is(1L), Long.class)) + .andExpect(jsonPath("$.[1].id",is(2L), Long.class)) + .andExpect(jsonPath("$.[2].id",is(3L), Long.class)); + } + + @Test + void getItemsForItemOwnerIdParsingRequestTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + mockMvc.perform(get("/bookings/owner") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()); + + Mockito.verify(bookingService, Mockito.times(1)) + .getBookingsForItemOwnerId(10); + } + + @Test + void postItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + Mockito.when(bookingService.createBooking(Mockito.any(BookingDto.class), Mockito.anyLong())) + .thenReturn(BookingDto.builder().id(50L).build()); + + mockMvc.perform(post("/bookings") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(BookingDto.builder().build())) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + } + + @Test + void postItemParsingRequestTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + var dto = BookingDto.builder().build(); + + mockMvc.perform(post("/bookings") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()); + + Mockito.verify(bookingService, Mockito.times(1)) + .createBooking(dto, 10L); + } + + @Test + void postItemWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + mockMvc.perform(post("/bookings") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } + + @Test + void patchItemApprovedTrueTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + Mockito.when(bookingService.setBookingStatus(Mockito.anyLong(), Mockito.anyBoolean(), Mockito.anyLong())) + .thenReturn(BookingDto.builder().status(BookingStatus.APPROVED).build()); + + mockMvc.perform(patch("/bookings/10?approved=true") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.status",is(BookingStatus.APPROVED.name()), String.class)); + } + + @Test + void patchItemApprovedFalseTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + Mockito.when(bookingService.setBookingStatus(Mockito.anyLong(), Mockito.anyBoolean(), Mockito.anyLong())) + .thenReturn(BookingDto.builder().status(BookingStatus.REJECTED).build()); + + mockMvc.perform(patch("/bookings/10?approved=false") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.status",is(BookingStatus.REJECTED.name()), String.class)); + } + + @Test + void patchItemParsingRequestTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + mockMvc.perform(patch("/bookings/100?approved=true") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()); + + mockMvc.perform(patch("/bookings/100?approved=false") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()); + + Mockito.verify(bookingService, Mockito.times(1)) + .setBookingStatus(100, true, 10L); + + Mockito.verify(bookingService, Mockito.times(1)) + .setBookingStatus(100, false, 10L); + } + + @Test + void patchItemWithoutParamsTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + mockMvc.perform(patch("/bookings/100") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } +} diff --git a/gateway/src/test/shareit/booking/BookingServiceTest.java b/gateway/src/test/shareit/booking/BookingServiceTest.java new file mode 100644 index 0000000..d2d1f5f --- /dev/null +++ b/gateway/src/test/shareit/booking/BookingServiceTest.java @@ -0,0 +1,271 @@ +package ru.practicum.shareit.booking; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import ru.practicum.shareit.booking.BookingMapper; +import ru.practicum.shareit.booking.BookingService; +import ru.practicum.shareit.booking.BookingStatus; +import ru.practicum.shareit.booking.BookingStorage; +import ru.practicum.shareit.booking.dto.BookingDto; +import ru.practicum.shareit.booking.dto.BookingStatusRequestDto; +import ru.practicum.shareit.booking.storage.BookingEntity; +import ru.practicum.shareit.exceptions.NotFoundException; +import ru.practicum.shareit.exceptions.NotValidException; +import ru.practicum.shareit.item.ItemStorage; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.storage.ItemEntity; +import ru.practicum.shareit.user.UserStorage; +import ru.practicum.shareit.user.dto.UserDto; +import ru.practicum.shareit.user.storage.UserEntity; + +import java.sql.Timestamp; +import java.time.Instant; +import java.util.List; +import java.util.Optional; + +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; + +@SpringBootTest +public class BookingServiceTest { + @Mock + BookingStorage bookingStorage; + @Mock + ItemStorage itemStorage; + @Mock + UserStorage userStorage; + + @InjectMocks + BookingService bookingService; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void getBookingTest() throws Exception { + var expectedBookingEntity = new BookingEntity(); + expectedBookingEntity.setId(8L); + expectedBookingEntity.setItem(new ItemEntity()); + expectedBookingEntity.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); + + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.of(new UserEntity())); + Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) + .thenReturn(Optional.of(expectedBookingEntity)); + Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) + .thenReturn(true); + + + try (MockedStatic mapper = Mockito.mockStatic(BookingMapper.class)) { + mapper + .when(() -> BookingMapper.toDto(Mockito.any(BookingEntity.class), + Mockito.any(UserDto.class), + Mockito.any(ItemDto.class))) + .thenAnswer(a -> { + var entity = a.getArgument(0, BookingEntity.class); + return BookingDto.builder() + .id(entity.getId()) + .build(); + }); + + var bookingDto = bookingService.getBooking(1, 1); + + Assertions.assertEquals(8L, bookingDto.id()); + + mapper.verify( + () -> BookingMapper.toDto( + Mockito.any(BookingEntity.class), + Mockito.any(UserDto.class), + Mockito.any(ItemDto.class)), + Mockito.times(1)); + } + } + + @Test + public void getBookingWhileUserNotIsOwnerTest() throws Exception { + var expectedBookingEntity = new BookingEntity(); + expectedBookingEntity.setId(10L); + expectedBookingEntity.setItem(new ItemEntity()); + expectedBookingEntity.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); + + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.of(new UserEntity())); + Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) + .thenReturn(Optional.of(expectedBookingEntity)); + Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) + .thenReturn(false); + + + try { + bookingService.getBooking(1,1); + + Assertions.fail(); + } catch (NotValidException ex) { + Assertions.assertEquals("Данные о бронировании может получить заказчик или владелец", ex.getMessage()); + } + } + + @Test + public void getBookingWhileNotFoundUserTest() throws Exception { + var expectedBookingEntity = new BookingEntity(); + expectedBookingEntity.setId(10L); + expectedBookingEntity.setItem(new ItemEntity()); + expectedBookingEntity.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); + + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.empty()); + Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) + .thenReturn(Optional.of(expectedBookingEntity)); + Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) + .thenReturn(true); + + + try { + bookingService.getBooking(1,1); + + Assertions.fail(); + } catch (NotFoundException ex) { + Assertions.assertEquals("Пользователь не найден", ex.getMessage()); + } + } + + @Test + public void getBookingWhileNotBookingTest() throws Exception { + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.of(new UserEntity())); + Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) + .thenReturn(Optional.empty()); + Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) + .thenReturn(true); + + + try { + bookingService.getBooking(1,1); + + Assertions.fail(); + } catch (NotFoundException ex) { + Assertions.assertEquals("Бронь не найдена", ex.getMessage()); + } + } + + @Test + public void getBookingForUserIdTest() { + var expectedBookingDtoList = List.of( + BookingDto.builder().id(8L).build(), + BookingDto.builder().id(107L).build()); + + var entity1 = new BookingEntity(); + entity1.setId(8L); + entity1.setItem(new ItemEntity()); + + var entity2 = new BookingEntity(); + entity2.setId(107L); + entity2.setItem(new ItemEntity()); + + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.of(new UserEntity())); + + Mockito.when(bookingStorage.findBookingsByBookerId(Mockito.anyLong())) + .thenReturn(List.of(entity1, entity2)); + + try (MockedStatic mapper = Mockito.mockStatic(BookingMapper.class)) { + mapper + .when(() -> BookingMapper.toDto(Mockito.any(BookingEntity.class), + Mockito.any(UserDto.class), + Mockito.any(ItemDto.class))) + .thenAnswer(a -> { + var entity = a.getArgument(0, BookingEntity.class); + return BookingDto.builder() + .id(entity.getId()) + .build(); + }); + + var bookingDtoList = bookingService.getBookingForUserId(1); + + Assertions.assertEquals(2, bookingDtoList.size()); + Assertions.assertEquals(8L, bookingDtoList.getFirst().id(), "Id dto[0] is expected 8L"); + Assertions.assertEquals(107L, bookingDtoList.get(1).id(), "Id dto[0] is expected 107L"); + + mapper.verify( + () -> BookingMapper.toDto( + Mockito.any(BookingEntity.class), + Mockito.any(UserDto.class), + Mockito.any(ItemDto.class)), + Mockito.times(2)); + } + } + + @Test + public void getBookingForUserIdWhileNotFoundUserTest() throws Exception { + var expectedBookingEntity = new BookingEntity(); + expectedBookingEntity.setId(10L); + expectedBookingEntity.setItem(new ItemEntity()); + expectedBookingEntity.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); + + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.empty()); + Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) + .thenReturn(Optional.of(expectedBookingEntity)); + + + try { + bookingService.getBookingForUserId(1); + + Assertions.fail(); + } catch (NotFoundException ex) { + Assertions.assertEquals("Пользователь не найден", ex.getMessage()); + } + } + + @Test + public void getBookingForUserIdWhileChangeStatusAndOwnerIdTest() throws Exception { + var expectedBookingEntity = new BookingEntity(); + expectedBookingEntity.setId(10L); + expectedBookingEntity.setItem(new ItemEntity()); + expectedBookingEntity.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); + + Mockito.when(userStorage.existsById(Mockito.anyLong())) + .thenReturn(true); + Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) + .thenReturn(Optional.of(expectedBookingEntity)); + + var statuses = List.of( + BookingStatusRequestDto.ALL, + BookingStatusRequestDto.CURRENT, + BookingStatusRequestDto.PAST, + BookingStatusRequestDto.FUTURE, + BookingStatusRequestDto.WAITING, + BookingStatusRequestDto.REJECTED, + BookingStatusRequestDto.APPROVED); + + var owners = List.of(1, 7, 19); + + for (var ownerId: owners) { + for (var requestStatus: statuses) { + bookingService.getBookingsForItemOwnerId(requestStatus, ownerId); + } + + Mockito.verify(bookingStorage, Mockito.times(4)) + .findBookingsByOwnerId(ownerId); + + Mockito.verify(bookingStorage, Mockito.times(1)) + .findBookingsByOwnerId(ownerId, BookingStatus.WAITING); + + Mockito.verify(bookingStorage, Mockito.times(1)) + .findBookingsByOwnerId(ownerId, BookingStatus.REJECTED); + + Mockito.verify(bookingStorage, Mockito.times(1)) + .findBookingsByOwnerId(ownerId, BookingStatus.APPROVED); + } + } +} diff --git a/gateway/src/test/shareit/item/ItemControllerTest.java b/gateway/src/test/shareit/item/ItemControllerTest.java new file mode 100644 index 0000000..b35edd9 --- /dev/null +++ b/gateway/src/test/shareit/item/ItemControllerTest.java @@ -0,0 +1,337 @@ +package ru.practicum.shareit.item; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import ru.practicum.shareit.booking.BookingStatus; +import ru.practicum.shareit.booking.dto.BookingDto; +import ru.practicum.shareit.item.ItemController; +import ru.practicum.shareit.item.ItemService; +import ru.practicum.shareit.item.dto.CommentDto; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.dto.ItemToUpdateDto; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +public class ItemControllerTest { + @Mock + ItemService itemService; + + @InjectMocks + ItemController itemController; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void requestPathWithoutUserIdInHead() throws Exception { + List needIdUserFromHeadRequest = + List.of(post("/items"), + post("/items/1/comment"), + put("/items"), + patch("/items/1"), + delete("/items/1")); + + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + for (var requestBuilder: needIdUserFromHeadRequest) { + var result = mockMvc.perform(requestBuilder) + .andReturn(); + + var status = result + .getResponse() + .getStatus(); + + var path = result.getRequest().getMethod() + " '" + result.getRequest().getRequestURI() + "'"; + + Assertions.assertEquals(400, status, path + " was needed userid as RequestHeader \"X-Sharer-User-Id\""); + } + } + + @Test + public void getItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var dto = ItemDto.builder() + .id(10L) + .build(); + + Mockito.when(itemService.getItem(Mockito.anyLong())) + .thenReturn(dto); + + mockMvc.perform(get("/items/1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(10L), Long.class)); + } + + @Test + void getItemParsingRequestId() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(get("/items/100")) + .andExpect(status().isOk()); + + Mockito.verify(itemService, Mockito.times(1)) + .getItem(100); + } + + @Test + void getItemsForUserIdTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var expectedResult = List.of( + ItemDto.builder().id(11L).build(), + ItemDto.builder().id(42L).build(), + ItemDto.builder().id(37L).build()); + + Mockito.when(itemService.getItems(Mockito.anyLong())) + .thenReturn(expectedResult); + + mockMvc.perform(get("/items") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.[0].id",is(11L), Long.class)) + .andExpect(jsonPath("$.[1].id",is(42L), Long.class)) + .andExpect(jsonPath("$.[2].id",is(37L), Long.class)); + } + + @Test + void getItemsForUserIdParsingRequestTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(get("/items") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()); + + Mockito.verify(itemService, Mockito.times(1)) + .getItems(10); + } + + @Test + void findItemsByTextTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var expectedResult = List.of( + ItemDto.builder().id(1L).build(), + ItemDto.builder().id(42L).build(), + ItemDto.builder().id(37L).build()); + + Mockito.when(itemService.findFreeItemsByText(Mockito.anyString(), Mockito.anyBoolean())) + .thenReturn(expectedResult); + + mockMvc.perform(get("/items/search?text=abc")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.[0].id",is(1L), Long.class)) + .andExpect(jsonPath("$.[1].id",is(42L), Long.class)) + .andExpect(jsonPath("$.[2].id",is(37L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .findFreeItemsByText("abc", true); + + Mockito.verify(itemService, Mockito.never()) + .findFreeItemsByText("abc", false); + } + + @Test + void findItemsByTextFailParsingRequestTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(get("/items/search")) + .andExpect(status().is(400)); + } + + @Test + void postItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + Mockito.when(itemService.createItem(Mockito.any(ItemDto.class), Mockito.anyLong())) + .thenReturn(ItemDto.builder().id(50L).build()); + + var dto = ItemDto.builder() + .id(13L) + .name("la") + .available(true) + .description("ma") + .build(); + + mockMvc.perform(post("/items") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .createItem(dto, 10L); + } + + @Test + void postItemWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(post("/items") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } + + @Test + void postCommentTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var dto = CommentDto.builder() + .id(47L) + .text("la") + .build(); + + Mockito.when(itemService.addComment(Mockito.any(CommentDto.class), Mockito.anyLong(), Mockito.anyLong())) + .thenReturn(CommentDto.builder().id(50L).build()); + + mockMvc.perform(post("/items/13/comment") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .addComment(dto, 13L, 10L); + } + + @Test + void postCommentWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(post("/items/13/comment") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } + + @Test + void putItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + Mockito.when(itemService.updateItem(Mockito.any(ItemDto.class), Mockito.anyLong())) + .thenReturn(ItemDto.builder().id(50L).build()); + + var dto = ItemDto.builder() + .id(13L) + .name("la") + .description("ma") + .available(true) + .build(); + + mockMvc.perform(put("/items") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .updateItem(dto, 10L); + } + + @Test + void putItemWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(put("/items") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } + + @Test + void patchItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var dto = ItemToUpdateDto.builder() + .build(); + + Mockito.when(itemService.updateItem(Mockito.anyLong(), Mockito.any(ItemToUpdateDto.class), Mockito.anyLong())) + .thenReturn(ItemDto.builder().id(50L).build()); + + mockMvc.perform(patch("/items/17") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .updateItem(17, dto, 10L); + } + + @Test + void patchItemWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(put("/items") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } + + @Test + void deleteItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + Mockito.when(itemService.deleteItem(17L, 10L)) + .thenReturn(ItemDto.builder().id(50L).build()); + + mockMvc.perform(delete("/items/17") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .deleteItem(17L, 10L); + } +} diff --git a/gateway/src/test/shareit/request/RequestControllerTest.java b/gateway/src/test/shareit/request/RequestControllerTest.java new file mode 100644 index 0000000..7b76193 --- /dev/null +++ b/gateway/src/test/shareit/request/RequestControllerTest.java @@ -0,0 +1,170 @@ +package ru.practicum.shareit.request; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import ru.practicum.shareit.item.dto.CommentDto; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.dto.ItemToUpdateDto; +import ru.practicum.shareit.request.RequestController; +import ru.practicum.shareit.request.RequestService; +import ru.practicum.shareit.request.dto.RequestDto; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +public class RequestControllerTest { + @Mock + RequestService requestService; + + @InjectMocks + RequestController requestController; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void requestPathWithoutUserIdInHead() throws Exception { + List needIdUserFromHeadRequest = + List.of(get("/requests"), + get("/requests/all"), + post("/requests")); + + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + for (var requestBuilder: needIdUserFromHeadRequest) { + var result = mockMvc.perform(requestBuilder) + .andReturn(); + + var status = result + .getResponse() + .getStatus(); + + var path = result.getRequest().getMethod() + " '" + result.getRequest().getRequestURI() + "'"; + + Assertions.assertEquals(400, status, path + " was needed userid as RequestHeader \"X-Sharer-User-Id\""); + } + } + + @Test + public void getSelfRequestsTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + List expectedRequests = List.of( + RequestDto.builder().id(13L).build(), + RequestDto.builder().id(24L).build(), + RequestDto.builder().id(37L).build() + ); + + Mockito.when(requestService.getRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) + .thenReturn(expectedRequests); + + mockMvc.perform(get("/requests") + .header("X-Sharer-User-Id", 7L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id", is(13L), Long.class)) + .andExpect(jsonPath("$[1].id", is(24L), Long.class)) + .andExpect(jsonPath("$[2].id", is(37L), Long.class)); + + Mockito.verify(requestService, Mockito.times(1)) + .getRequestsByUserId(7L, true); + } + + @Test + void getRequestByIdTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + var expectedResult = RequestDto.builder().id(13L).build(); + + Mockito.when(requestService.getRequestById(Mockito.anyLong())) + .thenReturn(expectedResult); + + mockMvc.perform(get("/requests/23")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(13L), Long.class)); + + Mockito.verify(requestService, Mockito.times(1)) + .getRequestById(23L); + } + + @Test + void getOtherUserRequestsTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + List expectedRequests = List.of( + RequestDto.builder().id(13L).build(), + RequestDto.builder().id(24L).build(), + RequestDto.builder().id(37L).build() + ); + + Mockito.when(requestService.getRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) + .thenReturn(expectedRequests); + + mockMvc.perform(get("/requests/all") + .header("X-Sharer-User-Id", 7L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id", is(13L), Long.class)) + .andExpect(jsonPath("$[1].id", is(24L), Long.class)) + .andExpect(jsonPath("$[2].id", is(37L), Long.class)); + + Mockito.verify(requestService, Mockito.times(1)) + .getRequestsByUserId(7L, false); + } + + @Test + void postRequestDtoTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + Mockito.when(requestService.createRequest(Mockito.any(RequestDto.class), Mockito.anyLong())) + .thenReturn(RequestDto.builder().id(50L).build()); + + var dto = RequestDto.builder() + .id(13L) + .description("la") + .build(); + + mockMvc.perform(post("/requests") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(requestService, Mockito.times(1)) + .createRequest(dto, 10L); + } + + @Test + void postRequestWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + mockMvc.perform(post("/requests") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } +} diff --git a/gateway/src/test/shareit/user/UserControllerTest.java b/gateway/src/test/shareit/user/UserControllerTest.java new file mode 100644 index 0000000..fd908bb --- /dev/null +++ b/gateway/src/test/shareit/user/UserControllerTest.java @@ -0,0 +1,179 @@ +package ru.practicum.shareit.user; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import ru.practicum.shareit.request.dto.RequestDto; +import ru.practicum.shareit.user.UserController; +import ru.practicum.shareit.user.UserService; +import ru.practicum.shareit.user.dto.UserDto; +import ru.practicum.shareit.user.dto.UserToUpdateDto; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +public class UserControllerTest { + @Mock + UserService userService; + + @InjectMocks + UserController userController; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void getUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + var dto = UserDto.builder() + .id(47L) + .name("la") + .email("email@mail.ru") + .build(); + + Mockito.when(userService.getUser(Mockito.anyLong())) + .thenReturn(dto); + + mockMvc.perform(get("/users/17")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(47L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .getUser(17L); + } + + @Test + void postUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + Mockito.when(userService.updateUser(Mockito.any(UserDto.class))) + .thenReturn(UserDto.builder().id(50L).build()); + + var dto = UserDto.builder() + .name("la") + .email("email@mail.ru") + .build(); + + mockMvc.perform(post("/users") + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .updateUser(dto); + } + + @Test + void postUserWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + mockMvc.perform(post("/users")) + .andExpect(status().is(400)); + } + + @Test + void putUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + Mockito.when(userService.updateUser(Mockito.any(UserDto.class))) + .thenReturn(UserDto.builder().id(52L).build()); + + var dto = UserDto.builder() + .id(10L) + .name("la") + .email("email@mail.ru") + .build(); + + mockMvc.perform(put("/users") + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(52L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .updateUser(dto); + } + + @Test + void putUserWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + mockMvc.perform(put("/users")) + .andExpect(status().is(400)); + } + + @Test + void patchUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + Mockito.when(userService.updateUser(Mockito.anyLong(), Mockito.any(UserToUpdateDto.class))) + .thenReturn(UserDto.builder().id(542L).build()); + + var dto = UserToUpdateDto.builder().name("la").build(); + + mockMvc.perform(patch("/users/13") + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(542L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .updateUser(13, dto); + } + + @Test + void patchUserWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + mockMvc.perform(patch("/users/13")) + .andExpect(status().is(400)); + } + + @Test + void deleteUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + Mockito.when(userService.deleteUser(Mockito.anyLong())) + .thenReturn(UserDto.builder().id(54L).build()); + + mockMvc.perform(delete("/users/13")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(54L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .deleteUser(13); + } +} diff --git a/gateway/src/test/user/UserControllerTest.java b/gateway/src/test/user/UserControllerTest.java new file mode 100644 index 0000000..fd908bb --- /dev/null +++ b/gateway/src/test/user/UserControllerTest.java @@ -0,0 +1,179 @@ +package ru.practicum.shareit.user; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import ru.practicum.shareit.request.dto.RequestDto; +import ru.practicum.shareit.user.UserController; +import ru.practicum.shareit.user.UserService; +import ru.practicum.shareit.user.dto.UserDto; +import ru.practicum.shareit.user.dto.UserToUpdateDto; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +public class UserControllerTest { + @Mock + UserService userService; + + @InjectMocks + UserController userController; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void getUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + var dto = UserDto.builder() + .id(47L) + .name("la") + .email("email@mail.ru") + .build(); + + Mockito.when(userService.getUser(Mockito.anyLong())) + .thenReturn(dto); + + mockMvc.perform(get("/users/17")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(47L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .getUser(17L); + } + + @Test + void postUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + Mockito.when(userService.updateUser(Mockito.any(UserDto.class))) + .thenReturn(UserDto.builder().id(50L).build()); + + var dto = UserDto.builder() + .name("la") + .email("email@mail.ru") + .build(); + + mockMvc.perform(post("/users") + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .updateUser(dto); + } + + @Test + void postUserWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + mockMvc.perform(post("/users")) + .andExpect(status().is(400)); + } + + @Test + void putUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + Mockito.when(userService.updateUser(Mockito.any(UserDto.class))) + .thenReturn(UserDto.builder().id(52L).build()); + + var dto = UserDto.builder() + .id(10L) + .name("la") + .email("email@mail.ru") + .build(); + + mockMvc.perform(put("/users") + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(52L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .updateUser(dto); + } + + @Test + void putUserWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + mockMvc.perform(put("/users")) + .andExpect(status().is(400)); + } + + @Test + void patchUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + Mockito.when(userService.updateUser(Mockito.anyLong(), Mockito.any(UserToUpdateDto.class))) + .thenReturn(UserDto.builder().id(542L).build()); + + var dto = UserToUpdateDto.builder().name("la").build(); + + mockMvc.perform(patch("/users/13") + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(542L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .updateUser(13, dto); + } + + @Test + void patchUserWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + mockMvc.perform(patch("/users/13")) + .andExpect(status().is(400)); + } + + @Test + void deleteUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + Mockito.when(userService.deleteUser(Mockito.anyLong())) + .thenReturn(UserDto.builder().id(54L).build()); + + mockMvc.perform(delete("/users/13")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(54L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .deleteUser(13); + } +} diff --git a/pom.xml b/pom.xml index 3b4c514..8c95aa8 100644 --- a/pom.xml +++ b/pom.xml @@ -12,10 +12,15 @@ ru.practicum shareit 0.0.1-SNAPSHOT + pom - ShareIt + ShareIt + + gateway + server + - + 21 diff --git a/postman/sprint.json b/postman/sprint.json new file mode 100644 index 0000000..6e87b6b --- /dev/null +++ b/postman/sprint.json @@ -0,0 +1,4052 @@ +{ + "info": { + "_postman_id": "7fc26681-0775-4307-885f-fd53560f0317", + "name": "Sprint 16 ShareIt (add-item-requests-and-gateway)", + "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/13708500-7fc26681-0775-4307-885f-fd53560f0317?action=share&source=collection_link&creator=23073145" + }, + "item": [ + { + "name": "users", + "item": [ + { + "name": "Create user", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " user = rnd.getUser();\r", + " pm.collectionVariables.set(\"userName\", user.name);\r", + " pm.collectionVariables.set(\"userEmail\", user.email);\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": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200 or 201\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,201]);\r", + "});\r", + "pm.test(\"Response have body\", 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" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"{{userName}}\",\n \"email\": \"{{userEmail}}\"\n}" + }, + "url": { + "raw": "localhost:8080/users", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "users" + ] + } + }, + "response": [] + }, + { + "name": "Create user without email", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " user2 = rnd.getUser();\r", + " pm.collectionVariables.set(\"userName\", user2.name);\r", + " pm.collectionVariables.set(\"userEmail\", user2.email);\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": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([400, 500]);\r", + "});\r", + "pm.test(\"Response have body\", 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" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"{{userName}}\"\n}" + }, + "url": { + "raw": "localhost:8080/users", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "users" + ] + } + }, + "response": [] + }, + { + "name": "Create 2 users with same email", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " user1 = rnd.getUser();\r", + " us = await api.addUser(user1);\r", + " user2 = rnd.getUser();\r", + " user2.email = user1.email;\r", + " pm.collectionVariables.set(\"userName\", user2.name);\r", + " pm.collectionVariables.set(\"userEmail\", user2.email);\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": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 409\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([409, 500]);\r", + "});\r", + "pm.test(\"Response have body\", 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" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"{{userName}}\",\n \"email\": \"{{userEmail}}\"\n}" + }, + "url": { + "raw": "localhost:8080/users", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "users" + ] + } + }, + "response": [] + }, + { + "name": "Create user with invalid email", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " user = rnd.getUser();\r", + " pm.collectionVariables.set(\"userName\", user.name);\r", + " pm.collectionVariables.set(\"userEmail\", user.email);\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": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([400, 500]);\r", + "});\r", + "pm.test(\"Response have body\", 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" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"{{userName}}\",\n \"email\": \"user.com\"\n}" + }, + "url": { + "raw": "localhost:8080/users", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "users" + ] + } + }, + "response": [] + }, + { + "name": "User update", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " user = rnd.getUser();\r", + " us = await api.addUser(user);\r", + " pm.collectionVariables.set(\"userId\", us.id);\r", + " us = rnd.getUser()\r", + " pm.collectionVariables.set(\"userName\", us.name);\r", + " pm.collectionVariables.set(\"userEmail\", us.email);\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": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Response have body\", 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", + " var id = pm.collectionVariables.get(\"userId\");\r", + " pm.expect(jsonData.id, '\"id\" must be ' + id).to.eql(Number(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", + " var email = pm.collectionVariables.get(\"userEmail\");\r", + " pm.expect(jsonData.email, '\"email\" must be ' + email).to.eql(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", + " var name = pm.collectionVariables.get(\"userName\");\r", + " pm.expect(jsonData.name, '\"name\" must be ' + name).to.eql(name);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"{{userName}}\",\n \"email\": \"{{userEmail}}\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/users/{{userId}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{userId}}" + ] + } + }, + "response": [] + }, + { + "name": "User update name", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " user = rnd.getUser();\r", + " us = await api.addUser(user);\r", + " pm.collectionVariables.set(\"userId\", us.id);\r", + " us = rnd.getUser()\r", + " pm.collectionVariables.set(\"userName\", us.name);\r", + " pm.collectionVariables.set(\"userEmail\", us.email);\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": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Response have body\", 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", + " var id = pm.collectionVariables.get(\"userId\");\r", + " pm.expect(jsonData.id, '\"id\" must be ' + id).to.eql(Number(id));\r", + "});\r", + "pm.test(\"Test user 'name' field\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('name');\r", + " var name = pm.collectionVariables.get(\"userName\");\r", + " pm.expect(jsonData.name, '\"name\" must be ' + name).to.eql(name);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"{{userName}}\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/users/{{userId}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{userId}}" + ] + } + }, + "response": [] + }, + { + "name": "User update email", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " user = rnd.getUser();\r", + " us = await api.addUser(user);\r", + " pm.collectionVariables.set(\"userId\", us.id);\r", + " us = rnd.getUser()\r", + " pm.collectionVariables.set(\"userName\", us.name);\r", + " pm.collectionVariables.set(\"userEmail\", us.email);\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": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Response have body\", 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", + " var id = pm.collectionVariables.get(\"userId\");\r", + " pm.expect(jsonData.id, '\"id\" must be ' + id).to.eql(Number(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", + " var email = pm.collectionVariables.get(\"userEmail\");\r", + " pm.expect(jsonData.email, '\"email\" must be ' + email).to.eql(email);\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"email\": \"{{userEmail}}\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/users/{{userId}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{userId}}" + ] + } + }, + "response": [] + }, + { + "name": "User update with existing email", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " user = rnd.getUser();\r", + " us = await api.addUser(user);\r", + " user2 = rnd.getUser();\r", + " us2 = await api.addUser(user2)\r", + " pm.collectionVariables.set(\"userId\", us2.id);\r", + " usa = rnd.getUser()\r", + " pm.collectionVariables.set(\"userName\", usa.name);\r", + " pm.collectionVariables.set(\"userEmail\", user.email);\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": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 409\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([409, 500]);\r", + "});\r", + "pm.test(\"Response have body\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"{{userName}}\",\n \"email\": \"{{userEmail}}\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/users/{{userId}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{userId}}" + ] + } + }, + "response": [] + }, + { + "name": "Get user", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " user = rnd.getUser();\r", + " us = await api.addUser(user);\r", + " pm.collectionVariables.set(\"userId\", us.id);\r", + " pm.collectionVariables.set(\"userName\", us.name);\r", + " pm.collectionVariables.set(\"userEmail\", us.email);\r", + "\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": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"Response have body\", 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", + " var id = pm.collectionVariables.get(\"userId\");\r", + " pm.expect(jsonData.id, '\"id\" must be ' + id).to.eql(Number(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", + " var email = pm.collectionVariables.get(\"userEmail\");\r", + " pm.expect(jsonData.email, '\"email\" must be ' + email).to.eql(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", + " var name = pm.collectionVariables.get(\"userName\");\r", + " pm.expect(jsonData.name, '\"name\" must be ' + name).to.eql(name);\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{baseUrl}}/users/{{userId}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{userId}}" + ] + } + }, + "response": [] + }, + { + "name": "User delete", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200,204]);", + "});", + "" + ], + "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", + " user = rnd.getUser();\r", + " us = await api.addUser(user);\r", + " pm.collectionVariables.set(\"userId\", us.id);\r", + " pm.collectionVariables.set(\"userName\", us.name);\r", + " pm.collectionVariables.set(\"userEmail\", us.email);\r", + "\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": "Accept", + "value": "*/*", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/users/{{userId}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "users", + "{{userId}}" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Item", + "item": [ + { + "name": "Create Item", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " item = rnd.getItem();\r", + " pm.collectionVariables.set(\"item\", item);\r", + " pm.collectionVariables.set(\"itemName\", item.name);\r", + " pm.collectionVariables.set(\"itemAvailable\", item.available);\r", + " pm.collectionVariables.set(\"itemDescription\", item.description);\r", + " user = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"userId\", user.id);\r", + "\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": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200 or 201\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,201]);\r", + "});\r", + "pm.test(\"Response have body\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "var item = pm.collectionVariables.get(\"item\");\r", + "\r", + "pm.test(\"Response data equal to request\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('id');\r", + " pm.expect(jsonData).to.have.property('name');\r", + " pm.expect(jsonData).to.have.property('description');\r", + " pm.expect(jsonData).to.have.property('available');\r", + " pm.expect(jsonData.name, `\"name\" must be ${item.name}`).to.eql(item.name);\r", + " pm.expect(jsonData.description, `\"description\" must be ${item.description}`).to.eql(item.description);\r", + " pm.expect(jsonData.available.toString(), `\"available\" must be ${item.available}`).to.eql(item.available.toString());\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"{{itemName}}\",\n \"description\": \"{{itemDescription}}\",\n \"available\": {{itemAvailable}}\n}" + }, + "url": { + "raw": "localhost:8080/items", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "items" + ] + } + }, + "response": [] + }, + { + "name": "Create Item on request", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " var request = await api.addRequest(rnd.getRequest(), user1.id);\r", + " pm.collectionVariables.set(\"requestId\", request.id);\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"userId\", user2.id);\r", + "\r", + " item = rnd.getItem();\r", + " pm.collectionVariables.set(\"item\", item);\r", + " pm.collectionVariables.set(\"itemName\", item.name);\r", + " pm.collectionVariables.set(\"itemAvailable\", item.available);\r", + " pm.collectionVariables.set(\"itemDescription\", item.description);\r", + "\r", + "\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": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200 or 201\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,201]);\r", + "});\r", + "pm.test(\"Response have body\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "var item = pm.collectionVariables.get(\"item\");\r", + "\r", + "pm.test(\"Response data equal to request\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('id');\r", + " pm.expect(jsonData).to.have.property('name');\r", + " pm.expect(jsonData).to.have.property('description');\r", + " pm.expect(jsonData).to.have.property('available');\r", + " pm.expect(jsonData.name, `\"name\" must be ${item.name}`).to.eql(item.name);\r", + " pm.expect(jsonData.description, `\"description\" must be ${item.description}`).to.eql(item.description);\r", + " pm.expect(jsonData.available.toString(), `\"available\" must be ${item.available}`).to.eql(item.available.toString());\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"{{itemName}}\",\n \"description\": \"{{itemDescription}}\",\n \"available\": {{itemAvailable}},\n \"requestId\": {{requestId}}\n}" + }, + "url": { + "raw": "localhost:8080/items", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "items" + ] + } + }, + "response": [] + }, + { + "name": "Create Item without name on request", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " var request = await api.addRequest(rnd.getRequest(), user1.id);\r", + " pm.collectionVariables.set(\"requestId\", request.id);\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"userId\", user2.id);\r", + "\r", + " item = rnd.getItem();\r", + " pm.collectionVariables.set(\"item\", item);\r", + " pm.collectionVariables.set(\"itemName\", item.name);\r", + " pm.collectionVariables.set(\"itemAvailable\", item.available);\r", + " pm.collectionVariables.set(\"itemDescription\", item.description);\r", + "\r", + "\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": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([400, 500]);\r", + "});\r", + "pm.test(\"Response have body\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "pm.test(\"Response data have error\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('error');\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"description\": \"{{itemDescription}}\",\n \"available\": {{itemAvailable}},\n \"requestId\": {{requestId}}\n}" + }, + "url": { + "raw": "localhost:8080/items", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "items" + ] + } + }, + "response": [] + }, + { + "name": "Create Item without description on request", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " var request = await api.addRequest(rnd.getRequest(), user1.id);\r", + " pm.collectionVariables.set(\"requestId\", request.id);\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"userId\", user2.id);\r", + "\r", + " item = rnd.getItem();\r", + " pm.collectionVariables.set(\"item\", item);\r", + " pm.collectionVariables.set(\"itemName\", item.name);\r", + " pm.collectionVariables.set(\"itemAvailable\", item.available);\r", + " pm.collectionVariables.set(\"itemDescription\", item.description);\r", + "\r", + "\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": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([400, 500]);\r", + "});\r", + "pm.test(\"Response have body\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "pm.test(\"Response data have error\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('error');\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"{{itemName}}\",\n \"available\": {{itemAvailable}},\n \"requestId\": {{requestId}}\n}" + }, + "url": { + "raw": "localhost:8080/items", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "items" + ] + } + }, + "response": [] + }, + { + "name": "Create Item without available on request", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " var request = await api.addRequest(rnd.getRequest(), user1.id);\r", + " pm.collectionVariables.set(\"requestId\", request.id);\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"userId\", user2.id);\r", + "\r", + " item = rnd.getItem();\r", + " pm.collectionVariables.set(\"item\", item);\r", + " pm.collectionVariables.set(\"itemName\", item.name);\r", + " pm.collectionVariables.set(\"itemAvailable\", item.available);\r", + " pm.collectionVariables.set(\"itemDescription\", item.description);\r", + "\r", + "\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": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([400, 500]);\r", + "});\r", + "pm.test(\"Response have body\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "pm.test(\"Response data have error\", function () {\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('error');\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"{{itemName}}\",\n \"description\": \"{{itemDescription}}\",\n \"requestId\": {{requestId}}\n}" + }, + "url": { + "raw": "localhost:8080/items", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "items" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "requests", + "item": [ + { + "name": "Create request", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " request1 = rnd.getRequest();\r", + " pm.collectionVariables.set(\"requestDescription\", request1.description);\r", + " user = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"userId\", user.id);\r", + "\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": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200 or 201\", function () {\r", + " pm.expect(pm.response.code).to.be.oneOf([200,201]);\r", + "});\r", + "pm.test(\"Response have body\", function () {\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + "});\r", + "\r", + "pm.test(\"Response data equal to request\", function () {\r", + " var description = pm.collectionVariables.get(\"requestDescription\");\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('id');\r", + " pm.expect(jsonData).to.have.property('description');\r", + " pm.expect(jsonData).to.have.property('created');\r", + " pm.expect(jsonData.description, `\"description\" must be ${description}`).to.eql(description);\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}" + } + ], + "body": { + "mode": "raw", + "raw": "{ \n \"description\": \"{{requestDescription}}\"\n}" + }, + "url": { + "raw": "localhost:8080/requests", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "requests" + ] + } + }, + "response": [] + }, + { + "name": "Get user requests", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " user = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"userId\", user.id);\r", + " request1 = await api.addRequest(rnd.getRequest(), user.id);\r", + " request2 = await api.addRequest(rnd.getRequest(), user.id);\r", + "\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": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"User requests amount\", 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 2').to.eql(2);\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}" + } + ], + "url": { + "raw": "localhost:8080/requests", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "requests" + ] + } + }, + "response": [] + }, + { + "name": "Get user request by id", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "const main = async () => {\r", + " const api = new API(pm);\r", + " const rnd = new RandomUtils();\r", + "\r", + " try {\r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"userId\", user2.id);\r", + " req = await api.addRequest(rnd.getRequest(), user1.id);\r", + " pm.collectionVariables.set(\"requestId\", req.id);\r", + " item = await api.addItem(rnd.getItemForRequest(req.id), user2.id);\r", + " pm.collectionVariables.set(\"itemName\", item.name);\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": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.be.ok;\r", + "});\r", + "pm.test(\"User requests amount\", function () {\r", + " var name = pm.collectionVariables.get(\"itemName\");\r", + " pm.response.to.be.withBody;\r", + " pm.response.to.be.json;\r", + " var jsonData = pm.response.json();\r", + " pm.expect(jsonData).to.have.property('id');\r", + " pm.expect(jsonData).to.have.property('description');\r", + " pm.expect(jsonData).to.have.property('created');\r", + " pm.expect(jsonData).to.have.property('items');\r", + " pm.expect(jsonData.items[0].name, `\"item name\" must be ${name}`).to.eql(name);\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}" + } + ], + "url": { + "raw": "localhost:8080/requests/{{requestId}}", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "requests", + "{{requestId}}" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "bookings", + "item": [ + { + "name": "Booking unavailable item", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([400, 500]);", + "});", + "" + ], + "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", + " var moment = require('moment');\r", + " const currentDate = moment();\r", + " var start = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " var end = currentDate.clone().add(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " pm.collectionVariables.set('start', start);\r", + " pm.collectionVariables.set('end', end);\r", + " \r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"userId\", user2.id);\r", + " it = rnd.getItem()\r", + " it.available = false\r", + " item = await api.addItem(it, user1.id)\r", + " pm.collectionVariables.set(\"itemId\", item.id);\r", + "\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": "POST", + "header": [ + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}", + "type": "text" + }, + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "Accept", + "value": "*/*", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"itemId\": {{itemId}},\n \"start\": \"{{start}}\",\n \"end\": \"{{end}}\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/bookings", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "bookings" + ] + } + }, + "response": [] + }, + { + "name": "Booking create failed by wrong userId", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 500\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([500, 404, 403]);", + "});", + "" + ], + "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", + " var moment = require('moment');\r", + " const currentDate = moment();\r", + " var start = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " var end = currentDate.clone().add(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " pm.collectionVariables.set('start', start);\r", + " pm.collectionVariables.set('end', end);\r", + " \r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"userId\", user2.id + 1);\r", + " it = rnd.getItem()\r", + " it.available = false\r", + " item = await api.addItem(it, user1.id)\r", + " pm.collectionVariables.set(\"itemId\", item.id);\r", + "\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": "POST", + "header": [ + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}", + "type": "text" + }, + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "Accept", + "value": "*/*", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"itemId\": {{itemId}},\n \"start\": \"{{start}}\",\n \"end\": \"{{end}}\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/bookings", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "bookings" + ] + } + }, + "response": [] + }, + { + "name": "Booking create failed by not found itemId", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([404]);", + "});", + "" + ], + "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", + " var moment = require('moment');\r", + " const currentDate = moment();\r", + " var start = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " var end = currentDate.clone().add(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " pm.collectionVariables.set('start', start);\r", + " pm.collectionVariables.set('end', end);\r", + " \r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"userId\", user2.id);\r", + " it = rnd.getItem()\r", + " it.available = false\r", + " item = await api.addItem(it, user1.id)\r", + " pm.collectionVariables.set(\"itemId\", item.id + 1);\r", + "\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": "POST", + "header": [ + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}", + "type": "text" + }, + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "Accept", + "value": "*/*", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"itemId\": {{itemId}},\n \"start\": \"{{start}}\",\n \"end\": \"{{end}}\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/bookings", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "bookings" + ] + } + }, + "response": [] + }, + { + "name": "Booking create failed by end in past", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([400, 500]);", + "});", + "" + ], + "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", + " var moment = require('moment');\r", + " const currentDate = moment();\r", + " var start = currentDate.clone().subtract(3, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " var end = currentDate.clone().subtract(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " pm.collectionVariables.set('start', start);\r", + " pm.collectionVariables.set('end', end);\r", + " \r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"userId\", user2.id);\r", + " it = rnd.getItem()\r", + " it.available = false\r", + " item = await api.addItem(it, user1.id)\r", + " pm.collectionVariables.set(\"itemId\", item.id);\r", + "\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": "POST", + "header": [ + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}", + "type": "text" + }, + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "Accept", + "value": "*/*", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"itemId\": {{itemId}},\n \"start\": \"{{start}}\",\n \"end\": \"{{end}}\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/bookings", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "bookings" + ] + } + }, + "response": [] + }, + { + "name": "Booking create failed by start equal end", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([400, 500]);", + "});", + "" + ], + "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", + " var moment = require('moment');\r", + " const currentDate = moment();\r", + " var start = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " var end = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " pm.collectionVariables.set('start', start);\r", + " pm.collectionVariables.set('end', end);\r", + " \r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"userId\", user2.id);\r", + " it = rnd.getItem()\r", + " it.available = false\r", + " item = await api.addItem(it, user1.id)\r", + " pm.collectionVariables.set(\"itemId\", item.id);\r", + "\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": "POST", + "header": [ + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}", + "type": "text" + }, + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "Accept", + "value": "*/*", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"itemId\": {{itemId}},\n \"start\": \"{{start}}\",\n \"end\": \"{{end}}\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/bookings", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "bookings" + ] + } + }, + "response": [] + }, + { + "name": "Booking create failed by start equal null", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([400, 500]);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "var moment = require('moment');\r", + "\r", + "var start = moment().add(2, 'd');\r", + "pm.environment.set('start_null', start.format('YYYY-MM-DDTHH:mm:ss'));\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}", + "type": "text" + }, + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "Accept", + "value": "*/*", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"itemId\": {{itemId}},\n \"end\": \"{{end}}\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/bookings", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "bookings" + ] + } + }, + "response": [] + }, + { + "name": "Booking create failed by end equal null", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([400, 500]);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "var moment = require('moment');\r", + "\r", + "var start = moment().add(2, 'd');\r", + "pm.environment.set('end_null', start.format('YYYY-MM-DDTHH:mm:ss'));\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}", + "type": "text" + }, + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "Accept", + "value": "*/*", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"itemId\": {{itemId}},\n \"start\": \"{{start}}\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/bookings", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "bookings" + ] + } + }, + "response": [] + }, + { + "name": "Booking create failed by start in past", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([400, 500]);", + "});" + ], + "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", + " var moment = require('moment');\r", + " const currentDate = moment();\r", + " var start = currentDate.clone().subtract(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " var end = currentDate.clone().add(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " pm.collectionVariables.set('start', start);\r", + " pm.collectionVariables.set('end', end);\r", + " \r", + " user1 = await api.addUser(rnd.getUser());\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"userId\", user2.id);\r", + " it = rnd.getItem()\r", + " it.available = false\r", + " item = await api.addItem(it, user1.id)\r", + " pm.collectionVariables.set(\"itemId\", item.id);\r", + "\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": "POST", + "header": [ + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}", + "type": "text" + }, + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "Accept", + "value": "*/*", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"itemId\": {{itemId}},\n \"start\": \"{{start}}\",\n \"end\": \"{{end}}\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/bookings", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "bookings" + ] + } + }, + "response": [] + }, + { + "name": "Booking available item", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200 or 201\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200,201]);", + "});", + "pm.test(\"Has booking create response\", function () {", + " pm.response.to.be.withBody;", + " pm.response.to.be.json;", + "});", + "var item = pm.collectionVariables.get('item')", + "var user1 = pm.collectionVariables.get('user1')", + "var user2 = pm.collectionVariables.get('user2')", + "var start = pm.collectionVariables.get('start')", + "var end = pm.collectionVariables.get('end')", + "pm.test(\"Test booking 'start' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('start');", + " pm.expect(jsonData.start, '\"start\" must be \"' + pm.collectionVariables.get('start') + '\"').to.eql(pm.collectionVariables.get('start'));", + "});", + "pm.test(\"Test booking 'end' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('end');", + " pm.expect(jsonData.end, '\"end\" must be \"' + pm.collectionVariables.get('end') + '\"').to.eql(pm.collectionVariables.get('end'));", + "});", + "pm.test(\"Test booking 'status' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('status');", + " pm.expect(jsonData.status, '\"status\" must be \"WAITING\"').to.eql('WAITING');", + "});", + "pm.test(\"Test booking 'booker.id' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('booker');", + " pm.expect(jsonData.booker).to.have.property('id');", + " pm.expect(jsonData.booker.id, '\"booker.id\" must be ${user2.id}').to.eql(user2.id);", + "});", + "pm.test(\"Test booking 'item.id' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('item');", + " pm.expect(jsonData.item).to.have.property('id');", + " pm.expect(jsonData.item.id, '\"item.id\" must be ${item.id}').to.eql(item.id);", + "});", + "pm.test(\"Test booking 'item.name' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('item');", + " pm.expect(jsonData.item).to.have.property('name');", + " pm.expect(jsonData.item.name, '\"item.name\" must be ${item.name}').to.eql(item.name);", + "});", + "" + ], + "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", + " var moment = require('moment');\r", + " const currentDate = moment();\r", + " var start = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " var end = currentDate.clone().add(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " pm.collectionVariables.set('start', start);\r", + " pm.collectionVariables.set('end', end);\r", + " \r", + " user1 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user1\", user1);\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user2\", user2);\r", + " pm.collectionVariables.set(\"userId\", user2.id);\r", + " it = rnd.getItem()\r", + " it.available = true\r", + " item = await api.addItem(it, user1.id)\r", + " pm.collectionVariables.set(\"itemId\", item.id);\r", + " pm.collectionVariables.set(\"item\", item);\r", + "\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": "POST", + "header": [ + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}", + "type": "text" + }, + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "Accept", + "value": "*/*", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"itemId\": {{itemId}},\n \"start\": \"{{start}}\",\n \"end\": \"{{end}}\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/bookings", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "bookings" + ] + } + }, + "response": [] + }, + { + "name": "Booking approve", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200]);", + "});", + "pm.test(\"Has booking patch response\", function () {", + " pm.response.to.be.withBody;", + " pm.response.to.be.json;", + "});", + "var item = pm.collectionVariables.get('item')", + "var book = pm.collectionVariables.get('booking')", + "var user1 = pm.collectionVariables.get('user1')", + "var user2 = pm.collectionVariables.get('user2')", + "pm.test(\"Test booking 'id' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('id');", + " pm.expect(jsonData.id, '\"id\" must be ${book.id}').to.eql(book.id);", + "});", + "pm.test(\"Test booking 'start' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('start');", + " pm.expect(jsonData.start, '\"start\" must be \"' + pm.collectionVariables.get('start') + '\"').to.eql(pm.collectionVariables.get('start'));", + "});", + "pm.test(\"Test booking 'end' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('end');", + " pm.expect(jsonData.end, '\"end\" must be \"' + pm.collectionVariables.get('end') + '\"').to.eql(pm.collectionVariables.get('end'));", + "});", + "pm.test(\"Test booking 'status' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('status');", + " pm.expect(jsonData.status, '\"status\" must be \"APPROVED\"').to.eql('APPROVED');", + "});", + "pm.test(\"Test booking 'booker.id' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('booker');", + " pm.expect(jsonData.booker).to.have.property('id');", + " pm.expect(jsonData.booker.id, '\"booker.id\" must be ${user2.id}').to.eql(user2.id);", + "});", + "pm.test(\"Test booking 'item.id' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('item');", + " pm.expect(jsonData.item).to.have.property('id');", + " pm.expect(jsonData.item.id, '\"item.id\" must be ${item.id}').to.eql(item.id);", + "});", + "pm.test(\"Test booking 'item.name' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('item');", + " pm.expect(jsonData.item).to.have.property('name');", + " pm.expect(jsonData.item.name, '\"item.name\" must be ${item.name}').to.eql(item.name);", + "});", + "" + ], + "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", + " var moment = require('moment');\r", + " const currentDate = moment();\r", + " var start = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " var end = currentDate.clone().add(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " pm.collectionVariables.set('start', start);\r", + " pm.collectionVariables.set('end', end);\r", + " \r", + " user1 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user1\", user1);\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user2\", user2);\r", + " pm.collectionVariables.set(\"userId\", user1.id);\r", + " it = rnd.getItem()\r", + " it.available = true\r", + " item = await api.addItem(it, user1.id)\r", + " pm.collectionVariables.set(\"itemId\", item.id);\r", + " pm.collectionVariables.set(\"item\", item);\r", + " book = await api.addBooking(rnd.getBooking(item.id, start, end), user2.id)\r", + " pm.collectionVariables.set(\"bookingId\", book.id);\r", + " pm.collectionVariables.set(\"booking\", book);\r", + "\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": "PATCH", + "header": [ + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}", + "type": "text" + }, + { + "key": "Accept", + "value": "*/*", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/bookings/{{bookingId}}?approved=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "bookings", + "{{bookingId}}" + ], + "query": [ + { + "key": "approved", + "value": "true" + } + ] + } + }, + "response": [] + }, + { + "name": "Booking approve by wrong user", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 403\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([400, 403, 500]);", + "});", + "pm.test(\"Has booking patch response\", function () {", + " pm.response.to.be.withBody;", + " pm.response.to.be.json;", + "});", + "" + ], + "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", + " var moment = require('moment');\r", + " const currentDate = moment();\r", + " var start = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " var end = currentDate.clone().add(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " pm.collectionVariables.set('start', start);\r", + " pm.collectionVariables.set('end', end);\r", + " \r", + " user1 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user1\", user1);\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user2\", user2);\r", + " pm.collectionVariables.set(\"userId\", user1.id + 2);\r", + " it = rnd.getItem()\r", + " it.available = true\r", + " item = await api.addItem(it, user1.id)\r", + " pm.collectionVariables.set(\"itemId\", item.id);\r", + " pm.collectionVariables.set(\"item\", item);\r", + " book = await api.addBooking(rnd.getBooking(item.id, start, end), user2.id)\r", + " pm.collectionVariables.set(\"bookingId\", book.id);\r", + " pm.collectionVariables.set(\"booking\", book);\r", + "\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": "PATCH", + "header": [ + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}", + "type": "text" + }, + { + "key": "Accept", + "value": "*/*", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/bookings/{{bookingId}}?approved=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "bookings", + "{{bookingId}}" + ], + "query": [ + { + "key": "approved", + "value": "true" + } + ] + } + }, + "response": [] + }, + { + "name": "Get booking by booker", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.be.ok;", + "});", + "pm.test(\"Has booking create response\", function () {", + " pm.response.to.be.withBody;", + " pm.response.to.be.json;", + "});", + "var item = pm.collectionVariables.get('item')", + "var user1 = pm.collectionVariables.get('user1')", + "var user2 = pm.collectionVariables.get('user2')", + "var start = pm.collectionVariables.get('start')", + "var end = pm.collectionVariables.get('end')", + "pm.test(\"Test booking 'start' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('start');", + " pm.expect(jsonData.start, '\"start\" must be \"' + pm.collectionVariables.get('start') + '\"').to.eql(pm.collectionVariables.get('start'));", + "});", + "pm.test(\"Test booking 'end' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('end');", + " pm.expect(jsonData.end, '\"end\" must be \"' + pm.collectionVariables.get('end') + '\"').to.eql(pm.collectionVariables.get('end'));", + "});", + "pm.test(\"Test booking 'status' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('status');", + " pm.expect(jsonData.status, '\"status\" must be \"WAITING\"').to.eql('WAITING');", + "});", + "pm.test(\"Test booking 'booker.id' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('booker');", + " pm.expect(jsonData.booker).to.have.property('id');", + " pm.expect(jsonData.booker.id, '\"booker.id\" must be ${user2.id}').to.eql(user2.id);", + "});", + "pm.test(\"Test booking 'item.id' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('item');", + " pm.expect(jsonData.item).to.have.property('id');", + " pm.expect(jsonData.item.id, '\"item.id\" must be ${item.id}').to.eql(item.id);", + "});", + "pm.test(\"Test booking 'item.name' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('item');", + " pm.expect(jsonData.item).to.have.property('name');", + " pm.expect(jsonData.item.name, '\"item.name\" must be ${item.name}').to.eql(item.name);", + "});", + "" + ], + "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", + " var moment = require('moment');\r", + " const currentDate = moment();\r", + " var start = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " var end = currentDate.clone().add(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " pm.collectionVariables.set('start', start);\r", + " pm.collectionVariables.set('end', end);\r", + " \r", + " user1 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user1\", user1);\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user2\", user2);\r", + " pm.collectionVariables.set(\"userId\", user2.id);\r", + " it = rnd.getItem()\r", + " it.available = true\r", + " item = await api.addItem(it, user1.id)\r", + " pm.collectionVariables.set(\"itemId\", item.id);\r", + " pm.collectionVariables.set(\"item\", item);\r", + " book = await api.addBooking(rnd.getBooking(item.id, start, end), user2.id)\r", + " pm.collectionVariables.set(\"bookingId\", book.id);\r", + " pm.collectionVariables.set(\"booking\", book);\r", + "\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": "X-Sharer-User-Id", + "value": "{{userId}}", + "type": "text" + }, + { + "key": "Accept", + "value": "*/*", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/bookings/{{bookingId}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "bookings", + "{{bookingId}}" + ] + } + }, + "response": [] + }, + { + "name": "Get booking by owner", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.be.ok;", + "});", + "pm.test(\"Has booking create response\", function () {", + " pm.response.to.be.withBody;", + " pm.response.to.be.json;", + "});", + "var item = pm.collectionVariables.get('item')", + "var user1 = pm.collectionVariables.get('user1')", + "var user2 = pm.collectionVariables.get('user2')", + "var start = pm.collectionVariables.get('start')", + "var end = pm.collectionVariables.get('end')", + "pm.test(\"Test booking 'start' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('start');", + " pm.expect(jsonData.start, '\"start\" must be \"' + pm.collectionVariables.get('start') + '\"').to.eql(pm.collectionVariables.get('start'));", + "});", + "pm.test(\"Test booking 'end' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('end');", + " pm.expect(jsonData.end, '\"end\" must be \"' + pm.collectionVariables.get('end') + '\"').to.eql(pm.collectionVariables.get('end'));", + "});", + "pm.test(\"Test booking 'status' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('status');", + " pm.expect(jsonData.status, '\"status\" must be \"WAITING\"').to.eql('WAITING');", + "});", + "pm.test(\"Test booking 'booker.id' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('booker');", + " pm.expect(jsonData.booker).to.have.property('id');", + " pm.expect(jsonData.booker.id, '\"booker.id\" must be ${user2.id}').to.eql(user2.id);", + "});", + "pm.test(\"Test booking 'item.id' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('item');", + " pm.expect(jsonData.item).to.have.property('id');", + " pm.expect(jsonData.item.id, '\"item.id\" must be ${item.id}').to.eql(item.id);", + "});", + "pm.test(\"Test booking 'item.name' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('item');", + " pm.expect(jsonData.item).to.have.property('name');", + " pm.expect(jsonData.item.name, '\"item.name\" must be ${item.name}').to.eql(item.name);", + "});", + "" + ], + "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", + " var moment = require('moment');\r", + " const currentDate = moment();\r", + " var start = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " var end = currentDate.clone().add(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " pm.collectionVariables.set('start', start);\r", + " pm.collectionVariables.set('end', end);\r", + " \r", + " user1 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user1\", user1);\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user2\", user2);\r", + " pm.collectionVariables.set(\"userId\", user2.id);\r", + " it = rnd.getItem()\r", + " it.available = true\r", + " item = await api.addItem(it, user1.id)\r", + " pm.collectionVariables.set(\"itemId\", item.id);\r", + " pm.collectionVariables.set(\"item\", item);\r", + " book = await api.addBooking(rnd.getBooking(item.id, start, end), user2.id)\r", + " pm.collectionVariables.set(\"bookingId\", book.id);\r", + " pm.collectionVariables.set(\"booking\", book);\r", + "\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": "X-Sharer-User-Id", + "value": "{{userId}}", + "type": "text" + }, + { + "key": "Accept", + "value": "*/*", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/bookings/{{bookingId}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "bookings", + "{{bookingId}}" + ] + } + }, + "response": [] + }, + { + "name": "Get all bookings from wrong user", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 500\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([500,404,403]);", + "});", + "" + ], + "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", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"userId\", user2.id + 1);\r", + "\r", + "\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": "X-Sharer-User-Id", + "value": "{{userId}}", + "type": "text" + }, + { + "key": "Accept", + "value": "*/*", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/bookings/owner", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "bookings", + "owner" + ] + } + }, + "response": [] + }, + { + "name": "Get all user bookings", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.be.ok;", + "});", + "pm.test(\"Has booking patch response\", function () {", + " pm.response.to.be.withBody;", + " pm.response.to.be.json;", + "});", + "var item = pm.collectionVariables.get('item')", + "var book = pm.collectionVariables.get('booking')", + "var user1 = pm.collectionVariables.get('user1')", + "var user2 = pm.collectionVariables.get('user2')", + "var jsonData = pm.response.json()[0];", + "", + "pm.test(\"Test booking 'id' field\", function () {", + " pm.expect(jsonData).to.have.property('id');", + " pm.expect(jsonData.id, '\"id\" must be ${book.id}').to.eql(book.id);", + "});", + "pm.test(\"Test booking 'start' field\", function () {", + " pm.expect(jsonData).to.have.property('start');", + " pm.expect(jsonData.start, '\"start\" must be \"' + pm.collectionVariables.get('start') + '\"').to.eql(pm.collectionVariables.get('start'));", + "});", + "pm.test(\"Test booking 'end' field\", function () {", + " pm.expect(jsonData).to.have.property('end');", + " pm.expect(jsonData.end, '\"end\" must be \"' + pm.collectionVariables.get('end') + '\"').to.eql(pm.collectionVariables.get('end'));", + "});", + "pm.test(\"Test booking 'status' field\", function () {", + " pm.expect(jsonData).to.have.property('status');", + " pm.expect(jsonData.status, '\"status\" must be \"WAITING\"').to.eql('WAITING');", + "});", + "pm.test(\"Test booking 'booker.id' field\", function () {", + " pm.expect(jsonData).to.have.property('booker');", + " pm.expect(jsonData.booker).to.have.property('id');", + " pm.expect(jsonData.booker.id, '\"booker.id\" must be ${user2.id}').to.eql(user2.id);", + "});", + "pm.test(\"Test booking 'item.id' field\", function () {", + " pm.expect(jsonData).to.have.property('item');", + " pm.expect(jsonData.item).to.have.property('id');", + " pm.expect(jsonData.item.id, '\"item.id\" must be ${item.id}').to.eql(item.id);", + "});", + "pm.test(\"Test booking 'item.name' field\", function () {", + " pm.expect(jsonData).to.have.property('item');", + " pm.expect(jsonData.item).to.have.property('name');", + " pm.expect(jsonData.item.name, '\"item.name\" must be ${item.name}').to.eql(item.name);", + "});", + "" + ], + "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", + " var moment = require('moment');\r", + " const currentDate = moment();\r", + " var start = currentDate.clone().add(1, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " var end = currentDate.clone().add(2, 'days').format('YYYY-MM-DDTHH:mm:ss');\r", + " pm.collectionVariables.set('start', start);\r", + " pm.collectionVariables.set('end', end);\r", + " \r", + " user1 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user1\", user1);\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user2\", user2);\r", + " pm.collectionVariables.set(\"userId\", user2.id);\r", + " it = rnd.getItem()\r", + " it.available = true\r", + " item = await api.addItem(it, user1.id)\r", + " pm.collectionVariables.set(\"itemId\", item.id);\r", + " pm.collectionVariables.set(\"item\", item);\r", + " book = await api.addBooking(rnd.getBooking(item.id, start, end), user2.id)\r", + " pm.collectionVariables.set(\"bookingId\", book.id);\r", + " pm.collectionVariables.set(\"booking\", book);\r", + "\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": "X-Sharer-User-Id", + "value": "{{userId}}", + "type": "text" + }, + { + "key": "Accept", + "value": "*/*", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/bookings", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "bookings" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "comments", + "item": [ + { + "name": "Comment past booking", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200 or 201\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([200,201]);", + "});", + "pm.test(\"Response have body\", function () {", + " pm.response.to.be.withBody;", + " pm.response.to.be.json;", + "});", + "var item = pm.collectionVariables.get(\"item\");", + "var user1 = pm.collectionVariables.get(\"user1\");", + "var user2 = pm.collectionVariables.get(\"user2\");", + "var text = pm.collectionVariables.get(\"commentText\")", + "pm.test(\"Response data equal to request\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('id');", + " pm.expect(jsonData).to.have.property('text');", + " pm.expect(jsonData).to.have.property('authorName');", + " pm.expect(jsonData).to.have.property('created');", + " pm.expect(jsonData.text, `\"text\" must be ` + text).to.eql(text);", + " pm.expect(jsonData.authorName, `\"authorName\" must be ${user2.name}`).to.eql(user2.name);", + "});" + ], + "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", + " var moment = require('moment');\r", + " const currentDate = moment();\r", + " var start = currentDate.clone().add(1, 'seconds').format('YYYY-MM-DDTHH:mm:ss');\r", + " var end = currentDate.clone().add(2, 'seconds').format('YYYY-MM-DDTHH:mm:ss');\r", + " pm.collectionVariables.set('start', start);\r", + " pm.collectionVariables.set('end', end);\r", + " \r", + " user1 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user1\", user1);\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user2\", user2);\r", + " pm.collectionVariables.set(\"userId\", user2.id);\r", + " it = rnd.getItem()\r", + " it.available = true\r", + " item = await api.addItem(it, user1.id)\r", + " pm.collectionVariables.set(\"itemId\", item.id);\r", + " pm.collectionVariables.set(\"item\", item);\r", + " book = await api.addBooking(rnd.getBooking(item.id, start, end), user2.id)\r", + " await api.approveBooking(book.id, user1.id)\r", + " pm.collectionVariables.set(\"bookingId\", book.id);\r", + " pm.collectionVariables.set(\"booking\", book);\r", + " pm.collectionVariables.set(\"commentText\", rnd.getWord(50));\r", + " setTimeout(function(){}, 3000);\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": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "Accept", + "value": "*/*", + "type": "text" + }, + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"text\": \"{{commentText}}\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/items/{{itemId}}/comment", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "items", + "{{itemId}}", + "comment" + ] + } + }, + "response": [] + }, + { + "name": "Comment approved booking", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.expect(pm.response.code).to.be.oneOf([400, 500])", + "});", + "" + ], + "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", + " var moment = require('moment');\r", + " const currentDate = moment();\r", + " var start = currentDate.clone().add(1, 'seconds').format('YYYY-MM-DDTHH:mm:ss');\r", + " var end = currentDate.clone().add(2, 'seconds').format('YYYY-MM-DDTHH:mm:ss');\r", + " pm.collectionVariables.set('start', start);\r", + " pm.collectionVariables.set('end', end);\r", + " \r", + " user1 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user1\", user1);\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user2\", user2);\r", + " pm.collectionVariables.set(\"userId\", user2.id);\r", + " it = rnd.getItem()\r", + " it.available = true\r", + " item = await api.addItem(it, user1.id)\r", + " pm.collectionVariables.set(\"itemId\", item.id);\r", + " pm.collectionVariables.set(\"item\", item);\r", + " book = await api.addBooking(rnd.getBooking(item.id, start, end), user2.id)\r", + " await api.approveBooking(book.id, user1.id)\r", + " pm.collectionVariables.set(\"bookingId\", book.id);\r", + " pm.collectionVariables.set(\"booking\", book);\r", + " pm.collectionVariables.set(\"commentText\", rnd.getWord(50));\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": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "Accept", + "value": "*/*", + "type": "text" + }, + { + "key": "X-Sharer-User-Id", + "value": "{{userId}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"text\": \"{{commentText}}\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/items/{{itemId}}/comment", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "items", + "{{itemId}}", + "comment" + ] + } + }, + "response": [] + }, + { + "name": "Get item with comments", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.be.ok;", + "});", + "pm.test(\"Has item create response\", function () {", + " pm.response.to.be.withBody;", + " pm.response.to.be.json;", + "});", + "pm.test(\"Test item 'id' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('id');", + "});", + "pm.test(\"Test item 'name' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('name');", + "});", + "pm.test(\"Test item 'description' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('description');", + "});", + "pm.test(\"Test item 'available' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('available');", + "});", + "pm.test(\"Test item 'lastBooking' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('lastBooking');", + " pm.expect(jsonData.lastBooking, '\"lastBooking\" must be \"null\"').null;", + "});", + "pm.test(\"Test item 'nextBooking' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('nextBooking');", + " pm.expect(jsonData.nextBooking, '\"nextBooking\" must be \"null\"').null;", + "});", + "pm.test(\"Test item 'comments' field\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('comments');", + " pm.expect(jsonData.comments.length, 'length of \"comments\" must be \"1\"').to.eql(1);", + "});", + "" + ], + "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", + " var moment = require('moment');\r", + " const currentDate = moment();\r", + " var start = currentDate.clone().add(1, 'seconds').format('YYYY-MM-DDTHH:mm:ss');\r", + " var end = currentDate.clone().add(2, 'seconds').format('YYYY-MM-DDTHH:mm:ss');\r", + " pm.collectionVariables.set('start', start);\r", + " pm.collectionVariables.set('end', end);\r", + " \r", + " user1 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user1\", user1);\r", + " user2 = await api.addUser(rnd.getUser());\r", + " pm.collectionVariables.set(\"user2\", user2);\r", + " pm.collectionVariables.set(\"userId\", user2.id);\r", + " it = rnd.getItem()\r", + " it.available = true\r", + " item = await api.addItem(it, user1.id)\r", + " pm.collectionVariables.set(\"itemId\", item.id);\r", + " pm.collectionVariables.set(\"item\", item);\r", + " book = await api.addBooking(rnd.getBooking(item.id, start, end), user2.id)\r", + " await api.approveBooking(book.id, user1.id)\r", + " pm.collectionVariables.set(\"bookingId\", book.id);\r", + " pm.collectionVariables.set(\"booking\", book);\r", + " pm.collectionVariables.set(\"commentText\", rnd.getWord(50));\r", + " pausecomp(3000);\r", + " await api.getBooking(book.id, user1.id)\r", + " comment = await api.addComment({\"text\": rnd.getWord(50)}, item.id, user2.id)\r", + " } catch(err) {\r", + " console.error(\"Ошибка при подготовке тестовых данных.\", err);\r", + " }\r", + "\r", + "};\r", + "\r", + "const interval = setInterval(() => {}, 1000);\r", + "function pausecomp(millis)\r", + " {\r", + " var date = new Date();\r", + " var curDate = null;\r", + " do { curDate = new Date(); }\r", + " while(curDate-date < millis);\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": "X-Sharer-User-Id", + "value": "{{userId}}", + "type": "text" + }, + { + "key": "Accept", + "value": "*/*", + "type": "text" + } + ], + "url": { + "raw": "{{baseUrl}}/items/{{itemId}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "items", + "{{itemId}}" + ] + } + }, + "response": [] + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "API = class {\r", + " constructor(postman, verbose = false, baseUrl = \"http://localhost:8080\") {\r", + " this.baseUrl = baseUrl;\r", + " this.pm = postman;\r", + " this._verbose = verbose;\r", + " }\r", + "\r", + " async addUser(user, id=0, verbose=null) {\r", + " return this.post(\"/users\", user, id, \"Ошибка при добавлении нового пользователя: \", verbose);\r", + " }\r", + "\r", + " async addItem(item, id=0, verbose=null) {\r", + " return this.post(\"/items\", item, id, \"Ошибка при добавлении новой вещи: \", verbose);\r", + " }\r", + "\r", + " async addBooking(booking, id=0, verbose=null) {\r", + " return this.post(\"/bookings\", booking, id, \"Ошибка при добавлении нового бронирования: \", verbose);\r", + " }\r", + "\r", + " async addComment(comment, itemId, id=0, verbose=null) {\r", + " return this.post(\"/items/\" + itemId + \"/comment\", comment, id, \"Ошибка при добавлении нового комментария: \", verbose);\r", + " }\r", + "\r", + " async getBooking(bookingId, id=0, verbose=null) {\r", + " return this.get(\"/bookings/\"+bookingId, {}, id, \"Ошибка при получении информации о бронировании: \", verbose);\r", + " }\r", + "\r", + " async approveBooking(bookingId, id=0, verbose=null) {\r", + " return this.patch(\"/bookings/\"+bookingId+\"?approved=true\", {}, id, \"Ошибка при подтверждении бронирования: \", verbose);\r", + " }\r", + "\r", + " async addRequest(request, id=0, verbose=null) {\r", + " return this.post(\"/requests\", request, id, \"Ошибка при добавлении нового запроса: \", verbose);\r", + " }\r", + " \r", + " async post(path, body, id=0, errorText = \"Ошибка при выполнении post-запроса: \", verbose=null) {\r", + " return this.sendRequest(\"POST\", path, body, id, errorText, verbose);\r", + " }\r", + "\r", + " async patch(path, body = null, id=0, errorText = \"Ошибка при выполнении patch-запроса: \", verbose=null) {\r", + " return this.sendRequest(\"PATCH\", path, body, id, errorText, verbose);\r", + " }\r", + "\r", + " async get(path, body = null, id=0, errorText = \"Ошибка при выполнении get-запроса: \", verbose=null) {\r", + " return this.sendRequest(\"GET\", path, body, id, errorText, verbose);\r", + " }\r", + "\r", + " async put(path, body = null, id=0, errorText = \"Ошибка при выполнении put-запроса: \", verbose=null) {\r", + " return this.sendRequest(\"PUT\", path, body, id, errorText, verbose);\r", + " }\r", + "\r", + " async delete(path, body = null, id=0, errorText = \"Ошибка при выполнении delte-запроса: \", verbose=null) {\r", + " return this.sendRequest(\"DELETE\", path, body, id, errorText, verbose);\r", + " }\r", + "\r", + " async sendRequest(method, path, body=null, id=0, errorText = \"Ошибка при выполнении запроса: \", verbose=null) {\r", + " return new Promise((resolve, reject) => {\r", + " verbose = verbose == null ? this._verbose : verbose;\r", + " var req = {};\r", + " if (id == 0){\r", + " req = {\r", + " url: this.baseUrl + path,\r", + " method: method,\r", + " body: body == null ? \"\" : JSON.stringify(body),\r", + " header: { \"Content-Type\": \"application/json\"},\r", + " };\r", + " }else{\r", + " req = {\r", + " url: this.baseUrl + path,\r", + " method: method,\r", + " body: body == null ? \"\" : JSON.stringify(body),\r", + " header: [{\r", + " \"key\": \"X-Sharer-User-Id\",\r", + " \"value\": id,\r", + " \"type\": \"text\",\r", + " },\r", + " {\r", + " \"key\": \"Content-Type\",\r", + " \"name\": \"Content-Type\",\r", + " \"value\": \"application/json\",\r", + " \"type\": \"text\"\r", + " }]\r", + " };\r", + " }\r", + " if(verbose) {\r", + " console.log(\"Отправляю запрос: \", req);\r", + " }\r", + "\r", + " try {\r", + " this.pm.sendRequest(req, (error, response) => {\r", + " if(error || (response.code >= 400 && response.code <= 599)) {\r", + " let err = error ? error : JSON.stringify(response.json());\r", + " console.error(\"При выполнении запроса к серверу возникла ошибка.\\n\", err,\r", + " \"\\nДля отладки проблемы повторите такой же запрос к вашей программе \" + \r", + " \"на локальном компьютере. Данные запроса:\\n\", JSON.stringify(request));\r", + "\r", + " reject(new Error(errorText + err));\r", + " }\r", + " if(verbose) {\r", + " console.log(\"Результат обработки запроса: код состояния - \", response.code, \", тело: \", response.json());\r", + " }\r", + " if (response.stream.length === 0){\r", + " resolve(null);\r", + " }else{\r", + " resolve(response.json());\r", + " }\r", + " });\r", + " \r", + " } catch(err) {\r", + " if(verbose) {\r", + " console.error(errorText, err);\r", + " }\r", + " return Promise.reject(err);\r", + " }\r", + " });\r", + " }\r", + "};\r", + "\r", + "RandomUtils = class {\r", + " constructor() {}\r", + "\r", + " getUser() {\r", + " return {\r", + " name: pm.variables.replaceIn('{{$randomFullName}}'),\r", + " email: pm.variables.replaceIn('{{$randomEmail}}'),\r", + " };\r", + " }\r", + "\r", + " getRequest() {\r", + " return {\r", + " description: this.getWord(50)\r", + " };\r", + " }\r", + "\r", + " getBooking(id, startBook, endBook) {\r", + " return {\r", + " itemId: id, \r", + " start: startBook,\r", + " end: endBook \r", + " };\r", + " }\r", + "\r", + " getItem() {\r", + " return {\r", + " name: this.getWord(10),\r", + " description: this.getWord(50),\r", + " available: pm.variables.replaceIn('{{$randomBoolean}}')\t\r", + " };\r", + " }\r", + "\r", + " getItemForRequest(id) {\r", + " return {\r", + " name: this.getWord(10),\r", + " description: this.getWord(50),\r", + " available: pm.variables.replaceIn('{{$randomBoolean}}'),\r", + " requestId: id\r", + " };\r", + " }\r", + "\r", + " getFilm(director=null) {\r", + " let date = new Date(new Date(1960, 0, 1).getTime() + Math.random() * (new Date(2010, 0, 1).getTime() - new Date(1960, 0, 1).getTime()));\r", + " var toReturn = {\r", + " name: this.getWord(15),\r", + " description: this.getWord(50),\r", + " releaseDate: date.toISOString().slice(0,10),\r", + " duration: Math.floor(Math.random() * (180 - 60 + 1) + 60),\r", + " mpa: { id: Math.floor(Math.random() * (5 - 1 + 1) + 1)},\r", + " genres: [{ id: Math.floor(Math.random() * (6 - 1 + 1) + 1)}]\r", + " };\r", + " if (director!==null)\r", + " toReturn.directors = [{ id: director.id}];\r", + " return toReturn;\r", + " }\r", + "\r", + "\r", + " getWord(length = 1) {\r", + " let result = '';\r", + " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\r", + " const charactersLength = characters.length;\r", + " let counter = 0;\r", + " while (counter < length) {\r", + " result += characters.charAt(Math.floor(Math.random() * charactersLength));\r", + " counter += 1;\r", + " }\r", + " return result;\r", + " }\r", + "\r", + " getName(length = 1) {\r", + " let result = '';\r", + " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\r", + " const charactersLength = characters.length;\r", + " let counter = 0;\r", + " while (counter < length) {\r", + " result += characters.charAt(Math.floor(Math.random() * charactersLength));\r", + " counter += 1;\r", + " }\r", + " return result;\r", + " }\r", + "\r", + "}" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "key": "userName", + "value": "" + }, + { + "key": "userEmail", + "value": "" + }, + { + "key": "userId", + "value": "1" + }, + { + "key": "itemName", + "value": "" + }, + { + "key": "itemAvailable", + "value": "" + }, + { + "key": "itemDescription", + "value": "" + }, + { + "key": "item", + "value": "" + }, + { + "key": "requestId", + "value": "" + }, + { + "key": "requestDescription", + "value": "" + }, + { + "key": "baseUrl", + "value": "localhost:8080" + }, + { + "key": "start", + "value": "" + }, + { + "key": "end", + "value": "" + }, + { + "key": "itemId", + "value": "" + }, + { + "key": "user1", + "value": "" + }, + { + "key": "user2", + "value": "" + }, + { + "key": "bookingId", + "value": "1" + }, + { + "key": "booking", + "value": "" + }, + { + "key": "commentText", + "value": "" + } + ] +} diff --git a/server/pom.xml b/server/pom.xml new file mode 100644 index 0000000..584f63d --- /dev/null +++ b/server/pom.xml @@ -0,0 +1,86 @@ + + + 4.0.0 + + ru.practicum + shareit + 0.0.1-SNAPSHOT + + + shareit-server + 0.0.1-SNAPSHOT + + ShareIt Server + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-actuator + + + + org.postgresql + postgresql + runtime + + + + com.h2database + h2 + runtime + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + org.projectlombok + lombok + true + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + coverage + + + + org.jacoco + jacoco-maven-plugin + + + + + + + diff --git a/server/src/main/java/ru/practicum/shareit/ShareItApp.java b/server/src/main/java/ru/practicum/shareit/ShareItApp.java new file mode 100644 index 0000000..a00ad56 --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/ShareItApp.java @@ -0,0 +1,13 @@ +package ru.practicum.shareit; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ShareItApp { + + public static void main(String[] args) { + SpringApplication.run(ShareItApp.class, args); + } + +} diff --git a/src/main/java/ru/practicum/shareit/booking/Booking.java b/server/src/main/java/ru/practicum/shareit/booking/Booking.java similarity index 100% rename from src/main/java/ru/practicum/shareit/booking/Booking.java rename to server/src/main/java/ru/practicum/shareit/booking/Booking.java diff --git a/src/main/java/ru/practicum/shareit/booking/BookingController.java b/server/src/main/java/ru/practicum/shareit/booking/BookingController.java similarity index 78% rename from src/main/java/ru/practicum/shareit/booking/BookingController.java rename to server/src/main/java/ru/practicum/shareit/booking/BookingController.java index 0dfb613..7c7879a 100644 --- a/src/main/java/ru/practicum/shareit/booking/BookingController.java +++ b/server/src/main/java/ru/practicum/shareit/booking/BookingController.java @@ -14,33 +14,33 @@ public class BookingController { private final BookingService bookingService; @GetMapping("/{id}") - public BookingDto getItem( + public BookingDto getBooking( @PathVariable long id, @RequestHeader("X-Sharer-User-Id") long userId) { return bookingService.getBooking(id, userId); } @GetMapping - public List getItemsForUserId( + public List getBookingForUserId( @RequestHeader("X-Sharer-User-Id") long userId) { - return bookingService.getItemsForUserId(userId); + return bookingService.getBookingForUserId(userId); } @GetMapping("/owner") - public List getItemsForItemOwnerId( + public List getBookingForItemOwnerId( @RequestHeader("X-Sharer-User-Id") long ownerId) { - return bookingService.getItemsForItemOwnerId(ownerId); + return bookingService.getBookingsForItemOwnerId(ownerId); } @PostMapping - public BookingDto postItem( + public BookingDto postBooking( @RequestHeader("X-Sharer-User-Id") long userId, @Valid @RequestBody BookingDto bookingDto) { return bookingService.createBooking(bookingDto, userId); } @PatchMapping("/{id}") - public BookingDto patchItem( + public BookingDto patchBooking( @PathVariable long id, @RequestParam(name = "approved") boolean approved, @RequestHeader("X-Sharer-User-Id") long userId) { diff --git a/src/main/java/ru/practicum/shareit/booking/BookingMapper.java b/server/src/main/java/ru/practicum/shareit/booking/BookingMapper.java similarity index 100% rename from src/main/java/ru/practicum/shareit/booking/BookingMapper.java rename to server/src/main/java/ru/practicum/shareit/booking/BookingMapper.java diff --git a/src/main/java/ru/practicum/shareit/booking/BookingService.java b/server/src/main/java/ru/practicum/shareit/booking/BookingService.java similarity index 92% rename from src/main/java/ru/practicum/shareit/booking/BookingService.java rename to server/src/main/java/ru/practicum/shareit/booking/BookingService.java index bfe9eb0..6f9b1c5 100644 --- a/src/main/java/ru/practicum/shareit/booking/BookingService.java +++ b/server/src/main/java/ru/practicum/shareit/booking/BookingService.java @@ -39,11 +39,11 @@ public BookingDto getBooking(long bookingId, long userId) { ItemMapper.toDto(bookingEntity.getItem())); } - public List getItemsForUserId(long userId) { - return getItemsForUserId(BookingStatusRequestDto.ALL, userId); + public List getBookingForUserId(long userId) { + return getBookingForUserId(BookingStatusRequestDto.ALL, userId); } - public List getItemsForUserId(BookingStatusRequestDto state, long userId) { + public List getBookingForUserId(BookingStatusRequestDto state, long userId) { var userEntity = userStorage.getUser(userId) .orElseThrow(() -> new NotFoundException("Пользователь не найден")); @@ -64,11 +64,11 @@ public List getItemsForUserId(BookingStatusRequestDto state, long us .toList(); } - public List getItemsForItemOwnerId(long userId) { - return getItemsForItemOwnerId(BookingStatusRequestDto.ALL, userId); + public List getBookingsForItemOwnerId(long userId) { + return getBookingsForItemOwnerId(BookingStatusRequestDto.ALL, userId); } - public List getItemsForItemOwnerId(BookingStatusRequestDto state, long ownerId) { + public List getBookingsForItemOwnerId(BookingStatusRequestDto state, long ownerId) { if (!userStorage.existsById(ownerId)) { throw new NotFoundException("Пользователь не найден"); } diff --git a/src/main/java/ru/practicum/shareit/booking/BookingStatus.java b/server/src/main/java/ru/practicum/shareit/booking/BookingStatus.java similarity index 100% rename from src/main/java/ru/practicum/shareit/booking/BookingStatus.java rename to server/src/main/java/ru/practicum/shareit/booking/BookingStatus.java diff --git a/src/main/java/ru/practicum/shareit/booking/BookingStorage.java b/server/src/main/java/ru/practicum/shareit/booking/BookingStorage.java similarity index 100% rename from src/main/java/ru/practicum/shareit/booking/BookingStorage.java rename to server/src/main/java/ru/practicum/shareit/booking/BookingStorage.java diff --git a/src/main/java/ru/practicum/shareit/booking/Review.java b/server/src/main/java/ru/practicum/shareit/booking/Review.java similarity index 100% rename from src/main/java/ru/practicum/shareit/booking/Review.java rename to server/src/main/java/ru/practicum/shareit/booking/Review.java diff --git a/src/main/java/ru/practicum/shareit/booking/Status.java b/server/src/main/java/ru/practicum/shareit/booking/Status.java similarity index 100% rename from src/main/java/ru/practicum/shareit/booking/Status.java rename to server/src/main/java/ru/practicum/shareit/booking/Status.java diff --git a/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java b/server/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java similarity index 100% rename from src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java rename to server/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java diff --git a/server/src/main/java/ru/practicum/shareit/booking/dto/BookingStatusRequestDto.java b/server/src/main/java/ru/practicum/shareit/booking/dto/BookingStatusRequestDto.java new file mode 100644 index 0000000..2bd64ee --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/booking/dto/BookingStatusRequestDto.java @@ -0,0 +1,11 @@ +package ru.practicum.shareit.booking.dto; + +public enum BookingStatusRequestDto { + ALL, + CURRENT, + PAST, + FUTURE, + WAITING, + REJECTED, + APPROVED +} diff --git a/server/src/main/java/ru/practicum/shareit/booking/dto/ReviewDto.java b/server/src/main/java/ru/practicum/shareit/booking/dto/ReviewDto.java new file mode 100644 index 0000000..a87829f --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/booking/dto/ReviewDto.java @@ -0,0 +1,13 @@ +package ru.practicum.shareit.booking.dto; + +import lombok.Builder; +import lombok.Value; + +@Value +@Builder(toBuilder = true) +public class ReviewDto { + Long id; + Long bookingId; + String text; + boolean isSuccess; +} diff --git a/src/main/java/ru/practicum/shareit/booking/dto/ReviewMapper.java b/server/src/main/java/ru/practicum/shareit/booking/dto/ReviewMapper.java similarity index 100% rename from src/main/java/ru/practicum/shareit/booking/dto/ReviewMapper.java rename to server/src/main/java/ru/practicum/shareit/booking/dto/ReviewMapper.java diff --git a/src/main/java/ru/practicum/shareit/booking/storage/BookingEntity.java b/server/src/main/java/ru/practicum/shareit/booking/storage/BookingEntity.java similarity index 100% rename from src/main/java/ru/practicum/shareit/booking/storage/BookingEntity.java rename to server/src/main/java/ru/practicum/shareit/booking/storage/BookingEntity.java diff --git a/src/main/java/ru/practicum/shareit/booking/storage/BookingRepository.java b/server/src/main/java/ru/practicum/shareit/booking/storage/BookingRepository.java similarity index 100% rename from src/main/java/ru/practicum/shareit/booking/storage/BookingRepository.java rename to server/src/main/java/ru/practicum/shareit/booking/storage/BookingRepository.java diff --git a/src/main/java/ru/practicum/shareit/booking/storage/BookingStorageInDb.java b/server/src/main/java/ru/practicum/shareit/booking/storage/BookingStorageInDb.java similarity index 100% rename from src/main/java/ru/practicum/shareit/booking/storage/BookingStorageInDb.java rename to server/src/main/java/ru/practicum/shareit/booking/storage/BookingStorageInDb.java diff --git a/src/main/java/ru/practicum/shareit/exceptions/IdIsAlreadyInUseException.java b/server/src/main/java/ru/practicum/shareit/exceptions/IdIsAlreadyInUseException.java similarity index 100% rename from src/main/java/ru/practicum/shareit/exceptions/IdIsAlreadyInUseException.java rename to server/src/main/java/ru/practicum/shareit/exceptions/IdIsAlreadyInUseException.java diff --git a/src/main/java/ru/practicum/shareit/exceptions/NotFoundException.java b/server/src/main/java/ru/practicum/shareit/exceptions/NotFoundException.java similarity index 100% rename from src/main/java/ru/practicum/shareit/exceptions/NotFoundException.java rename to server/src/main/java/ru/practicum/shareit/exceptions/NotFoundException.java diff --git a/src/main/java/ru/practicum/shareit/exceptions/NotValidException.java b/server/src/main/java/ru/practicum/shareit/exceptions/NotValidException.java similarity index 100% rename from src/main/java/ru/practicum/shareit/exceptions/NotValidException.java rename to server/src/main/java/ru/practicum/shareit/exceptions/NotValidException.java diff --git a/src/main/java/ru/practicum/shareit/item/CommentMapper.java b/server/src/main/java/ru/practicum/shareit/item/CommentMapper.java similarity index 100% rename from src/main/java/ru/practicum/shareit/item/CommentMapper.java rename to server/src/main/java/ru/practicum/shareit/item/CommentMapper.java diff --git a/server/src/main/java/ru/practicum/shareit/item/ItemController.java b/server/src/main/java/ru/practicum/shareit/item/ItemController.java new file mode 100644 index 0000000..1105422 --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/item/ItemController.java @@ -0,0 +1,70 @@ +package ru.practicum.shareit.item; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; +import ru.practicum.shareit.item.dto.CommentDto; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.dto.ItemToUpdateDto; + +import java.util.List; + + +@RestController +@RequestMapping("/items") +@RequiredArgsConstructor +public class ItemController { + private final ItemService itemService; + + @GetMapping + public List getItems(@RequestHeader("X-Sharer-User-Id") long userId) { + return itemService.getItems(userId); + } + + @GetMapping("/{id}") + public ItemDto getItem(@PathVariable long id) { + return itemService.getItem(id); + } + + @GetMapping("/search") + public List findItemsByText(@RequestParam String text) { + return itemService.findFreeItemsByText(text, true); + } + + @PostMapping + public ItemDto postItem( + @Valid @RequestBody ItemDto itemDto, + @RequestHeader("X-Sharer-User-Id") long userId) { + return itemService.createItem(itemDto, userId); + } + + @PostMapping("/{id}/comment") + public CommentDto postComment( + @PathVariable long id, + @RequestHeader("X-Sharer-User-Id") long userId, + @Valid @RequestBody CommentDto commentDto) { + return itemService.addComment(commentDto, id, userId); + } + + @PutMapping() + public ItemDto putItem( + @Valid @RequestBody ItemDto itemDto, + @RequestHeader("X-Sharer-User-Id") long userId) { + + return itemService.updateItem(itemDto, userId); + } + + @PatchMapping("/{id}") + public ItemDto patchItem( + @PathVariable long id, + @Valid @RequestBody ItemToUpdateDto item, + @RequestHeader("X-Sharer-User-Id") long userId) { + return itemService.updateItem(id, item, userId); + } + + @DeleteMapping("/{id}") + public ItemDto deleteItem(@PathVariable long id, + @RequestHeader("X-Sharer-User-Id") long userId) { + return itemService.deleteItem(id, userId); + } +} diff --git a/src/main/java/ru/practicum/shareit/item/ItemMapper.java b/server/src/main/java/ru/practicum/shareit/item/ItemMapper.java similarity index 100% rename from src/main/java/ru/practicum/shareit/item/ItemMapper.java rename to server/src/main/java/ru/practicum/shareit/item/ItemMapper.java diff --git a/src/main/java/ru/practicum/shareit/item/ItemService.java b/server/src/main/java/ru/practicum/shareit/item/ItemService.java similarity index 99% rename from src/main/java/ru/practicum/shareit/item/ItemService.java rename to server/src/main/java/ru/practicum/shareit/item/ItemService.java index e43e6aa..f094afb 100644 --- a/src/main/java/ru/practicum/shareit/item/ItemService.java +++ b/server/src/main/java/ru/practicum/shareit/item/ItemService.java @@ -131,7 +131,7 @@ public List findFreeItemsByText(String text, boolean available) { if (text == null || text.isEmpty()) return List.of(); - var itemEntities = itemStorage.findItemsByTextAndStatus(text, true); + var itemEntities = itemStorage.findItemsByTextAndStatus(text, available); return itemEntities .stream() diff --git a/src/main/java/ru/practicum/shareit/item/ItemStorage.java b/server/src/main/java/ru/practicum/shareit/item/ItemStorage.java similarity index 100% rename from src/main/java/ru/practicum/shareit/item/ItemStorage.java rename to server/src/main/java/ru/practicum/shareit/item/ItemStorage.java diff --git a/server/src/main/java/ru/practicum/shareit/item/dto/CommentDto.java b/server/src/main/java/ru/practicum/shareit/item/dto/CommentDto.java new file mode 100644 index 0000000..6b72310 --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/item/dto/CommentDto.java @@ -0,0 +1,14 @@ +package ru.practicum.shareit.item.dto; + +import jakarta.validation.constraints.NotBlank; +import lombok.Builder; + +import java.sql.Timestamp; + +@Builder(toBuilder = true) +public record CommentDto( + Long id, + @NotBlank String text, + String authorName, + Timestamp created +) { } diff --git a/server/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java b/server/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java new file mode 100644 index 0000000..842bbd5 --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java @@ -0,0 +1,20 @@ +package ru.practicum.shareit.item.dto; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Builder; + +import java.sql.Timestamp; +import java.util.List; + +@Builder(toBuilder = true) +public record ItemDto( + Long id, + @NotBlank String name, + @NotBlank String description, + @NotNull Boolean available, + Timestamp lastBooking, + Timestamp nextBooking, + List comments, + Long requestId +) { } diff --git a/server/src/main/java/ru/practicum/shareit/item/dto/ItemToUpdateDto.java b/server/src/main/java/ru/practicum/shareit/item/dto/ItemToUpdateDto.java new file mode 100644 index 0000000..af7523d --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/item/dto/ItemToUpdateDto.java @@ -0,0 +1,10 @@ +package ru.practicum.shareit.item.dto; + +import lombok.Builder; + +@Builder +public record ItemToUpdateDto( + String name, + String description, + Boolean available +) { } diff --git a/src/main/java/ru/practicum/shareit/item/storage/CommentEntity.java b/server/src/main/java/ru/practicum/shareit/item/storage/CommentEntity.java similarity index 100% rename from src/main/java/ru/practicum/shareit/item/storage/CommentEntity.java rename to server/src/main/java/ru/practicum/shareit/item/storage/CommentEntity.java diff --git a/src/main/java/ru/practicum/shareit/item/storage/CommentRepository.java b/server/src/main/java/ru/practicum/shareit/item/storage/CommentRepository.java similarity index 100% rename from src/main/java/ru/practicum/shareit/item/storage/CommentRepository.java rename to server/src/main/java/ru/practicum/shareit/item/storage/CommentRepository.java diff --git a/src/main/java/ru/practicum/shareit/item/storage/ItemEntity.java b/server/src/main/java/ru/practicum/shareit/item/storage/ItemEntity.java similarity index 100% rename from src/main/java/ru/practicum/shareit/item/storage/ItemEntity.java rename to server/src/main/java/ru/practicum/shareit/item/storage/ItemEntity.java diff --git a/src/main/java/ru/practicum/shareit/item/storage/ItemRepository.java b/server/src/main/java/ru/practicum/shareit/item/storage/ItemRepository.java similarity index 100% rename from src/main/java/ru/practicum/shareit/item/storage/ItemRepository.java rename to server/src/main/java/ru/practicum/shareit/item/storage/ItemRepository.java diff --git a/src/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java b/server/src/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java similarity index 100% rename from src/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java rename to server/src/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java diff --git a/src/main/java/ru/practicum/shareit/item/storage/ItemWithDateOfBookings.java b/server/src/main/java/ru/practicum/shareit/item/storage/ItemWithDateOfBookings.java similarity index 100% rename from src/main/java/ru/practicum/shareit/item/storage/ItemWithDateOfBookings.java rename to server/src/main/java/ru/practicum/shareit/item/storage/ItemWithDateOfBookings.java diff --git a/src/main/java/ru/practicum/shareit/request/RequestController.java b/server/src/main/java/ru/practicum/shareit/request/RequestController.java similarity index 94% rename from src/main/java/ru/practicum/shareit/request/RequestController.java rename to server/src/main/java/ru/practicum/shareit/request/RequestController.java index 2058da5..6509229 100644 --- a/src/main/java/ru/practicum/shareit/request/RequestController.java +++ b/server/src/main/java/ru/practicum/shareit/request/RequestController.java @@ -32,6 +32,6 @@ public List getOtherUserRequests(@RequestHeader("X-Sharer-User-Id") public RequestDto postRequestDto( @Valid @RequestBody RequestDto requestDto, @RequestHeader("X-Sharer-User-Id") long userId) { - return requestService.createItem(requestDto, userId); + return requestService.createRequest(requestDto, userId); } } diff --git a/src/main/java/ru/practicum/shareit/request/RequestMapper.java b/server/src/main/java/ru/practicum/shareit/request/RequestMapper.java similarity index 100% rename from src/main/java/ru/practicum/shareit/request/RequestMapper.java rename to server/src/main/java/ru/practicum/shareit/request/RequestMapper.java diff --git a/src/main/java/ru/practicum/shareit/request/RequestService.java b/server/src/main/java/ru/practicum/shareit/request/RequestService.java similarity index 96% rename from src/main/java/ru/practicum/shareit/request/RequestService.java rename to server/src/main/java/ru/practicum/shareit/request/RequestService.java index 52255ff..7416a85 100644 --- a/src/main/java/ru/practicum/shareit/request/RequestService.java +++ b/server/src/main/java/ru/practicum/shareit/request/RequestService.java @@ -20,7 +20,7 @@ public class RequestService { private final RequestStorage requestStorage; private final UserStorage userStorage; - public RequestDto createItem(@Valid RequestDto requestDto, long userId) { + public RequestDto createRequest(@Valid RequestDto requestDto, long userId) { var userEntity = userStorage.getUser(userId) .orElseThrow(() -> new NotFoundException("Пользователь не найден")); diff --git a/src/main/java/ru/practicum/shareit/request/RequestStorage.java b/server/src/main/java/ru/practicum/shareit/request/RequestStorage.java similarity index 100% rename from src/main/java/ru/practicum/shareit/request/RequestStorage.java rename to server/src/main/java/ru/practicum/shareit/request/RequestStorage.java diff --git a/server/src/main/java/ru/practicum/shareit/request/dto/RequestDto.java b/server/src/main/java/ru/practicum/shareit/request/dto/RequestDto.java new file mode 100644 index 0000000..7b74515 --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/request/dto/RequestDto.java @@ -0,0 +1,19 @@ +package ru.practicum.shareit.request.dto; + +import jakarta.validation.constraints.NotBlank; +import lombok.Builder; +import ru.practicum.shareit.item.dto.ItemDto; + +import java.sql.Timestamp; +import java.util.List; + +@Builder(toBuilder = true) +public record RequestDto( + Long id, + String text, + @NotBlank + String description, + Timestamp created, + List items +) { +} diff --git a/src/main/java/ru/practicum/shareit/request/storage/RequestEntity.java b/server/src/main/java/ru/practicum/shareit/request/storage/RequestEntity.java similarity index 100% rename from src/main/java/ru/practicum/shareit/request/storage/RequestEntity.java rename to server/src/main/java/ru/practicum/shareit/request/storage/RequestEntity.java diff --git a/src/main/java/ru/practicum/shareit/request/storage/RequestRepository.java b/server/src/main/java/ru/practicum/shareit/request/storage/RequestRepository.java similarity index 100% rename from src/main/java/ru/practicum/shareit/request/storage/RequestRepository.java rename to server/src/main/java/ru/practicum/shareit/request/storage/RequestRepository.java diff --git a/src/main/java/ru/practicum/shareit/request/storage/RequestStorageInDb.java b/server/src/main/java/ru/practicum/shareit/request/storage/RequestStorageInDb.java similarity index 100% rename from src/main/java/ru/practicum/shareit/request/storage/RequestStorageInDb.java rename to server/src/main/java/ru/practicum/shareit/request/storage/RequestStorageInDb.java diff --git a/src/main/java/ru/practicum/shareit/tool/ErrorHandler.java b/server/src/main/java/ru/practicum/shareit/tool/ErrorHandler.java similarity index 100% rename from src/main/java/ru/practicum/shareit/tool/ErrorHandler.java rename to server/src/main/java/ru/practicum/shareit/tool/ErrorHandler.java diff --git a/src/main/java/ru/practicum/shareit/tool/ErrorResponse.java b/server/src/main/java/ru/practicum/shareit/tool/ErrorResponse.java similarity index 100% rename from src/main/java/ru/practicum/shareit/tool/ErrorResponse.java rename to server/src/main/java/ru/practicum/shareit/tool/ErrorResponse.java diff --git a/src/main/java/ru/practicum/shareit/user/UserController.java b/server/src/main/java/ru/practicum/shareit/user/UserController.java similarity index 100% rename from src/main/java/ru/practicum/shareit/user/UserController.java rename to server/src/main/java/ru/practicum/shareit/user/UserController.java diff --git a/src/main/java/ru/practicum/shareit/user/UserMapper.java b/server/src/main/java/ru/practicum/shareit/user/UserMapper.java similarity index 100% rename from src/main/java/ru/practicum/shareit/user/UserMapper.java rename to server/src/main/java/ru/practicum/shareit/user/UserMapper.java diff --git a/src/main/java/ru/practicum/shareit/user/UserService.java b/server/src/main/java/ru/practicum/shareit/user/UserService.java similarity index 100% rename from src/main/java/ru/practicum/shareit/user/UserService.java rename to server/src/main/java/ru/practicum/shareit/user/UserService.java diff --git a/src/main/java/ru/practicum/shareit/user/UserStorage.java b/server/src/main/java/ru/practicum/shareit/user/UserStorage.java similarity index 100% rename from src/main/java/ru/practicum/shareit/user/UserStorage.java rename to server/src/main/java/ru/practicum/shareit/user/UserStorage.java diff --git a/server/src/main/java/ru/practicum/shareit/user/dto/UserDto.java b/server/src/main/java/ru/practicum/shareit/user/dto/UserDto.java new file mode 100644 index 0000000..ec096cc --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/user/dto/UserDto.java @@ -0,0 +1,18 @@ +package ru.practicum.shareit.user.dto; + +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Builder; + +@Builder(toBuilder = true) +public record UserDto( + Long id, + + @NotBlank + String name, + + @NotNull + @Email + String email +) { } diff --git a/server/src/main/java/ru/practicum/shareit/user/dto/UserToUpdateDto.java b/server/src/main/java/ru/practicum/shareit/user/dto/UserToUpdateDto.java new file mode 100644 index 0000000..918e784 --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/user/dto/UserToUpdateDto.java @@ -0,0 +1,10 @@ +package ru.practicum.shareit.user.dto; + +import lombok.Builder; + +@Builder +public record UserToUpdateDto( + Long id, + String name, + String email +) { } diff --git a/src/main/java/ru/practicum/shareit/user/storage/UserEntity.java b/server/src/main/java/ru/practicum/shareit/user/storage/UserEntity.java similarity index 100% rename from src/main/java/ru/practicum/shareit/user/storage/UserEntity.java rename to server/src/main/java/ru/practicum/shareit/user/storage/UserEntity.java diff --git a/src/main/java/ru/practicum/shareit/user/storage/UserRepository.java b/server/src/main/java/ru/practicum/shareit/user/storage/UserRepository.java similarity index 100% rename from src/main/java/ru/practicum/shareit/user/storage/UserRepository.java rename to server/src/main/java/ru/practicum/shareit/user/storage/UserRepository.java diff --git a/src/main/java/ru/practicum/shareit/user/storage/UserStorageInDB.java b/server/src/main/java/ru/practicum/shareit/user/storage/UserStorageInDB.java similarity index 100% rename from src/main/java/ru/practicum/shareit/user/storage/UserStorageInDB.java rename to server/src/main/java/ru/practicum/shareit/user/storage/UserStorageInDB.java diff --git a/server/src/main/resources/application-dev.yaml b/server/src/main/resources/application-dev.yaml new file mode 100644 index 0000000..39e9429 --- /dev/null +++ b/server/src/main/resources/application-dev.yaml @@ -0,0 +1,17 @@ +spring: + main: + log-startup-info: true # выводим служебную информацию + banner-mode: off # не выводим баннер + datasource: + driverClassName: org.h2.Driver + url: jdbc:h2:mem:shareit + jpa: + #show-sql: true + show-sql: false +logging.level: + ru.practicum.shareit: TRACE + org: + zalando.logbook: TRACE +# hibernate: +# type.descriptor.sql.BasicBinder: TRACE +# orm.jdbc.bind: TRACE diff --git a/server/src/main/resources/application.properties b/server/src/main/resources/application.properties new file mode 100644 index 0000000..5ff0285 --- /dev/null +++ b/server/src/main/resources/application.properties @@ -0,0 +1 @@ +server.port=9090 \ No newline at end of file diff --git a/server/src/main/resources/application.yaml b/server/src/main/resources/application.yaml new file mode 100644 index 0000000..55085a4 --- /dev/null +++ b/server/src/main/resources/application.yaml @@ -0,0 +1,11 @@ +spring: + jpa: + hibernate.ddl-auto: none + properties: + hibernate: + jdbc.time_zone: UTC + format_sql: true + sql.init: + mode: always + schema-locations: classpath:schema.sql +logging.level.org.springframework: INFO \ No newline at end of file diff --git a/server/src/main/resources/schema.sql b/server/src/main/resources/schema.sql new file mode 100644 index 0000000..66ec3f6 --- /dev/null +++ b/server/src/main/resources/schema.sql @@ -0,0 +1,41 @@ +CREATE TABLE if NOT EXISTS Users( + user_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(100) NOT NULL, + email VARCHAR(100) NOT NULL, + CONSTRAINT uniqueEmails UNIQUE(email) +); + +CREATE TABLE IF NOT EXISTS Requests( + request_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + user_id BIGINT REFERENCES Users(user_id), + text VARCHAR(1000), + description VARCHAR(1000), + created timestamp WITHOUT TIME ZONE NOT NULL +); + +CREATE TABLE IF NOT EXISTS Items( + item_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + owner_id BIGINT REFERENCES Users(user_id), + name VARCHAR(100) NOT NULL, + description VARCHAR(1000) NOT NULL, + available boolean, + request_id BIGINT REFERENCES Requests(request_id) +); + +CREATE TABLE IF NOT EXISTS Comments( + comment_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + user_id BIGINT REFERENCES Users(user_id), + item_id BIGINT REFERENCES Items(item_id), + text VARCHAR(1000) NOT NULL, + created timestamp WITHOUT TIME ZONE NOT NULL +); + +CREATE TABLE IF NOT EXISTS Bookings( + booking_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + booker_id BIGINT REFERENCES Users(user_id), + item_id BIGINT REFERENCES Items(item_id), + status VARCHAR(100) NOT NULL, + description VARCHAR(1000), + start timestamp WITHOUT TIME ZONE NOT NULL, + finish timestamp WITHOUT TIME ZONE NOT NULL +); \ No newline at end of file diff --git a/server/src/test/java/ru/practicum/shareit/ShareItTests.java b/server/src/test/java/ru/practicum/shareit/ShareItTests.java new file mode 100644 index 0000000..4d79052 --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/ShareItTests.java @@ -0,0 +1,13 @@ +package ru.practicum.shareit; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ShareItTests { + + @Test + void contextLoads() { + } + +} diff --git a/server/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java b/server/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java new file mode 100644 index 0000000..9aa62f4 --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java @@ -0,0 +1,277 @@ +package ru.practicum.shareit.booking; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import ru.practicum.shareit.booking.BookingController; +import ru.practicum.shareit.booking.BookingService; +import ru.practicum.shareit.booking.BookingStatus; +import ru.practicum.shareit.booking.dto.BookingDto; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.hamcrest.Matchers.is; + +@SpringBootTest +public class BookingControllerTest { + @Mock + BookingService bookingService; + + @InjectMocks + BookingController bookingController; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void requestPathWithoutUserIdInHead() throws Exception { + List needIdUserFromHeadRequest = + List.of(get("/bookings/1"), + get("/bookings"), + get("/bookings/owner"), + post("/bookings"), + patch("/bookings/1?approved=true")); + + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + for (var requestBuilder: needIdUserFromHeadRequest) { + var result = mockMvc.perform(requestBuilder) + .andReturn(); + + var status = result + .getResponse() + .getStatus(); + + var path = result.getRequest().getMethod() + " '" + result.getRequest().getRequestURI() + "'"; + + Assertions.assertEquals(400, status, path + " was needed userid as RequestHeader \"X-Sharer-User-Id\""); + } + } + + @Test + public void getBookingTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + var dto = BookingDto.builder() + .id(10L) + .build(); + + Mockito.when(bookingService.getBooking(Mockito.anyLong(), Mockito.anyLong())) + .thenReturn(dto); + + mockMvc.perform(get("/bookings/1") + .header("X-Sharer-User-Id", 1L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(10L), Long.class)); + } + + @Test + void getItemParsingRequestId() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + mockMvc.perform(get("/bookings/100") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()); + + Mockito.verify(bookingService, Mockito.times(1)) + .getBooking(100, 10); + } + + @Test + void getItemsForUserIdTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + var expectedResult = List.of( + BookingDto.builder().id(1L).build(), + BookingDto.builder().id(2L).build(), + BookingDto.builder().id(3L).build()); + + Mockito.when(bookingService.getBookingForUserId(Mockito.anyLong())) + .thenReturn(expectedResult); + + mockMvc.perform(get("/bookings") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.[0].id",is(1L), Long.class)) + .andExpect(jsonPath("$.[1].id",is(2L), Long.class)) + .andExpect(jsonPath("$.[2].id",is(3L), Long.class)); + } + + @Test + void getItemsForUserIdParsingRequestTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + mockMvc.perform(get("/bookings") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()); + + Mockito.verify(bookingService, Mockito.times(1)) + .getBookingForUserId(10); + } + + @Test + void getItemsForItemOwnerIdTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + var expectedResult = List.of( + BookingDto.builder().id(1L).build(), + BookingDto.builder().id(2L).build(), + BookingDto.builder().id(3L).build()); + + Mockito.when(bookingService.getBookingsForItemOwnerId(Mockito.anyLong())) + .thenReturn(expectedResult); + + mockMvc.perform(get("/bookings/owner") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.[0].id",is(1L), Long.class)) + .andExpect(jsonPath("$.[1].id",is(2L), Long.class)) + .andExpect(jsonPath("$.[2].id",is(3L), Long.class)); + } + + @Test + void getItemsForItemOwnerIdParsingRequestTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + mockMvc.perform(get("/bookings/owner") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()); + + Mockito.verify(bookingService, Mockito.times(1)) + .getBookingsForItemOwnerId(10); + } + + @Test + void postItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + Mockito.when(bookingService.createBooking(Mockito.any(BookingDto.class), Mockito.anyLong())) + .thenReturn(BookingDto.builder().id(50L).build()); + + mockMvc.perform(post("/bookings") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(BookingDto.builder().build())) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + } + + @Test + void postItemParsingRequestTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + var dto = BookingDto.builder().build(); + + mockMvc.perform(post("/bookings") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()); + + Mockito.verify(bookingService, Mockito.times(1)) + .createBooking(dto, 10L); + } + + @Test + void postItemWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + mockMvc.perform(post("/bookings") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } + + @Test + void patchItemApprovedTrueTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + Mockito.when(bookingService.setBookingStatus(Mockito.anyLong(), Mockito.anyBoolean(), Mockito.anyLong())) + .thenReturn(BookingDto.builder().status(BookingStatus.APPROVED).build()); + + mockMvc.perform(patch("/bookings/10?approved=true") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.status",is(BookingStatus.APPROVED.name()), String.class)); + } + + @Test + void patchItemApprovedFalseTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + Mockito.when(bookingService.setBookingStatus(Mockito.anyLong(), Mockito.anyBoolean(), Mockito.anyLong())) + .thenReturn(BookingDto.builder().status(BookingStatus.REJECTED).build()); + + mockMvc.perform(patch("/bookings/10?approved=false") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.status",is(BookingStatus.REJECTED.name()), String.class)); + } + + @Test + void patchItemParsingRequestTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + mockMvc.perform(patch("/bookings/100?approved=true") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()); + + mockMvc.perform(patch("/bookings/100?approved=false") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()); + + Mockito.verify(bookingService, Mockito.times(1)) + .setBookingStatus(100, true, 10L); + + Mockito.verify(bookingService, Mockito.times(1)) + .setBookingStatus(100, false, 10L); + } + + @Test + void patchItemWithoutParamsTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + mockMvc.perform(patch("/bookings/100") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } +} diff --git a/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java b/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java new file mode 100644 index 0000000..d2d1f5f --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java @@ -0,0 +1,271 @@ +package ru.practicum.shareit.booking; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import ru.practicum.shareit.booking.BookingMapper; +import ru.practicum.shareit.booking.BookingService; +import ru.practicum.shareit.booking.BookingStatus; +import ru.practicum.shareit.booking.BookingStorage; +import ru.practicum.shareit.booking.dto.BookingDto; +import ru.practicum.shareit.booking.dto.BookingStatusRequestDto; +import ru.practicum.shareit.booking.storage.BookingEntity; +import ru.practicum.shareit.exceptions.NotFoundException; +import ru.practicum.shareit.exceptions.NotValidException; +import ru.practicum.shareit.item.ItemStorage; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.storage.ItemEntity; +import ru.practicum.shareit.user.UserStorage; +import ru.practicum.shareit.user.dto.UserDto; +import ru.practicum.shareit.user.storage.UserEntity; + +import java.sql.Timestamp; +import java.time.Instant; +import java.util.List; +import java.util.Optional; + +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; + +@SpringBootTest +public class BookingServiceTest { + @Mock + BookingStorage bookingStorage; + @Mock + ItemStorage itemStorage; + @Mock + UserStorage userStorage; + + @InjectMocks + BookingService bookingService; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void getBookingTest() throws Exception { + var expectedBookingEntity = new BookingEntity(); + expectedBookingEntity.setId(8L); + expectedBookingEntity.setItem(new ItemEntity()); + expectedBookingEntity.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); + + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.of(new UserEntity())); + Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) + .thenReturn(Optional.of(expectedBookingEntity)); + Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) + .thenReturn(true); + + + try (MockedStatic mapper = Mockito.mockStatic(BookingMapper.class)) { + mapper + .when(() -> BookingMapper.toDto(Mockito.any(BookingEntity.class), + Mockito.any(UserDto.class), + Mockito.any(ItemDto.class))) + .thenAnswer(a -> { + var entity = a.getArgument(0, BookingEntity.class); + return BookingDto.builder() + .id(entity.getId()) + .build(); + }); + + var bookingDto = bookingService.getBooking(1, 1); + + Assertions.assertEquals(8L, bookingDto.id()); + + mapper.verify( + () -> BookingMapper.toDto( + Mockito.any(BookingEntity.class), + Mockito.any(UserDto.class), + Mockito.any(ItemDto.class)), + Mockito.times(1)); + } + } + + @Test + public void getBookingWhileUserNotIsOwnerTest() throws Exception { + var expectedBookingEntity = new BookingEntity(); + expectedBookingEntity.setId(10L); + expectedBookingEntity.setItem(new ItemEntity()); + expectedBookingEntity.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); + + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.of(new UserEntity())); + Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) + .thenReturn(Optional.of(expectedBookingEntity)); + Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) + .thenReturn(false); + + + try { + bookingService.getBooking(1,1); + + Assertions.fail(); + } catch (NotValidException ex) { + Assertions.assertEquals("Данные о бронировании может получить заказчик или владелец", ex.getMessage()); + } + } + + @Test + public void getBookingWhileNotFoundUserTest() throws Exception { + var expectedBookingEntity = new BookingEntity(); + expectedBookingEntity.setId(10L); + expectedBookingEntity.setItem(new ItemEntity()); + expectedBookingEntity.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); + + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.empty()); + Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) + .thenReturn(Optional.of(expectedBookingEntity)); + Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) + .thenReturn(true); + + + try { + bookingService.getBooking(1,1); + + Assertions.fail(); + } catch (NotFoundException ex) { + Assertions.assertEquals("Пользователь не найден", ex.getMessage()); + } + } + + @Test + public void getBookingWhileNotBookingTest() throws Exception { + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.of(new UserEntity())); + Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) + .thenReturn(Optional.empty()); + Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) + .thenReturn(true); + + + try { + bookingService.getBooking(1,1); + + Assertions.fail(); + } catch (NotFoundException ex) { + Assertions.assertEquals("Бронь не найдена", ex.getMessage()); + } + } + + @Test + public void getBookingForUserIdTest() { + var expectedBookingDtoList = List.of( + BookingDto.builder().id(8L).build(), + BookingDto.builder().id(107L).build()); + + var entity1 = new BookingEntity(); + entity1.setId(8L); + entity1.setItem(new ItemEntity()); + + var entity2 = new BookingEntity(); + entity2.setId(107L); + entity2.setItem(new ItemEntity()); + + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.of(new UserEntity())); + + Mockito.when(bookingStorage.findBookingsByBookerId(Mockito.anyLong())) + .thenReturn(List.of(entity1, entity2)); + + try (MockedStatic mapper = Mockito.mockStatic(BookingMapper.class)) { + mapper + .when(() -> BookingMapper.toDto(Mockito.any(BookingEntity.class), + Mockito.any(UserDto.class), + Mockito.any(ItemDto.class))) + .thenAnswer(a -> { + var entity = a.getArgument(0, BookingEntity.class); + return BookingDto.builder() + .id(entity.getId()) + .build(); + }); + + var bookingDtoList = bookingService.getBookingForUserId(1); + + Assertions.assertEquals(2, bookingDtoList.size()); + Assertions.assertEquals(8L, bookingDtoList.getFirst().id(), "Id dto[0] is expected 8L"); + Assertions.assertEquals(107L, bookingDtoList.get(1).id(), "Id dto[0] is expected 107L"); + + mapper.verify( + () -> BookingMapper.toDto( + Mockito.any(BookingEntity.class), + Mockito.any(UserDto.class), + Mockito.any(ItemDto.class)), + Mockito.times(2)); + } + } + + @Test + public void getBookingForUserIdWhileNotFoundUserTest() throws Exception { + var expectedBookingEntity = new BookingEntity(); + expectedBookingEntity.setId(10L); + expectedBookingEntity.setItem(new ItemEntity()); + expectedBookingEntity.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); + + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.empty()); + Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) + .thenReturn(Optional.of(expectedBookingEntity)); + + + try { + bookingService.getBookingForUserId(1); + + Assertions.fail(); + } catch (NotFoundException ex) { + Assertions.assertEquals("Пользователь не найден", ex.getMessage()); + } + } + + @Test + public void getBookingForUserIdWhileChangeStatusAndOwnerIdTest() throws Exception { + var expectedBookingEntity = new BookingEntity(); + expectedBookingEntity.setId(10L); + expectedBookingEntity.setItem(new ItemEntity()); + expectedBookingEntity.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); + + Mockito.when(userStorage.existsById(Mockito.anyLong())) + .thenReturn(true); + Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) + .thenReturn(Optional.of(expectedBookingEntity)); + + var statuses = List.of( + BookingStatusRequestDto.ALL, + BookingStatusRequestDto.CURRENT, + BookingStatusRequestDto.PAST, + BookingStatusRequestDto.FUTURE, + BookingStatusRequestDto.WAITING, + BookingStatusRequestDto.REJECTED, + BookingStatusRequestDto.APPROVED); + + var owners = List.of(1, 7, 19); + + for (var ownerId: owners) { + for (var requestStatus: statuses) { + bookingService.getBookingsForItemOwnerId(requestStatus, ownerId); + } + + Mockito.verify(bookingStorage, Mockito.times(4)) + .findBookingsByOwnerId(ownerId); + + Mockito.verify(bookingStorage, Mockito.times(1)) + .findBookingsByOwnerId(ownerId, BookingStatus.WAITING); + + Mockito.verify(bookingStorage, Mockito.times(1)) + .findBookingsByOwnerId(ownerId, BookingStatus.REJECTED); + + Mockito.verify(bookingStorage, Mockito.times(1)) + .findBookingsByOwnerId(ownerId, BookingStatus.APPROVED); + } + } +} diff --git a/server/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java b/server/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java new file mode 100644 index 0000000..b35edd9 --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java @@ -0,0 +1,337 @@ +package ru.practicum.shareit.item; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import ru.practicum.shareit.booking.BookingStatus; +import ru.practicum.shareit.booking.dto.BookingDto; +import ru.practicum.shareit.item.ItemController; +import ru.practicum.shareit.item.ItemService; +import ru.practicum.shareit.item.dto.CommentDto; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.dto.ItemToUpdateDto; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +public class ItemControllerTest { + @Mock + ItemService itemService; + + @InjectMocks + ItemController itemController; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void requestPathWithoutUserIdInHead() throws Exception { + List needIdUserFromHeadRequest = + List.of(post("/items"), + post("/items/1/comment"), + put("/items"), + patch("/items/1"), + delete("/items/1")); + + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + for (var requestBuilder: needIdUserFromHeadRequest) { + var result = mockMvc.perform(requestBuilder) + .andReturn(); + + var status = result + .getResponse() + .getStatus(); + + var path = result.getRequest().getMethod() + " '" + result.getRequest().getRequestURI() + "'"; + + Assertions.assertEquals(400, status, path + " was needed userid as RequestHeader \"X-Sharer-User-Id\""); + } + } + + @Test + public void getItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var dto = ItemDto.builder() + .id(10L) + .build(); + + Mockito.when(itemService.getItem(Mockito.anyLong())) + .thenReturn(dto); + + mockMvc.perform(get("/items/1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(10L), Long.class)); + } + + @Test + void getItemParsingRequestId() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(get("/items/100")) + .andExpect(status().isOk()); + + Mockito.verify(itemService, Mockito.times(1)) + .getItem(100); + } + + @Test + void getItemsForUserIdTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var expectedResult = List.of( + ItemDto.builder().id(11L).build(), + ItemDto.builder().id(42L).build(), + ItemDto.builder().id(37L).build()); + + Mockito.when(itemService.getItems(Mockito.anyLong())) + .thenReturn(expectedResult); + + mockMvc.perform(get("/items") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.[0].id",is(11L), Long.class)) + .andExpect(jsonPath("$.[1].id",is(42L), Long.class)) + .andExpect(jsonPath("$.[2].id",is(37L), Long.class)); + } + + @Test + void getItemsForUserIdParsingRequestTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(get("/items") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()); + + Mockito.verify(itemService, Mockito.times(1)) + .getItems(10); + } + + @Test + void findItemsByTextTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var expectedResult = List.of( + ItemDto.builder().id(1L).build(), + ItemDto.builder().id(42L).build(), + ItemDto.builder().id(37L).build()); + + Mockito.when(itemService.findFreeItemsByText(Mockito.anyString(), Mockito.anyBoolean())) + .thenReturn(expectedResult); + + mockMvc.perform(get("/items/search?text=abc")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.[0].id",is(1L), Long.class)) + .andExpect(jsonPath("$.[1].id",is(42L), Long.class)) + .andExpect(jsonPath("$.[2].id",is(37L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .findFreeItemsByText("abc", true); + + Mockito.verify(itemService, Mockito.never()) + .findFreeItemsByText("abc", false); + } + + @Test + void findItemsByTextFailParsingRequestTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(get("/items/search")) + .andExpect(status().is(400)); + } + + @Test + void postItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + Mockito.when(itemService.createItem(Mockito.any(ItemDto.class), Mockito.anyLong())) + .thenReturn(ItemDto.builder().id(50L).build()); + + var dto = ItemDto.builder() + .id(13L) + .name("la") + .available(true) + .description("ma") + .build(); + + mockMvc.perform(post("/items") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .createItem(dto, 10L); + } + + @Test + void postItemWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(post("/items") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } + + @Test + void postCommentTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var dto = CommentDto.builder() + .id(47L) + .text("la") + .build(); + + Mockito.when(itemService.addComment(Mockito.any(CommentDto.class), Mockito.anyLong(), Mockito.anyLong())) + .thenReturn(CommentDto.builder().id(50L).build()); + + mockMvc.perform(post("/items/13/comment") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .addComment(dto, 13L, 10L); + } + + @Test + void postCommentWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(post("/items/13/comment") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } + + @Test + void putItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + Mockito.when(itemService.updateItem(Mockito.any(ItemDto.class), Mockito.anyLong())) + .thenReturn(ItemDto.builder().id(50L).build()); + + var dto = ItemDto.builder() + .id(13L) + .name("la") + .description("ma") + .available(true) + .build(); + + mockMvc.perform(put("/items") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .updateItem(dto, 10L); + } + + @Test + void putItemWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(put("/items") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } + + @Test + void patchItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var dto = ItemToUpdateDto.builder() + .build(); + + Mockito.when(itemService.updateItem(Mockito.anyLong(), Mockito.any(ItemToUpdateDto.class), Mockito.anyLong())) + .thenReturn(ItemDto.builder().id(50L).build()); + + mockMvc.perform(patch("/items/17") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .updateItem(17, dto, 10L); + } + + @Test + void patchItemWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(put("/items") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } + + @Test + void deleteItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + Mockito.when(itemService.deleteItem(17L, 10L)) + .thenReturn(ItemDto.builder().id(50L).build()); + + mockMvc.perform(delete("/items/17") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .deleteItem(17L, 10L); + } +} diff --git a/server/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java b/server/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java new file mode 100644 index 0000000..7b76193 --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java @@ -0,0 +1,170 @@ +package ru.practicum.shareit.request; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import ru.practicum.shareit.item.dto.CommentDto; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.dto.ItemToUpdateDto; +import ru.practicum.shareit.request.RequestController; +import ru.practicum.shareit.request.RequestService; +import ru.practicum.shareit.request.dto.RequestDto; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +public class RequestControllerTest { + @Mock + RequestService requestService; + + @InjectMocks + RequestController requestController; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void requestPathWithoutUserIdInHead() throws Exception { + List needIdUserFromHeadRequest = + List.of(get("/requests"), + get("/requests/all"), + post("/requests")); + + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + for (var requestBuilder: needIdUserFromHeadRequest) { + var result = mockMvc.perform(requestBuilder) + .andReturn(); + + var status = result + .getResponse() + .getStatus(); + + var path = result.getRequest().getMethod() + " '" + result.getRequest().getRequestURI() + "'"; + + Assertions.assertEquals(400, status, path + " was needed userid as RequestHeader \"X-Sharer-User-Id\""); + } + } + + @Test + public void getSelfRequestsTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + List expectedRequests = List.of( + RequestDto.builder().id(13L).build(), + RequestDto.builder().id(24L).build(), + RequestDto.builder().id(37L).build() + ); + + Mockito.when(requestService.getRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) + .thenReturn(expectedRequests); + + mockMvc.perform(get("/requests") + .header("X-Sharer-User-Id", 7L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id", is(13L), Long.class)) + .andExpect(jsonPath("$[1].id", is(24L), Long.class)) + .andExpect(jsonPath("$[2].id", is(37L), Long.class)); + + Mockito.verify(requestService, Mockito.times(1)) + .getRequestsByUserId(7L, true); + } + + @Test + void getRequestByIdTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + var expectedResult = RequestDto.builder().id(13L).build(); + + Mockito.when(requestService.getRequestById(Mockito.anyLong())) + .thenReturn(expectedResult); + + mockMvc.perform(get("/requests/23")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(13L), Long.class)); + + Mockito.verify(requestService, Mockito.times(1)) + .getRequestById(23L); + } + + @Test + void getOtherUserRequestsTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + List expectedRequests = List.of( + RequestDto.builder().id(13L).build(), + RequestDto.builder().id(24L).build(), + RequestDto.builder().id(37L).build() + ); + + Mockito.when(requestService.getRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) + .thenReturn(expectedRequests); + + mockMvc.perform(get("/requests/all") + .header("X-Sharer-User-Id", 7L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id", is(13L), Long.class)) + .andExpect(jsonPath("$[1].id", is(24L), Long.class)) + .andExpect(jsonPath("$[2].id", is(37L), Long.class)); + + Mockito.verify(requestService, Mockito.times(1)) + .getRequestsByUserId(7L, false); + } + + @Test + void postRequestDtoTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + Mockito.when(requestService.createRequest(Mockito.any(RequestDto.class), Mockito.anyLong())) + .thenReturn(RequestDto.builder().id(50L).build()); + + var dto = RequestDto.builder() + .id(13L) + .description("la") + .build(); + + mockMvc.perform(post("/requests") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(requestService, Mockito.times(1)) + .createRequest(dto, 10L); + } + + @Test + void postRequestWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + mockMvc.perform(post("/requests") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } +} diff --git a/server/src/test/java/ru/practicum/shareit/user/UserControllerTest.java b/server/src/test/java/ru/practicum/shareit/user/UserControllerTest.java new file mode 100644 index 0000000..fd908bb --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/user/UserControllerTest.java @@ -0,0 +1,179 @@ +package ru.practicum.shareit.user; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import ru.practicum.shareit.request.dto.RequestDto; +import ru.practicum.shareit.user.UserController; +import ru.practicum.shareit.user.UserService; +import ru.practicum.shareit.user.dto.UserDto; +import ru.practicum.shareit.user.dto.UserToUpdateDto; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +public class UserControllerTest { + @Mock + UserService userService; + + @InjectMocks + UserController userController; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void getUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + var dto = UserDto.builder() + .id(47L) + .name("la") + .email("email@mail.ru") + .build(); + + Mockito.when(userService.getUser(Mockito.anyLong())) + .thenReturn(dto); + + mockMvc.perform(get("/users/17")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(47L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .getUser(17L); + } + + @Test + void postUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + Mockito.when(userService.updateUser(Mockito.any(UserDto.class))) + .thenReturn(UserDto.builder().id(50L).build()); + + var dto = UserDto.builder() + .name("la") + .email("email@mail.ru") + .build(); + + mockMvc.perform(post("/users") + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .updateUser(dto); + } + + @Test + void postUserWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + mockMvc.perform(post("/users")) + .andExpect(status().is(400)); + } + + @Test + void putUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + Mockito.when(userService.updateUser(Mockito.any(UserDto.class))) + .thenReturn(UserDto.builder().id(52L).build()); + + var dto = UserDto.builder() + .id(10L) + .name("la") + .email("email@mail.ru") + .build(); + + mockMvc.perform(put("/users") + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(52L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .updateUser(dto); + } + + @Test + void putUserWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + mockMvc.perform(put("/users")) + .andExpect(status().is(400)); + } + + @Test + void patchUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + Mockito.when(userService.updateUser(Mockito.anyLong(), Mockito.any(UserToUpdateDto.class))) + .thenReturn(UserDto.builder().id(542L).build()); + + var dto = UserToUpdateDto.builder().name("la").build(); + + mockMvc.perform(patch("/users/13") + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(542L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .updateUser(13, dto); + } + + @Test + void patchUserWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + mockMvc.perform(patch("/users/13")) + .andExpect(status().is(400)); + } + + @Test + void deleteUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + Mockito.when(userService.deleteUser(Mockito.anyLong())) + .thenReturn(UserDto.builder().id(54L).build()); + + mockMvc.perform(delete("/users/13")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(54L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .deleteUser(13); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..5ff0285 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1 @@ +server.port=9090 \ No newline at end of file diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 38cb0fe..55085a4 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -1,9 +1,4 @@ spring: -# datasource: -# driverClassName: org.postgresql.Driver -# url: jdbc:postgresql://localhost:5432/shareit -# username: dbuser -# password: 12345 jpa: hibernate.ddl-auto: none properties: diff --git a/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java b/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java new file mode 100644 index 0000000..e74eac5 --- /dev/null +++ b/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java @@ -0,0 +1,274 @@ +package ru.practicum.shareit.booking; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import ru.practicum.shareit.booking.dto.BookingDto; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.hamcrest.Matchers.is; + +@SpringBootTest +public class BookingControllerTest { + @Mock + BookingService bookingService; + + @InjectMocks + BookingController bookingController; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void requestPathWithoutUserIdInHead() throws Exception { + List needIdUserFromHeadRequest = + List.of(get("/bookings/1"), + get("/bookings"), + get("/bookings/owner"), + post("/bookings"), + patch("/bookings/1?approved=true")); + + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + for (var requestBuilder: needIdUserFromHeadRequest) { + var result = mockMvc.perform(requestBuilder) + .andReturn(); + + var status = result + .getResponse() + .getStatus(); + + var path = result.getRequest().getMethod() + " '" + result.getRequest().getRequestURI() + "'"; + + Assertions.assertEquals(400, status, path + " was needed userid as RequestHeader \"X-Sharer-User-Id\""); + } + } + + @Test + public void getBookingTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + var dto = BookingDto.builder() + .id(10L) + .build(); + + Mockito.when(bookingService.getBooking(Mockito.anyLong(), Mockito.anyLong())) + .thenReturn(dto); + + mockMvc.perform(get("/bookings/1") + .header("X-Sharer-User-Id", 1L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(10L), Long.class)); + } + + @Test + void getItemParsingRequestId() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + mockMvc.perform(get("/bookings/100") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()); + + Mockito.verify(bookingService, Mockito.times(1)) + .getBooking(100, 10); + } + + @Test + void getItemsForUserIdTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + var expectedResult = List.of( + BookingDto.builder().id(1L).build(), + BookingDto.builder().id(2L).build(), + BookingDto.builder().id(3L).build()); + + Mockito.when(bookingService.getBookingForUserId(Mockito.anyLong())) + .thenReturn(expectedResult); + + mockMvc.perform(get("/bookings") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.[0].id",is(1L), Long.class)) + .andExpect(jsonPath("$.[1].id",is(2L), Long.class)) + .andExpect(jsonPath("$.[2].id",is(3L), Long.class)); + } + + @Test + void getItemsForUserIdParsingRequestTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + mockMvc.perform(get("/bookings") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()); + + Mockito.verify(bookingService, Mockito.times(1)) + .getBookingForUserId(10); + } + + @Test + void getItemsForItemOwnerIdTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + var expectedResult = List.of( + BookingDto.builder().id(1L).build(), + BookingDto.builder().id(2L).build(), + BookingDto.builder().id(3L).build()); + + Mockito.when(bookingService.getBookingsForItemOwnerId(Mockito.anyLong())) + .thenReturn(expectedResult); + + mockMvc.perform(get("/bookings/owner") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.[0].id",is(1L), Long.class)) + .andExpect(jsonPath("$.[1].id",is(2L), Long.class)) + .andExpect(jsonPath("$.[2].id",is(3L), Long.class)); + } + + @Test + void getItemsForItemOwnerIdParsingRequestTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + mockMvc.perform(get("/bookings/owner") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()); + + Mockito.verify(bookingService, Mockito.times(1)) + .getBookingsForItemOwnerId(10); + } + + @Test + void postItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + Mockito.when(bookingService.createBooking(Mockito.any(BookingDto.class), Mockito.anyLong())) + .thenReturn(BookingDto.builder().id(50L).build()); + + mockMvc.perform(post("/bookings") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(BookingDto.builder().build())) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + } + + @Test + void postItemParsingRequestTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + var dto = BookingDto.builder().build(); + + mockMvc.perform(post("/bookings") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()); + + Mockito.verify(bookingService, Mockito.times(1)) + .createBooking(dto, 10L); + } + + @Test + void postItemWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + mockMvc.perform(post("/bookings") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } + + @Test + void patchItemApprovedTrueTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + Mockito.when(bookingService.setBookingStatus(Mockito.anyLong(), Mockito.anyBoolean(), Mockito.anyLong())) + .thenReturn(BookingDto.builder().status(BookingStatus.APPROVED).build()); + + mockMvc.perform(patch("/bookings/10?approved=true") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.status",is(BookingStatus.APPROVED.name()), String.class)); + } + + @Test + void patchItemApprovedFalseTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + Mockito.when(bookingService.setBookingStatus(Mockito.anyLong(), Mockito.anyBoolean(), Mockito.anyLong())) + .thenReturn(BookingDto.builder().status(BookingStatus.REJECTED).build()); + + mockMvc.perform(patch("/bookings/10?approved=false") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.status",is(BookingStatus.REJECTED.name()), String.class)); + } + + @Test + void patchItemParsingRequestTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + mockMvc.perform(patch("/bookings/100?approved=true") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()); + + mockMvc.perform(patch("/bookings/100?approved=false") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()); + + Mockito.verify(bookingService, Mockito.times(1)) + .setBookingStatus(100, true, 10L); + + Mockito.verify(bookingService, Mockito.times(1)) + .setBookingStatus(100, false, 10L); + } + + @Test + void patchItemWithoutParamsTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(bookingController) + .build(); + + mockMvc.perform(patch("/bookings/100") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } +} diff --git a/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java b/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java new file mode 100644 index 0000000..179622e --- /dev/null +++ b/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java @@ -0,0 +1,267 @@ +package ru.practicum.shareit.booking; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import ru.practicum.shareit.booking.dto.BookingDto; +import ru.practicum.shareit.booking.dto.BookingStatusRequestDto; +import ru.practicum.shareit.booking.storage.BookingEntity; +import ru.practicum.shareit.exceptions.NotFoundException; +import ru.practicum.shareit.exceptions.NotValidException; +import ru.practicum.shareit.item.ItemStorage; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.storage.ItemEntity; +import ru.practicum.shareit.user.UserStorage; +import ru.practicum.shareit.user.dto.UserDto; +import ru.practicum.shareit.user.storage.UserEntity; + +import java.sql.Timestamp; +import java.time.Instant; +import java.util.List; +import java.util.Optional; + +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; + +@SpringBootTest +public class BookingServiceTest { + @Mock + BookingStorage bookingStorage; + @Mock + ItemStorage itemStorage; + @Mock + UserStorage userStorage; + + @InjectMocks + BookingService bookingService; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void getBookingTest() throws Exception { + var expectedBookingEntity = new BookingEntity(); + expectedBookingEntity.setId(8L); + expectedBookingEntity.setItem(new ItemEntity()); + expectedBookingEntity.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); + + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.of(new UserEntity())); + Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) + .thenReturn(Optional.of(expectedBookingEntity)); + Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) + .thenReturn(true); + + + try (MockedStatic mapper = Mockito.mockStatic(BookingMapper.class)) { + mapper + .when(() -> BookingMapper.toDto(Mockito.any(BookingEntity.class), + Mockito.any(UserDto.class), + Mockito.any(ItemDto.class))) + .thenAnswer(a -> { + var entity = a.getArgument(0, BookingEntity.class); + return BookingDto.builder() + .id(entity.getId()) + .build(); + }); + + var bookingDto = bookingService.getBooking(1, 1); + + Assertions.assertEquals(8L, bookingDto.id()); + + mapper.verify( + () -> BookingMapper.toDto( + Mockito.any(BookingEntity.class), + Mockito.any(UserDto.class), + Mockito.any(ItemDto.class)), + Mockito.times(1)); + } + } + + @Test + public void getBookingWhileUserNotIsOwnerTest() throws Exception { + var expectedBookingEntity = new BookingEntity(); + expectedBookingEntity.setId(10L); + expectedBookingEntity.setItem(new ItemEntity()); + expectedBookingEntity.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); + + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.of(new UserEntity())); + Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) + .thenReturn(Optional.of(expectedBookingEntity)); + Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) + .thenReturn(false); + + + try { + bookingService.getBooking(1,1); + + Assertions.fail(); + } catch (NotValidException ex) { + Assertions.assertEquals("Данные о бронировании может получить заказчик или владелец", ex.getMessage()); + } + } + + @Test + public void getBookingWhileNotFoundUserTest() throws Exception { + var expectedBookingEntity = new BookingEntity(); + expectedBookingEntity.setId(10L); + expectedBookingEntity.setItem(new ItemEntity()); + expectedBookingEntity.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); + + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.empty()); + Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) + .thenReturn(Optional.of(expectedBookingEntity)); + Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) + .thenReturn(true); + + + try { + bookingService.getBooking(1,1); + + Assertions.fail(); + } catch (NotFoundException ex) { + Assertions.assertEquals("Пользователь не найден", ex.getMessage()); + } + } + + @Test + public void getBookingWhileNotBookingTest() throws Exception { + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.of(new UserEntity())); + Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) + .thenReturn(Optional.empty()); + Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) + .thenReturn(true); + + + try { + bookingService.getBooking(1,1); + + Assertions.fail(); + } catch (NotFoundException ex) { + Assertions.assertEquals("Бронь не найдена", ex.getMessage()); + } + } + + @Test + public void getBookingForUserIdTest() { + var expectedBookingDtoList = List.of( + BookingDto.builder().id(8L).build(), + BookingDto.builder().id(107L).build()); + + var entity1 = new BookingEntity(); + entity1.setId(8L); + entity1.setItem(new ItemEntity()); + + var entity2 = new BookingEntity(); + entity2.setId(107L); + entity2.setItem(new ItemEntity()); + + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.of(new UserEntity())); + + Mockito.when(bookingStorage.findBookingsByBookerId(Mockito.anyLong())) + .thenReturn(List.of(entity1, entity2)); + + try (MockedStatic mapper = Mockito.mockStatic(BookingMapper.class)) { + mapper + .when(() -> BookingMapper.toDto(Mockito.any(BookingEntity.class), + Mockito.any(UserDto.class), + Mockito.any(ItemDto.class))) + .thenAnswer(a -> { + var entity = a.getArgument(0, BookingEntity.class); + return BookingDto.builder() + .id(entity.getId()) + .build(); + }); + + var bookingDtoList = bookingService.getBookingForUserId(1); + + Assertions.assertEquals(2, bookingDtoList.size()); + Assertions.assertEquals(8L, bookingDtoList.getFirst().id(), "Id dto[0] is expected 8L"); + Assertions.assertEquals(107L, bookingDtoList.get(1).id(), "Id dto[0] is expected 107L"); + + mapper.verify( + () -> BookingMapper.toDto( + Mockito.any(BookingEntity.class), + Mockito.any(UserDto.class), + Mockito.any(ItemDto.class)), + Mockito.times(2)); + } + } + + @Test + public void getBookingForUserIdWhileNotFoundUserTest() throws Exception { + var expectedBookingEntity = new BookingEntity(); + expectedBookingEntity.setId(10L); + expectedBookingEntity.setItem(new ItemEntity()); + expectedBookingEntity.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); + + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.empty()); + Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) + .thenReturn(Optional.of(expectedBookingEntity)); + + + try { + bookingService.getBookingForUserId(1); + + Assertions.fail(); + } catch (NotFoundException ex) { + Assertions.assertEquals("Пользователь не найден", ex.getMessage()); + } + } + + @Test + public void getBookingForUserIdWhileChangeStatusAndOwnerIdTest() throws Exception { + var expectedBookingEntity = new BookingEntity(); + expectedBookingEntity.setId(10L); + expectedBookingEntity.setItem(new ItemEntity()); + expectedBookingEntity.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); + + Mockito.when(userStorage.existsById(Mockito.anyLong())) + .thenReturn(true); + Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) + .thenReturn(Optional.of(expectedBookingEntity)); + + var statuses = List.of( + BookingStatusRequestDto.ALL, + BookingStatusRequestDto.CURRENT, + BookingStatusRequestDto.PAST, + BookingStatusRequestDto.FUTURE, + BookingStatusRequestDto.WAITING, + BookingStatusRequestDto.REJECTED, + BookingStatusRequestDto.APPROVED); + + var owners = List.of(1, 7, 19); + + for (var ownerId: owners) { + for (var requestStatus: statuses) { + bookingService.getBookingsForItemOwnerId(requestStatus, ownerId); + } + + Mockito.verify(bookingStorage, Mockito.times(4)) + .findBookingsByOwnerId(ownerId); + + Mockito.verify(bookingStorage, Mockito.times(1)) + .findBookingsByOwnerId(ownerId, BookingStatus.WAITING); + + Mockito.verify(bookingStorage, Mockito.times(1)) + .findBookingsByOwnerId(ownerId, BookingStatus.REJECTED); + + Mockito.verify(bookingStorage, Mockito.times(1)) + .findBookingsByOwnerId(ownerId, BookingStatus.APPROVED); + } + } +} diff --git a/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java b/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java new file mode 100644 index 0000000..163c00d --- /dev/null +++ b/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java @@ -0,0 +1,335 @@ +package ru.practicum.shareit.item; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import ru.practicum.shareit.booking.BookingStatus; +import ru.practicum.shareit.booking.dto.BookingDto; +import ru.practicum.shareit.item.dto.CommentDto; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.dto.ItemToUpdateDto; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +public class ItemControllerTest { + @Mock + ItemService itemService; + + @InjectMocks + ItemController itemController; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void requestPathWithoutUserIdInHead() throws Exception { + List needIdUserFromHeadRequest = + List.of(post("/items"), + post("/items/1/comment"), + put("/items"), + patch("/items/1"), + delete("/items/1")); + + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + for (var requestBuilder: needIdUserFromHeadRequest) { + var result = mockMvc.perform(requestBuilder) + .andReturn(); + + var status = result + .getResponse() + .getStatus(); + + var path = result.getRequest().getMethod() + " '" + result.getRequest().getRequestURI() + "'"; + + Assertions.assertEquals(400, status, path + " was needed userid as RequestHeader \"X-Sharer-User-Id\""); + } + } + + @Test + public void getItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var dto = ItemDto.builder() + .id(10L) + .build(); + + Mockito.when(itemService.getItem(Mockito.anyLong())) + .thenReturn(dto); + + mockMvc.perform(get("/items/1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(10L), Long.class)); + } + + @Test + void getItemParsingRequestId() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(get("/items/100")) + .andExpect(status().isOk()); + + Mockito.verify(itemService, Mockito.times(1)) + .getItem(100); + } + + @Test + void getItemsForUserIdTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var expectedResult = List.of( + ItemDto.builder().id(11L).build(), + ItemDto.builder().id(42L).build(), + ItemDto.builder().id(37L).build()); + + Mockito.when(itemService.getItems(Mockito.anyLong())) + .thenReturn(expectedResult); + + mockMvc.perform(get("/items") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.[0].id",is(11L), Long.class)) + .andExpect(jsonPath("$.[1].id",is(42L), Long.class)) + .andExpect(jsonPath("$.[2].id",is(37L), Long.class)); + } + + @Test + void getItemsForUserIdParsingRequestTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(get("/items") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()); + + Mockito.verify(itemService, Mockito.times(1)) + .getItems(10); + } + + @Test + void findItemsByTextTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var expectedResult = List.of( + ItemDto.builder().id(1L).build(), + ItemDto.builder().id(42L).build(), + ItemDto.builder().id(37L).build()); + + Mockito.when(itemService.findFreeItemsByText(Mockito.anyString(), Mockito.anyBoolean())) + .thenReturn(expectedResult); + + mockMvc.perform(get("/items/search?text=abc")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.[0].id",is(1L), Long.class)) + .andExpect(jsonPath("$.[1].id",is(42L), Long.class)) + .andExpect(jsonPath("$.[2].id",is(37L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .findFreeItemsByText("abc", true); + + Mockito.verify(itemService, Mockito.never()) + .findFreeItemsByText("abc", false); + } + + @Test + void findItemsByTextFailParsingRequestTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(get("/items/search")) + .andExpect(status().is(400)); + } + + @Test + void postItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + Mockito.when(itemService.createItem(Mockito.any(ItemDto.class), Mockito.anyLong())) + .thenReturn(ItemDto.builder().id(50L).build()); + + var dto = ItemDto.builder() + .id(13L) + .name("la") + .available(true) + .description("ma") + .build(); + + mockMvc.perform(post("/items") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .createItem(dto, 10L); + } + + @Test + void postItemWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(post("/items") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } + + @Test + void postCommentTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var dto = CommentDto.builder() + .id(47L) + .text("la") + .build(); + + Mockito.when(itemService.addComment(Mockito.any(CommentDto.class), Mockito.anyLong(), Mockito.anyLong())) + .thenReturn(CommentDto.builder().id(50L).build()); + + mockMvc.perform(post("/items/13/comment") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .addComment(dto, 13L, 10L); + } + + @Test + void postCommentWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(post("/items/13/comment") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } + + @Test + void putItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + Mockito.when(itemService.updateItem(Mockito.any(ItemDto.class), Mockito.anyLong())) + .thenReturn(ItemDto.builder().id(50L).build()); + + var dto = ItemDto.builder() + .id(13L) + .name("la") + .description("ma") + .available(true) + .build(); + + mockMvc.perform(put("/items") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .updateItem(dto, 10L); + } + + @Test + void putItemWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(put("/items") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } + + @Test + void patchItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + var dto = ItemToUpdateDto.builder() + .build(); + + Mockito.when(itemService.updateItem(Mockito.anyLong(), Mockito.any(ItemToUpdateDto.class), Mockito.anyLong())) + .thenReturn(ItemDto.builder().id(50L).build()); + + mockMvc.perform(patch("/items/17") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .updateItem(17, dto, 10L); + } + + @Test + void patchItemWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + mockMvc.perform(put("/items") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } + + @Test + void deleteItemTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(itemController) + .build(); + + Mockito.when(itemService.deleteItem(17L, 10L)) + .thenReturn(ItemDto.builder().id(50L).build()); + + mockMvc.perform(delete("/items/17") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(itemService, Mockito.times(1)) + .deleteItem(17L, 10L); + } +} diff --git a/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java b/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java new file mode 100644 index 0000000..8e4a4c5 --- /dev/null +++ b/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java @@ -0,0 +1,168 @@ +package ru.practicum.shareit.request; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import ru.practicum.shareit.item.dto.CommentDto; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.dto.ItemToUpdateDto; +import ru.practicum.shareit.request.dto.RequestDto; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +public class RequestControllerTest { + @Mock + RequestService requestService; + + @InjectMocks + RequestController requestController; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void requestPathWithoutUserIdInHead() throws Exception { + List needIdUserFromHeadRequest = + List.of(get("/requests"), + get("/requests/all"), + post("/requests")); + + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + for (var requestBuilder: needIdUserFromHeadRequest) { + var result = mockMvc.perform(requestBuilder) + .andReturn(); + + var status = result + .getResponse() + .getStatus(); + + var path = result.getRequest().getMethod() + " '" + result.getRequest().getRequestURI() + "'"; + + Assertions.assertEquals(400, status, path + " was needed userid as RequestHeader \"X-Sharer-User-Id\""); + } + } + + @Test + public void getSelfRequestsTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + List expectedRequests = List.of( + RequestDto.builder().id(13L).build(), + RequestDto.builder().id(24L).build(), + RequestDto.builder().id(37L).build() + ); + + Mockito.when(requestService.getRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) + .thenReturn(expectedRequests); + + mockMvc.perform(get("/requests") + .header("X-Sharer-User-Id", 7L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id", is(13L), Long.class)) + .andExpect(jsonPath("$[1].id", is(24L), Long.class)) + .andExpect(jsonPath("$[2].id", is(37L), Long.class)); + + Mockito.verify(requestService, Mockito.times(1)) + .getRequestsByUserId(7L, true); + } + + @Test + void getRequestByIdTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + var expectedResult = RequestDto.builder().id(13L).build(); + + Mockito.when(requestService.getRequestById(Mockito.anyLong())) + .thenReturn(expectedResult); + + mockMvc.perform(get("/requests/23")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(13L), Long.class)); + + Mockito.verify(requestService, Mockito.times(1)) + .getRequestById(23L); + } + + @Test + void getOtherUserRequestsTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + List expectedRequests = List.of( + RequestDto.builder().id(13L).build(), + RequestDto.builder().id(24L).build(), + RequestDto.builder().id(37L).build() + ); + + Mockito.when(requestService.getRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) + .thenReturn(expectedRequests); + + mockMvc.perform(get("/requests/all") + .header("X-Sharer-User-Id", 7L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id", is(13L), Long.class)) + .andExpect(jsonPath("$[1].id", is(24L), Long.class)) + .andExpect(jsonPath("$[2].id", is(37L), Long.class)); + + Mockito.verify(requestService, Mockito.times(1)) + .getRequestsByUserId(7L, false); + } + + @Test + void postRequestDtoTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + Mockito.when(requestService.createRequest(Mockito.any(RequestDto.class), Mockito.anyLong())) + .thenReturn(RequestDto.builder().id(50L).build()); + + var dto = RequestDto.builder() + .id(13L) + .description("la") + .build(); + + mockMvc.perform(post("/requests") + .header("X-Sharer-User-Id", 10L) + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(requestService, Mockito.times(1)) + .createRequest(dto, 10L); + } + + @Test + void postRequestWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(requestController) + .build(); + + mockMvc.perform(post("/requests") + .header("X-Sharer-User-Id", 10L)) + .andExpect(status().is(400)); + } +} diff --git a/src/test/java/ru/practicum/shareit/user/UserControllerTest.java b/src/test/java/ru/practicum/shareit/user/UserControllerTest.java new file mode 100644 index 0000000..67d01dc --- /dev/null +++ b/src/test/java/ru/practicum/shareit/user/UserControllerTest.java @@ -0,0 +1,177 @@ +package ru.practicum.shareit.user; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import ru.practicum.shareit.request.dto.RequestDto; +import ru.practicum.shareit.user.dto.UserDto; +import ru.practicum.shareit.user.dto.UserToUpdateDto; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +public class UserControllerTest { + @Mock + UserService userService; + + @InjectMocks + UserController userController; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void getUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + var dto = UserDto.builder() + .id(47L) + .name("la") + .email("email@mail.ru") + .build(); + + Mockito.when(userService.getUser(Mockito.anyLong())) + .thenReturn(dto); + + mockMvc.perform(get("/users/17")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(47L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .getUser(17L); + } + + @Test + void postUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + Mockito.when(userService.updateUser(Mockito.any(UserDto.class))) + .thenReturn(UserDto.builder().id(50L).build()); + + var dto = UserDto.builder() + .name("la") + .email("email@mail.ru") + .build(); + + mockMvc.perform(post("/users") + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(50L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .updateUser(dto); + } + + @Test + void postUserWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + mockMvc.perform(post("/users")) + .andExpect(status().is(400)); + } + + @Test + void putUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + Mockito.when(userService.updateUser(Mockito.any(UserDto.class))) + .thenReturn(UserDto.builder().id(52L).build()); + + var dto = UserDto.builder() + .id(10L) + .name("la") + .email("email@mail.ru") + .build(); + + mockMvc.perform(put("/users") + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(52L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .updateUser(dto); + } + + @Test + void putUserWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + mockMvc.perform(put("/users")) + .andExpect(status().is(400)); + } + + @Test + void patchUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + Mockito.when(userService.updateUser(Mockito.anyLong(), Mockito.any(UserToUpdateDto.class))) + .thenReturn(UserDto.builder().id(542L).build()); + + var dto = UserToUpdateDto.builder().name("la").build(); + + mockMvc.perform(patch("/users/13") + .characterEncoding(StandardCharsets.UTF_8) + .content(objectMapper.writeValueAsBytes(dto)) + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(542L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .updateUser(13, dto); + } + + @Test + void patchUserWithoutBodyTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + mockMvc.perform(patch("/users/13")) + .andExpect(status().is(400)); + } + + @Test + void deleteUserTest() throws Exception { + MockMvc mockMvc = MockMvcBuilders + .standaloneSetup(userController) + .build(); + + Mockito.when(userService.deleteUser(Mockito.anyLong())) + .thenReturn(UserDto.builder().id(54L).build()); + + mockMvc.perform(delete("/users/13")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id",is(54L), Long.class)); + + Mockito.verify(userService, Mockito.times(1)) + .deleteUser(13); + } +} From 02ef3cd25f537425494c0a04b97499587ad8b227 Mon Sep 17 00:00:00 2001 From: aKorishev Date: Sun, 1 Dec 2024 12:40:25 +0300 Subject: [PATCH 05/11] =?UTF-8?q?[add-item-requests-and-gateway]=20=D0=98?= =?UTF-8?q?=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=20checkStyle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shareit/booking/BookingController.java | 1 - .../shareit/item/ItemController.java | 2 - .../shareit/rest/RestQueryBuilder.java | 1 - .../shareit/user/UserController.java | 1 - gateway/src/test/ShareItTests.java | 13 - .../shareit/item/ItemControllerTest.java | 3 - .../request/RequestControllerTest.java | 6 - .../shareit/user/UserControllerTest.java | 6 - .../test/request/RequestControllerTest.java | 170 --------- gateway/src/test/shareit/ShareItTests.java | 13 - .../booking/BookingControllerTest.java | 277 -------------- .../shareit/booking/BookingServiceTest.java | 271 -------------- .../test/shareit/item/ItemControllerTest.java | 337 ------------------ .../request/RequestControllerTest.java | 170 --------- .../test/shareit/user/UserControllerTest.java | 179 ---------- gateway/src/test/user/UserControllerTest.java | 179 ---------- .../shareit/booking/BookingServiceTest.java | 3 - .../shareit/item/ItemControllerTest.java | 4 - .../request/RequestControllerTest.java | 5 - .../shareit/user/UserControllerTest.java | 6 - 20 files changed, 1647 deletions(-) delete mode 100644 gateway/src/test/ShareItTests.java delete mode 100644 gateway/src/test/request/RequestControllerTest.java delete mode 100644 gateway/src/test/shareit/ShareItTests.java delete mode 100644 gateway/src/test/shareit/booking/BookingControllerTest.java delete mode 100644 gateway/src/test/shareit/booking/BookingServiceTest.java delete mode 100644 gateway/src/test/shareit/item/ItemControllerTest.java delete mode 100644 gateway/src/test/shareit/request/RequestControllerTest.java delete mode 100644 gateway/src/test/shareit/user/UserControllerTest.java delete mode 100644 gateway/src/test/user/UserControllerTest.java diff --git a/gateway/src/main/java/ru/practicum/shareit/booking/BookingController.java b/gateway/src/main/java/ru/practicum/shareit/booking/BookingController.java index 4a7b045..9f87656 100644 --- a/gateway/src/main/java/ru/practicum/shareit/booking/BookingController.java +++ b/gateway/src/main/java/ru/practicum/shareit/booking/BookingController.java @@ -6,7 +6,6 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import ru.practicum.shareit.rest.RestQueryBuilder; -import ru.practicum.shareit.rest.RestService; import ru.practicum.shareit.booking.dto.BookingDto; @RestController diff --git a/gateway/src/main/java/ru/practicum/shareit/item/ItemController.java b/gateway/src/main/java/ru/practicum/shareit/item/ItemController.java index 4d11657..946cddc 100644 --- a/gateway/src/main/java/ru/practicum/shareit/item/ItemController.java +++ b/gateway/src/main/java/ru/practicum/shareit/item/ItemController.java @@ -10,8 +10,6 @@ import ru.practicum.shareit.item.dto.ItemToUpdateDto; import ru.practicum.shareit.rest.RestQueryBuilder; -import java.util.List; - @RestController @RequestMapping("/items") diff --git a/gateway/src/main/java/ru/practicum/shareit/rest/RestQueryBuilder.java b/gateway/src/main/java/ru/practicum/shareit/rest/RestQueryBuilder.java index 4892f5f..7db61e0 100644 --- a/gateway/src/main/java/ru/practicum/shareit/rest/RestQueryBuilder.java +++ b/gateway/src/main/java/ru/practicum/shareit/rest/RestQueryBuilder.java @@ -1,6 +1,5 @@ package ru.practicum.shareit.rest; -import lombok.Value; import org.springframework.http.HttpMethod; import java.util.Optional; diff --git a/gateway/src/main/java/ru/practicum/shareit/user/UserController.java b/gateway/src/main/java/ru/practicum/shareit/user/UserController.java index 91bd234..d9727f8 100644 --- a/gateway/src/main/java/ru/practicum/shareit/user/UserController.java +++ b/gateway/src/main/java/ru/practicum/shareit/user/UserController.java @@ -6,7 +6,6 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import ru.practicum.shareit.rest.RestQueryBuilder; -import ru.practicum.shareit.rest.RestService; import ru.practicum.shareit.user.dto.UserDto; import ru.practicum.shareit.user.dto.UserToUpdateDto; diff --git a/gateway/src/test/ShareItTests.java b/gateway/src/test/ShareItTests.java deleted file mode 100644 index 4d79052..0000000 --- a/gateway/src/test/ShareItTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package ru.practicum.shareit; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class ShareItTests { - - @Test - void contextLoads() { - } - -} diff --git a/gateway/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java b/gateway/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java index 558660a..c5901e7 100644 --- a/gateway/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java +++ b/gateway/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java @@ -13,9 +13,6 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import ru.practicum.shareit.booking.dto.BookingDto; -import ru.practicum.shareit.item.ItemController; -import ru.practicum.shareit.item.ItemService; import ru.practicum.shareit.item.dto.CommentDto; import ru.practicum.shareit.item.dto.ItemDto; import ru.practicum.shareit.item.dto.ItemToUpdateDto; diff --git a/gateway/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java b/gateway/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java index 3f14d2c..9a99a7b 100644 --- a/gateway/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java +++ b/gateway/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java @@ -13,12 +13,6 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import ru.practicum.shareit.booking.dto.BookingDto; -import ru.practicum.shareit.item.dto.CommentDto; -import ru.practicum.shareit.item.dto.ItemDto; -import ru.practicum.shareit.item.dto.ItemToUpdateDto; -import ru.practicum.shareit.request.RequestController; -import ru.practicum.shareit.request.RequestService; import ru.practicum.shareit.request.dto.RequestDto; import ru.practicum.shareit.rest.RestQueryBuilder; import ru.practicum.shareit.rest.RestQueryDto; diff --git a/gateway/src/test/java/ru/practicum/shareit/user/UserControllerTest.java b/gateway/src/test/java/ru/practicum/shareit/user/UserControllerTest.java index 1f72b5f..2d581b8 100644 --- a/gateway/src/test/java/ru/practicum/shareit/user/UserControllerTest.java +++ b/gateway/src/test/java/ru/practicum/shareit/user/UserControllerTest.java @@ -1,7 +1,6 @@ package ru.practicum.shareit.user; import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; @@ -11,19 +10,14 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import ru.practicum.shareit.item.dto.ItemDto; -import ru.practicum.shareit.request.dto.RequestDto; import ru.practicum.shareit.rest.RestQueryBuilder; import ru.practicum.shareit.rest.RestQueryDto; -import ru.practicum.shareit.user.UserController; -import ru.practicum.shareit.user.UserService; import ru.practicum.shareit.user.dto.UserDto; import ru.practicum.shareit.user.dto.UserToUpdateDto; import java.nio.charset.StandardCharsets; -import java.util.List; import static org.hamcrest.Matchers.is; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; diff --git a/gateway/src/test/request/RequestControllerTest.java b/gateway/src/test/request/RequestControllerTest.java deleted file mode 100644 index 7b76193..0000000 --- a/gateway/src/test/request/RequestControllerTest.java +++ /dev/null @@ -1,170 +0,0 @@ -package ru.practicum.shareit.request; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import ru.practicum.shareit.item.dto.CommentDto; -import ru.practicum.shareit.item.dto.ItemDto; -import ru.practicum.shareit.item.dto.ItemToUpdateDto; -import ru.practicum.shareit.request.RequestController; -import ru.practicum.shareit.request.RequestService; -import ru.practicum.shareit.request.dto.RequestDto; - -import java.nio.charset.StandardCharsets; -import java.util.List; - -import static org.hamcrest.Matchers.is; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@SpringBootTest -public class RequestControllerTest { - @Mock - RequestService requestService; - - @InjectMocks - RequestController requestController; - - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Test - public void requestPathWithoutUserIdInHead() throws Exception { - List needIdUserFromHeadRequest = - List.of(get("/requests"), - get("/requests/all"), - post("/requests")); - - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(requestController) - .build(); - - for (var requestBuilder: needIdUserFromHeadRequest) { - var result = mockMvc.perform(requestBuilder) - .andReturn(); - - var status = result - .getResponse() - .getStatus(); - - var path = result.getRequest().getMethod() + " '" + result.getRequest().getRequestURI() + "'"; - - Assertions.assertEquals(400, status, path + " was needed userid as RequestHeader \"X-Sharer-User-Id\""); - } - } - - @Test - public void getSelfRequestsTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(requestController) - .build(); - - List expectedRequests = List.of( - RequestDto.builder().id(13L).build(), - RequestDto.builder().id(24L).build(), - RequestDto.builder().id(37L).build() - ); - - Mockito.when(requestService.getRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) - .thenReturn(expectedRequests); - - mockMvc.perform(get("/requests") - .header("X-Sharer-User-Id", 7L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$[0].id", is(13L), Long.class)) - .andExpect(jsonPath("$[1].id", is(24L), Long.class)) - .andExpect(jsonPath("$[2].id", is(37L), Long.class)); - - Mockito.verify(requestService, Mockito.times(1)) - .getRequestsByUserId(7L, true); - } - - @Test - void getRequestByIdTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(requestController) - .build(); - - var expectedResult = RequestDto.builder().id(13L).build(); - - Mockito.when(requestService.getRequestById(Mockito.anyLong())) - .thenReturn(expectedResult); - - mockMvc.perform(get("/requests/23")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(13L), Long.class)); - - Mockito.verify(requestService, Mockito.times(1)) - .getRequestById(23L); - } - - @Test - void getOtherUserRequestsTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(requestController) - .build(); - - List expectedRequests = List.of( - RequestDto.builder().id(13L).build(), - RequestDto.builder().id(24L).build(), - RequestDto.builder().id(37L).build() - ); - - Mockito.when(requestService.getRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) - .thenReturn(expectedRequests); - - mockMvc.perform(get("/requests/all") - .header("X-Sharer-User-Id", 7L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$[0].id", is(13L), Long.class)) - .andExpect(jsonPath("$[1].id", is(24L), Long.class)) - .andExpect(jsonPath("$[2].id", is(37L), Long.class)); - - Mockito.verify(requestService, Mockito.times(1)) - .getRequestsByUserId(7L, false); - } - - @Test - void postRequestDtoTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(requestController) - .build(); - - Mockito.when(requestService.createRequest(Mockito.any(RequestDto.class), Mockito.anyLong())) - .thenReturn(RequestDto.builder().id(50L).build()); - - var dto = RequestDto.builder() - .id(13L) - .description("la") - .build(); - - mockMvc.perform(post("/requests") - .header("X-Sharer-User-Id", 10L) - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(50L), Long.class)); - - Mockito.verify(requestService, Mockito.times(1)) - .createRequest(dto, 10L); - } - - @Test - void postRequestWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(requestController) - .build(); - - mockMvc.perform(post("/requests") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().is(400)); - } -} diff --git a/gateway/src/test/shareit/ShareItTests.java b/gateway/src/test/shareit/ShareItTests.java deleted file mode 100644 index 4d79052..0000000 --- a/gateway/src/test/shareit/ShareItTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package ru.practicum.shareit; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class ShareItTests { - - @Test - void contextLoads() { - } - -} diff --git a/gateway/src/test/shareit/booking/BookingControllerTest.java b/gateway/src/test/shareit/booking/BookingControllerTest.java deleted file mode 100644 index 9aa62f4..0000000 --- a/gateway/src/test/shareit/booking/BookingControllerTest.java +++ /dev/null @@ -1,277 +0,0 @@ -package ru.practicum.shareit.booking; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import ru.practicum.shareit.booking.BookingController; -import ru.practicum.shareit.booking.BookingService; -import ru.practicum.shareit.booking.BookingStatus; -import ru.practicum.shareit.booking.dto.BookingDto; - -import java.nio.charset.StandardCharsets; -import java.util.List; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.hamcrest.Matchers.is; - -@SpringBootTest -public class BookingControllerTest { - @Mock - BookingService bookingService; - - @InjectMocks - BookingController bookingController; - - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Test - public void requestPathWithoutUserIdInHead() throws Exception { - List needIdUserFromHeadRequest = - List.of(get("/bookings/1"), - get("/bookings"), - get("/bookings/owner"), - post("/bookings"), - patch("/bookings/1?approved=true")); - - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - for (var requestBuilder: needIdUserFromHeadRequest) { - var result = mockMvc.perform(requestBuilder) - .andReturn(); - - var status = result - .getResponse() - .getStatus(); - - var path = result.getRequest().getMethod() + " '" + result.getRequest().getRequestURI() + "'"; - - Assertions.assertEquals(400, status, path + " was needed userid as RequestHeader \"X-Sharer-User-Id\""); - } - } - - @Test - public void getBookingTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - var dto = BookingDto.builder() - .id(10L) - .build(); - - Mockito.when(bookingService.getBooking(Mockito.anyLong(), Mockito.anyLong())) - .thenReturn(dto); - - mockMvc.perform(get("/bookings/1") - .header("X-Sharer-User-Id", 1L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id", is(10L), Long.class)); - } - - @Test - void getItemParsingRequestId() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - mockMvc.perform(get("/bookings/100") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()); - - Mockito.verify(bookingService, Mockito.times(1)) - .getBooking(100, 10); - } - - @Test - void getItemsForUserIdTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - var expectedResult = List.of( - BookingDto.builder().id(1L).build(), - BookingDto.builder().id(2L).build(), - BookingDto.builder().id(3L).build()); - - Mockito.when(bookingService.getBookingForUserId(Mockito.anyLong())) - .thenReturn(expectedResult); - - mockMvc.perform(get("/bookings") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.[0].id",is(1L), Long.class)) - .andExpect(jsonPath("$.[1].id",is(2L), Long.class)) - .andExpect(jsonPath("$.[2].id",is(3L), Long.class)); - } - - @Test - void getItemsForUserIdParsingRequestTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - mockMvc.perform(get("/bookings") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()); - - Mockito.verify(bookingService, Mockito.times(1)) - .getBookingForUserId(10); - } - - @Test - void getItemsForItemOwnerIdTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - var expectedResult = List.of( - BookingDto.builder().id(1L).build(), - BookingDto.builder().id(2L).build(), - BookingDto.builder().id(3L).build()); - - Mockito.when(bookingService.getBookingsForItemOwnerId(Mockito.anyLong())) - .thenReturn(expectedResult); - - mockMvc.perform(get("/bookings/owner") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.[0].id",is(1L), Long.class)) - .andExpect(jsonPath("$.[1].id",is(2L), Long.class)) - .andExpect(jsonPath("$.[2].id",is(3L), Long.class)); - } - - @Test - void getItemsForItemOwnerIdParsingRequestTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - mockMvc.perform(get("/bookings/owner") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()); - - Mockito.verify(bookingService, Mockito.times(1)) - .getBookingsForItemOwnerId(10); - } - - @Test - void postItemTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - Mockito.when(bookingService.createBooking(Mockito.any(BookingDto.class), Mockito.anyLong())) - .thenReturn(BookingDto.builder().id(50L).build()); - - mockMvc.perform(post("/bookings") - .header("X-Sharer-User-Id", 10L) - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(BookingDto.builder().build())) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(50L), Long.class)); - } - - @Test - void postItemParsingRequestTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - var dto = BookingDto.builder().build(); - - mockMvc.perform(post("/bookings") - .header("X-Sharer-User-Id", 10L) - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()); - - Mockito.verify(bookingService, Mockito.times(1)) - .createBooking(dto, 10L); - } - - @Test - void postItemWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - mockMvc.perform(post("/bookings") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().is(400)); - } - - @Test - void patchItemApprovedTrueTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - Mockito.when(bookingService.setBookingStatus(Mockito.anyLong(), Mockito.anyBoolean(), Mockito.anyLong())) - .thenReturn(BookingDto.builder().status(BookingStatus.APPROVED).build()); - - mockMvc.perform(patch("/bookings/10?approved=true") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.status",is(BookingStatus.APPROVED.name()), String.class)); - } - - @Test - void patchItemApprovedFalseTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - Mockito.when(bookingService.setBookingStatus(Mockito.anyLong(), Mockito.anyBoolean(), Mockito.anyLong())) - .thenReturn(BookingDto.builder().status(BookingStatus.REJECTED).build()); - - mockMvc.perform(patch("/bookings/10?approved=false") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.status",is(BookingStatus.REJECTED.name()), String.class)); - } - - @Test - void patchItemParsingRequestTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - mockMvc.perform(patch("/bookings/100?approved=true") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()); - - mockMvc.perform(patch("/bookings/100?approved=false") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()); - - Mockito.verify(bookingService, Mockito.times(1)) - .setBookingStatus(100, true, 10L); - - Mockito.verify(bookingService, Mockito.times(1)) - .setBookingStatus(100, false, 10L); - } - - @Test - void patchItemWithoutParamsTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - mockMvc.perform(patch("/bookings/100") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().is(400)); - } -} diff --git a/gateway/src/test/shareit/booking/BookingServiceTest.java b/gateway/src/test/shareit/booking/BookingServiceTest.java deleted file mode 100644 index d2d1f5f..0000000 --- a/gateway/src/test/shareit/booking/BookingServiceTest.java +++ /dev/null @@ -1,271 +0,0 @@ -package ru.practicum.shareit.booking; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.springframework.boot.test.context.SpringBootTest; -import ru.practicum.shareit.booking.BookingMapper; -import ru.practicum.shareit.booking.BookingService; -import ru.practicum.shareit.booking.BookingStatus; -import ru.practicum.shareit.booking.BookingStorage; -import ru.practicum.shareit.booking.dto.BookingDto; -import ru.practicum.shareit.booking.dto.BookingStatusRequestDto; -import ru.practicum.shareit.booking.storage.BookingEntity; -import ru.practicum.shareit.exceptions.NotFoundException; -import ru.practicum.shareit.exceptions.NotValidException; -import ru.practicum.shareit.item.ItemStorage; -import ru.practicum.shareit.item.dto.ItemDto; -import ru.practicum.shareit.item.storage.ItemEntity; -import ru.practicum.shareit.user.UserStorage; -import ru.practicum.shareit.user.dto.UserDto; -import ru.practicum.shareit.user.storage.UserEntity; - -import java.sql.Timestamp; -import java.time.Instant; -import java.util.List; -import java.util.Optional; - -import static org.hamcrest.Matchers.is; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; - -@SpringBootTest -public class BookingServiceTest { - @Mock - BookingStorage bookingStorage; - @Mock - ItemStorage itemStorage; - @Mock - UserStorage userStorage; - - @InjectMocks - BookingService bookingService; - - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Test - public void getBookingTest() throws Exception { - var expectedBookingEntity = new BookingEntity(); - expectedBookingEntity.setId(8L); - expectedBookingEntity.setItem(new ItemEntity()); - expectedBookingEntity.setStart(Timestamp.from(Instant.now())); - expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); - - Mockito.when(userStorage.getUser(Mockito.anyLong())) - .thenReturn(Optional.of(new UserEntity())); - Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) - .thenReturn(Optional.of(expectedBookingEntity)); - Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) - .thenReturn(true); - - - try (MockedStatic mapper = Mockito.mockStatic(BookingMapper.class)) { - mapper - .when(() -> BookingMapper.toDto(Mockito.any(BookingEntity.class), - Mockito.any(UserDto.class), - Mockito.any(ItemDto.class))) - .thenAnswer(a -> { - var entity = a.getArgument(0, BookingEntity.class); - return BookingDto.builder() - .id(entity.getId()) - .build(); - }); - - var bookingDto = bookingService.getBooking(1, 1); - - Assertions.assertEquals(8L, bookingDto.id()); - - mapper.verify( - () -> BookingMapper.toDto( - Mockito.any(BookingEntity.class), - Mockito.any(UserDto.class), - Mockito.any(ItemDto.class)), - Mockito.times(1)); - } - } - - @Test - public void getBookingWhileUserNotIsOwnerTest() throws Exception { - var expectedBookingEntity = new BookingEntity(); - expectedBookingEntity.setId(10L); - expectedBookingEntity.setItem(new ItemEntity()); - expectedBookingEntity.setStart(Timestamp.from(Instant.now())); - expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); - - Mockito.when(userStorage.getUser(Mockito.anyLong())) - .thenReturn(Optional.of(new UserEntity())); - Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) - .thenReturn(Optional.of(expectedBookingEntity)); - Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) - .thenReturn(false); - - - try { - bookingService.getBooking(1,1); - - Assertions.fail(); - } catch (NotValidException ex) { - Assertions.assertEquals("Данные о бронировании может получить заказчик или владелец", ex.getMessage()); - } - } - - @Test - public void getBookingWhileNotFoundUserTest() throws Exception { - var expectedBookingEntity = new BookingEntity(); - expectedBookingEntity.setId(10L); - expectedBookingEntity.setItem(new ItemEntity()); - expectedBookingEntity.setStart(Timestamp.from(Instant.now())); - expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); - - Mockito.when(userStorage.getUser(Mockito.anyLong())) - .thenReturn(Optional.empty()); - Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) - .thenReturn(Optional.of(expectedBookingEntity)); - Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) - .thenReturn(true); - - - try { - bookingService.getBooking(1,1); - - Assertions.fail(); - } catch (NotFoundException ex) { - Assertions.assertEquals("Пользователь не найден", ex.getMessage()); - } - } - - @Test - public void getBookingWhileNotBookingTest() throws Exception { - Mockito.when(userStorage.getUser(Mockito.anyLong())) - .thenReturn(Optional.of(new UserEntity())); - Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) - .thenReturn(Optional.empty()); - Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) - .thenReturn(true); - - - try { - bookingService.getBooking(1,1); - - Assertions.fail(); - } catch (NotFoundException ex) { - Assertions.assertEquals("Бронь не найдена", ex.getMessage()); - } - } - - @Test - public void getBookingForUserIdTest() { - var expectedBookingDtoList = List.of( - BookingDto.builder().id(8L).build(), - BookingDto.builder().id(107L).build()); - - var entity1 = new BookingEntity(); - entity1.setId(8L); - entity1.setItem(new ItemEntity()); - - var entity2 = new BookingEntity(); - entity2.setId(107L); - entity2.setItem(new ItemEntity()); - - Mockito.when(userStorage.getUser(Mockito.anyLong())) - .thenReturn(Optional.of(new UserEntity())); - - Mockito.when(bookingStorage.findBookingsByBookerId(Mockito.anyLong())) - .thenReturn(List.of(entity1, entity2)); - - try (MockedStatic mapper = Mockito.mockStatic(BookingMapper.class)) { - mapper - .when(() -> BookingMapper.toDto(Mockito.any(BookingEntity.class), - Mockito.any(UserDto.class), - Mockito.any(ItemDto.class))) - .thenAnswer(a -> { - var entity = a.getArgument(0, BookingEntity.class); - return BookingDto.builder() - .id(entity.getId()) - .build(); - }); - - var bookingDtoList = bookingService.getBookingForUserId(1); - - Assertions.assertEquals(2, bookingDtoList.size()); - Assertions.assertEquals(8L, bookingDtoList.getFirst().id(), "Id dto[0] is expected 8L"); - Assertions.assertEquals(107L, bookingDtoList.get(1).id(), "Id dto[0] is expected 107L"); - - mapper.verify( - () -> BookingMapper.toDto( - Mockito.any(BookingEntity.class), - Mockito.any(UserDto.class), - Mockito.any(ItemDto.class)), - Mockito.times(2)); - } - } - - @Test - public void getBookingForUserIdWhileNotFoundUserTest() throws Exception { - var expectedBookingEntity = new BookingEntity(); - expectedBookingEntity.setId(10L); - expectedBookingEntity.setItem(new ItemEntity()); - expectedBookingEntity.setStart(Timestamp.from(Instant.now())); - expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); - - Mockito.when(userStorage.getUser(Mockito.anyLong())) - .thenReturn(Optional.empty()); - Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) - .thenReturn(Optional.of(expectedBookingEntity)); - - - try { - bookingService.getBookingForUserId(1); - - Assertions.fail(); - } catch (NotFoundException ex) { - Assertions.assertEquals("Пользователь не найден", ex.getMessage()); - } - } - - @Test - public void getBookingForUserIdWhileChangeStatusAndOwnerIdTest() throws Exception { - var expectedBookingEntity = new BookingEntity(); - expectedBookingEntity.setId(10L); - expectedBookingEntity.setItem(new ItemEntity()); - expectedBookingEntity.setStart(Timestamp.from(Instant.now())); - expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); - - Mockito.when(userStorage.existsById(Mockito.anyLong())) - .thenReturn(true); - Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) - .thenReturn(Optional.of(expectedBookingEntity)); - - var statuses = List.of( - BookingStatusRequestDto.ALL, - BookingStatusRequestDto.CURRENT, - BookingStatusRequestDto.PAST, - BookingStatusRequestDto.FUTURE, - BookingStatusRequestDto.WAITING, - BookingStatusRequestDto.REJECTED, - BookingStatusRequestDto.APPROVED); - - var owners = List.of(1, 7, 19); - - for (var ownerId: owners) { - for (var requestStatus: statuses) { - bookingService.getBookingsForItemOwnerId(requestStatus, ownerId); - } - - Mockito.verify(bookingStorage, Mockito.times(4)) - .findBookingsByOwnerId(ownerId); - - Mockito.verify(bookingStorage, Mockito.times(1)) - .findBookingsByOwnerId(ownerId, BookingStatus.WAITING); - - Mockito.verify(bookingStorage, Mockito.times(1)) - .findBookingsByOwnerId(ownerId, BookingStatus.REJECTED); - - Mockito.verify(bookingStorage, Mockito.times(1)) - .findBookingsByOwnerId(ownerId, BookingStatus.APPROVED); - } - } -} diff --git a/gateway/src/test/shareit/item/ItemControllerTest.java b/gateway/src/test/shareit/item/ItemControllerTest.java deleted file mode 100644 index b35edd9..0000000 --- a/gateway/src/test/shareit/item/ItemControllerTest.java +++ /dev/null @@ -1,337 +0,0 @@ -package ru.practicum.shareit.item; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import ru.practicum.shareit.booking.BookingStatus; -import ru.practicum.shareit.booking.dto.BookingDto; -import ru.practicum.shareit.item.ItemController; -import ru.practicum.shareit.item.ItemService; -import ru.practicum.shareit.item.dto.CommentDto; -import ru.practicum.shareit.item.dto.ItemDto; -import ru.practicum.shareit.item.dto.ItemToUpdateDto; - -import java.nio.charset.StandardCharsets; -import java.util.List; - -import static org.hamcrest.Matchers.is; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@SpringBootTest -public class ItemControllerTest { - @Mock - ItemService itemService; - - @InjectMocks - ItemController itemController; - - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Test - public void requestPathWithoutUserIdInHead() throws Exception { - List needIdUserFromHeadRequest = - List.of(post("/items"), - post("/items/1/comment"), - put("/items"), - patch("/items/1"), - delete("/items/1")); - - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - for (var requestBuilder: needIdUserFromHeadRequest) { - var result = mockMvc.perform(requestBuilder) - .andReturn(); - - var status = result - .getResponse() - .getStatus(); - - var path = result.getRequest().getMethod() + " '" + result.getRequest().getRequestURI() + "'"; - - Assertions.assertEquals(400, status, path + " was needed userid as RequestHeader \"X-Sharer-User-Id\""); - } - } - - @Test - public void getItemTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - var dto = ItemDto.builder() - .id(10L) - .build(); - - Mockito.when(itemService.getItem(Mockito.anyLong())) - .thenReturn(dto); - - mockMvc.perform(get("/items/1")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id", is(10L), Long.class)); - } - - @Test - void getItemParsingRequestId() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - mockMvc.perform(get("/items/100")) - .andExpect(status().isOk()); - - Mockito.verify(itemService, Mockito.times(1)) - .getItem(100); - } - - @Test - void getItemsForUserIdTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - var expectedResult = List.of( - ItemDto.builder().id(11L).build(), - ItemDto.builder().id(42L).build(), - ItemDto.builder().id(37L).build()); - - Mockito.when(itemService.getItems(Mockito.anyLong())) - .thenReturn(expectedResult); - - mockMvc.perform(get("/items") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.[0].id",is(11L), Long.class)) - .andExpect(jsonPath("$.[1].id",is(42L), Long.class)) - .andExpect(jsonPath("$.[2].id",is(37L), Long.class)); - } - - @Test - void getItemsForUserIdParsingRequestTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - mockMvc.perform(get("/items") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()); - - Mockito.verify(itemService, Mockito.times(1)) - .getItems(10); - } - - @Test - void findItemsByTextTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - var expectedResult = List.of( - ItemDto.builder().id(1L).build(), - ItemDto.builder().id(42L).build(), - ItemDto.builder().id(37L).build()); - - Mockito.when(itemService.findFreeItemsByText(Mockito.anyString(), Mockito.anyBoolean())) - .thenReturn(expectedResult); - - mockMvc.perform(get("/items/search?text=abc")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.[0].id",is(1L), Long.class)) - .andExpect(jsonPath("$.[1].id",is(42L), Long.class)) - .andExpect(jsonPath("$.[2].id",is(37L), Long.class)); - - Mockito.verify(itemService, Mockito.times(1)) - .findFreeItemsByText("abc", true); - - Mockito.verify(itemService, Mockito.never()) - .findFreeItemsByText("abc", false); - } - - @Test - void findItemsByTextFailParsingRequestTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - mockMvc.perform(get("/items/search")) - .andExpect(status().is(400)); - } - - @Test - void postItemTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - Mockito.when(itemService.createItem(Mockito.any(ItemDto.class), Mockito.anyLong())) - .thenReturn(ItemDto.builder().id(50L).build()); - - var dto = ItemDto.builder() - .id(13L) - .name("la") - .available(true) - .description("ma") - .build(); - - mockMvc.perform(post("/items") - .header("X-Sharer-User-Id", 10L) - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(50L), Long.class)); - - Mockito.verify(itemService, Mockito.times(1)) - .createItem(dto, 10L); - } - - @Test - void postItemWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - mockMvc.perform(post("/items") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().is(400)); - } - - @Test - void postCommentTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - var dto = CommentDto.builder() - .id(47L) - .text("la") - .build(); - - Mockito.when(itemService.addComment(Mockito.any(CommentDto.class), Mockito.anyLong(), Mockito.anyLong())) - .thenReturn(CommentDto.builder().id(50L).build()); - - mockMvc.perform(post("/items/13/comment") - .header("X-Sharer-User-Id", 10L) - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(50L), Long.class)); - - Mockito.verify(itemService, Mockito.times(1)) - .addComment(dto, 13L, 10L); - } - - @Test - void postCommentWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - mockMvc.perform(post("/items/13/comment") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().is(400)); - } - - @Test - void putItemTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - Mockito.when(itemService.updateItem(Mockito.any(ItemDto.class), Mockito.anyLong())) - .thenReturn(ItemDto.builder().id(50L).build()); - - var dto = ItemDto.builder() - .id(13L) - .name("la") - .description("ma") - .available(true) - .build(); - - mockMvc.perform(put("/items") - .header("X-Sharer-User-Id", 10L) - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(50L), Long.class)); - - Mockito.verify(itemService, Mockito.times(1)) - .updateItem(dto, 10L); - } - - @Test - void putItemWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - mockMvc.perform(put("/items") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().is(400)); - } - - @Test - void patchItemTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - var dto = ItemToUpdateDto.builder() - .build(); - - Mockito.when(itemService.updateItem(Mockito.anyLong(), Mockito.any(ItemToUpdateDto.class), Mockito.anyLong())) - .thenReturn(ItemDto.builder().id(50L).build()); - - mockMvc.perform(patch("/items/17") - .header("X-Sharer-User-Id", 10L) - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(50L), Long.class)); - - Mockito.verify(itemService, Mockito.times(1)) - .updateItem(17, dto, 10L); - } - - @Test - void patchItemWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - mockMvc.perform(put("/items") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().is(400)); - } - - @Test - void deleteItemTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - Mockito.when(itemService.deleteItem(17L, 10L)) - .thenReturn(ItemDto.builder().id(50L).build()); - - mockMvc.perform(delete("/items/17") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(50L), Long.class)); - - Mockito.verify(itemService, Mockito.times(1)) - .deleteItem(17L, 10L); - } -} diff --git a/gateway/src/test/shareit/request/RequestControllerTest.java b/gateway/src/test/shareit/request/RequestControllerTest.java deleted file mode 100644 index 7b76193..0000000 --- a/gateway/src/test/shareit/request/RequestControllerTest.java +++ /dev/null @@ -1,170 +0,0 @@ -package ru.practicum.shareit.request; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import ru.practicum.shareit.item.dto.CommentDto; -import ru.practicum.shareit.item.dto.ItemDto; -import ru.practicum.shareit.item.dto.ItemToUpdateDto; -import ru.practicum.shareit.request.RequestController; -import ru.practicum.shareit.request.RequestService; -import ru.practicum.shareit.request.dto.RequestDto; - -import java.nio.charset.StandardCharsets; -import java.util.List; - -import static org.hamcrest.Matchers.is; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@SpringBootTest -public class RequestControllerTest { - @Mock - RequestService requestService; - - @InjectMocks - RequestController requestController; - - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Test - public void requestPathWithoutUserIdInHead() throws Exception { - List needIdUserFromHeadRequest = - List.of(get("/requests"), - get("/requests/all"), - post("/requests")); - - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(requestController) - .build(); - - for (var requestBuilder: needIdUserFromHeadRequest) { - var result = mockMvc.perform(requestBuilder) - .andReturn(); - - var status = result - .getResponse() - .getStatus(); - - var path = result.getRequest().getMethod() + " '" + result.getRequest().getRequestURI() + "'"; - - Assertions.assertEquals(400, status, path + " was needed userid as RequestHeader \"X-Sharer-User-Id\""); - } - } - - @Test - public void getSelfRequestsTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(requestController) - .build(); - - List expectedRequests = List.of( - RequestDto.builder().id(13L).build(), - RequestDto.builder().id(24L).build(), - RequestDto.builder().id(37L).build() - ); - - Mockito.when(requestService.getRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) - .thenReturn(expectedRequests); - - mockMvc.perform(get("/requests") - .header("X-Sharer-User-Id", 7L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$[0].id", is(13L), Long.class)) - .andExpect(jsonPath("$[1].id", is(24L), Long.class)) - .andExpect(jsonPath("$[2].id", is(37L), Long.class)); - - Mockito.verify(requestService, Mockito.times(1)) - .getRequestsByUserId(7L, true); - } - - @Test - void getRequestByIdTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(requestController) - .build(); - - var expectedResult = RequestDto.builder().id(13L).build(); - - Mockito.when(requestService.getRequestById(Mockito.anyLong())) - .thenReturn(expectedResult); - - mockMvc.perform(get("/requests/23")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(13L), Long.class)); - - Mockito.verify(requestService, Mockito.times(1)) - .getRequestById(23L); - } - - @Test - void getOtherUserRequestsTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(requestController) - .build(); - - List expectedRequests = List.of( - RequestDto.builder().id(13L).build(), - RequestDto.builder().id(24L).build(), - RequestDto.builder().id(37L).build() - ); - - Mockito.when(requestService.getRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) - .thenReturn(expectedRequests); - - mockMvc.perform(get("/requests/all") - .header("X-Sharer-User-Id", 7L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$[0].id", is(13L), Long.class)) - .andExpect(jsonPath("$[1].id", is(24L), Long.class)) - .andExpect(jsonPath("$[2].id", is(37L), Long.class)); - - Mockito.verify(requestService, Mockito.times(1)) - .getRequestsByUserId(7L, false); - } - - @Test - void postRequestDtoTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(requestController) - .build(); - - Mockito.when(requestService.createRequest(Mockito.any(RequestDto.class), Mockito.anyLong())) - .thenReturn(RequestDto.builder().id(50L).build()); - - var dto = RequestDto.builder() - .id(13L) - .description("la") - .build(); - - mockMvc.perform(post("/requests") - .header("X-Sharer-User-Id", 10L) - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(50L), Long.class)); - - Mockito.verify(requestService, Mockito.times(1)) - .createRequest(dto, 10L); - } - - @Test - void postRequestWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(requestController) - .build(); - - mockMvc.perform(post("/requests") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().is(400)); - } -} diff --git a/gateway/src/test/shareit/user/UserControllerTest.java b/gateway/src/test/shareit/user/UserControllerTest.java deleted file mode 100644 index fd908bb..0000000 --- a/gateway/src/test/shareit/user/UserControllerTest.java +++ /dev/null @@ -1,179 +0,0 @@ -package ru.practicum.shareit.user; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import ru.practicum.shareit.request.dto.RequestDto; -import ru.practicum.shareit.user.UserController; -import ru.practicum.shareit.user.UserService; -import ru.practicum.shareit.user.dto.UserDto; -import ru.practicum.shareit.user.dto.UserToUpdateDto; - -import java.nio.charset.StandardCharsets; -import java.util.List; - -import static org.hamcrest.Matchers.is; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@SpringBootTest -public class UserControllerTest { - @Mock - UserService userService; - - @InjectMocks - UserController userController; - - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Test - public void getUserTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - var dto = UserDto.builder() - .id(47L) - .name("la") - .email("email@mail.ru") - .build(); - - Mockito.when(userService.getUser(Mockito.anyLong())) - .thenReturn(dto); - - mockMvc.perform(get("/users/17")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id", is(47L), Long.class)); - - Mockito.verify(userService, Mockito.times(1)) - .getUser(17L); - } - - @Test - void postUserTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - Mockito.when(userService.updateUser(Mockito.any(UserDto.class))) - .thenReturn(UserDto.builder().id(50L).build()); - - var dto = UserDto.builder() - .name("la") - .email("email@mail.ru") - .build(); - - mockMvc.perform(post("/users") - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(50L), Long.class)); - - Mockito.verify(userService, Mockito.times(1)) - .updateUser(dto); - } - - @Test - void postUserWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - mockMvc.perform(post("/users")) - .andExpect(status().is(400)); - } - - @Test - void putUserTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - Mockito.when(userService.updateUser(Mockito.any(UserDto.class))) - .thenReturn(UserDto.builder().id(52L).build()); - - var dto = UserDto.builder() - .id(10L) - .name("la") - .email("email@mail.ru") - .build(); - - mockMvc.perform(put("/users") - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(52L), Long.class)); - - Mockito.verify(userService, Mockito.times(1)) - .updateUser(dto); - } - - @Test - void putUserWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - mockMvc.perform(put("/users")) - .andExpect(status().is(400)); - } - - @Test - void patchUserTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - Mockito.when(userService.updateUser(Mockito.anyLong(), Mockito.any(UserToUpdateDto.class))) - .thenReturn(UserDto.builder().id(542L).build()); - - var dto = UserToUpdateDto.builder().name("la").build(); - - mockMvc.perform(patch("/users/13") - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(542L), Long.class)); - - Mockito.verify(userService, Mockito.times(1)) - .updateUser(13, dto); - } - - @Test - void patchUserWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - mockMvc.perform(patch("/users/13")) - .andExpect(status().is(400)); - } - - @Test - void deleteUserTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - Mockito.when(userService.deleteUser(Mockito.anyLong())) - .thenReturn(UserDto.builder().id(54L).build()); - - mockMvc.perform(delete("/users/13")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(54L), Long.class)); - - Mockito.verify(userService, Mockito.times(1)) - .deleteUser(13); - } -} diff --git a/gateway/src/test/user/UserControllerTest.java b/gateway/src/test/user/UserControllerTest.java deleted file mode 100644 index fd908bb..0000000 --- a/gateway/src/test/user/UserControllerTest.java +++ /dev/null @@ -1,179 +0,0 @@ -package ru.practicum.shareit.user; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import ru.practicum.shareit.request.dto.RequestDto; -import ru.practicum.shareit.user.UserController; -import ru.practicum.shareit.user.UserService; -import ru.practicum.shareit.user.dto.UserDto; -import ru.practicum.shareit.user.dto.UserToUpdateDto; - -import java.nio.charset.StandardCharsets; -import java.util.List; - -import static org.hamcrest.Matchers.is; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@SpringBootTest -public class UserControllerTest { - @Mock - UserService userService; - - @InjectMocks - UserController userController; - - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Test - public void getUserTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - var dto = UserDto.builder() - .id(47L) - .name("la") - .email("email@mail.ru") - .build(); - - Mockito.when(userService.getUser(Mockito.anyLong())) - .thenReturn(dto); - - mockMvc.perform(get("/users/17")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id", is(47L), Long.class)); - - Mockito.verify(userService, Mockito.times(1)) - .getUser(17L); - } - - @Test - void postUserTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - Mockito.when(userService.updateUser(Mockito.any(UserDto.class))) - .thenReturn(UserDto.builder().id(50L).build()); - - var dto = UserDto.builder() - .name("la") - .email("email@mail.ru") - .build(); - - mockMvc.perform(post("/users") - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(50L), Long.class)); - - Mockito.verify(userService, Mockito.times(1)) - .updateUser(dto); - } - - @Test - void postUserWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - mockMvc.perform(post("/users")) - .andExpect(status().is(400)); - } - - @Test - void putUserTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - Mockito.when(userService.updateUser(Mockito.any(UserDto.class))) - .thenReturn(UserDto.builder().id(52L).build()); - - var dto = UserDto.builder() - .id(10L) - .name("la") - .email("email@mail.ru") - .build(); - - mockMvc.perform(put("/users") - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(52L), Long.class)); - - Mockito.verify(userService, Mockito.times(1)) - .updateUser(dto); - } - - @Test - void putUserWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - mockMvc.perform(put("/users")) - .andExpect(status().is(400)); - } - - @Test - void patchUserTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - Mockito.when(userService.updateUser(Mockito.anyLong(), Mockito.any(UserToUpdateDto.class))) - .thenReturn(UserDto.builder().id(542L).build()); - - var dto = UserToUpdateDto.builder().name("la").build(); - - mockMvc.perform(patch("/users/13") - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(542L), Long.class)); - - Mockito.verify(userService, Mockito.times(1)) - .updateUser(13, dto); - } - - @Test - void patchUserWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - mockMvc.perform(patch("/users/13")) - .andExpect(status().is(400)); - } - - @Test - void deleteUserTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - Mockito.when(userService.deleteUser(Mockito.anyLong())) - .thenReturn(UserDto.builder().id(54L).build()); - - mockMvc.perform(delete("/users/13")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(54L), Long.class)); - - Mockito.verify(userService, Mockito.times(1)) - .deleteUser(13); - } -} diff --git a/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java b/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java index d2d1f5f..886e1fd 100644 --- a/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java +++ b/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java @@ -29,9 +29,6 @@ import java.util.List; import java.util.Optional; -import static org.hamcrest.Matchers.is; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; - @SpringBootTest public class BookingServiceTest { @Mock diff --git a/server/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java b/server/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java index b35edd9..c7a3e26 100644 --- a/server/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java +++ b/server/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java @@ -10,10 +10,6 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import ru.practicum.shareit.booking.BookingStatus; -import ru.practicum.shareit.booking.dto.BookingDto; -import ru.practicum.shareit.item.ItemController; -import ru.practicum.shareit.item.ItemService; import ru.practicum.shareit.item.dto.CommentDto; import ru.practicum.shareit.item.dto.ItemDto; import ru.practicum.shareit.item.dto.ItemToUpdateDto; diff --git a/server/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java b/server/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java index 7b76193..c41bed8 100644 --- a/server/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java +++ b/server/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java @@ -10,11 +10,6 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import ru.practicum.shareit.item.dto.CommentDto; -import ru.practicum.shareit.item.dto.ItemDto; -import ru.practicum.shareit.item.dto.ItemToUpdateDto; -import ru.practicum.shareit.request.RequestController; -import ru.practicum.shareit.request.RequestService; import ru.practicum.shareit.request.dto.RequestDto; import java.nio.charset.StandardCharsets; diff --git a/server/src/test/java/ru/practicum/shareit/user/UserControllerTest.java b/server/src/test/java/ru/practicum/shareit/user/UserControllerTest.java index fd908bb..93898b0 100644 --- a/server/src/test/java/ru/practicum/shareit/user/UserControllerTest.java +++ b/server/src/test/java/ru/practicum/shareit/user/UserControllerTest.java @@ -1,23 +1,17 @@ package ru.practicum.shareit.user; import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import ru.practicum.shareit.request.dto.RequestDto; -import ru.practicum.shareit.user.UserController; -import ru.practicum.shareit.user.UserService; import ru.practicum.shareit.user.dto.UserDto; import ru.practicum.shareit.user.dto.UserToUpdateDto; import java.nio.charset.StandardCharsets; -import java.util.List; import static org.hamcrest.Matchers.is; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; From 1b3abdfdf733813c5b98e50efb275d5e7d0c5598 Mon Sep 17 00:00:00 2001 From: aKorishev Date: Sun, 1 Dec 2024 12:45:41 +0300 Subject: [PATCH 06/11] =?UTF-8?q?[add-item-requests-and-gateway]=20=D0=A3?= =?UTF-8?q?=D0=B4=D0=B0=D0=BB=D0=B8=D0=BB=20=D1=84=D0=B0=D0=B9=D0=BB=D1=8B?= =?UTF-8?q?=20java=20=D0=B8=D0=B7=20=D0=BE=D0=B1=D1=89=D0=B5=D0=B3=D0=BE?= =?UTF-8?q?=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/ru/practicum/shareit/ShareItApp.java | 13 - .../shareit/item/ItemController.java | 72 ---- .../shareit/item/dto/CommentDto.java | 14 - .../practicum/shareit/item/dto/ItemDto.java | 20 -- .../shareit/item/dto/ItemToUpdateDto.java | 11 - src/main/resources/application-dev.yaml | 17 - src/main/resources/application.properties | 1 - src/main/resources/application.yaml | 11 - src/main/resources/schema.sql | 41 --- .../ru/practicum/shareit/ShareItTests.java | 13 - .../booking/BookingControllerTest.java | 274 -------------- .../shareit/booking/BookingServiceTest.java | 267 -------------- .../shareit/item/ItemControllerTest.java | 335 ------------------ .../request/RequestControllerTest.java | 168 --------- .../shareit/user/UserControllerTest.java | 177 --------- 15 files changed, 1434 deletions(-) delete mode 100644 src/main/java/ru/practicum/shareit/ShareItApp.java delete mode 100644 src/main/java/ru/practicum/shareit/item/ItemController.java delete mode 100644 src/main/java/ru/practicum/shareit/item/dto/CommentDto.java delete mode 100644 src/main/java/ru/practicum/shareit/item/dto/ItemDto.java delete mode 100644 src/main/java/ru/practicum/shareit/item/dto/ItemToUpdateDto.java delete mode 100644 src/main/resources/application-dev.yaml delete mode 100644 src/main/resources/application.properties delete mode 100644 src/main/resources/application.yaml delete mode 100644 src/main/resources/schema.sql delete mode 100644 src/test/java/ru/practicum/shareit/ShareItTests.java delete mode 100644 src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java delete mode 100644 src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java delete mode 100644 src/test/java/ru/practicum/shareit/item/ItemControllerTest.java delete mode 100644 src/test/java/ru/practicum/shareit/request/RequestControllerTest.java delete mode 100644 src/test/java/ru/practicum/shareit/user/UserControllerTest.java diff --git a/src/main/java/ru/practicum/shareit/ShareItApp.java b/src/main/java/ru/practicum/shareit/ShareItApp.java deleted file mode 100644 index a00ad56..0000000 --- a/src/main/java/ru/practicum/shareit/ShareItApp.java +++ /dev/null @@ -1,13 +0,0 @@ -package ru.practicum.shareit; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class ShareItApp { - - public static void main(String[] args) { - SpringApplication.run(ShareItApp.class, args); - } - -} diff --git a/src/main/java/ru/practicum/shareit/item/ItemController.java b/src/main/java/ru/practicum/shareit/item/ItemController.java deleted file mode 100644 index 6538f36..0000000 --- a/src/main/java/ru/practicum/shareit/item/ItemController.java +++ /dev/null @@ -1,72 +0,0 @@ -package ru.practicum.shareit.item; - -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.*; -import ru.practicum.shareit.item.dto.CommentDto; -import ru.practicum.shareit.item.dto.ItemDto; -import ru.practicum.shareit.item.dto.ItemToUpdateDto; - -import java.util.List; - - -@RestController -@RequestMapping("/items") -@RequiredArgsConstructor -public class ItemController { - private final ItemService itemService; - - @GetMapping - public List getItems(@RequestHeader("X-Sharer-User-Id") long userId) { - return itemService.getItems(userId); - } - - @GetMapping("/{id}") - public ItemDto getItem(@PathVariable long id) { - return itemService.getItem(id); - } - - @GetMapping("/search") - public List findItemsByText(@RequestParam String text) { - return itemService.findFreeItemsByText(text, true); - } - - @PostMapping - public ItemDto postItem( - @Valid @RequestBody ItemDto itemDto, - @RequestHeader("X-Sharer-User-Id") long userId) { - return itemService.createItem(itemDto, userId); - } - - @PostMapping("/{id}/comment") - public CommentDto postComment( - @PathVariable long id, - @RequestHeader("X-Sharer-User-Id") long userId, - @Valid @RequestBody CommentDto commentDto) { - return itemService.addComment(commentDto, id, userId); - } - - @PutMapping() - public ItemDto putItem( - @Valid @RequestBody ItemDto itemDto, - @RequestHeader("X-Sharer-User-Id") long userId) { - - return itemService.updateItem(itemDto, userId); - } - - @PatchMapping("/{id}") - public ItemDto patchItem( - @PathVariable long id, - @Valid @RequestBody ItemToUpdateDto item, - @RequestHeader("X-Sharer-User-Id") long userId) { - itemService.updateItem(id, item, userId); - - return itemService.getItem(id); - } - - @DeleteMapping("/{id}") - public ItemDto deleteItem(@RequestParam long id, - @RequestHeader("X-Sharer-User-Id") long userId) { - return itemService.deleteItem(id, userId); - } -} diff --git a/src/main/java/ru/practicum/shareit/item/dto/CommentDto.java b/src/main/java/ru/practicum/shareit/item/dto/CommentDto.java deleted file mode 100644 index 6b72310..0000000 --- a/src/main/java/ru/practicum/shareit/item/dto/CommentDto.java +++ /dev/null @@ -1,14 +0,0 @@ -package ru.practicum.shareit.item.dto; - -import jakarta.validation.constraints.NotBlank; -import lombok.Builder; - -import java.sql.Timestamp; - -@Builder(toBuilder = true) -public record CommentDto( - Long id, - @NotBlank String text, - String authorName, - Timestamp created -) { } diff --git a/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java b/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java deleted file mode 100644 index 842bbd5..0000000 --- a/src/main/java/ru/practicum/shareit/item/dto/ItemDto.java +++ /dev/null @@ -1,20 +0,0 @@ -package ru.practicum.shareit.item.dto; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Builder; - -import java.sql.Timestamp; -import java.util.List; - -@Builder(toBuilder = true) -public record ItemDto( - Long id, - @NotBlank String name, - @NotBlank String description, - @NotNull Boolean available, - Timestamp lastBooking, - Timestamp nextBooking, - List comments, - Long requestId -) { } diff --git a/src/main/java/ru/practicum/shareit/item/dto/ItemToUpdateDto.java b/src/main/java/ru/practicum/shareit/item/dto/ItemToUpdateDto.java deleted file mode 100644 index 8e023b4..0000000 --- a/src/main/java/ru/practicum/shareit/item/dto/ItemToUpdateDto.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.practicum.shareit.item.dto; - -import lombok.Builder; - -@Builder -public record ItemToUpdateDto( - Long itemId, - String name, - String description, - Boolean available -) { } diff --git a/src/main/resources/application-dev.yaml b/src/main/resources/application-dev.yaml deleted file mode 100644 index 39e9429..0000000 --- a/src/main/resources/application-dev.yaml +++ /dev/null @@ -1,17 +0,0 @@ -spring: - main: - log-startup-info: true # выводим служебную информацию - banner-mode: off # не выводим баннер - datasource: - driverClassName: org.h2.Driver - url: jdbc:h2:mem:shareit - jpa: - #show-sql: true - show-sql: false -logging.level: - ru.practicum.shareit: TRACE - org: - zalando.logbook: TRACE -# hibernate: -# type.descriptor.sql.BasicBinder: TRACE -# orm.jdbc.bind: TRACE diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index 5ff0285..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -server.port=9090 \ No newline at end of file diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml deleted file mode 100644 index 55085a4..0000000 --- a/src/main/resources/application.yaml +++ /dev/null @@ -1,11 +0,0 @@ -spring: - jpa: - hibernate.ddl-auto: none - properties: - hibernate: - jdbc.time_zone: UTC - format_sql: true - sql.init: - mode: always - schema-locations: classpath:schema.sql -logging.level.org.springframework: INFO \ No newline at end of file diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql deleted file mode 100644 index 66ec3f6..0000000 --- a/src/main/resources/schema.sql +++ /dev/null @@ -1,41 +0,0 @@ -CREATE TABLE if NOT EXISTS Users( - user_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - name VARCHAR(100) NOT NULL, - email VARCHAR(100) NOT NULL, - CONSTRAINT uniqueEmails UNIQUE(email) -); - -CREATE TABLE IF NOT EXISTS Requests( - request_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - user_id BIGINT REFERENCES Users(user_id), - text VARCHAR(1000), - description VARCHAR(1000), - created timestamp WITHOUT TIME ZONE NOT NULL -); - -CREATE TABLE IF NOT EXISTS Items( - item_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - owner_id BIGINT REFERENCES Users(user_id), - name VARCHAR(100) NOT NULL, - description VARCHAR(1000) NOT NULL, - available boolean, - request_id BIGINT REFERENCES Requests(request_id) -); - -CREATE TABLE IF NOT EXISTS Comments( - comment_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - user_id BIGINT REFERENCES Users(user_id), - item_id BIGINT REFERENCES Items(item_id), - text VARCHAR(1000) NOT NULL, - created timestamp WITHOUT TIME ZONE NOT NULL -); - -CREATE TABLE IF NOT EXISTS Bookings( - booking_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - booker_id BIGINT REFERENCES Users(user_id), - item_id BIGINT REFERENCES Items(item_id), - status VARCHAR(100) NOT NULL, - description VARCHAR(1000), - start timestamp WITHOUT TIME ZONE NOT NULL, - finish timestamp WITHOUT TIME ZONE NOT NULL -); \ No newline at end of file diff --git a/src/test/java/ru/practicum/shareit/ShareItTests.java b/src/test/java/ru/practicum/shareit/ShareItTests.java deleted file mode 100644 index 4d79052..0000000 --- a/src/test/java/ru/practicum/shareit/ShareItTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package ru.practicum.shareit; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class ShareItTests { - - @Test - void contextLoads() { - } - -} diff --git a/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java b/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java deleted file mode 100644 index e74eac5..0000000 --- a/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java +++ /dev/null @@ -1,274 +0,0 @@ -package ru.practicum.shareit.booking; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import ru.practicum.shareit.booking.dto.BookingDto; - -import java.nio.charset.StandardCharsets; -import java.util.List; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.hamcrest.Matchers.is; - -@SpringBootTest -public class BookingControllerTest { - @Mock - BookingService bookingService; - - @InjectMocks - BookingController bookingController; - - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Test - public void requestPathWithoutUserIdInHead() throws Exception { - List needIdUserFromHeadRequest = - List.of(get("/bookings/1"), - get("/bookings"), - get("/bookings/owner"), - post("/bookings"), - patch("/bookings/1?approved=true")); - - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - for (var requestBuilder: needIdUserFromHeadRequest) { - var result = mockMvc.perform(requestBuilder) - .andReturn(); - - var status = result - .getResponse() - .getStatus(); - - var path = result.getRequest().getMethod() + " '" + result.getRequest().getRequestURI() + "'"; - - Assertions.assertEquals(400, status, path + " was needed userid as RequestHeader \"X-Sharer-User-Id\""); - } - } - - @Test - public void getBookingTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - var dto = BookingDto.builder() - .id(10L) - .build(); - - Mockito.when(bookingService.getBooking(Mockito.anyLong(), Mockito.anyLong())) - .thenReturn(dto); - - mockMvc.perform(get("/bookings/1") - .header("X-Sharer-User-Id", 1L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id", is(10L), Long.class)); - } - - @Test - void getItemParsingRequestId() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - mockMvc.perform(get("/bookings/100") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()); - - Mockito.verify(bookingService, Mockito.times(1)) - .getBooking(100, 10); - } - - @Test - void getItemsForUserIdTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - var expectedResult = List.of( - BookingDto.builder().id(1L).build(), - BookingDto.builder().id(2L).build(), - BookingDto.builder().id(3L).build()); - - Mockito.when(bookingService.getBookingForUserId(Mockito.anyLong())) - .thenReturn(expectedResult); - - mockMvc.perform(get("/bookings") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.[0].id",is(1L), Long.class)) - .andExpect(jsonPath("$.[1].id",is(2L), Long.class)) - .andExpect(jsonPath("$.[2].id",is(3L), Long.class)); - } - - @Test - void getItemsForUserIdParsingRequestTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - mockMvc.perform(get("/bookings") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()); - - Mockito.verify(bookingService, Mockito.times(1)) - .getBookingForUserId(10); - } - - @Test - void getItemsForItemOwnerIdTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - var expectedResult = List.of( - BookingDto.builder().id(1L).build(), - BookingDto.builder().id(2L).build(), - BookingDto.builder().id(3L).build()); - - Mockito.when(bookingService.getBookingsForItemOwnerId(Mockito.anyLong())) - .thenReturn(expectedResult); - - mockMvc.perform(get("/bookings/owner") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.[0].id",is(1L), Long.class)) - .andExpect(jsonPath("$.[1].id",is(2L), Long.class)) - .andExpect(jsonPath("$.[2].id",is(3L), Long.class)); - } - - @Test - void getItemsForItemOwnerIdParsingRequestTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - mockMvc.perform(get("/bookings/owner") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()); - - Mockito.verify(bookingService, Mockito.times(1)) - .getBookingsForItemOwnerId(10); - } - - @Test - void postItemTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - Mockito.when(bookingService.createBooking(Mockito.any(BookingDto.class), Mockito.anyLong())) - .thenReturn(BookingDto.builder().id(50L).build()); - - mockMvc.perform(post("/bookings") - .header("X-Sharer-User-Id", 10L) - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(BookingDto.builder().build())) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(50L), Long.class)); - } - - @Test - void postItemParsingRequestTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - var dto = BookingDto.builder().build(); - - mockMvc.perform(post("/bookings") - .header("X-Sharer-User-Id", 10L) - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()); - - Mockito.verify(bookingService, Mockito.times(1)) - .createBooking(dto, 10L); - } - - @Test - void postItemWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - mockMvc.perform(post("/bookings") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().is(400)); - } - - @Test - void patchItemApprovedTrueTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - Mockito.when(bookingService.setBookingStatus(Mockito.anyLong(), Mockito.anyBoolean(), Mockito.anyLong())) - .thenReturn(BookingDto.builder().status(BookingStatus.APPROVED).build()); - - mockMvc.perform(patch("/bookings/10?approved=true") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.status",is(BookingStatus.APPROVED.name()), String.class)); - } - - @Test - void patchItemApprovedFalseTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - Mockito.when(bookingService.setBookingStatus(Mockito.anyLong(), Mockito.anyBoolean(), Mockito.anyLong())) - .thenReturn(BookingDto.builder().status(BookingStatus.REJECTED).build()); - - mockMvc.perform(patch("/bookings/10?approved=false") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.status",is(BookingStatus.REJECTED.name()), String.class)); - } - - @Test - void patchItemParsingRequestTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - mockMvc.perform(patch("/bookings/100?approved=true") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()); - - mockMvc.perform(patch("/bookings/100?approved=false") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()); - - Mockito.verify(bookingService, Mockito.times(1)) - .setBookingStatus(100, true, 10L); - - Mockito.verify(bookingService, Mockito.times(1)) - .setBookingStatus(100, false, 10L); - } - - @Test - void patchItemWithoutParamsTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(bookingController) - .build(); - - mockMvc.perform(patch("/bookings/100") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().is(400)); - } -} diff --git a/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java b/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java deleted file mode 100644 index 179622e..0000000 --- a/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java +++ /dev/null @@ -1,267 +0,0 @@ -package ru.practicum.shareit.booking; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.springframework.boot.test.context.SpringBootTest; -import ru.practicum.shareit.booking.dto.BookingDto; -import ru.practicum.shareit.booking.dto.BookingStatusRequestDto; -import ru.practicum.shareit.booking.storage.BookingEntity; -import ru.practicum.shareit.exceptions.NotFoundException; -import ru.practicum.shareit.exceptions.NotValidException; -import ru.practicum.shareit.item.ItemStorage; -import ru.practicum.shareit.item.dto.ItemDto; -import ru.practicum.shareit.item.storage.ItemEntity; -import ru.practicum.shareit.user.UserStorage; -import ru.practicum.shareit.user.dto.UserDto; -import ru.practicum.shareit.user.storage.UserEntity; - -import java.sql.Timestamp; -import java.time.Instant; -import java.util.List; -import java.util.Optional; - -import static org.hamcrest.Matchers.is; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; - -@SpringBootTest -public class BookingServiceTest { - @Mock - BookingStorage bookingStorage; - @Mock - ItemStorage itemStorage; - @Mock - UserStorage userStorage; - - @InjectMocks - BookingService bookingService; - - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Test - public void getBookingTest() throws Exception { - var expectedBookingEntity = new BookingEntity(); - expectedBookingEntity.setId(8L); - expectedBookingEntity.setItem(new ItemEntity()); - expectedBookingEntity.setStart(Timestamp.from(Instant.now())); - expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); - - Mockito.when(userStorage.getUser(Mockito.anyLong())) - .thenReturn(Optional.of(new UserEntity())); - Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) - .thenReturn(Optional.of(expectedBookingEntity)); - Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) - .thenReturn(true); - - - try (MockedStatic mapper = Mockito.mockStatic(BookingMapper.class)) { - mapper - .when(() -> BookingMapper.toDto(Mockito.any(BookingEntity.class), - Mockito.any(UserDto.class), - Mockito.any(ItemDto.class))) - .thenAnswer(a -> { - var entity = a.getArgument(0, BookingEntity.class); - return BookingDto.builder() - .id(entity.getId()) - .build(); - }); - - var bookingDto = bookingService.getBooking(1, 1); - - Assertions.assertEquals(8L, bookingDto.id()); - - mapper.verify( - () -> BookingMapper.toDto( - Mockito.any(BookingEntity.class), - Mockito.any(UserDto.class), - Mockito.any(ItemDto.class)), - Mockito.times(1)); - } - } - - @Test - public void getBookingWhileUserNotIsOwnerTest() throws Exception { - var expectedBookingEntity = new BookingEntity(); - expectedBookingEntity.setId(10L); - expectedBookingEntity.setItem(new ItemEntity()); - expectedBookingEntity.setStart(Timestamp.from(Instant.now())); - expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); - - Mockito.when(userStorage.getUser(Mockito.anyLong())) - .thenReturn(Optional.of(new UserEntity())); - Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) - .thenReturn(Optional.of(expectedBookingEntity)); - Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) - .thenReturn(false); - - - try { - bookingService.getBooking(1,1); - - Assertions.fail(); - } catch (NotValidException ex) { - Assertions.assertEquals("Данные о бронировании может получить заказчик или владелец", ex.getMessage()); - } - } - - @Test - public void getBookingWhileNotFoundUserTest() throws Exception { - var expectedBookingEntity = new BookingEntity(); - expectedBookingEntity.setId(10L); - expectedBookingEntity.setItem(new ItemEntity()); - expectedBookingEntity.setStart(Timestamp.from(Instant.now())); - expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); - - Mockito.when(userStorage.getUser(Mockito.anyLong())) - .thenReturn(Optional.empty()); - Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) - .thenReturn(Optional.of(expectedBookingEntity)); - Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) - .thenReturn(true); - - - try { - bookingService.getBooking(1,1); - - Assertions.fail(); - } catch (NotFoundException ex) { - Assertions.assertEquals("Пользователь не найден", ex.getMessage()); - } - } - - @Test - public void getBookingWhileNotBookingTest() throws Exception { - Mockito.when(userStorage.getUser(Mockito.anyLong())) - .thenReturn(Optional.of(new UserEntity())); - Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) - .thenReturn(Optional.empty()); - Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) - .thenReturn(true); - - - try { - bookingService.getBooking(1,1); - - Assertions.fail(); - } catch (NotFoundException ex) { - Assertions.assertEquals("Бронь не найдена", ex.getMessage()); - } - } - - @Test - public void getBookingForUserIdTest() { - var expectedBookingDtoList = List.of( - BookingDto.builder().id(8L).build(), - BookingDto.builder().id(107L).build()); - - var entity1 = new BookingEntity(); - entity1.setId(8L); - entity1.setItem(new ItemEntity()); - - var entity2 = new BookingEntity(); - entity2.setId(107L); - entity2.setItem(new ItemEntity()); - - Mockito.when(userStorage.getUser(Mockito.anyLong())) - .thenReturn(Optional.of(new UserEntity())); - - Mockito.when(bookingStorage.findBookingsByBookerId(Mockito.anyLong())) - .thenReturn(List.of(entity1, entity2)); - - try (MockedStatic mapper = Mockito.mockStatic(BookingMapper.class)) { - mapper - .when(() -> BookingMapper.toDto(Mockito.any(BookingEntity.class), - Mockito.any(UserDto.class), - Mockito.any(ItemDto.class))) - .thenAnswer(a -> { - var entity = a.getArgument(0, BookingEntity.class); - return BookingDto.builder() - .id(entity.getId()) - .build(); - }); - - var bookingDtoList = bookingService.getBookingForUserId(1); - - Assertions.assertEquals(2, bookingDtoList.size()); - Assertions.assertEquals(8L, bookingDtoList.getFirst().id(), "Id dto[0] is expected 8L"); - Assertions.assertEquals(107L, bookingDtoList.get(1).id(), "Id dto[0] is expected 107L"); - - mapper.verify( - () -> BookingMapper.toDto( - Mockito.any(BookingEntity.class), - Mockito.any(UserDto.class), - Mockito.any(ItemDto.class)), - Mockito.times(2)); - } - } - - @Test - public void getBookingForUserIdWhileNotFoundUserTest() throws Exception { - var expectedBookingEntity = new BookingEntity(); - expectedBookingEntity.setId(10L); - expectedBookingEntity.setItem(new ItemEntity()); - expectedBookingEntity.setStart(Timestamp.from(Instant.now())); - expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); - - Mockito.when(userStorage.getUser(Mockito.anyLong())) - .thenReturn(Optional.empty()); - Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) - .thenReturn(Optional.of(expectedBookingEntity)); - - - try { - bookingService.getBookingForUserId(1); - - Assertions.fail(); - } catch (NotFoundException ex) { - Assertions.assertEquals("Пользователь не найден", ex.getMessage()); - } - } - - @Test - public void getBookingForUserIdWhileChangeStatusAndOwnerIdTest() throws Exception { - var expectedBookingEntity = new BookingEntity(); - expectedBookingEntity.setId(10L); - expectedBookingEntity.setItem(new ItemEntity()); - expectedBookingEntity.setStart(Timestamp.from(Instant.now())); - expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); - - Mockito.when(userStorage.existsById(Mockito.anyLong())) - .thenReturn(true); - Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) - .thenReturn(Optional.of(expectedBookingEntity)); - - var statuses = List.of( - BookingStatusRequestDto.ALL, - BookingStatusRequestDto.CURRENT, - BookingStatusRequestDto.PAST, - BookingStatusRequestDto.FUTURE, - BookingStatusRequestDto.WAITING, - BookingStatusRequestDto.REJECTED, - BookingStatusRequestDto.APPROVED); - - var owners = List.of(1, 7, 19); - - for (var ownerId: owners) { - for (var requestStatus: statuses) { - bookingService.getBookingsForItemOwnerId(requestStatus, ownerId); - } - - Mockito.verify(bookingStorage, Mockito.times(4)) - .findBookingsByOwnerId(ownerId); - - Mockito.verify(bookingStorage, Mockito.times(1)) - .findBookingsByOwnerId(ownerId, BookingStatus.WAITING); - - Mockito.verify(bookingStorage, Mockito.times(1)) - .findBookingsByOwnerId(ownerId, BookingStatus.REJECTED); - - Mockito.verify(bookingStorage, Mockito.times(1)) - .findBookingsByOwnerId(ownerId, BookingStatus.APPROVED); - } - } -} diff --git a/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java b/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java deleted file mode 100644 index 163c00d..0000000 --- a/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java +++ /dev/null @@ -1,335 +0,0 @@ -package ru.practicum.shareit.item; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import ru.practicum.shareit.booking.BookingStatus; -import ru.practicum.shareit.booking.dto.BookingDto; -import ru.practicum.shareit.item.dto.CommentDto; -import ru.practicum.shareit.item.dto.ItemDto; -import ru.practicum.shareit.item.dto.ItemToUpdateDto; - -import java.nio.charset.StandardCharsets; -import java.util.List; - -import static org.hamcrest.Matchers.is; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@SpringBootTest -public class ItemControllerTest { - @Mock - ItemService itemService; - - @InjectMocks - ItemController itemController; - - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Test - public void requestPathWithoutUserIdInHead() throws Exception { - List needIdUserFromHeadRequest = - List.of(post("/items"), - post("/items/1/comment"), - put("/items"), - patch("/items/1"), - delete("/items/1")); - - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - for (var requestBuilder: needIdUserFromHeadRequest) { - var result = mockMvc.perform(requestBuilder) - .andReturn(); - - var status = result - .getResponse() - .getStatus(); - - var path = result.getRequest().getMethod() + " '" + result.getRequest().getRequestURI() + "'"; - - Assertions.assertEquals(400, status, path + " was needed userid as RequestHeader \"X-Sharer-User-Id\""); - } - } - - @Test - public void getItemTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - var dto = ItemDto.builder() - .id(10L) - .build(); - - Mockito.when(itemService.getItem(Mockito.anyLong())) - .thenReturn(dto); - - mockMvc.perform(get("/items/1")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id", is(10L), Long.class)); - } - - @Test - void getItemParsingRequestId() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - mockMvc.perform(get("/items/100")) - .andExpect(status().isOk()); - - Mockito.verify(itemService, Mockito.times(1)) - .getItem(100); - } - - @Test - void getItemsForUserIdTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - var expectedResult = List.of( - ItemDto.builder().id(11L).build(), - ItemDto.builder().id(42L).build(), - ItemDto.builder().id(37L).build()); - - Mockito.when(itemService.getItems(Mockito.anyLong())) - .thenReturn(expectedResult); - - mockMvc.perform(get("/items") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.[0].id",is(11L), Long.class)) - .andExpect(jsonPath("$.[1].id",is(42L), Long.class)) - .andExpect(jsonPath("$.[2].id",is(37L), Long.class)); - } - - @Test - void getItemsForUserIdParsingRequestTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - mockMvc.perform(get("/items") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()); - - Mockito.verify(itemService, Mockito.times(1)) - .getItems(10); - } - - @Test - void findItemsByTextTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - var expectedResult = List.of( - ItemDto.builder().id(1L).build(), - ItemDto.builder().id(42L).build(), - ItemDto.builder().id(37L).build()); - - Mockito.when(itemService.findFreeItemsByText(Mockito.anyString(), Mockito.anyBoolean())) - .thenReturn(expectedResult); - - mockMvc.perform(get("/items/search?text=abc")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.[0].id",is(1L), Long.class)) - .andExpect(jsonPath("$.[1].id",is(42L), Long.class)) - .andExpect(jsonPath("$.[2].id",is(37L), Long.class)); - - Mockito.verify(itemService, Mockito.times(1)) - .findFreeItemsByText("abc", true); - - Mockito.verify(itemService, Mockito.never()) - .findFreeItemsByText("abc", false); - } - - @Test - void findItemsByTextFailParsingRequestTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - mockMvc.perform(get("/items/search")) - .andExpect(status().is(400)); - } - - @Test - void postItemTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - Mockito.when(itemService.createItem(Mockito.any(ItemDto.class), Mockito.anyLong())) - .thenReturn(ItemDto.builder().id(50L).build()); - - var dto = ItemDto.builder() - .id(13L) - .name("la") - .available(true) - .description("ma") - .build(); - - mockMvc.perform(post("/items") - .header("X-Sharer-User-Id", 10L) - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(50L), Long.class)); - - Mockito.verify(itemService, Mockito.times(1)) - .createItem(dto, 10L); - } - - @Test - void postItemWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - mockMvc.perform(post("/items") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().is(400)); - } - - @Test - void postCommentTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - var dto = CommentDto.builder() - .id(47L) - .text("la") - .build(); - - Mockito.when(itemService.addComment(Mockito.any(CommentDto.class), Mockito.anyLong(), Mockito.anyLong())) - .thenReturn(CommentDto.builder().id(50L).build()); - - mockMvc.perform(post("/items/13/comment") - .header("X-Sharer-User-Id", 10L) - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(50L), Long.class)); - - Mockito.verify(itemService, Mockito.times(1)) - .addComment(dto, 13L, 10L); - } - - @Test - void postCommentWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - mockMvc.perform(post("/items/13/comment") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().is(400)); - } - - @Test - void putItemTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - Mockito.when(itemService.updateItem(Mockito.any(ItemDto.class), Mockito.anyLong())) - .thenReturn(ItemDto.builder().id(50L).build()); - - var dto = ItemDto.builder() - .id(13L) - .name("la") - .description("ma") - .available(true) - .build(); - - mockMvc.perform(put("/items") - .header("X-Sharer-User-Id", 10L) - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(50L), Long.class)); - - Mockito.verify(itemService, Mockito.times(1)) - .updateItem(dto, 10L); - } - - @Test - void putItemWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - mockMvc.perform(put("/items") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().is(400)); - } - - @Test - void patchItemTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - var dto = ItemToUpdateDto.builder() - .build(); - - Mockito.when(itemService.updateItem(Mockito.anyLong(), Mockito.any(ItemToUpdateDto.class), Mockito.anyLong())) - .thenReturn(ItemDto.builder().id(50L).build()); - - mockMvc.perform(patch("/items/17") - .header("X-Sharer-User-Id", 10L) - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(50L), Long.class)); - - Mockito.verify(itemService, Mockito.times(1)) - .updateItem(17, dto, 10L); - } - - @Test - void patchItemWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - mockMvc.perform(put("/items") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().is(400)); - } - - @Test - void deleteItemTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(itemController) - .build(); - - Mockito.when(itemService.deleteItem(17L, 10L)) - .thenReturn(ItemDto.builder().id(50L).build()); - - mockMvc.perform(delete("/items/17") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(50L), Long.class)); - - Mockito.verify(itemService, Mockito.times(1)) - .deleteItem(17L, 10L); - } -} diff --git a/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java b/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java deleted file mode 100644 index 8e4a4c5..0000000 --- a/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java +++ /dev/null @@ -1,168 +0,0 @@ -package ru.practicum.shareit.request; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import ru.practicum.shareit.item.dto.CommentDto; -import ru.practicum.shareit.item.dto.ItemDto; -import ru.practicum.shareit.item.dto.ItemToUpdateDto; -import ru.practicum.shareit.request.dto.RequestDto; - -import java.nio.charset.StandardCharsets; -import java.util.List; - -import static org.hamcrest.Matchers.is; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@SpringBootTest -public class RequestControllerTest { - @Mock - RequestService requestService; - - @InjectMocks - RequestController requestController; - - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Test - public void requestPathWithoutUserIdInHead() throws Exception { - List needIdUserFromHeadRequest = - List.of(get("/requests"), - get("/requests/all"), - post("/requests")); - - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(requestController) - .build(); - - for (var requestBuilder: needIdUserFromHeadRequest) { - var result = mockMvc.perform(requestBuilder) - .andReturn(); - - var status = result - .getResponse() - .getStatus(); - - var path = result.getRequest().getMethod() + " '" + result.getRequest().getRequestURI() + "'"; - - Assertions.assertEquals(400, status, path + " was needed userid as RequestHeader \"X-Sharer-User-Id\""); - } - } - - @Test - public void getSelfRequestsTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(requestController) - .build(); - - List expectedRequests = List.of( - RequestDto.builder().id(13L).build(), - RequestDto.builder().id(24L).build(), - RequestDto.builder().id(37L).build() - ); - - Mockito.when(requestService.getRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) - .thenReturn(expectedRequests); - - mockMvc.perform(get("/requests") - .header("X-Sharer-User-Id", 7L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$[0].id", is(13L), Long.class)) - .andExpect(jsonPath("$[1].id", is(24L), Long.class)) - .andExpect(jsonPath("$[2].id", is(37L), Long.class)); - - Mockito.verify(requestService, Mockito.times(1)) - .getRequestsByUserId(7L, true); - } - - @Test - void getRequestByIdTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(requestController) - .build(); - - var expectedResult = RequestDto.builder().id(13L).build(); - - Mockito.when(requestService.getRequestById(Mockito.anyLong())) - .thenReturn(expectedResult); - - mockMvc.perform(get("/requests/23")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(13L), Long.class)); - - Mockito.verify(requestService, Mockito.times(1)) - .getRequestById(23L); - } - - @Test - void getOtherUserRequestsTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(requestController) - .build(); - - List expectedRequests = List.of( - RequestDto.builder().id(13L).build(), - RequestDto.builder().id(24L).build(), - RequestDto.builder().id(37L).build() - ); - - Mockito.when(requestService.getRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) - .thenReturn(expectedRequests); - - mockMvc.perform(get("/requests/all") - .header("X-Sharer-User-Id", 7L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$[0].id", is(13L), Long.class)) - .andExpect(jsonPath("$[1].id", is(24L), Long.class)) - .andExpect(jsonPath("$[2].id", is(37L), Long.class)); - - Mockito.verify(requestService, Mockito.times(1)) - .getRequestsByUserId(7L, false); - } - - @Test - void postRequestDtoTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(requestController) - .build(); - - Mockito.when(requestService.createRequest(Mockito.any(RequestDto.class), Mockito.anyLong())) - .thenReturn(RequestDto.builder().id(50L).build()); - - var dto = RequestDto.builder() - .id(13L) - .description("la") - .build(); - - mockMvc.perform(post("/requests") - .header("X-Sharer-User-Id", 10L) - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(50L), Long.class)); - - Mockito.verify(requestService, Mockito.times(1)) - .createRequest(dto, 10L); - } - - @Test - void postRequestWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(requestController) - .build(); - - mockMvc.perform(post("/requests") - .header("X-Sharer-User-Id", 10L)) - .andExpect(status().is(400)); - } -} diff --git a/src/test/java/ru/practicum/shareit/user/UserControllerTest.java b/src/test/java/ru/practicum/shareit/user/UserControllerTest.java deleted file mode 100644 index 67d01dc..0000000 --- a/src/test/java/ru/practicum/shareit/user/UserControllerTest.java +++ /dev/null @@ -1,177 +0,0 @@ -package ru.practicum.shareit.user; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import ru.practicum.shareit.request.dto.RequestDto; -import ru.practicum.shareit.user.dto.UserDto; -import ru.practicum.shareit.user.dto.UserToUpdateDto; - -import java.nio.charset.StandardCharsets; -import java.util.List; - -import static org.hamcrest.Matchers.is; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@SpringBootTest -public class UserControllerTest { - @Mock - UserService userService; - - @InjectMocks - UserController userController; - - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Test - public void getUserTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - var dto = UserDto.builder() - .id(47L) - .name("la") - .email("email@mail.ru") - .build(); - - Mockito.when(userService.getUser(Mockito.anyLong())) - .thenReturn(dto); - - mockMvc.perform(get("/users/17")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id", is(47L), Long.class)); - - Mockito.verify(userService, Mockito.times(1)) - .getUser(17L); - } - - @Test - void postUserTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - Mockito.when(userService.updateUser(Mockito.any(UserDto.class))) - .thenReturn(UserDto.builder().id(50L).build()); - - var dto = UserDto.builder() - .name("la") - .email("email@mail.ru") - .build(); - - mockMvc.perform(post("/users") - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(50L), Long.class)); - - Mockito.verify(userService, Mockito.times(1)) - .updateUser(dto); - } - - @Test - void postUserWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - mockMvc.perform(post("/users")) - .andExpect(status().is(400)); - } - - @Test - void putUserTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - Mockito.when(userService.updateUser(Mockito.any(UserDto.class))) - .thenReturn(UserDto.builder().id(52L).build()); - - var dto = UserDto.builder() - .id(10L) - .name("la") - .email("email@mail.ru") - .build(); - - mockMvc.perform(put("/users") - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(52L), Long.class)); - - Mockito.verify(userService, Mockito.times(1)) - .updateUser(dto); - } - - @Test - void putUserWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - mockMvc.perform(put("/users")) - .andExpect(status().is(400)); - } - - @Test - void patchUserTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - Mockito.when(userService.updateUser(Mockito.anyLong(), Mockito.any(UserToUpdateDto.class))) - .thenReturn(UserDto.builder().id(542L).build()); - - var dto = UserToUpdateDto.builder().name("la").build(); - - mockMvc.perform(patch("/users/13") - .characterEncoding(StandardCharsets.UTF_8) - .content(objectMapper.writeValueAsBytes(dto)) - .contentType("application/json")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(542L), Long.class)); - - Mockito.verify(userService, Mockito.times(1)) - .updateUser(13, dto); - } - - @Test - void patchUserWithoutBodyTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - mockMvc.perform(patch("/users/13")) - .andExpect(status().is(400)); - } - - @Test - void deleteUserTest() throws Exception { - MockMvc mockMvc = MockMvcBuilders - .standaloneSetup(userController) - .build(); - - Mockito.when(userService.deleteUser(Mockito.anyLong())) - .thenReturn(UserDto.builder().id(54L).build()); - - mockMvc.perform(delete("/users/13")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.id",is(54L), Long.class)); - - Mockito.verify(userService, Mockito.times(1)) - .deleteUser(13); - } -} From 0f9dc7e24ab5dcec6d368866e1548acef2881058 Mon Sep 17 00:00:00 2001 From: aKorishev Date: Sun, 1 Dec 2024 12:49:12 +0300 Subject: [PATCH 07/11] =?UTF-8?q?[add-item-requests-and-gateway]=20=D0=94?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20=D1=84=D0=B0=D0=B9=D0=BB?= =?UTF-8?q?=D1=8B,=20=D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B=D0=B5=20=D0=BD?= =?UTF-8?q?=D0=B5=20=D0=BF=D0=BE=D0=BF=D0=B0=D0=BB=D0=B8=20=D0=B2=20=D0=BA?= =?UTF-8?q?=D0=B8=D0=BC=D0=BC=D0=B8=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yml | 39 +++++++++++++++++++ .../practicum/shareit/item/ItemService.java | 26 +++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 docker-compose.yml create mode 100644 gateway/src/main/java/ru/practicum/shareit/item/ItemService.java diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..abe6570 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,39 @@ +services: + gateway: + build: gateway + image: shareit-gateway + container_name: shareit-gateway + ports: + - "8080:8080" + depends_on: + - server + environment: + - SHAREIT_SERVER_URL=http://server:9090 + + server: + build: server + image: shareit-server + container_name: shareit-server + ports: + - "9090:9090" + depends_on: + - db + environment: + - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/shareit + - SPRING_DATASOURCE_USERNAME=shareit + - SPRING_DATASOURCE_PASSWORD=shareit + + db: + image: postgres:16.1 + container_name: postgres + ports: + - "6541:5432" + environment: + - POSTGRES_PASSWORD=shareit + - POSTGRES_USER=shareit + - POSTGRES_DB=shareit + healthcheck: + test: pg_isready -q -d $$POSTGRES_DB -U $$POSTGRES_USER + timeout: 5s + interval: 5s + retries: 10 \ No newline at end of file diff --git a/gateway/src/main/java/ru/practicum/shareit/item/ItemService.java b/gateway/src/main/java/ru/practicum/shareit/item/ItemService.java new file mode 100644 index 0000000..73eeea8 --- /dev/null +++ b/gateway/src/main/java/ru/practicum/shareit/item/ItemService.java @@ -0,0 +1,26 @@ +package ru.practicum.shareit.item; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.stereotype.Service; +import org.springframework.web.util.DefaultUriBuilderFactory; +import ru.practicum.shareit.rest.RestService; + +@Service +public class ItemService extends RestService { + private static final String API_PREFIX = "/items"; + + @Autowired + public ItemService( + @Value("${shareit-server.url}") String serverUrl, + RestTemplateBuilder builder) { + super( + builder + .uriTemplateHandler(new DefaultUriBuilderFactory(serverUrl + API_PREFIX)) + .requestFactory(() -> new HttpComponentsClientHttpRequestFactory()) + .build() + ); + } +} From 7433bddb804010e1e1ad14f045acbc30b9a91b9c Mon Sep 17 00:00:00 2001 From: aKorishev Date: Tue, 3 Dec 2024 20:01:22 +0300 Subject: [PATCH 08/11] =?UTF-8?q?[add-item-requests-and-gateway]=20=D0=94?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20=D1=82=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gateway/pom.xml | 54 +++ server/pom.xml | 10 + .../ru/practicum/shareit/booking/Booking.java | 7 - .../shareit/booking/BookingController.java | 6 +- .../shareit/booking/BookingService.java | 68 +-- .../shareit/booking/BookingStorage.java | 2 +- .../ru/practicum/shareit/booking/Status.java | 6 - .../booking/storage/BookingEntity.java | 11 + .../booking/storage/BookingStorageInDb.java | 2 +- .../shareit/tool/IgnoreJacocoGenerated.java | 9 + .../booking/BookingControllerTest.java | 15 +- .../shareit/booking/BookingServiceTest.java | 396 +++++++++++------- 12 files changed, 352 insertions(+), 234 deletions(-) delete mode 100644 server/src/main/java/ru/practicum/shareit/booking/Booking.java delete mode 100644 server/src/main/java/ru/practicum/shareit/booking/Status.java create mode 100644 server/src/main/java/ru/practicum/shareit/tool/IgnoreJacocoGenerated.java diff --git a/gateway/pom.xml b/gateway/pom.xml index f3394c1..f420171 100644 --- a/gateway/pom.xml +++ b/gateway/pom.xml @@ -64,6 +64,60 @@ org.springframework.boot spring-boot-maven-plugin + + org.jacoco + jacoco-maven-plugin + + + ru/practicum/shareit/**/dto/* + ru/practicum/shareit/ShareItGateway.class + ru/practicum/shareit/rest/*.class + + + + + default-prepare-agent + + prepare-agent + + + ${project.build.directory}/coverage-reports/jacoco.exec + surefireArgLine + + + + default-report + test + + report + + + ${project.build.directory}/coverage-reports/jacoco.exec + ${project.reporting.outputDirectory}/jacoco + + + + default-check + + check + + + + + BUNDLE + + + COMPLEXITY + COVEREDRATIO + 0.70 + + + + + + + + diff --git a/server/pom.xml b/server/pom.xml index 584f63d..cd6cc65 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -77,6 +77,16 @@ org.jacoco jacoco-maven-plugin + + + ru/practicum/shareit/ShareItApp.class + ru/practicum/shareit/**/dto/*.* + ru/practicum/shareit/**/*Mapper.class + ru/practicum/shareit/exceptions/*.class + ru/practicum/shareit/**/storage/*.class + ru/practicum/shareit/tool/*.class + + diff --git a/server/src/main/java/ru/practicum/shareit/booking/Booking.java b/server/src/main/java/ru/practicum/shareit/booking/Booking.java deleted file mode 100644 index 2d9c666..0000000 --- a/server/src/main/java/ru/practicum/shareit/booking/Booking.java +++ /dev/null @@ -1,7 +0,0 @@ -package ru.practicum.shareit.booking; - -/** - * TODO Sprint add-bookings. - */ -public class Booking { -} diff --git a/server/src/main/java/ru/practicum/shareit/booking/BookingController.java b/server/src/main/java/ru/practicum/shareit/booking/BookingController.java index 7c7879a..39e50bf 100644 --- a/server/src/main/java/ru/practicum/shareit/booking/BookingController.java +++ b/server/src/main/java/ru/practicum/shareit/booking/BookingController.java @@ -17,19 +17,19 @@ public class BookingController { public BookingDto getBooking( @PathVariable long id, @RequestHeader("X-Sharer-User-Id") long userId) { - return bookingService.getBooking(id, userId); + return bookingService.findBooking(id, userId); } @GetMapping public List getBookingForUserId( @RequestHeader("X-Sharer-User-Id") long userId) { - return bookingService.getBookingForUserId(userId); + return bookingService.findBookingsForUserId(userId); } @GetMapping("/owner") public List getBookingForItemOwnerId( @RequestHeader("X-Sharer-User-Id") long ownerId) { - return bookingService.getBookingsForItemOwnerId(ownerId); + return bookingService.findBookingsForItemOwnerId(ownerId); } @PostMapping diff --git a/server/src/main/java/ru/practicum/shareit/booking/BookingService.java b/server/src/main/java/ru/practicum/shareit/booking/BookingService.java index 6f9b1c5..17cdea3 100644 --- a/server/src/main/java/ru/practicum/shareit/booking/BookingService.java +++ b/server/src/main/java/ru/practicum/shareit/booking/BookingService.java @@ -3,7 +3,6 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import ru.practicum.shareit.booking.dto.BookingDto; -import ru.practicum.shareit.booking.dto.BookingStatusRequestDto; import ru.practicum.shareit.booking.storage.BookingEntity; import ru.practicum.shareit.exceptions.NotFoundException; import ru.practicum.shareit.exceptions.NotValidException; @@ -22,71 +21,41 @@ public class BookingService { private final UserStorage userStorage; private final BookingStorage bookingStorage; - public BookingDto getBooking(long bookingId, long userId) { + public BookingDto findBooking(long bookingId, long userId) { var userEntity = userStorage.getUser(userId) .orElseThrow(() -> new NotFoundException("Пользователь не найден")); - var bookingEntity = bookingStorage.getBooking(bookingId) + var bookingEntity = bookingStorage.findBooking(bookingId) .orElseThrow(() -> new NotFoundException("Бронь не найдена")); if (!bookingStorage.userIdIsBookerOrOwner(bookingEntity, userId)) { throw new NotValidException("Данные о бронировании может получить заказчик или владелец"); } - return BookingMapper.toDto( - bookingEntity, - UserMapper.toDto(userEntity), - ItemMapper.toDto(bookingEntity.getItem())); + return bookingEntity.toDto(); } - public List getBookingForUserId(long userId) { - return getBookingForUserId(BookingStatusRequestDto.ALL, userId); - } + public List findBookingsForUserId(long userId) { + if (userStorage.getUser(userId).isEmpty()) + throw new NotFoundException("Пользователь не найден"); - public List getBookingForUserId(BookingStatusRequestDto state, long userId) { - var userEntity = userStorage.getUser(userId) - .orElseThrow(() -> new NotFoundException("Пользователь не найден")); + var entities = bookingStorage.findBookingsByBookerId(userId); - List bookingEntities = switch (state) { - case ALL, CURRENT, PAST, FUTURE -> bookingStorage.findBookingsByBookerId(userId); - case WAITING -> bookingStorage.findBookingsByBookerId(userId, BookingStatus.WAITING); - case REJECTED -> bookingStorage.findBookingsByBookerId(userId, BookingStatus.REJECTED); - case APPROVED -> bookingStorage.findBookingsByBookerId(userId, BookingStatus.APPROVED); - default -> List.of(); - }; - - return bookingEntities + return entities .stream() - .map(i -> BookingMapper.toDto( - i, - UserMapper.toDto(userEntity), - ItemMapper.toDto(i.getItem()))) + .map(BookingEntity::toDto) .toList(); } - public List getBookingsForItemOwnerId(long userId) { - return getBookingsForItemOwnerId(BookingStatusRequestDto.ALL, userId); - } - - public List getBookingsForItemOwnerId(BookingStatusRequestDto state, long ownerId) { - if (!userStorage.existsById(ownerId)) { - throw new NotFoundException("Пользователь не найден"); - } + public List findBookingsForItemOwnerId(long userId) { + if (userStorage.getUser(userId).isEmpty()) + throw new NotFoundException("Пользователь не найден"); - List bookingEntities = switch (state) { - case ALL, CURRENT, PAST, FUTURE -> bookingStorage.findBookingsByOwnerId(ownerId); - case WAITING -> bookingStorage.findBookingsByOwnerId(ownerId, BookingStatus.WAITING); - case REJECTED -> bookingStorage.findBookingsByOwnerId(ownerId, BookingStatus.REJECTED); - case APPROVED -> bookingStorage.findBookingsByOwnerId(ownerId, BookingStatus.APPROVED); - default -> List.of(); - }; + var entities = bookingStorage.findBookingsByOwnerId(userId); - return bookingEntities + return entities .stream() - .map(i -> BookingMapper.toDto( - i, - UserMapper.toDto(i.getBooker()), - ItemMapper.toDto(i.getItem()))) + .map(BookingEntity::toDto) .toList(); } @@ -106,10 +75,7 @@ public BookingDto createBooking(BookingDto bookingDto, long userId) { bookingStorage.updateBooking(bookingEntity); - return BookingMapper.toDto( - bookingEntity, - UserMapper.toDto(userEntity), - ItemMapper.toDto(itemEntity)); + return bookingEntity.toDto(); } catch (ParseException e) { throw new NotValidException("Произошла ошибка чтения данных"); } @@ -120,7 +86,7 @@ public BookingDto setBookingStatus(long id, boolean approved, long userId) { throw new NotValidException("Пользователь не найден"); } - var bookingEntity = bookingStorage.getBooking(id) + var bookingEntity = bookingStorage.findBooking(id) .orElseThrow(() -> new NotFoundException("Бронь не найдена")); var itemEntity = bookingEntity.getItem(); diff --git a/server/src/main/java/ru/practicum/shareit/booking/BookingStorage.java b/server/src/main/java/ru/practicum/shareit/booking/BookingStorage.java index 621fd56..4e88a49 100644 --- a/server/src/main/java/ru/practicum/shareit/booking/BookingStorage.java +++ b/server/src/main/java/ru/practicum/shareit/booking/BookingStorage.java @@ -6,7 +6,7 @@ import java.util.Optional; public interface BookingStorage { - Optional getBooking(long bookingId); + Optional findBooking(long bookingId); boolean userIdIsBookerOrOwner(BookingEntity bookingEntity, long userId); diff --git a/server/src/main/java/ru/practicum/shareit/booking/Status.java b/server/src/main/java/ru/practicum/shareit/booking/Status.java deleted file mode 100644 index c91c225..0000000 --- a/server/src/main/java/ru/practicum/shareit/booking/Status.java +++ /dev/null @@ -1,6 +0,0 @@ -package ru.practicum.shareit.booking; - -public enum Status { - Request, - Accept -} diff --git a/server/src/main/java/ru/practicum/shareit/booking/storage/BookingEntity.java b/server/src/main/java/ru/practicum/shareit/booking/storage/BookingEntity.java index 97fc183..f454e7b 100644 --- a/server/src/main/java/ru/practicum/shareit/booking/storage/BookingEntity.java +++ b/server/src/main/java/ru/practicum/shareit/booking/storage/BookingEntity.java @@ -2,8 +2,12 @@ import jakarta.persistence.*; import lombok.Data; +import ru.practicum.shareit.booking.BookingMapper; import ru.practicum.shareit.booking.BookingStatus; +import ru.practicum.shareit.booking.dto.BookingDto; +import ru.practicum.shareit.item.ItemMapper; import ru.practicum.shareit.item.storage.ItemEntity; +import ru.practicum.shareit.user.UserMapper; import ru.practicum.shareit.user.storage.UserEntity; import java.sql.Timestamp; @@ -42,4 +46,11 @@ public BookingEntity() { public String toString() { return String.format("id=%d,booker=%d,item=%d,status=%s,start=%s,end=%s", id, booker.getId(), item.getId(), status, start.toString(), end.toString()); } + + public BookingDto toDto() { + return BookingMapper.toDto( + this, + UserMapper.toDto(getBooker()), + ItemMapper.toDto(getItem())); + } } diff --git a/server/src/main/java/ru/practicum/shareit/booking/storage/BookingStorageInDb.java b/server/src/main/java/ru/practicum/shareit/booking/storage/BookingStorageInDb.java index 8d70bbd..5d8f770 100644 --- a/server/src/main/java/ru/practicum/shareit/booking/storage/BookingStorageInDb.java +++ b/server/src/main/java/ru/practicum/shareit/booking/storage/BookingStorageInDb.java @@ -20,7 +20,7 @@ public class BookingStorageInDb implements BookingStorage { private final BookingRepository bookingRepository; @Override - public Optional getBooking(long bookingId) { + public Optional findBooking(long bookingId) { return bookingRepository.findById(bookingId); } diff --git a/server/src/main/java/ru/practicum/shareit/tool/IgnoreJacocoGenerated.java b/server/src/main/java/ru/practicum/shareit/tool/IgnoreJacocoGenerated.java new file mode 100644 index 0000000..4e52be2 --- /dev/null +++ b/server/src/main/java/ru/practicum/shareit/tool/IgnoreJacocoGenerated.java @@ -0,0 +1,9 @@ +package ru.practicum.shareit.tool; + +import java.lang.annotation.*; + +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD}) +public @interface IgnoreJacocoGenerated { +} diff --git a/server/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java b/server/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java index 9aa62f4..5aae708 100644 --- a/server/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java +++ b/server/src/test/java/ru/practicum/shareit/booking/BookingControllerTest.java @@ -10,9 +10,6 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import ru.practicum.shareit.booking.BookingController; -import ru.practicum.shareit.booking.BookingService; -import ru.practicum.shareit.booking.BookingStatus; import ru.practicum.shareit.booking.dto.BookingDto; import java.nio.charset.StandardCharsets; @@ -70,7 +67,7 @@ public void getBookingTest() throws Exception { .id(10L) .build(); - Mockito.when(bookingService.getBooking(Mockito.anyLong(), Mockito.anyLong())) + Mockito.when(bookingService.findBooking(Mockito.anyLong(), Mockito.anyLong())) .thenReturn(dto); mockMvc.perform(get("/bookings/1") @@ -90,7 +87,7 @@ void getItemParsingRequestId() throws Exception { .andExpect(status().isOk()); Mockito.verify(bookingService, Mockito.times(1)) - .getBooking(100, 10); + .findBooking(100, 10); } @Test @@ -104,7 +101,7 @@ void getItemsForUserIdTest() throws Exception { BookingDto.builder().id(2L).build(), BookingDto.builder().id(3L).build()); - Mockito.when(bookingService.getBookingForUserId(Mockito.anyLong())) + Mockito.when(bookingService.findBookingsForUserId(Mockito.anyLong())) .thenReturn(expectedResult); mockMvc.perform(get("/bookings") @@ -126,7 +123,7 @@ void getItemsForUserIdParsingRequestTest() throws Exception { .andExpect(status().isOk()); Mockito.verify(bookingService, Mockito.times(1)) - .getBookingForUserId(10); + .findBookingsForUserId(10); } @Test @@ -140,7 +137,7 @@ void getItemsForItemOwnerIdTest() throws Exception { BookingDto.builder().id(2L).build(), BookingDto.builder().id(3L).build()); - Mockito.when(bookingService.getBookingsForItemOwnerId(Mockito.anyLong())) + Mockito.when(bookingService.findBookingsForItemOwnerId(Mockito.anyLong())) .thenReturn(expectedResult); mockMvc.perform(get("/bookings/owner") @@ -162,7 +159,7 @@ void getItemsForItemOwnerIdParsingRequestTest() throws Exception { .andExpect(status().isOk()); Mockito.verify(bookingService, Mockito.times(1)) - .getBookingsForItemOwnerId(10); + .findBookingsForItemOwnerId(10); } @Test diff --git a/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java b/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java index 886e1fd..9224177 100644 --- a/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java +++ b/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java @@ -8,24 +8,22 @@ import org.mockito.MockedStatic; import org.mockito.Mockito; import org.springframework.boot.test.context.SpringBootTest; -import ru.practicum.shareit.booking.BookingMapper; -import ru.practicum.shareit.booking.BookingService; -import ru.practicum.shareit.booking.BookingStatus; -import ru.practicum.shareit.booking.BookingStorage; import ru.practicum.shareit.booking.dto.BookingDto; -import ru.practicum.shareit.booking.dto.BookingStatusRequestDto; import ru.practicum.shareit.booking.storage.BookingEntity; import ru.practicum.shareit.exceptions.NotFoundException; import ru.practicum.shareit.exceptions.NotValidException; +import ru.practicum.shareit.item.ItemMapper; import ru.practicum.shareit.item.ItemStorage; import ru.practicum.shareit.item.dto.ItemDto; import ru.practicum.shareit.item.storage.ItemEntity; +import ru.practicum.shareit.user.UserMapper; import ru.practicum.shareit.user.UserStorage; import ru.practicum.shareit.user.dto.UserDto; import ru.practicum.shareit.user.storage.UserEntity; import java.sql.Timestamp; import java.time.Instant; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @@ -44,225 +42,311 @@ public class BookingServiceTest { private final ObjectMapper objectMapper = new ObjectMapper(); @Test - public void getBookingTest() throws Exception { - var expectedBookingEntity = new BookingEntity(); - expectedBookingEntity.setId(8L); - expectedBookingEntity.setItem(new ItemEntity()); - expectedBookingEntity.setStart(Timestamp.from(Instant.now())); - expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); + public void findBookingWhileNotFoundUser() { + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.empty()); + + try { + bookingService.findBooking(10L, 10L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Пользователь не найден", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Пользователь не найден\")"); + } + @Test + public void findBookingWhileNotFoundBookingId() { Mockito.when(userStorage.getUser(Mockito.anyLong())) .thenReturn(Optional.of(new UserEntity())); - Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) - .thenReturn(Optional.of(expectedBookingEntity)); - Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) - .thenReturn(true); + Mockito.when(bookingStorage.findBooking(Mockito.anyLong())) + .thenReturn(Optional.empty()); - try (MockedStatic mapper = Mockito.mockStatic(BookingMapper.class)) { - mapper - .when(() -> BookingMapper.toDto(Mockito.any(BookingEntity.class), - Mockito.any(UserDto.class), - Mockito.any(ItemDto.class))) - .thenAnswer(a -> { - var entity = a.getArgument(0, BookingEntity.class); - return BookingDto.builder() - .id(entity.getId()) - .build(); - }); - - var bookingDto = bookingService.getBooking(1, 1); - - Assertions.assertEquals(8L, bookingDto.id()); - - mapper.verify( - () -> BookingMapper.toDto( - Mockito.any(BookingEntity.class), - Mockito.any(UserDto.class), - Mockito.any(ItemDto.class)), - Mockito.times(1)); + try { + bookingService.findBooking(10L, 10L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Бронь не найдена", ex.getMessage()); + return; } + + Assertions.fail("Expected NotFoundException(\"Бронь не найдена\")"); } @Test - public void getBookingWhileUserNotIsOwnerTest() throws Exception { - var expectedBookingEntity = new BookingEntity(); - expectedBookingEntity.setId(10L); - expectedBookingEntity.setItem(new ItemEntity()); - expectedBookingEntity.setStart(Timestamp.from(Instant.now())); - expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); - + public void findBookingWhileUserIsNotCreatorOrOwner() { Mockito.when(userStorage.getUser(Mockito.anyLong())) .thenReturn(Optional.of(new UserEntity())); - Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) - .thenReturn(Optional.of(expectedBookingEntity)); + + Mockito.when(bookingStorage.findBooking(Mockito.anyLong())) + .thenReturn(Optional.of(new BookingEntity())); + Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) .thenReturn(false); - try { - bookingService.getBooking(1,1); - - Assertions.fail(); + bookingService.findBooking(10L, 10L); } catch (NotValidException ex) { Assertions.assertEquals("Данные о бронировании может получить заказчик или владелец", ex.getMessage()); + return; } + + Assertions.fail("Expected NotValidException(\"Данные о бронировании может получить заказчик или владелец\")"); } @Test - public void getBookingWhileNotFoundUserTest() throws Exception { - var expectedBookingEntity = new BookingEntity(); - expectedBookingEntity.setId(10L); - expectedBookingEntity.setItem(new ItemEntity()); - expectedBookingEntity.setStart(Timestamp.from(Instant.now())); - expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); - + public void findBooking() { + var userEntity = new UserEntity(); userEntity.setId(1L); Mockito.when(userStorage.getUser(Mockito.anyLong())) - .thenReturn(Optional.empty()); - Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) - .thenReturn(Optional.of(expectedBookingEntity)); + .thenReturn(Optional.of(userEntity)); + + var itemEntity = new ItemEntity(); itemEntity.setId(2L); + + var bookingEntity = new BookingEntity(); + bookingEntity.setId(3L); + bookingEntity.setItem(itemEntity); + bookingEntity.setBooker(userEntity); + bookingEntity.setStart(Timestamp.from(Instant.now())); + bookingEntity.setEnd(Timestamp.from(Instant.now())); + + Mockito.when(bookingStorage.findBooking(Mockito.anyLong())) + .thenReturn(Optional.of(bookingEntity)); + Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) .thenReturn(true); + var expectedBookingDto = bookingEntity.toDto(); + var actualBookingDto = bookingService.findBooking(13L, 14L); - try { - bookingService.getBooking(1,1); + Assertions.assertEquals(expectedBookingDto, actualBookingDto); + + Mockito.verify(bookingStorage, Mockito.times(1)) + .findBooking(13L); + } - Assertions.fail(); + @Test + public void findBookingsForUserIdWhileNotFoundUserId() { + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.empty()); + + try { + bookingService.findBookingsForUserId(10L); } catch (NotFoundException ex) { Assertions.assertEquals("Пользователь не найден", ex.getMessage()); + return; } + + Assertions.fail("Expected NotFoundException(\"Пользователь не найден\")"); } @Test - public void getBookingWhileNotBookingTest() throws Exception { + public void findBookingsForUserId() { + var userEntity = new UserEntity(); userEntity.setId(2L); + + var itemEntity = new ItemEntity(); itemEntity.setId(3L); + + var expectedBookingEntity1 = new BookingEntity(); + expectedBookingEntity1.setId(4L); + expectedBookingEntity1.setBooker(userEntity); + expectedBookingEntity1.setItem(itemEntity); + expectedBookingEntity1.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity1.setEnd(Timestamp.from(Instant.now())); + + var expectedBookingEntity2 = new BookingEntity(); + expectedBookingEntity2.setId(5L); + expectedBookingEntity2.setBooker(userEntity); + expectedBookingEntity2.setItem(itemEntity); + expectedBookingEntity2.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity2.setEnd(Timestamp.from(Instant.now())); + + var expectedBookingEntity3 = new BookingEntity(); + expectedBookingEntity3.setId(6L); + expectedBookingEntity3.setBooker(userEntity); + expectedBookingEntity3.setItem(itemEntity); + expectedBookingEntity3.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity3.setEnd(Timestamp.from(Instant.now())); + + var bookingEntities = List.of( + expectedBookingEntity1, + expectedBookingEntity2, + expectedBookingEntity3 + ); + Mockito.when(userStorage.getUser(Mockito.anyLong())) - .thenReturn(Optional.of(new UserEntity())); - Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) - .thenReturn(Optional.empty()); - Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) - .thenReturn(true); + .thenReturn(Optional.of(userEntity)); + Mockito.when(bookingStorage.findBookingsByBookerId(Mockito.anyLong())) + .thenReturn(bookingEntities); - try { - bookingService.getBooking(1,1); + var actualBookingList = bookingService.findBookingsForUserId(4L); + var expectedBookingList = bookingEntities.stream().map(BookingEntity::toDto).toList(); + + Assertions.assertEquals(actualBookingList, expectedBookingList); + } + + @Test + public void findBookingsForOwnerIdWhileNotFoundUserId() { + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.empty()); - Assertions.fail(); + try { + bookingService.findBookingsForItemOwnerId(10L); } catch (NotFoundException ex) { - Assertions.assertEquals("Бронь не найдена", ex.getMessage()); + Assertions.assertEquals("Пользователь не найден", ex.getMessage()); + return; } + + Assertions.fail("Expected NotFoundException(\"Пользователь не найден\")"); } @Test - public void getBookingForUserIdTest() { - var expectedBookingDtoList = List.of( - BookingDto.builder().id(8L).build(), - BookingDto.builder().id(107L).build()); + public void findBookingsForOwnerId() { + var userEntity = new UserEntity(); userEntity.setId(2L); + + var itemEntity = new ItemEntity(); itemEntity.setId(3L); + + var expectedBookingEntity1 = new BookingEntity(); + expectedBookingEntity1.setId(4L); + expectedBookingEntity1.setBooker(userEntity); + expectedBookingEntity1.setItem(itemEntity); + expectedBookingEntity1.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity1.setEnd(Timestamp.from(Instant.now())); + + var expectedBookingEntity2 = new BookingEntity(); + expectedBookingEntity2.setId(5L); + expectedBookingEntity2.setBooker(userEntity); + expectedBookingEntity2.setItem(itemEntity); + expectedBookingEntity2.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity2.setEnd(Timestamp.from(Instant.now())); + + var expectedBookingEntity3 = new BookingEntity(); + expectedBookingEntity3.setId(6L); + expectedBookingEntity3.setBooker(userEntity); + expectedBookingEntity3.setItem(itemEntity); + expectedBookingEntity3.setStart(Timestamp.from(Instant.now())); + expectedBookingEntity3.setEnd(Timestamp.from(Instant.now())); + + var bookingEntities = List.of( + expectedBookingEntity1, + expectedBookingEntity2, + expectedBookingEntity3 + ); - var entity1 = new BookingEntity(); - entity1.setId(8L); - entity1.setItem(new ItemEntity()); + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.of(userEntity)); + + Mockito.when(bookingStorage.findBookingsByOwnerId(Mockito.anyLong())) + .thenReturn(bookingEntities); + + var actualBookingList = bookingService.findBookingsForItemOwnerId(6L); + var expectedBookingList = bookingEntities.stream().map(BookingEntity::toDto).toList(); - var entity2 = new BookingEntity(); - entity2.setId(107L); - entity2.setItem(new ItemEntity()); + Assertions.assertEquals(expectedBookingList, actualBookingList); + Mockito.verify(bookingStorage, Mockito.times(1)) + .findBookingsByOwnerId(6L); + } + + @Test + public void createBookingWhileNotFoundUserId() { Mockito.when(userStorage.getUser(Mockito.anyLong())) - .thenReturn(Optional.of(new UserEntity())); + .thenReturn(Optional.empty()); - Mockito.when(bookingStorage.findBookingsByBookerId(Mockito.anyLong())) - .thenReturn(List.of(entity1, entity2)); - - try (MockedStatic mapper = Mockito.mockStatic(BookingMapper.class)) { - mapper - .when(() -> BookingMapper.toDto(Mockito.any(BookingEntity.class), - Mockito.any(UserDto.class), - Mockito.any(ItemDto.class))) - .thenAnswer(a -> { - var entity = a.getArgument(0, BookingEntity.class); - return BookingDto.builder() - .id(entity.getId()) - .build(); - }); - - var bookingDtoList = bookingService.getBookingForUserId(1); - - Assertions.assertEquals(2, bookingDtoList.size()); - Assertions.assertEquals(8L, bookingDtoList.getFirst().id(), "Id dto[0] is expected 8L"); - Assertions.assertEquals(107L, bookingDtoList.get(1).id(), "Id dto[0] is expected 107L"); - - mapper.verify( - () -> BookingMapper.toDto( - Mockito.any(BookingEntity.class), - Mockito.any(UserDto.class), - Mockito.any(ItemDto.class)), - Mockito.times(2)); + try { + bookingService.createBooking(BookingDto.builder().build(), 1L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Пользователь не найден", ex.getMessage()); + return; } + + Assertions.fail("Expected NotFoundException(\"Пользователь не найден\")"); } @Test - public void getBookingForUserIdWhileNotFoundUserTest() throws Exception { - var expectedBookingEntity = new BookingEntity(); - expectedBookingEntity.setId(10L); - expectedBookingEntity.setItem(new ItemEntity()); - expectedBookingEntity.setStart(Timestamp.from(Instant.now())); - expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); - + public void createBookingWhileNotFoundItemId() { Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.of(new UserEntity())); + Mockito.when(itemStorage.getItem(Mockito.anyLong())) .thenReturn(Optional.empty()); - Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) - .thenReturn(Optional.of(expectedBookingEntity)); + var dto = BookingDto + .builder() + .itemId(10L) + .build(); try { - bookingService.getBookingForUserId(1); - - Assertions.fail(); + bookingService.createBooking(dto, 1L); } catch (NotFoundException ex) { - Assertions.assertEquals("Пользователь не найден", ex.getMessage()); + Assertions.assertEquals("Вещь не найдена", ex.getMessage()); + return; } + + Assertions.fail("Expected NotFoundException(\"Вещь не найдена\")"); } @Test - public void getBookingForUserIdWhileChangeStatusAndOwnerIdTest() throws Exception { - var expectedBookingEntity = new BookingEntity(); - expectedBookingEntity.setId(10L); - expectedBookingEntity.setItem(new ItemEntity()); - expectedBookingEntity.setStart(Timestamp.from(Instant.now())); - expectedBookingEntity.setEnd(Timestamp.from(Instant.now())); + public void createBookingWhileItemIsNotFree() { + var itemEntity = new ItemEntity(); + itemEntity.setAvailable(false); - Mockito.when(userStorage.existsById(Mockito.anyLong())) - .thenReturn(true); - Mockito.when(bookingStorage.getBooking(Mockito.anyLong())) - .thenReturn(Optional.of(expectedBookingEntity)); + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.of(new UserEntity())); + Mockito.when(itemStorage.getItem(Mockito.anyLong())) + .thenReturn(Optional.of(itemEntity)); - var statuses = List.of( - BookingStatusRequestDto.ALL, - BookingStatusRequestDto.CURRENT, - BookingStatusRequestDto.PAST, - BookingStatusRequestDto.FUTURE, - BookingStatusRequestDto.WAITING, - BookingStatusRequestDto.REJECTED, - BookingStatusRequestDto.APPROVED); + var dto = BookingDto + .builder() + .itemId(10L) + .build(); - var owners = List.of(1, 7, 19); + try { + bookingService.createBooking(dto, 1L); + } catch (NotValidException ex) { + Assertions.assertEquals("Вещь не доступна к бронированию", ex.getMessage()); + return; + } - for (var ownerId: owners) { - for (var requestStatus: statuses) { - bookingService.getBookingsForItemOwnerId(requestStatus, ownerId); - } + Assertions.fail("Expected NotValidException(\"Вещь не доступна к бронированию\")"); + } - Mockito.verify(bookingStorage, Mockito.times(4)) - .findBookingsByOwnerId(ownerId); + @Test + public void createBooking() { + var itemEntity = new ItemEntity(); + itemEntity.setAvailable(true); + itemEntity.setId(3L); + + var userEntity = new UserEntity(); + userEntity.setId(4L); + + var bookingDto = BookingDto + .builder() + .id(5L) + .itemId(10L) + .start("2024-12-03T00:00:00") + .end("2024-12-04T00:00:00") + .build(); - Mockito.verify(bookingStorage, Mockito.times(1)) - .findBookingsByOwnerId(ownerId, BookingStatus.WAITING); + var expectedBookingEntity = new BookingEntity(); + expectedBookingEntity.setId(5L); + expectedBookingEntity.setBooker(userEntity); + expectedBookingEntity.setItem(itemEntity); + expectedBookingEntity.setStart(Timestamp.valueOf(LocalDateTime.of(2024,12,03,0,0))); + expectedBookingEntity.setEnd(Timestamp.valueOf(LocalDateTime.of(2024,12,04,0,0))); + expectedBookingEntity.setStatus(BookingStatus.WAITING); - Mockito.verify(bookingStorage, Mockito.times(1)) - .findBookingsByOwnerId(ownerId, BookingStatus.REJECTED); + var expectedBookingDto = expectedBookingEntity.toDto(); - Mockito.verify(bookingStorage, Mockito.times(1)) - .findBookingsByOwnerId(ownerId, BookingStatus.APPROVED); - } + Mockito.when(userStorage.getUser(Mockito.anyLong())) + .thenReturn(Optional.of(userEntity)); + Mockito.when(itemStorage.getItem(Mockito.anyLong())) + .thenReturn(Optional.of(itemEntity)); + + var actualBooking = bookingService.createBooking(bookingDto, 7L); + + Assertions.assertEquals(expectedBookingDto, actualBooking); + + Mockito.verify(bookingStorage, Mockito.times(1)) + .updateBooking(expectedBookingEntity); } } From a91c6b4e85ae74f7367a6c00d49ac4d4ddc24f2d Mon Sep 17 00:00:00 2001 From: aKorishev Date: Tue, 3 Dec 2024 20:04:17 +0300 Subject: [PATCH 09/11] [add-item-requests-and-gateway] checkstyle --- .../ru/practicum/shareit/booking/BookingServiceTest.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java b/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java index 9224177..7673297 100644 --- a/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java +++ b/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java @@ -5,20 +5,15 @@ import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.MockedStatic; import org.mockito.Mockito; import org.springframework.boot.test.context.SpringBootTest; import ru.practicum.shareit.booking.dto.BookingDto; import ru.practicum.shareit.booking.storage.BookingEntity; import ru.practicum.shareit.exceptions.NotFoundException; import ru.practicum.shareit.exceptions.NotValidException; -import ru.practicum.shareit.item.ItemMapper; import ru.practicum.shareit.item.ItemStorage; -import ru.practicum.shareit.item.dto.ItemDto; import ru.practicum.shareit.item.storage.ItemEntity; -import ru.practicum.shareit.user.UserMapper; import ru.practicum.shareit.user.UserStorage; -import ru.practicum.shareit.user.dto.UserDto; import ru.practicum.shareit.user.storage.UserEntity; import java.sql.Timestamp; From 08a730703ca509a179d8e8a801b162b374e50656 Mon Sep 17 00:00:00 2001 From: aKorishev Date: Thu, 5 Dec 2024 20:00:21 +0300 Subject: [PATCH 10/11] =?UTF-8?q?[add-item-requests-and-gateway]=20=D0=94?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20=D1=82=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D1=8B=20=D0=B4=D0=BB=D1=8F=20server?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shareit/booking/BookingService.java | 10 +- .../shareit/item/ItemController.java | 2 +- .../ru/practicum/shareit/item/ItemMapper.java | 4 + .../practicum/shareit/item/ItemService.java | 48 +- .../practicum/shareit/item/ItemStorage.java | 2 +- .../shareit/item/storage/ItemEntity.java | 17 + .../shareit/item/storage/ItemStorageInDb.java | 2 +- .../shareit/request/RequestService.java | 20 +- .../request/storage/RequestEntity.java | 14 + .../shareit/user/UserController.java | 2 +- .../practicum/shareit/user/UserService.java | 8 +- .../practicum/shareit/user/UserStorage.java | 2 +- .../shareit/user/storage/UserStorageInDB.java | 2 +- .../shareit/booking/BookingServiceTest.java | 176 +++- .../shareit/item/ItemControllerTest.java | 4 +- .../shareit/item/ItemServiceTest.java | 769 ++++++++++++++++++ .../shareit/request/RequestServiceTest.java | 194 +++++ .../shareit/user/UserControllerTest.java | 4 +- .../shareit/user/UserServiceTest.java | 210 +++++ 19 files changed, 1412 insertions(+), 78 deletions(-) create mode 100644 server/src/test/java/ru/practicum/shareit/item/ItemServiceTest.java create mode 100644 server/src/test/java/ru/practicum/shareit/request/RequestServiceTest.java create mode 100644 server/src/test/java/ru/practicum/shareit/user/UserServiceTest.java diff --git a/server/src/main/java/ru/practicum/shareit/booking/BookingService.java b/server/src/main/java/ru/practicum/shareit/booking/BookingService.java index 17cdea3..1e0ebd8 100644 --- a/server/src/main/java/ru/practicum/shareit/booking/BookingService.java +++ b/server/src/main/java/ru/practicum/shareit/booking/BookingService.java @@ -22,7 +22,7 @@ public class BookingService { private final BookingStorage bookingStorage; public BookingDto findBooking(long bookingId, long userId) { - var userEntity = userStorage.getUser(userId) + var userEntity = userStorage.findUserId(userId) .orElseThrow(() -> new NotFoundException("Пользователь не найден")); var bookingEntity = bookingStorage.findBooking(bookingId) @@ -36,7 +36,7 @@ public BookingDto findBooking(long bookingId, long userId) { } public List findBookingsForUserId(long userId) { - if (userStorage.getUser(userId).isEmpty()) + if (userStorage.findUserId(userId).isEmpty()) throw new NotFoundException("Пользователь не найден"); var entities = bookingStorage.findBookingsByBookerId(userId); @@ -48,7 +48,7 @@ public List findBookingsForUserId(long userId) { } public List findBookingsForItemOwnerId(long userId) { - if (userStorage.getUser(userId).isEmpty()) + if (userStorage.findUserId(userId).isEmpty()) throw new NotFoundException("Пользователь не найден"); var entities = bookingStorage.findBookingsByOwnerId(userId); @@ -60,9 +60,9 @@ public List findBookingsForItemOwnerId(long userId) { } public BookingDto createBooking(BookingDto bookingDto, long userId) { - var userEntity = userStorage.getUser(userId) + var userEntity = userStorage.findUserId(userId) .orElseThrow(() -> new NotFoundException("Пользователь не найден")); - var itemEntity = itemStorage.getItem(bookingDto.itemId()) + var itemEntity = itemStorage.findItem(bookingDto.itemId()) .orElseThrow(() -> new NotFoundException("Вещь не найдена")); if (!itemEntity.isAvailable()) { diff --git a/server/src/main/java/ru/practicum/shareit/item/ItemController.java b/server/src/main/java/ru/practicum/shareit/item/ItemController.java index 1105422..35e8a73 100644 --- a/server/src/main/java/ru/practicum/shareit/item/ItemController.java +++ b/server/src/main/java/ru/practicum/shareit/item/ItemController.java @@ -23,7 +23,7 @@ public List getItems(@RequestHeader("X-Sharer-User-Id") long userId) { @GetMapping("/{id}") public ItemDto getItem(@PathVariable long id) { - return itemService.getItem(id); + return itemService.findItem(id); } @GetMapping("/search") diff --git a/server/src/main/java/ru/practicum/shareit/item/ItemMapper.java b/server/src/main/java/ru/practicum/shareit/item/ItemMapper.java index 9c4d244..01ae09b 100644 --- a/server/src/main/java/ru/practicum/shareit/item/ItemMapper.java +++ b/server/src/main/java/ru/practicum/shareit/item/ItemMapper.java @@ -50,6 +50,10 @@ public static ItemDto toDto( .available(itemEntity.isAvailable()) .comments(comments); + var request = itemEntity.getRequest(); + if (request != null) + build.requestId(request.getId()); + lastBooking.ifPresent(build::lastBooking); nextBooking.ifPresent(build::nextBooking); diff --git a/server/src/main/java/ru/practicum/shareit/item/ItemService.java b/server/src/main/java/ru/practicum/shareit/item/ItemService.java index f094afb..462d797 100644 --- a/server/src/main/java/ru/practicum/shareit/item/ItemService.java +++ b/server/src/main/java/ru/practicum/shareit/item/ItemService.java @@ -10,7 +10,6 @@ import ru.practicum.shareit.item.dto.ItemDto; import ru.practicum.shareit.item.dto.ItemToUpdateDto; import ru.practicum.shareit.request.RequestStorage; -import ru.practicum.shareit.request.storage.RequestEntity; import ru.practicum.shareit.user.UserStorage; import java.sql.Timestamp; @@ -26,27 +25,21 @@ public class ItemService { private final BookingStorage bookingStorage; private final RequestStorage requestStorage; - public ItemDto getItem(long itemId) { - var itemEntity = itemStorage.getItem(itemId) + public ItemDto findItem(long itemId) { + var itemEntity = itemStorage.findItem(itemId) .orElseThrow(() -> new NotFoundException("Вещь не найдена")); - var comments = itemEntity.getComments() - .stream() - .map(CommentMapper::toDto) - .toList(); - - return ItemMapper.toDto(itemEntity, comments); + return itemEntity.toDto(); } public ItemDto createItem(ItemDto item, long userId) { - var userEntity = userStorage.getUser(userId) + var userEntity = userStorage.findUserId(userId) .orElseThrow(() -> new NotFoundException("Пользователь не найден")); - RequestEntity requestEntity = null; - - if (item.requestId() != null) - requestEntity = requestStorage.findRequestById(item.requestId()) - .orElseThrow(() -> new NotFoundException("Запрос не найден")); + var requestEntity = item.requestId() != null + ? requestStorage.findRequestById(item.requestId()) + .orElseThrow(() -> new NotFoundException("Запрос не найден")) + : null; var itemEntity = ItemMapper.toEntity(item, userEntity, requestEntity); @@ -56,7 +49,7 @@ public ItemDto createItem(ItemDto item, long userId) { } public ItemDto updateItem(ItemDto item, long userId) { - var itemEntityOld = itemStorage.getItem(item.id()) + var itemEntityOld = itemStorage.findItem(item.id()) .orElseThrow(() -> new NotFoundException("Вещь не найдена")); var owner = itemEntityOld.getOwner(); @@ -65,11 +58,10 @@ public ItemDto updateItem(ItemDto item, long userId) { throw new NotFoundException("Владелец не найден"); } - RequestEntity requestEntity = null; - - if (item.requestId() != null) - requestEntity = requestStorage.findRequestById(item.requestId()) - .orElseThrow(() -> new NotFoundException("Запрос не найден")); + var requestEntity = item.requestId() != null + ? requestStorage.findRequestById(item.requestId()) + .orElseThrow(() -> new NotFoundException("Запрос не найден")) + : null; var itemEntity = ItemMapper.toEntity(item, owner, requestEntity); @@ -79,7 +71,7 @@ public ItemDto updateItem(ItemDto item, long userId) { } public ItemDto updateItem(long itemId, ItemToUpdateDto item, long userId) { - var itemEntity = itemStorage.getItem(itemId) + var itemEntity = itemStorage.findItem(itemId) .orElseThrow(() -> new NotFoundException("Вещь не найдена")); var owner = itemEntity.getOwner(); @@ -101,7 +93,7 @@ public ItemDto updateItem(long itemId, ItemToUpdateDto item, long userId) { } public ItemDto deleteItem(long itemId, long userId) { - var itemEntityOld = itemStorage.getItem(itemId) + var itemEntityOld = itemStorage.findItem(itemId) .orElseThrow(() -> new NotFoundException("Вещь не найдена")); var owner = itemEntityOld.getOwner(); @@ -116,7 +108,7 @@ public ItemDto deleteItem(long itemId, long userId) { } public List getItems(long userId) { - var userEntity = userStorage.getUser(userId) + var userEntity = userStorage.findUserId(userId) .orElseThrow(() -> new NotFoundException("Пользователь не найден")); var itemEntities = userEntity.getItems(); @@ -140,15 +132,15 @@ public List findFreeItemsByText(String text, boolean available) { } public CommentDto addComment(CommentDto commentDto, long itemId, long userId) { - log.trace(String.format("addComment: itemId = %d, userId = %d", itemId, userId)); + //log.trace(String.format("addComment: itemId = %d, userId = %d", itemId, userId)); - var userEntity = userStorage.getUser(userId) + var userEntity = userStorage.findUserId(userId) .orElseThrow(() -> new NotFoundException("Пользователь не найден")); - var itemEntity = itemStorage.getItem(itemId) + var itemEntity = itemStorage.findItem(itemId) .orElseThrow(() -> new NotFoundException("Вешь не найдена")); - log.trace(String.format("addComment: itemEntity = {%s}", itemEntity)); + //log.trace(String.format("addComment: itemEntity = {%s}", itemEntity)); if (!bookingStorage.existsByBookerIdAndItemIdAndAfterEnd(userId, itemId)) { throw new NotValidException("Пользователь не брал вещь, не может оставить комментарий"); diff --git a/server/src/main/java/ru/practicum/shareit/item/ItemStorage.java b/server/src/main/java/ru/practicum/shareit/item/ItemStorage.java index 25c0db6..5083479 100644 --- a/server/src/main/java/ru/practicum/shareit/item/ItemStorage.java +++ b/server/src/main/java/ru/practicum/shareit/item/ItemStorage.java @@ -7,7 +7,7 @@ import java.util.Optional; public interface ItemStorage { - Optional getItem(long itemId); + Optional findItem(long itemId); void updateItem(ItemEntity itemEntity); diff --git a/server/src/main/java/ru/practicum/shareit/item/storage/ItemEntity.java b/server/src/main/java/ru/practicum/shareit/item/storage/ItemEntity.java index d466979..0bbd06a 100644 --- a/server/src/main/java/ru/practicum/shareit/item/storage/ItemEntity.java +++ b/server/src/main/java/ru/practicum/shareit/item/storage/ItemEntity.java @@ -2,6 +2,9 @@ import jakarta.persistence.*; import lombok.Data; +import ru.practicum.shareit.item.CommentMapper; +import ru.practicum.shareit.item.ItemMapper; +import ru.practicum.shareit.item.dto.ItemDto; import ru.practicum.shareit.request.storage.RequestEntity; import ru.practicum.shareit.user.storage.UserEntity; @@ -42,4 +45,18 @@ public ItemEntity() { public String toString() { return String.format("id=%d,owner=%d,name=%s,desc=%s,available=%b", id, owner.getId(), name, description, available); } + + public ItemDto toDto() { + var comments = getComments(); + + if (comments == null) + return ItemMapper.toDto(this, List.of()); + + var commentDtos = comments + .stream() + .map(CommentMapper::toDto) + .toList(); + + return ItemMapper.toDto(this, commentDtos); + } } diff --git a/server/src/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java b/server/src/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java index cabd26c..aabd98c 100644 --- a/server/src/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java +++ b/server/src/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java @@ -26,7 +26,7 @@ public class ItemStorageInDb implements ItemStorage { private final CommentMapper commentMapper = new CommentMapper(); @Override - public Optional getItem(long itemId) { + public Optional findItem(long itemId) { return itemRepository.findById(itemId); } diff --git a/server/src/main/java/ru/practicum/shareit/request/RequestService.java b/server/src/main/java/ru/practicum/shareit/request/RequestService.java index 7416a85..adc8f3c 100644 --- a/server/src/main/java/ru/practicum/shareit/request/RequestService.java +++ b/server/src/main/java/ru/practicum/shareit/request/RequestService.java @@ -4,7 +4,6 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import ru.practicum.shareit.exceptions.NotFoundException; -import ru.practicum.shareit.item.ItemMapper; import ru.practicum.shareit.request.dto.RequestDto; import ru.practicum.shareit.request.storage.RequestEntity; import ru.practicum.shareit.user.UserStorage; @@ -12,7 +11,6 @@ import java.sql.Timestamp; import java.time.LocalDateTime; import java.util.List; -import java.util.Optional; @Service @RequiredArgsConstructor @@ -21,7 +19,7 @@ public class RequestService { private final UserStorage userStorage; public RequestDto createRequest(@Valid RequestDto requestDto, long userId) { - var userEntity = userStorage.getUser(userId) + var userEntity = userStorage.findUserId(userId) .orElseThrow(() -> new NotFoundException("Пользователь не найден")); var requestEntity = RequestMapper.toEntity(requestDto, userEntity); @@ -29,7 +27,7 @@ public RequestDto createRequest(@Valid RequestDto requestDto, long userId) { requestStorage.updateRequest(requestEntity); - return mapToDto(requestEntity); + return requestEntity.toDto(); } public List getRequestsByUserId(long userId, boolean findByUserId) { @@ -38,7 +36,7 @@ public List getRequestsByUserId(long userId, boolean findByUserId) { return requestStorage.getRequestsByUserId(userId, findByUserId) .stream() - .map(this::mapToDto) + .map(RequestEntity::toDto) .toList(); } @@ -46,16 +44,6 @@ public RequestDto getRequestById(long id) { var requestEntity = requestStorage.findRequestById(id) .orElseThrow(() -> new NotFoundException("Запрос не найден")); - return mapToDto(requestEntity); - } - - private RequestDto mapToDto(RequestEntity requestEntity) { - var items = Optional.ofNullable(requestEntity.getItems()) - .orElse(List.of()) - .stream() - .map(ItemMapper::toDto) - .toList(); - - return RequestMapper.toDto(requestEntity, items); + return requestEntity.toDto(); } } diff --git a/server/src/main/java/ru/practicum/shareit/request/storage/RequestEntity.java b/server/src/main/java/ru/practicum/shareit/request/storage/RequestEntity.java index 9558642..5bdf255 100644 --- a/server/src/main/java/ru/practicum/shareit/request/storage/RequestEntity.java +++ b/server/src/main/java/ru/practicum/shareit/request/storage/RequestEntity.java @@ -2,11 +2,15 @@ import jakarta.persistence.*; import lombok.Data; +import ru.practicum.shareit.item.ItemMapper; import ru.practicum.shareit.item.storage.ItemEntity; +import ru.practicum.shareit.request.RequestMapper; +import ru.practicum.shareit.request.dto.RequestDto; import ru.practicum.shareit.user.storage.UserEntity; import java.sql.Timestamp; import java.util.List; +import java.util.Optional; @Entity @Table(name = "Requests") @@ -34,4 +38,14 @@ public class RequestEntity { public RequestEntity() { } + + public RequestDto toDto() { + var items = Optional.ofNullable(getItems()) + .orElse(List.of()) + .stream() + .map(ItemMapper::toDto) + .toList(); + + return RequestMapper.toDto(this, items); + } } diff --git a/server/src/main/java/ru/practicum/shareit/user/UserController.java b/server/src/main/java/ru/practicum/shareit/user/UserController.java index c1da386..cd98382 100644 --- a/server/src/main/java/ru/practicum/shareit/user/UserController.java +++ b/server/src/main/java/ru/practicum/shareit/user/UserController.java @@ -15,7 +15,7 @@ public class UserController { @GetMapping("/{id}") public UserDto getUser(@PathVariable long id) { - return userService.getUser(id); + return userService.findUserId(id); } @PostMapping diff --git a/server/src/main/java/ru/practicum/shareit/user/UserService.java b/server/src/main/java/ru/practicum/shareit/user/UserService.java index 159e9a1..6ba2042 100644 --- a/server/src/main/java/ru/practicum/shareit/user/UserService.java +++ b/server/src/main/java/ru/practicum/shareit/user/UserService.java @@ -11,8 +11,8 @@ public class UserService { private final UserStorage userStorage; - public UserDto getUser(long userId) { - var userEntity = userStorage.getUser(userId) + public UserDto findUserId(long userId) { + var userEntity = userStorage.findUserId(userId) .orElseThrow(() -> new NotFoundException("Не нашел userId в системе")); return UserMapper.toDto(userEntity); @@ -27,7 +27,7 @@ public UserDto updateUser(UserDto user) { } public UserDto updateUser(long userId, UserToUpdateDto user) { - var userEntity = userStorage.getUser(userId) + var userEntity = userStorage.findUserId(userId) .orElseThrow(() -> new NotFoundException("Не нашел userId в системе")); if (user.name() != null) @@ -41,7 +41,7 @@ public UserDto updateUser(long userId, UserToUpdateDto user) { } public UserDto deleteUser(long userId) { - var userEntity = userStorage.getUser(userId) + var userEntity = userStorage.findUserId(userId) .orElseThrow(() -> new NotFoundException("Не нашел userId в системе")); userStorage.deleteUser(userEntity); diff --git a/server/src/main/java/ru/practicum/shareit/user/UserStorage.java b/server/src/main/java/ru/practicum/shareit/user/UserStorage.java index 151ed33..7e9922f 100644 --- a/server/src/main/java/ru/practicum/shareit/user/UserStorage.java +++ b/server/src/main/java/ru/practicum/shareit/user/UserStorage.java @@ -5,7 +5,7 @@ import java.util.Optional; public interface UserStorage { - Optional getUser(long userId); + Optional findUserId(long userId); void updateUser(UserEntity user); diff --git a/server/src/main/java/ru/practicum/shareit/user/storage/UserStorageInDB.java b/server/src/main/java/ru/practicum/shareit/user/storage/UserStorageInDB.java index f5e48ab..01d0e73 100644 --- a/server/src/main/java/ru/practicum/shareit/user/storage/UserStorageInDB.java +++ b/server/src/main/java/ru/practicum/shareit/user/storage/UserStorageInDB.java @@ -18,7 +18,7 @@ public class UserStorageInDB implements UserStorage { private final UserMapper userMapper = new UserMapper(); @Override - public Optional getUser(long userId) { + public Optional findUserId(long userId) { return userRepository.findById(userId); } diff --git a/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java b/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java index 7673297..c2edae8 100644 --- a/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java +++ b/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java @@ -38,7 +38,7 @@ public class BookingServiceTest { @Test public void findBookingWhileNotFoundUser() { - Mockito.when(userStorage.getUser(Mockito.anyLong())) + Mockito.when(userStorage.findUserId(Mockito.anyLong())) .thenReturn(Optional.empty()); try { @@ -53,7 +53,7 @@ public void findBookingWhileNotFoundUser() { @Test public void findBookingWhileNotFoundBookingId() { - Mockito.when(userStorage.getUser(Mockito.anyLong())) + Mockito.when(userStorage.findUserId(Mockito.anyLong())) .thenReturn(Optional.of(new UserEntity())); Mockito.when(bookingStorage.findBooking(Mockito.anyLong())) @@ -71,7 +71,7 @@ public void findBookingWhileNotFoundBookingId() { @Test public void findBookingWhileUserIsNotCreatorOrOwner() { - Mockito.when(userStorage.getUser(Mockito.anyLong())) + Mockito.when(userStorage.findUserId(Mockito.anyLong())) .thenReturn(Optional.of(new UserEntity())); Mockito.when(bookingStorage.findBooking(Mockito.anyLong())) @@ -93,7 +93,7 @@ public void findBookingWhileUserIsNotCreatorOrOwner() { @Test public void findBooking() { var userEntity = new UserEntity(); userEntity.setId(1L); - Mockito.when(userStorage.getUser(Mockito.anyLong())) + Mockito.when(userStorage.findUserId(Mockito.anyLong())) .thenReturn(Optional.of(userEntity)); var itemEntity = new ItemEntity(); itemEntity.setId(2L); @@ -122,7 +122,7 @@ public void findBooking() { @Test public void findBookingsForUserIdWhileNotFoundUserId() { - Mockito.when(userStorage.getUser(Mockito.anyLong())) + Mockito.when(userStorage.findUserId(Mockito.anyLong())) .thenReturn(Optional.empty()); try { @@ -168,7 +168,7 @@ public void findBookingsForUserId() { expectedBookingEntity3 ); - Mockito.when(userStorage.getUser(Mockito.anyLong())) + Mockito.when(userStorage.findUserId(Mockito.anyLong())) .thenReturn(Optional.of(userEntity)); Mockito.when(bookingStorage.findBookingsByBookerId(Mockito.anyLong())) @@ -182,7 +182,7 @@ public void findBookingsForUserId() { @Test public void findBookingsForOwnerIdWhileNotFoundUserId() { - Mockito.when(userStorage.getUser(Mockito.anyLong())) + Mockito.when(userStorage.findUserId(Mockito.anyLong())) .thenReturn(Optional.empty()); try { @@ -228,7 +228,7 @@ public void findBookingsForOwnerId() { expectedBookingEntity3 ); - Mockito.when(userStorage.getUser(Mockito.anyLong())) + Mockito.when(userStorage.findUserId(Mockito.anyLong())) .thenReturn(Optional.of(userEntity)); Mockito.when(bookingStorage.findBookingsByOwnerId(Mockito.anyLong())) @@ -245,7 +245,7 @@ public void findBookingsForOwnerId() { @Test public void createBookingWhileNotFoundUserId() { - Mockito.when(userStorage.getUser(Mockito.anyLong())) + Mockito.when(userStorage.findUserId(Mockito.anyLong())) .thenReturn(Optional.empty()); try { @@ -260,9 +260,9 @@ public void createBookingWhileNotFoundUserId() { @Test public void createBookingWhileNotFoundItemId() { - Mockito.when(userStorage.getUser(Mockito.anyLong())) + Mockito.when(userStorage.findUserId(Mockito.anyLong())) .thenReturn(Optional.of(new UserEntity())); - Mockito.when(itemStorage.getItem(Mockito.anyLong())) + Mockito.when(itemStorage.findItem(Mockito.anyLong())) .thenReturn(Optional.empty()); var dto = BookingDto @@ -285,9 +285,9 @@ public void createBookingWhileItemIsNotFree() { var itemEntity = new ItemEntity(); itemEntity.setAvailable(false); - Mockito.when(userStorage.getUser(Mockito.anyLong())) + Mockito.when(userStorage.findUserId(Mockito.anyLong())) .thenReturn(Optional.of(new UserEntity())); - Mockito.when(itemStorage.getItem(Mockito.anyLong())) + Mockito.when(itemStorage.findItem(Mockito.anyLong())) .thenReturn(Optional.of(itemEntity)); var dto = BookingDto @@ -332,9 +332,9 @@ public void createBooking() { var expectedBookingDto = expectedBookingEntity.toDto(); - Mockito.when(userStorage.getUser(Mockito.anyLong())) + Mockito.when(userStorage.findUserId(Mockito.anyLong())) .thenReturn(Optional.of(userEntity)); - Mockito.when(itemStorage.getItem(Mockito.anyLong())) + Mockito.when(itemStorage.findItem(Mockito.anyLong())) .thenReturn(Optional.of(itemEntity)); var actualBooking = bookingService.createBooking(bookingDto, 7L); @@ -344,4 +344,150 @@ public void createBooking() { Mockito.verify(bookingStorage, Mockito.times(1)) .updateBooking(expectedBookingEntity); } + + @Test + public void setBookingStatusWhileNotFoundUserId() { + Mockito.when(userStorage.existsById(Mockito.anyLong())) + .thenReturn(false); + + try { + bookingService.setBookingStatus(1L, true, 1L); + } catch (NotValidException ex) { + Assertions.assertEquals("Пользователь не найден", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotValidException(\"Пользователь не найден\")"); + } + + @Test + public void setBookingStatusWhileNotFoundBookingId() { + Mockito.when(userStorage.existsById(Mockito.anyLong())) + .thenReturn(true); + Mockito.when(bookingStorage.findBooking(Mockito.anyLong())) + .thenReturn(Optional.empty()); + + try { + bookingService.setBookingStatus(1L, true, 1L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Бронь не найдена", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Бронь не найдена\"\")"); + } + + @Test + public void setBookingStatusWhileUserIdIsNotOwner() { + var ownerEntity = new UserEntity(); + ownerEntity.setId(4L); + + var bookerEntity = new UserEntity(); + bookerEntity.setId(7L); + + var itemEntity = new ItemEntity(); + itemEntity.setAvailable(true); + itemEntity.setId(3L); + itemEntity.setOwner(ownerEntity); + + var bookingEntity = new BookingEntity(); + bookingEntity.setId(5L); + bookingEntity.setBooker(bookerEntity); + bookingEntity.setItem(itemEntity); + bookingEntity.setStart(Timestamp.valueOf(LocalDateTime.of(2024,12,03,0,0))); + bookingEntity.setEnd(Timestamp.valueOf(LocalDateTime.of(2024,12,04,0,0))); + bookingEntity.setStatus(BookingStatus.WAITING); + + Mockito.when(userStorage.existsById(Mockito.anyLong())) + .thenReturn(true); + Mockito.when(bookingStorage.findBooking(Mockito.anyLong())) + .thenReturn(Optional.of(bookingEntity)); + + try { + bookingService.setBookingStatus(1L, true, 1L); + } catch (NotValidException ex) { + Assertions.assertEquals("Подтвердить бронь может только владелец", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotValidException(\"Подтвердить бронь может только владелец\")"); + } + + @Test + public void setBookingStatusApprovedTest() { + var ownerEntity = new UserEntity(); + ownerEntity.setId(4L); + + var bookerEntity = new UserEntity(); + bookerEntity.setId(7L); + + var itemEntity = new ItemEntity(); + itemEntity.setAvailable(true); + itemEntity.setId(3L); + itemEntity.setOwner(ownerEntity); + + var bookingEntity = new BookingEntity(); + bookingEntity.setId(5L); + bookingEntity.setBooker(bookerEntity); + bookingEntity.setItem(itemEntity); + bookingEntity.setStart(Timestamp.valueOf(LocalDateTime.of(2024,12,03,0,0))); + bookingEntity.setEnd(Timestamp.valueOf(LocalDateTime.of(2024,12,04,0,0))); + bookingEntity.setStatus(BookingStatus.WAITING); + + Mockito.when(userStorage.existsById(Mockito.anyLong())) + .thenReturn(true); + Mockito.when(bookingStorage.findBooking(Mockito.anyLong())) + .thenReturn(Optional.of(bookingEntity)); + + var expectedBookingDto = bookingEntity.toDto() + .toBuilder() + .status(BookingStatus.APPROVED) + .build(); + + var actualBooking = bookingService.setBookingStatus(1L, true, 4L); + + Assertions.assertEquals(expectedBookingDto, actualBooking); + + Mockito.verify(bookingStorage, Mockito.times(1)) + .updateBooking(bookingEntity); + } + + @Test + public void setBookingStatusRejectTest() { + var ownerEntity = new UserEntity(); + ownerEntity.setId(4L); + + var bookerEntity = new UserEntity(); + bookerEntity.setId(7L); + + var itemEntity = new ItemEntity(); + itemEntity.setAvailable(true); + itemEntity.setId(3L); + itemEntity.setOwner(ownerEntity); + + var bookingEntity = new BookingEntity(); + bookingEntity.setId(5L); + bookingEntity.setBooker(bookerEntity); + bookingEntity.setItem(itemEntity); + bookingEntity.setStart(Timestamp.valueOf(LocalDateTime.of(2024,12,03,0,0))); + bookingEntity.setEnd(Timestamp.valueOf(LocalDateTime.of(2024,12,04,0,0))); + bookingEntity.setStatus(BookingStatus.WAITING); + + Mockito.when(userStorage.existsById(Mockito.anyLong())) + .thenReturn(true); + Mockito.when(bookingStorage.findBooking(Mockito.anyLong())) + .thenReturn(Optional.of(bookingEntity)); + + var expectedBookingDto = bookingEntity.toDto() + .toBuilder() + .status(BookingStatus.REJECTED) + .build(); + + var actualBooking = bookingService.setBookingStatus(1L, false, 4L); + + Assertions.assertEquals(expectedBookingDto, actualBooking); + + Mockito.verify(bookingStorage, Mockito.times(1)) + .updateBooking(bookingEntity); + } } diff --git a/server/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java b/server/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java index c7a3e26..6280811 100644 --- a/server/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java +++ b/server/src/test/java/ru/practicum/shareit/item/ItemControllerTest.java @@ -69,7 +69,7 @@ public void getItemTest() throws Exception { .id(10L) .build(); - Mockito.when(itemService.getItem(Mockito.anyLong())) + Mockito.when(itemService.findItem(Mockito.anyLong())) .thenReturn(dto); mockMvc.perform(get("/items/1")) @@ -87,7 +87,7 @@ void getItemParsingRequestId() throws Exception { .andExpect(status().isOk()); Mockito.verify(itemService, Mockito.times(1)) - .getItem(100); + .findItem(100); } @Test diff --git a/server/src/test/java/ru/practicum/shareit/item/ItemServiceTest.java b/server/src/test/java/ru/practicum/shareit/item/ItemServiceTest.java new file mode 100644 index 0000000..16d9f54 --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/item/ItemServiceTest.java @@ -0,0 +1,769 @@ +package ru.practicum.shareit.item; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import ru.practicum.shareit.booking.BookingStorage; +import ru.practicum.shareit.exceptions.NotFoundException; +import ru.practicum.shareit.exceptions.NotValidException; +import ru.practicum.shareit.item.dto.CommentDto; +import ru.practicum.shareit.item.dto.ItemDto; +import ru.practicum.shareit.item.dto.ItemToUpdateDto; +import ru.practicum.shareit.item.storage.ItemEntity; +import ru.practicum.shareit.request.RequestStorage; +import ru.practicum.shareit.request.storage.RequestEntity; +import ru.practicum.shareit.user.UserStorage; +import ru.practicum.shareit.user.storage.UserEntity; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; + +@SpringBootTest +public class ItemServiceTest { + @Mock + UserStorage userStorage; + @Mock + ItemStorage itemStorage; + @Mock + RequestStorage requestStorage; + @Mock + BookingStorage bookingStorage; + + @InjectMocks + ItemService itemService; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void findItemIdWhileNotFoundUserTest() { + Mockito.when(itemStorage.findItem(Mockito.anyLong())) + .thenReturn(Optional.empty()); + + try { + itemService.findItem(10L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Вещь не найдена", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Вещь не найдена\")"); + } + + @Test + public void findItemIdTest() { + var itemEntity = new ItemEntity(); + itemEntity.setId(54L);; + + Mockito.when(itemStorage.findItem(Mockito.anyLong())) + .thenReturn(Optional.of(itemEntity)); + + var actualItemDto = itemService.findItem(4L); + + var expectedItemDto = itemEntity.toDto(); + + Assertions.assertEquals(expectedItemDto, actualItemDto); + + Mockito.verify(itemStorage, Mockito.times(1)) + .findItem(4L); + } + + @Test + public void createItemWhileNotFoundUserIdTest() { + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.empty()); + + try { + itemService.createItem(ItemDto.builder().build(), 14L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Пользователь не найден", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Пользователь не найден\")"); + } + + @Test + public void createItemWhileNotFoundRequestIdTest() { + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.of(new UserEntity())); + + Mockito.when(requestStorage.findRequestById(Mockito.anyLong())) + .thenReturn(Optional.empty()); + + try { + itemService.createItem(ItemDto.builder().requestId(1L).build(), 14L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Запрос не найден", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Запрос не найден\")"); + } + + @Test + public void createItemWhileRequestIdIsNullTest() { + var userEntity = new UserEntity(); + userEntity.setId(10L); + + RequestEntity requestEntity = null; + + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.of(userEntity)); + + Mockito.when(requestStorage.findRequestById(Mockito.anyLong())) + .thenReturn(Optional.empty()); + + var itemDto = ItemDto.builder() + .id(14L) + .available(true) + .build(); + + var itemEntity = ItemMapper.toEntity(itemDto, userEntity, null); + + var actualItemDto = itemService.createItem(itemDto, 16L); + + var expectedItemDto = itemDto.toBuilder() + .comments(List.of()) + .build(); + + Assertions.assertEquals(expectedItemDto, actualItemDto); + + Mockito.verify(userStorage, Mockito.times(1)) + .findUserId(16L); + + Mockito.verify(requestStorage, Mockito.never()) + .findRequestById(Mockito.anyLong()); + + Mockito.verify(itemStorage, Mockito.times(1)) + .updateItem(itemEntity); + } + + @Test + public void createItemTest() { + var userEntity = new UserEntity(); + userEntity.setId(10L); + + RequestEntity requestEntity = new RequestEntity(); + requestEntity.setId(17L); + + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.of(userEntity)); + + Mockito.when(requestStorage.findRequestById(Mockito.anyLong())) + .thenReturn(Optional.of(requestEntity)); + + var itemDto = ItemDto.builder() + .id(14L) + .available(true) + .requestId(17L) + .build(); + + var itemEntity = ItemMapper.toEntity(itemDto, userEntity, requestEntity); + + var actualItemDto = itemService.createItem(itemDto, 16L); + + var expectedItemDto = itemDto.toBuilder() + .comments(List.of()) + .build(); + + Assertions.assertEquals(expectedItemDto, actualItemDto); + + Mockito.verify(userStorage, Mockito.times(1)) + .findUserId(16L); + + Mockito.verify(requestStorage, Mockito.times(1)) + .findRequestById(17L); + + Mockito.verify(itemStorage, Mockito.times(1)) + .updateItem(itemEntity); + } + + @Test + public void updateItemWhileNotFoundItemIdTest() { + Mockito.when(itemStorage.findItem(Mockito.anyLong())) + .thenReturn(Optional.empty()); + + try { + itemService.updateItem(ItemDto.builder().id(2L).build(), 14L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Вещь не найдена", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Вещь не найдена\")"); + } + + @Test + public void updateItemWhileUserIdIsNotOwnerTest() { + var ownerId = new UserEntity(); + ownerId.setId(11L); + + var itemEntity = new ItemEntity(); + itemEntity.setId(13L); + itemEntity.setOwner(ownerId); + + Mockito.when(itemStorage.findItem(Mockito.anyLong())) + .thenReturn(Optional.of(itemEntity)); + + try { + itemService.updateItem(ItemDto.builder().id(10L).build(), 14L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Владелец не найден", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Владелец не найден\")"); + } + + @Test + public void updateItemWhileNotFoundRequestIdTest() { + var ownerId = new UserEntity(); + ownerId.setId(11L); + + var itemEntity = new ItemEntity(); + itemEntity.setId(13L); + itemEntity.setOwner(ownerId); + + Mockito.when(itemStorage.findItem(Mockito.anyLong())) + .thenReturn(Optional.of(itemEntity)); + + try { + itemService.updateItem(ItemDto.builder().id(1L).requestId(1L).build(), 11L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Запрос не найден", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Запрос не найден\")"); + } + + @Test + public void updateItemWhileRequestIdIsNullTest() { + var ownerId = new UserEntity(); + ownerId.setId(11L); + + var itemEntity = new ItemEntity(); + itemEntity.setId(13L); + itemEntity.setOwner(ownerId); + itemEntity.setAvailable(true); + + Mockito.when(itemStorage.findItem(Mockito.anyLong())) + .thenReturn(Optional.of(itemEntity)); + + Mockito.when(requestStorage.findRequestById(Mockito.anyLong())) + .thenReturn(Optional.empty()); + + var itemDto = ItemDto.builder() + .id(13L) + .available(true) + .build(); + + var actualItemDto = itemService.updateItem(itemDto, 11L); + + var expectedItemDto = ItemMapper.toDto(itemEntity); + + Assertions.assertEquals(expectedItemDto, actualItemDto); + + Mockito.verify(requestStorage, Mockito.never()) + .findRequestById(Mockito.anyLong()); + + Mockito.verify(itemStorage, Mockito.times(1)) + .updateItem(itemEntity); + } + + @Test + public void updateItemItemTest() { + RequestEntity requestEntity = new RequestEntity(); + requestEntity.setId(17L); + + Mockito.when(requestStorage.findRequestById(Mockito.anyLong())) + .thenReturn(Optional.of(requestEntity)); + var ownerId = new UserEntity(); + ownerId.setId(11L); + + var itemEntity = new ItemEntity(); + itemEntity.setId(13L); + itemEntity.setOwner(ownerId); + itemEntity.setAvailable(true); + itemEntity.setRequest(requestEntity); + + Mockito.when(itemStorage.findItem(Mockito.anyLong())) + .thenReturn(Optional.of(itemEntity)); + + var itemDto = ItemDto.builder() + .id(13L) + .available(true) + .requestId(17L) + .build(); + + var actualItemDto = itemService.updateItem(itemDto, 11L); + + var expectedItemDto = ItemMapper.toDto(itemEntity); + + Assertions.assertEquals(expectedItemDto, actualItemDto); + + Mockito.verify(requestStorage, Mockito.times(1)) + .findRequestById(17L); + + Mockito.verify(itemStorage, Mockito.times(1)) + .updateItem(itemEntity); + } + + @Test + public void updateItemForRequestWhileNotFoundItemIdTest() { + Mockito.when(itemStorage.findItem(Mockito.anyLong())) + .thenReturn(Optional.empty()); + + try { + itemService.updateItem(1L, ItemToUpdateDto.builder().build(), 2L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Вещь не найдена", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Вещь не найдена\")"); + } + + @Test + public void updateItemForRequestWhileUserIdIsNotEqualOwnerTest() { + var ownerEntity = new UserEntity(); + ownerEntity.setId(11L); + + var itemEntity = new ItemEntity(); + itemEntity.setId(12L); + itemEntity.setOwner(ownerEntity); + + Mockito.when(itemStorage.findItem(Mockito.anyLong())) + .thenReturn(Optional.of(itemEntity)); + + try { + itemService.updateItem(1L, ItemToUpdateDto.builder().build(), 2L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Вещь не доступна", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Вещь не доступна\")"); + } + + @Test + public void updateItemForRequestChangeNameTest() { + var ownerEntity = new UserEntity(); + ownerEntity.setId(11L); + + var itemEntity = new ItemEntity(); + itemEntity.setId(12L); + itemEntity.setOwner(ownerEntity); + itemEntity.setName("test"); + itemEntity.setDescription("test"); + itemEntity.setAvailable(false); + + var expectedItemDto = ItemMapper.toDto(itemEntity).toBuilder() + .name("updated") + .build(); + + Mockito.when(itemStorage.findItem(Mockito.anyLong())) + .thenReturn(Optional.of(itemEntity)); + + var actualItemDto = itemService.updateItem( + 1L, + ItemToUpdateDto.builder().name("updated").build(), + 11L); + + Assertions.assertEquals(expectedItemDto, actualItemDto); + + itemEntity = new ItemEntity(); + itemEntity.setId(12L); + itemEntity.setOwner(ownerEntity); + itemEntity.setName("updated"); + itemEntity.setDescription("test"); + itemEntity.setAvailable(false); + + Mockito.verify(itemStorage, Mockito.times(1)) + .updateItem(itemEntity); + } + + @Test + public void updateItemForRequestChangeDescriptionTest() { + var ownerEntity = new UserEntity(); + ownerEntity.setId(11L); + + var itemEntity = new ItemEntity(); + itemEntity.setId(12L); + itemEntity.setOwner(ownerEntity); + itemEntity.setName("test"); + itemEntity.setDescription("test"); + itemEntity.setAvailable(false); + + var expectedItemDto = ItemMapper.toDto(itemEntity).toBuilder() + .description("updated") + .build(); + + Mockito.when(itemStorage.findItem(Mockito.anyLong())) + .thenReturn(Optional.of(itemEntity)); + + var actualItemDto = itemService.updateItem( + 1L, + ItemToUpdateDto.builder().description("updated").build(), + 11L); + + Assertions.assertEquals(expectedItemDto, actualItemDto); + + itemEntity = new ItemEntity(); + itemEntity.setId(12L); + itemEntity.setOwner(ownerEntity); + itemEntity.setName("test"); + itemEntity.setDescription("updated"); + itemEntity.setAvailable(false); + + Mockito.verify(itemStorage, Mockito.times(1)) + .updateItem(itemEntity); + } + + @Test + public void updateItemForRequestChangeSetAvailableTrueTest() { + var ownerEntity = new UserEntity(); + ownerEntity.setId(11L); + + var itemEntity = new ItemEntity(); + itemEntity.setId(12L); + itemEntity.setOwner(ownerEntity); + itemEntity.setName("test"); + itemEntity.setDescription("test"); + itemEntity.setAvailable(false); + + var expectedItemDto = ItemMapper.toDto(itemEntity).toBuilder() + .available(true) + .build(); + + Mockito.when(itemStorage.findItem(Mockito.anyLong())) + .thenReturn(Optional.of(itemEntity)); + + var actualItemDto = itemService.updateItem( + 1L, + ItemToUpdateDto.builder().available(true).build(), + 11L); + + Assertions.assertEquals(expectedItemDto, actualItemDto); + + itemEntity = new ItemEntity(); + itemEntity.setId(12L); + itemEntity.setOwner(ownerEntity); + itemEntity.setName("test"); + itemEntity.setDescription("test"); + itemEntity.setAvailable(true); + + Mockito.verify(itemStorage, Mockito.times(1)) + .updateItem(itemEntity); + } + + @Test + public void updateItemForRequestChangeSetAvailableFalseTest() { + var ownerEntity = new UserEntity(); + ownerEntity.setId(11L); + + var itemEntity = new ItemEntity(); + itemEntity.setId(12L); + itemEntity.setOwner(ownerEntity); + itemEntity.setName("test"); + itemEntity.setDescription("test"); + itemEntity.setAvailable(true); + + var expectedItemDto = ItemMapper.toDto(itemEntity).toBuilder() + .available(false) + .build(); + + Mockito.when(itemStorage.findItem(Mockito.anyLong())) + .thenReturn(Optional.of(itemEntity)); + + var actualItemDto = itemService.updateItem( + 1L, + ItemToUpdateDto.builder().available(false).build(), + 11L); + + Assertions.assertEquals(expectedItemDto, actualItemDto); + + itemEntity = new ItemEntity(); + itemEntity.setId(12L); + itemEntity.setOwner(ownerEntity); + itemEntity.setName("test"); + itemEntity.setDescription("test"); + itemEntity.setAvailable(false); + + Mockito.verify(itemStorage, Mockito.times(1)) + .updateItem(itemEntity); + } + + @Test + public void deleteItemWhileNotFoundItemIdTest() { + Mockito.when(itemStorage.findItem(Mockito.anyLong())) + .thenReturn(Optional.empty()); + + try { + itemService.deleteItem(1L, 2L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Вещь не найдена", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Вещь не найдена\")"); + } + + @Test + public void deleteItemWhileUserIdIsNotEqualOwnerTest() { + var ownerEntity = new UserEntity(); + ownerEntity.setId(11L); + + var itemEntity = new ItemEntity(); + itemEntity.setId(12L); + itemEntity.setOwner(ownerEntity); + + Mockito.when(itemStorage.findItem(Mockito.anyLong())) + .thenReturn(Optional.of(itemEntity)); + + try { + itemService.deleteItem(1L, 2L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Вещь не доступна", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Вещь не доступна\")"); + } + + @Test + public void deleteItemTest() { + var ownerEntity = new UserEntity(); + ownerEntity.setId(11L); + + var itemEntity = new ItemEntity(); + itemEntity.setId(12L); + itemEntity.setOwner(ownerEntity); + + Mockito.when(itemStorage.findItem(Mockito.anyLong())) + .thenReturn(Optional.of(itemEntity)); + + var expectedItemDto = ItemMapper.toDto(itemEntity); + + var actualItemDto = itemService.deleteItem(1L, 11L); + + Assertions.assertEquals(expectedItemDto, actualItemDto); + + Mockito.verify(itemStorage, Mockito.times(1)) + .deleteItem(1L); + + Mockito.verify(itemStorage, Mockito.times(1)) + .findItem(1L); + } + + @Test + public void getItemsWhileNotFoundUserIdTest() { + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.empty()); + + try { + itemService.getItems(2L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Пользователь не найден", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Пользователь не найден\")"); + } + + @Test + public void getItemsTest() { + var ownerEntity = new UserEntity(); + ownerEntity.setId(1L); + + var item1 = new ItemEntity(); + item1.setId(11L); + item1.setOwner(ownerEntity); + + var item2 = new ItemEntity(); + item2.setId(12L); + item2.setOwner(ownerEntity); + + ownerEntity.setItems(List.of(item1, item2)); + + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.of(ownerEntity)); + + var expectedList = Stream.of(item1, item2) + .map(ItemMapper::toDto) + .toList(); + + var actualList = itemService.getItems(14L); + + Assertions.assertEquals(expectedList, actualList); + + Mockito.verify(userStorage, Mockito.times(1)) + .findUserId(14L); + } + + @Test + public void findFreeItemsByTextWhileNullTextTest() { + var item1 = new ItemEntity(); + item1.setId(11L); + + var item2 = new ItemEntity(); + item2.setId(12L); + + Mockito.when(itemStorage.findItemsByTextAndStatus(Mockito.anyString(), Mockito.anyBoolean())) + .thenReturn(List.of(item1, item2)); + + Assertions.assertEquals(0, itemService.findFreeItemsByText(null, true).size()); + + Mockito.verify(itemStorage, Mockito.never()) + .findItemsByTextAndStatus(Mockito.anyString(), Mockito.anyBoolean()); + } + + @Test + public void findFreeItemsByTextWhileBlankTextTest() { + var item1 = new ItemEntity(); + item1.setId(11L); + + var item2 = new ItemEntity(); + item2.setId(12L); + + Mockito.when(itemStorage.findItemsByTextAndStatus(Mockito.anyString(), Mockito.anyBoolean())) + .thenReturn(List.of(item1, item2)); + + Assertions.assertEquals(0, itemService.findFreeItemsByText("", true).size()); + + Mockito.verify(itemStorage, Mockito.never()) + .findItemsByTextAndStatus(Mockito.anyString(), Mockito.anyBoolean()); + } + + @Test + public void findFreeItemsByTextWhileAvailableIsTrueTest() { + var item1 = new ItemEntity(); + item1.setId(11L); + + var item2 = new ItemEntity(); + item2.setId(12L); + + Mockito.when(itemStorage.findItemsByTextAndStatus(Mockito.anyString(), Mockito.anyBoolean())) + .thenReturn(List.of(item1, item2)); + + itemService.findFreeItemsByText("a", true); + + Mockito.verify(itemStorage, Mockito.never()) + .findItemsByTextAndStatus("a", false); + + Mockito.verify(itemStorage, Mockito.times(1)) + .findItemsByTextAndStatus("a", true); + } + + @Test + public void findFreeItemsByTextWhileAvailableIsFalseTest() { + var item1 = new ItemEntity(); + item1.setId(11L); + + var item2 = new ItemEntity(); + item2.setId(12L); + + Mockito.when(itemStorage.findItemsByTextAndStatus(Mockito.anyString(), Mockito.anyBoolean())) + .thenReturn(List.of(item1, item2)); + + itemService.findFreeItemsByText("a", false); + + Mockito.verify(itemStorage, Mockito.never()) + .findItemsByTextAndStatus("a", true); + + Mockito.verify(itemStorage, Mockito.times(1)) + .findItemsByTextAndStatus("a", false); + } + + @Test + public void findFreeItemsByTextTest() { + var item1 = new ItemEntity(); + item1.setId(11L); + + var item2 = new ItemEntity(); + item2.setId(12L); + + Mockito.when(itemStorage.findItemsByTextAndStatus(Mockito.anyString(), Mockito.anyBoolean())) + .thenReturn(List.of(item1, item2)); + + var expectedList = Stream.of(item1, item2) + .map(ItemMapper::toDto) + .toList(); + + var actualList = itemService.findFreeItemsByText("a", false); + + Assertions.assertEquals(expectedList, actualList); + } + + @Test + public void addCommentWhileNotFoundUserIdTest() { + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.empty()); + + try { + itemService.addComment( + CommentDto.builder().build(), + 1L, + 2L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Пользователь не найден", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Пользователь не найден\")"); + } + + @Test + public void addCommentWhileNotFoundItemIdTest() { + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.of(new UserEntity())); + + Mockito.when(itemStorage.findItem(Mockito.anyLong())) + .thenReturn(Optional.empty()); + + try { + itemService.addComment( + CommentDto.builder().build(), + 1L, + 2L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Вешь не найдена", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Вешь не найдена\")"); + } + + @Test + public void addCommentWhileUserNotUsedItemTest() { + var userEntity = new UserEntity(); + userEntity.setId(11L); + + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.of(userEntity)); + + Mockito.when(itemStorage.findItem(Mockito.anyLong())) + .thenReturn(Optional.of(new ItemEntity())); + + Mockito.when( + bookingStorage.existsByBookerIdAndItemIdAndAfterEnd(Mockito.anyLong(), Mockito.anyLong())) + .thenReturn(false); + + try { + itemService.addComment( + CommentDto.builder().build(), + 1L, + 2L); + } catch (NotValidException ex) { + Assertions.assertEquals("Пользователь не брал вещь, не может оставить комментарий", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotValidException(\"Пользователь не брал вещь, не может оставить комментарий\")"); + } +} diff --git a/server/src/test/java/ru/practicum/shareit/request/RequestServiceTest.java b/server/src/test/java/ru/practicum/shareit/request/RequestServiceTest.java new file mode 100644 index 0000000..4f109f9 --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/request/RequestServiceTest.java @@ -0,0 +1,194 @@ +package ru.practicum.shareit.request; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import ru.practicum.shareit.exceptions.NotFoundException; +import ru.practicum.shareit.request.dto.RequestDto; +import ru.practicum.shareit.request.storage.RequestEntity; +import ru.practicum.shareit.user.UserStorage; +import ru.practicum.shareit.user.storage.UserEntity; + +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.util.Optional; +import java.util.stream.Stream; + +@SpringBootTest +public class RequestServiceTest { + @Mock + UserStorage userStorage; + @Mock + RequestStorage requestStorage; + + @InjectMocks + RequestService requestService; + + @Test + public void createRequestWhileNotFoundUserTest() { + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.empty()); + + try { + requestService.createRequest(RequestDto.builder().build(), 1L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Пользователь не найден", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Пользователь не найден\")"); + } + + @Test + public void createRequestTest() { + var userEntity = new UserEntity(); + userEntity.setId(2L); + + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.of(userEntity)); + + var requestEntity = new RequestEntity(); + requestEntity.setId(3L); + + var requestDto = RequestDto.builder() + .id(3L) + .build(); + + var createdDate = Timestamp.valueOf(LocalDateTime.now().minusMinutes(1)); + + var actualRequestDto = requestService.createRequest(requestDto, 7L); + + requestEntity.setCreated(createdDate); + requestEntity.setUser(userEntity); + + var expectedRequestDto = requestEntity.toDto(); + + Assertions.assertTrue(createdDate.before(actualRequestDto.created())); + + expectedRequestDto = expectedRequestDto.toBuilder() + .created(actualRequestDto.created()) + .build(); + + Assertions.assertEquals(expectedRequestDto, actualRequestDto); + + Mockito.verify(userStorage, Mockito.times(1)) + .findUserId(7L); + + requestEntity.setCreated(actualRequestDto.created()); + + Mockito.verify(requestStorage, Mockito.times(1)) + .updateRequest(requestEntity); + } + + @Test + public void getRequestsByUserIdWhileNotFoundUserTest() { + Mockito.when(userStorage.existsById(Mockito.anyLong())) + .thenReturn(false); + + try { + requestService.getRequestsByUserId(1L, true); + } catch (NotFoundException ex) { + Assertions.assertEquals("Пользователь не найден", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Пользователь не найден\")"); + } + + @Test + public void getRequestsByUserIdTest() { + Mockito.when(userStorage.existsById(Mockito.anyLong())) + .thenReturn(true); + + var userEntity = new UserEntity(); + userEntity.setId(1L); + + var requestEntities = Stream.of( + RequestDto.builder().id(2L).build(), + RequestDto.builder().id(5L).build(), + RequestDto.builder().id(7L).build() + ) + .map(i -> RequestMapper.toEntity(i, userEntity)) + .toList(); + + Mockito.when(requestStorage.getRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) + .thenReturn(requestEntities); + + var actualRequestDtos = requestService.getRequestsByUserId(11L, true); + + var expectedRequestDtos = requestEntities.stream().map(RequestEntity::toDto).toList(); + + Assertions.assertEquals(expectedRequestDtos, actualRequestDtos); + + Mockito.verify(userStorage, Mockito.times(1)) + .existsById(11L); + + Mockito.verify(requestStorage, Mockito.times(1)) + .getRequestsByUserId(11L, true); + } + + @Test + public void getRequestsByUserIdWhileParamIsFalseTest() { + Mockito.when(userStorage.existsById(Mockito.anyLong())) + .thenReturn(true); + + var userEntity = new UserEntity(); + userEntity.setId(1L); + + var requestEntities = Stream.of( + RequestDto.builder().id(2L).build(), + RequestDto.builder().id(5L).build(), + RequestDto.builder().id(7L).build() + ) + .map(i -> RequestMapper.toEntity(i, userEntity)) + .toList(); + + Mockito.when(requestStorage.getRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) + .thenReturn(requestEntities); + + var actualRequestDtos = requestService.getRequestsByUserId(13L, false); + + var expectedRequestDtos = requestEntities.stream().map(RequestEntity::toDto).toList(); + + Assertions.assertEquals(expectedRequestDtos, actualRequestDtos); + + Mockito.verify(requestStorage, Mockito.times(1)) + .getRequestsByUserId(13L, false); + } + + @Test + public void getRequestsIdWhileNotFoundUserTest() { + Mockito.when(requestStorage.findRequestById(Mockito.anyLong())) + .thenReturn(Optional.empty()); + + try { + requestService.getRequestById(1L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Запрос не найден", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Запрос не найден\")"); + } + + @Test + public void getRequestByIdTest() { + var requestEntity = new RequestEntity(); + requestEntity.setId(15L); + + Mockito.when(requestStorage.findRequestById(Mockito.anyLong())) + .thenReturn(Optional.of(requestEntity)); + + var actualRequestDto = requestService.getRequestById(11L); + + var expectedRequestDto = requestEntity.toDto(); + + Assertions.assertEquals(expectedRequestDto, actualRequestDto); + + Mockito.verify(requestStorage, Mockito.times(1)) + .findRequestById(11L); + } +} diff --git a/server/src/test/java/ru/practicum/shareit/user/UserControllerTest.java b/server/src/test/java/ru/practicum/shareit/user/UserControllerTest.java index 93898b0..5276a5b 100644 --- a/server/src/test/java/ru/practicum/shareit/user/UserControllerTest.java +++ b/server/src/test/java/ru/practicum/shareit/user/UserControllerTest.java @@ -40,7 +40,7 @@ public void getUserTest() throws Exception { .email("email@mail.ru") .build(); - Mockito.when(userService.getUser(Mockito.anyLong())) + Mockito.when(userService.findUserId(Mockito.anyLong())) .thenReturn(dto); mockMvc.perform(get("/users/17")) @@ -48,7 +48,7 @@ public void getUserTest() throws Exception { .andExpect(jsonPath("$.id", is(47L), Long.class)); Mockito.verify(userService, Mockito.times(1)) - .getUser(17L); + .findUserId(17L); } @Test diff --git a/server/src/test/java/ru/practicum/shareit/user/UserServiceTest.java b/server/src/test/java/ru/practicum/shareit/user/UserServiceTest.java new file mode 100644 index 0000000..4819584 --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/user/UserServiceTest.java @@ -0,0 +1,210 @@ +package ru.practicum.shareit.user; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import ru.practicum.shareit.exceptions.NotFoundException; +import ru.practicum.shareit.user.dto.UserDto; +import ru.practicum.shareit.user.dto.UserToUpdateDto; +import ru.practicum.shareit.user.storage.UserEntity; + +import java.util.Optional; + +@SpringBootTest +public class UserServiceTest { + @Mock + UserStorage userStorage; + + @InjectMocks + UserService userService; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void findUserIdWhileNotFoundUserTest() { + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.empty()); + + try { + userService.findUserId(10L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Не нашел userId в системе", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Не нашел userId в системе\")"); + } + + @Test + public void findUserIdTest() { + var userEntity = new UserEntity(); + userEntity.setId(2L); + + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.of(userEntity)); + + var expectedUserDto = UserMapper.toDto(userEntity); + + var actualUserDto = userService.findUserId(5L); + + Assertions.assertEquals(expectedUserDto, actualUserDto); + + Mockito.verify(userStorage, Mockito.times(1)) + .findUserId(5L); + } + + @Test + public void updateUserTest() { + var userDto = UserDto.builder() + .id(10L) + .name("test") + .build(); + + var actualUserDto = userService.updateUser(userDto); + + Assertions.assertEquals(userDto, actualUserDto); + + Mockito.verify(userStorage, Mockito.times(1)) + .updateUser(UserMapper.toEntity(userDto)); + } + + @Test + public void updateUserByRequestWhileNotFoundUserId() { + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.empty()); + + var userRequestToUpdate = UserToUpdateDto.builder().build(); + + try { + userService.updateUser(10L, userRequestToUpdate); + } catch (NotFoundException ex) { + Assertions.assertEquals("Не нашел userId в системе", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Не нашел userId в системе\")"); + } + + @Test + public void updateUserByRequestChangeName() { + var userDto = UserDto.builder() + .id(10L) + .name("test") + .build(); + + var updateDto = UserToUpdateDto.builder() + .name("updated") + .build(); + + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.of(UserMapper.toEntity(userDto))); + + var userEntity = UserMapper.toEntity(userDto); + userEntity.setName("updated"); + + var actualUserDto = userService.updateUser(1L, updateDto); + + Assertions.assertEquals("updated", actualUserDto.name()); + + Mockito.verify(userStorage, Mockito.times(1)) + .findUserId(1L); + + Mockito.verify(userStorage, Mockito.times(1)) + .updateUser(userEntity); + } + + @Test + public void updateUserByRequestChangeEmail() { + var userDto = UserDto.builder() + .id(10L) + .email("test@aa.bb") + .build(); + + var updateDto = UserToUpdateDto.builder() + .email("updated@aa.bb") + .build(); + + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.of(UserMapper.toEntity(userDto))); + + var userEntity = UserMapper.toEntity(userDto); + userEntity.setEmail("updated@aa.bb"); + + var actualUserDto = userService.updateUser(1L, updateDto); + + Assertions.assertEquals("updated@aa.bb", actualUserDto.email()); + + Mockito.verify(userStorage, Mockito.times(1)) + .findUserId(1L); + + Mockito.verify(userStorage, Mockito.times(1)) + .updateUser(userEntity); + } + + @Test + public void updateUserByRequestNotChanges() { + var userDto = UserDto.builder() + .id(10L) + .name("test") + .email("test@aa.bb") + .build(); + + var updateDto = UserToUpdateDto.builder() + .build(); + + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.of(UserMapper.toEntity(userDto))); + + var userEntity = UserMapper.toEntity(userDto); + + var actualUserDto = userService.updateUser(1L, updateDto); + + Assertions.assertEquals(userDto, actualUserDto); + + Mockito.verify(userStorage, Mockito.times(1)) + .findUserId(1L); + + Mockito.verify(userStorage, Mockito.times(1)) + .updateUser(userEntity); + } + + @Test + public void deleteUserByRequestWhileNotFoundUserId() { + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.empty()); + + try { + userService.deleteUser(10L); + } catch (NotFoundException ex) { + Assertions.assertEquals("Не нашел userId в системе", ex.getMessage()); + return; + } + + Assertions.fail("Expected NotFoundException(\"Не нашел userId в системе\")"); + } + + @Test + public void deleteUserTest() { + var oldUserEntity = new UserEntity(); + oldUserEntity.setId(17L); + + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.of(oldUserEntity)); + + var expectedUserDto = UserMapper.toDto(oldUserEntity); + + var actualUserDto = userService.deleteUser(5L); + + Assertions.assertEquals(expectedUserDto, actualUserDto); + + Mockito.verify(userStorage, Mockito.times(1)) + .findUserId(5L); + + Mockito.verify(userStorage, Mockito.times(1)) + .deleteUser(oldUserEntity); + } +} From 48ded6e93eaae7ca37e635cd9f1ba6537897a995 Mon Sep 17 00:00:00 2001 From: aKorishev Date: Fri, 6 Dec 2024 19:08:28 +0300 Subject: [PATCH 11/11] =?UTF-8?q?[add-item-requests-and-gateway]=20=D0=98?= =?UTF-8?q?=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=B7=D0=B0=D0=BC?= =?UTF-8?q?=D0=B5=D1=87=D0=B0=D0=BD=D0=B8=D1=8F=20=D1=80=D0=B5=D0=B2=D1=8C?= =?UTF-8?q?=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shareit/booking/BookingController.java | 3 +- .../shareit/booking/BookingService.java | 4 +- .../shareit/booking/BookingStorage.java | 2 - .../booking/storage/BookingRepository.java | 2 + .../booking/storage/BookingStorageInDb.java | 11 -- .../shareit/item/ItemController.java | 9 +- .../practicum/shareit/item/ItemStorage.java | 4 +- .../shareit/item/storage/ItemStorageInDb.java | 28 +--- .../shareit/request/RequestController.java | 9 +- .../shareit/request/RequestService.java | 12 +- .../shareit/request/RequestStorage.java | 4 +- .../request/storage/RequestStorageInDb.java | 13 +- .../shareit/user/UserController.java | 7 +- .../shareit/user/storage/UserEntity.java | 2 +- .../shareit/user/storage/UserStorageInDB.java | 2 - .../shareit/booking/BookingServiceTest.java | 94 +++++++++++-- .../booking/BookingStorageInDbTest.java | 127 ++++++++++++++++++ .../request/RequestControllerTest.java | 12 +- .../shareit/request/RequestServiceTest.java | 35 +++-- 19 files changed, 277 insertions(+), 103 deletions(-) create mode 100644 server/src/test/java/ru/practicum/shareit/booking/BookingStorageInDbTest.java diff --git a/server/src/main/java/ru/practicum/shareit/booking/BookingController.java b/server/src/main/java/ru/practicum/shareit/booking/BookingController.java index 39e50bf..763feb6 100644 --- a/server/src/main/java/ru/practicum/shareit/booking/BookingController.java +++ b/server/src/main/java/ru/practicum/shareit/booking/BookingController.java @@ -1,6 +1,5 @@ package ru.practicum.shareit.booking; -import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import ru.practicum.shareit.booking.dto.BookingDto; @@ -35,7 +34,7 @@ public List getBookingForItemOwnerId( @PostMapping public BookingDto postBooking( @RequestHeader("X-Sharer-User-Id") long userId, - @Valid @RequestBody BookingDto bookingDto) { + @RequestBody BookingDto bookingDto) { return bookingService.createBooking(bookingDto, userId); } diff --git a/server/src/main/java/ru/practicum/shareit/booking/BookingService.java b/server/src/main/java/ru/practicum/shareit/booking/BookingService.java index 1e0ebd8..ddbb996 100644 --- a/server/src/main/java/ru/practicum/shareit/booking/BookingService.java +++ b/server/src/main/java/ru/practicum/shareit/booking/BookingService.java @@ -28,9 +28,9 @@ public BookingDto findBooking(long bookingId, long userId) { var bookingEntity = bookingStorage.findBooking(bookingId) .orElseThrow(() -> new NotFoundException("Бронь не найдена")); - if (!bookingStorage.userIdIsBookerOrOwner(bookingEntity, userId)) { + if (bookingEntity.getBooker().getId() != userId && + bookingEntity.getItem().getOwner().getId() != userId) throw new NotValidException("Данные о бронировании может получить заказчик или владелец"); - } return bookingEntity.toDto(); } diff --git a/server/src/main/java/ru/practicum/shareit/booking/BookingStorage.java b/server/src/main/java/ru/practicum/shareit/booking/BookingStorage.java index 4e88a49..5c5ad44 100644 --- a/server/src/main/java/ru/practicum/shareit/booking/BookingStorage.java +++ b/server/src/main/java/ru/practicum/shareit/booking/BookingStorage.java @@ -8,8 +8,6 @@ public interface BookingStorage { Optional findBooking(long bookingId); - boolean userIdIsBookerOrOwner(BookingEntity bookingEntity, long userId); - void updateBooking(BookingEntity entity); List findBookingsByBookerId(long userId); diff --git a/server/src/main/java/ru/practicum/shareit/booking/storage/BookingRepository.java b/server/src/main/java/ru/practicum/shareit/booking/storage/BookingRepository.java index b20711d..094dc89 100644 --- a/server/src/main/java/ru/practicum/shareit/booking/storage/BookingRepository.java +++ b/server/src/main/java/ru/practicum/shareit/booking/storage/BookingRepository.java @@ -3,12 +3,14 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; import ru.practicum.shareit.booking.BookingStatus; import java.sql.Timestamp; import java.util.List; import java.util.Optional; +@Repository public interface BookingRepository extends JpaRepository { List findByBookerId(long userId); diff --git a/server/src/main/java/ru/practicum/shareit/booking/storage/BookingStorageInDb.java b/server/src/main/java/ru/practicum/shareit/booking/storage/BookingStorageInDb.java index 5d8f770..2612972 100644 --- a/server/src/main/java/ru/practicum/shareit/booking/storage/BookingStorageInDb.java +++ b/server/src/main/java/ru/practicum/shareit/booking/storage/BookingStorageInDb.java @@ -24,17 +24,6 @@ public Optional findBooking(long bookingId) { return bookingRepository.findById(bookingId); } - @Override - public boolean userIdIsBookerOrOwner(BookingEntity bookingEntity, long userId) { - if (bookingEntity.getBooker().getId() == userId) - return true; - - if (bookingEntity.getItem().getOwner().getId() == userId) - return true; - - return false; - } - @Override public void updateBooking(BookingEntity bookingEntity) { bookingRepository.saveAndFlush(bookingEntity); diff --git a/server/src/main/java/ru/practicum/shareit/item/ItemController.java b/server/src/main/java/ru/practicum/shareit/item/ItemController.java index 35e8a73..423cb16 100644 --- a/server/src/main/java/ru/practicum/shareit/item/ItemController.java +++ b/server/src/main/java/ru/practicum/shareit/item/ItemController.java @@ -1,6 +1,5 @@ package ru.practicum.shareit.item; -import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import ru.practicum.shareit.item.dto.CommentDto; @@ -33,7 +32,7 @@ public List findItemsByText(@RequestParam String text) { @PostMapping public ItemDto postItem( - @Valid @RequestBody ItemDto itemDto, + @RequestBody ItemDto itemDto, @RequestHeader("X-Sharer-User-Id") long userId) { return itemService.createItem(itemDto, userId); } @@ -42,13 +41,13 @@ public ItemDto postItem( public CommentDto postComment( @PathVariable long id, @RequestHeader("X-Sharer-User-Id") long userId, - @Valid @RequestBody CommentDto commentDto) { + @RequestBody CommentDto commentDto) { return itemService.addComment(commentDto, id, userId); } @PutMapping() public ItemDto putItem( - @Valid @RequestBody ItemDto itemDto, + @RequestBody ItemDto itemDto, @RequestHeader("X-Sharer-User-Id") long userId) { return itemService.updateItem(itemDto, userId); @@ -57,7 +56,7 @@ public ItemDto putItem( @PatchMapping("/{id}") public ItemDto patchItem( @PathVariable long id, - @Valid @RequestBody ItemToUpdateDto item, + @RequestBody ItemToUpdateDto item, @RequestHeader("X-Sharer-User-Id") long userId) { return itemService.updateItem(id, item, userId); } diff --git a/server/src/main/java/ru/practicum/shareit/item/ItemStorage.java b/server/src/main/java/ru/practicum/shareit/item/ItemStorage.java index 5083479..2591818 100644 --- a/server/src/main/java/ru/practicum/shareit/item/ItemStorage.java +++ b/server/src/main/java/ru/practicum/shareit/item/ItemStorage.java @@ -13,9 +13,9 @@ public interface ItemStorage { void updateComment(CommentEntity commentEntity); - Optional deleteItem(long itemId); + void deleteItem(long itemId); - Optional deleteComment(long commentId); + void deleteComment(long commentId); List getItemsForOwner(long userId); diff --git a/server/src/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java b/server/src/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java index aabd98c..b5c2b18 100644 --- a/server/src/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java +++ b/server/src/main/java/ru/practicum/shareit/item/storage/ItemStorageInDb.java @@ -4,11 +4,7 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; -import ru.practicum.shareit.booking.storage.BookingRepository; -import ru.practicum.shareit.item.CommentMapper; -import ru.practicum.shareit.item.ItemMapper; import ru.practicum.shareit.item.ItemStorage; -import ru.practicum.shareit.user.storage.UserRepository; import java.util.List; import java.util.Optional; @@ -18,12 +14,8 @@ @Qualifier("ItemStorageInDb") @Primary public class ItemStorageInDb implements ItemStorage { - private final UserRepository userRepository; private final ItemRepository itemRepository; - private final BookingRepository bookingRepository; private final CommentRepository commentRepository; - private final ItemMapper itemMapper = new ItemMapper(); - private final CommentMapper commentMapper = new CommentMapper(); @Override public Optional findItem(long itemId) { @@ -41,25 +33,13 @@ public void updateComment(CommentEntity commentEntity) { } @Override - public Optional deleteItem(long itemId) { - var entity = itemRepository.findById(itemId); - - if (entity.isPresent()) { - itemRepository.deleteById(itemId); - } - - return entity; + public void deleteItem(long itemId) { + itemRepository.deleteById(itemId); } @Override - public Optional deleteComment(long commentId) { - var entity = commentRepository.findById(commentId); - - if (entity.isPresent()) { - commentRepository.deleteById(commentId); - } - - return entity; + public void deleteComment(long commentId) { + commentRepository.deleteById(commentId); } @Override diff --git a/server/src/main/java/ru/practicum/shareit/request/RequestController.java b/server/src/main/java/ru/practicum/shareit/request/RequestController.java index 6509229..39264f8 100644 --- a/server/src/main/java/ru/practicum/shareit/request/RequestController.java +++ b/server/src/main/java/ru/practicum/shareit/request/RequestController.java @@ -1,6 +1,5 @@ package ru.practicum.shareit.request; -import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import ru.practicum.shareit.request.dto.RequestDto; @@ -15,22 +14,22 @@ public class RequestController { @GetMapping public List getSelfRequests(@RequestHeader("X-Sharer-User-Id") long userId) { - return requestService.getRequestsByUserId(userId, true); + return requestService.findRequestsByUserId(userId, true); } @GetMapping("/{id}") public RequestDto getRequestById(@PathVariable long id) { - return requestService.getRequestById(id); + return requestService.findRequestById(id); } @GetMapping("/all") public List getOtherUserRequests(@RequestHeader("X-Sharer-User-Id") long userId) { - return requestService.getRequestsByUserId(userId, false); + return requestService.findRequestsByUserId(userId, false); } @PostMapping public RequestDto postRequestDto( - @Valid @RequestBody RequestDto requestDto, + @RequestBody RequestDto requestDto, @RequestHeader("X-Sharer-User-Id") long userId) { return requestService.createRequest(requestDto, userId); } diff --git a/server/src/main/java/ru/practicum/shareit/request/RequestService.java b/server/src/main/java/ru/practicum/shareit/request/RequestService.java index adc8f3c..8063583 100644 --- a/server/src/main/java/ru/practicum/shareit/request/RequestService.java +++ b/server/src/main/java/ru/practicum/shareit/request/RequestService.java @@ -30,17 +30,21 @@ public RequestDto createRequest(@Valid RequestDto requestDto, long userId) { return requestEntity.toDto(); } - public List getRequestsByUserId(long userId, boolean findByUserId) { - if (findByUserId && !userStorage.existsById(userId)) + public List findRequestsByUserId(long userId, boolean findByEqualUserId) { + if (findByEqualUserId && !userStorage.existsById(userId)) throw new NotFoundException("Пользователь не найден"); - return requestStorage.getRequestsByUserId(userId, findByUserId) + var requests = findByEqualUserId + ? requestStorage.findRequestsByUserId(userId) + : requestStorage.findRequestsByNotUserId(userId); + + return requests .stream() .map(RequestEntity::toDto) .toList(); } - public RequestDto getRequestById(long id) { + public RequestDto findRequestById(long id) { var requestEntity = requestStorage.findRequestById(id) .orElseThrow(() -> new NotFoundException("Запрос не найден")); diff --git a/server/src/main/java/ru/practicum/shareit/request/RequestStorage.java b/server/src/main/java/ru/practicum/shareit/request/RequestStorage.java index de99a42..6b6a0c9 100644 --- a/server/src/main/java/ru/practicum/shareit/request/RequestStorage.java +++ b/server/src/main/java/ru/practicum/shareit/request/RequestStorage.java @@ -8,7 +8,9 @@ public interface RequestStorage { void updateRequest(RequestEntity requestEntity); - List getRequestsByUserId(long userId, boolean findByUserId); + List findRequestsByUserId(long userId); + + List findRequestsByNotUserId(long userId); Optional findRequestById(long id); } diff --git a/server/src/main/java/ru/practicum/shareit/request/storage/RequestStorageInDb.java b/server/src/main/java/ru/practicum/shareit/request/storage/RequestStorageInDb.java index 5bf6e18..3b7bc32 100644 --- a/server/src/main/java/ru/practicum/shareit/request/storage/RequestStorageInDb.java +++ b/server/src/main/java/ru/practicum/shareit/request/storage/RequestStorageInDb.java @@ -20,12 +20,13 @@ public void updateRequest(RequestEntity requestEntity) { } @Override - public List getRequestsByUserId(long userId, boolean findByUserId) { - if (findByUserId) { - return requestRepository.findByUserId(userId); - } else { - return requestRepository.findByUserIdNot(userId); - } + public List findRequestsByUserId(long userId) { + return requestRepository.findByUserId(userId); + } + + @Override + public List findRequestsByNotUserId(long userId) { + return requestRepository.findByUserIdNot(userId); } @Override diff --git a/server/src/main/java/ru/practicum/shareit/user/UserController.java b/server/src/main/java/ru/practicum/shareit/user/UserController.java index cd98382..df1602c 100644 --- a/server/src/main/java/ru/practicum/shareit/user/UserController.java +++ b/server/src/main/java/ru/practicum/shareit/user/UserController.java @@ -1,6 +1,5 @@ package ru.practicum.shareit.user; -import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import ru.practicum.shareit.user.dto.UserDto; @@ -19,17 +18,17 @@ public UserDto getUser(@PathVariable long id) { } @PostMapping - public UserDto postUser(@Valid @RequestBody UserDto user) { + public UserDto postUser(@RequestBody UserDto user) { return userService.updateUser(user); } @PutMapping - public UserDto putUser(@Valid @RequestBody UserDto user) { + public UserDto putUser(@RequestBody UserDto user) { return userService.updateUser(user); } @PatchMapping("/{id}") - public UserDto patchUser(@PathVariable long id, @RequestBody @Valid UserToUpdateDto user) { + public UserDto patchUser(@PathVariable long id, @RequestBody UserToUpdateDto user) { return userService.updateUser(id, user); } diff --git a/server/src/main/java/ru/practicum/shareit/user/storage/UserEntity.java b/server/src/main/java/ru/practicum/shareit/user/storage/UserEntity.java index 621f169..da64f3b 100644 --- a/server/src/main/java/ru/practicum/shareit/user/storage/UserEntity.java +++ b/server/src/main/java/ru/practicum/shareit/user/storage/UserEntity.java @@ -15,7 +15,7 @@ public class UserEntity { @Column(name = "user_id", nullable = false) private Long id; - @Column + @Column(nullable = false) private String name; @Column(nullable = false) private String email; diff --git a/server/src/main/java/ru/practicum/shareit/user/storage/UserStorageInDB.java b/server/src/main/java/ru/practicum/shareit/user/storage/UserStorageInDB.java index 01d0e73..75d8fff 100644 --- a/server/src/main/java/ru/practicum/shareit/user/storage/UserStorageInDB.java +++ b/server/src/main/java/ru/practicum/shareit/user/storage/UserStorageInDB.java @@ -4,7 +4,6 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; -import ru.practicum.shareit.user.UserMapper; import ru.practicum.shareit.user.UserStorage; import java.util.Optional; @@ -15,7 +14,6 @@ @Primary public class UserStorageInDB implements UserStorage { private final UserRepository userRepository; - private final UserMapper userMapper = new UserMapper(); @Override public Optional findUserId(long userId) { diff --git a/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java b/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java index c2edae8..139990f 100644 --- a/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java +++ b/server/src/test/java/ru/practicum/shareit/booking/BookingServiceTest.java @@ -70,15 +70,26 @@ public void findBookingWhileNotFoundBookingId() { } @Test - public void findBookingWhileUserIsNotCreatorOrOwner() { + public void findBookingWhileUserIsNotCreatorAndOwner() { + var ownerEntity = new UserEntity(); + ownerEntity.setId(1L); Mockito.when(userStorage.findUserId(Mockito.anyLong())) - .thenReturn(Optional.of(new UserEntity())); + .thenReturn(Optional.of(ownerEntity)); - Mockito.when(bookingStorage.findBooking(Mockito.anyLong())) - .thenReturn(Optional.of(new BookingEntity())); + var itemEntity = new ItemEntity(); + itemEntity.setId(2L); + itemEntity.setOwner(ownerEntity); - Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) - .thenReturn(false); + var bookerEntity = new UserEntity(); + bookerEntity.setId(4L); + + var bookingEntity = new BookingEntity(); + bookingEntity.setId(3L); + bookingEntity.setItem(itemEntity); + bookingEntity.setBooker(bookerEntity); + + Mockito.when(bookingStorage.findBooking(Mockito.anyLong())) + .thenReturn(Optional.of(bookingEntity)); try { bookingService.findBooking(10L, 10L); @@ -91,28 +102,85 @@ public void findBookingWhileUserIsNotCreatorOrOwner() { } @Test - public void findBooking() { - var userEntity = new UserEntity(); userEntity.setId(1L); + public void findBookingWhileUserIsNotCreator() { + var userEntity = new UserEntity(); + userEntity.setId(1L); Mockito.when(userStorage.findUserId(Mockito.anyLong())) .thenReturn(Optional.of(userEntity)); - var itemEntity = new ItemEntity(); itemEntity.setId(2L); + var itemEntity = new ItemEntity(); + itemEntity.setId(2L); + itemEntity.setOwner(userEntity); + + var bookerEntity = new UserEntity(); + bookerEntity.setId(4L); var bookingEntity = new BookingEntity(); bookingEntity.setId(3L); bookingEntity.setItem(itemEntity); - bookingEntity.setBooker(userEntity); + bookingEntity.setBooker(bookerEntity); bookingEntity.setStart(Timestamp.from(Instant.now())); bookingEntity.setEnd(Timestamp.from(Instant.now())); Mockito.when(bookingStorage.findBooking(Mockito.anyLong())) .thenReturn(Optional.of(bookingEntity)); - Mockito.when(bookingStorage.userIdIsBookerOrOwner(Mockito.any(BookingEntity.class), Mockito.anyLong())) - .thenReturn(true); + bookingService.findBooking(10L, 1L); + } + + @Test + public void findBookingWhileUserIsNotItemOwner() { + var userEntity = new UserEntity(); + userEntity.setId(1L); + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.of(userEntity)); + + var itemEntity = new ItemEntity(); + itemEntity.setId(2L); + itemEntity.setOwner(userEntity); + + var bookerEntity = new UserEntity(); + bookerEntity.setId(4L); + + var bookingEntity = new BookingEntity(); + bookingEntity.setId(3L); + bookingEntity.setItem(itemEntity); + bookingEntity.setBooker(bookerEntity); + bookingEntity.setStart(Timestamp.from(Instant.now())); + bookingEntity.setEnd(Timestamp.from(Instant.now())); + + Mockito.when(bookingStorage.findBooking(Mockito.anyLong())) + .thenReturn(Optional.of(bookingEntity)); + + bookingService.findBooking(10L, 4L); + } + + @Test + public void findBooking() { + var userEntity = new UserEntity(); + userEntity.setId(1L); + Mockito.when(userStorage.findUserId(Mockito.anyLong())) + .thenReturn(Optional.of(userEntity)); + + var itemEntity = new ItemEntity(); + itemEntity.setId(2L); + itemEntity.setOwner(userEntity); + + var bookerEntity = new UserEntity(); + bookerEntity.setId(4L); + + var bookingEntity = new BookingEntity(); + bookingEntity.setId(3L); + bookingEntity.setItem(itemEntity); + bookingEntity.setBooker(bookerEntity); + bookingEntity.setStart(Timestamp.from(Instant.now())); + bookingEntity.setEnd(Timestamp.from(Instant.now())); + + Mockito.when(bookingStorage.findBooking(Mockito.anyLong())) + .thenReturn(Optional.of(bookingEntity)); var expectedBookingDto = bookingEntity.toDto(); - var actualBookingDto = bookingService.findBooking(13L, 14L); + var actualBookingDto = bookingService.findBooking(13L, 1L); Assertions.assertEquals(expectedBookingDto, actualBookingDto); diff --git a/server/src/test/java/ru/practicum/shareit/booking/BookingStorageInDbTest.java b/server/src/test/java/ru/practicum/shareit/booking/BookingStorageInDbTest.java new file mode 100644 index 0000000..0eff88a --- /dev/null +++ b/server/src/test/java/ru/practicum/shareit/booking/BookingStorageInDbTest.java @@ -0,0 +1,127 @@ +package ru.practicum.shareit.booking; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.ComponentScan; +import ru.practicum.shareit.booking.storage.BookingEntity; +import ru.practicum.shareit.booking.storage.BookingStorageInDb; +import ru.practicum.shareit.item.ItemStorage; +import ru.practicum.shareit.item.storage.ItemEntity; +import ru.practicum.shareit.user.UserStorage; +import ru.practicum.shareit.user.storage.UserEntity; + +import java.sql.Timestamp; +import java.time.Instant; + +@DataJpaTest(properties = { + "spring.datasource.url=jdbc:h2:mem:testdb", + "spring.jpa.hibernate.ddl-auto=create-drop", + // "driverClassName=org.h2.Driver" + }, +showSql = false) +@ComponentScan(basePackages = "ru.practicum.shareit") +public class BookingStorageInDbTest { + @Autowired + BookingStorageInDb bookingStorageInDb; + @Autowired + UserStorage userStorage; + @Autowired + ItemStorage itemStorage; + + @Test + public void findBookingAndNotResult() { + var userEntity = new UserEntity(); + userEntity.setName("test"); + userEntity.setEmail("aa@BB.cc"); + userStorage.updateUser(userEntity); + + var itemEntity = new ItemEntity(); + itemEntity.setName("test"); + itemEntity.setOwner(userEntity); + + itemStorage.updateItem(itemEntity); + + var maxId = 0L; + + for (int i = 0; i < 10; i++) { + var entity = new BookingEntity(); + entity.setStatus(BookingStatus.APPROVED); + entity.setBooker(userEntity); + entity.setItem(itemEntity); + entity.setStart(Timestamp.from(Instant.now())); + entity.setEnd(Timestamp.from(Instant.now())); + + bookingStorageInDb.updateBooking(entity); + + var id = entity.getId(); + if (maxId < id) maxId = id; + } + + var actualBookingEntity = bookingStorageInDb.findBooking(maxId + 1L); + Assertions.assertTrue(actualBookingEntity.isEmpty()); + } + + @Test + public void findBooking() { + var userEntity = new UserEntity(); + userEntity.setName("test"); + userEntity.setEmail("aa@BB.cc"); + userStorage.updateUser(userEntity); + + var itemEntity = new ItemEntity(); + itemEntity.setName("test"); + itemEntity.setOwner(userEntity); + + itemStorage.updateItem(itemEntity); + + var entity = new BookingEntity(); + entity.setStatus(BookingStatus.APPROVED); + entity.setBooker(userEntity); + entity.setItem(itemEntity); + entity.setStart(Timestamp.from(Instant.now())); + entity.setEnd(Timestamp.from(Instant.now())); + + bookingStorageInDb.updateBooking(entity); + + var actualBookingEntity = bookingStorageInDb.findBooking(entity.getId()); + Assertions.assertTrue(actualBookingEntity.isPresent()); + Assertions.assertEquals(entity, actualBookingEntity.get()); + } + + @Test + public void updateBooking() { + var userEntity = new UserEntity(); + userEntity.setName("test"); + userEntity.setEmail("aa@BB.cc"); + userStorage.updateUser(userEntity); + + var itemEntity = new ItemEntity(); + itemEntity.setName("test"); + itemEntity.setOwner(userEntity); + + itemStorage.updateItem(itemEntity); + + var entity = new BookingEntity(); + entity.setStatus(BookingStatus.APPROVED); + entity.setBooker(userEntity); + entity.setItem(itemEntity); + + entity.setStart(Timestamp.from(Instant.now())); + entity.setEnd(Timestamp.from(Instant.now())); + + var otherUserEntity = new UserEntity(); + otherUserEntity.setName("test2"); + otherUserEntity.setEmail("aa2@BB.cc"); + userStorage.updateUser(otherUserEntity); + + bookingStorageInDb.updateBooking(entity); //Создание записи + + entity.setBooker(otherUserEntity); + + bookingStorageInDb.updateBooking(entity); + + Assertions.assertEquals(otherUserEntity, entity.getBooker()); + } +} diff --git a/server/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java b/server/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java index c41bed8..4e5abc1 100644 --- a/server/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java +++ b/server/src/test/java/ru/practicum/shareit/request/RequestControllerTest.java @@ -67,7 +67,7 @@ public void getSelfRequestsTest() throws Exception { RequestDto.builder().id(37L).build() ); - Mockito.when(requestService.getRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) + Mockito.when(requestService.findRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) .thenReturn(expectedRequests); mockMvc.perform(get("/requests") @@ -78,7 +78,7 @@ public void getSelfRequestsTest() throws Exception { .andExpect(jsonPath("$[2].id", is(37L), Long.class)); Mockito.verify(requestService, Mockito.times(1)) - .getRequestsByUserId(7L, true); + .findRequestsByUserId(7L, true); } @Test @@ -89,7 +89,7 @@ void getRequestByIdTest() throws Exception { var expectedResult = RequestDto.builder().id(13L).build(); - Mockito.when(requestService.getRequestById(Mockito.anyLong())) + Mockito.when(requestService.findRequestById(Mockito.anyLong())) .thenReturn(expectedResult); mockMvc.perform(get("/requests/23")) @@ -97,7 +97,7 @@ void getRequestByIdTest() throws Exception { .andExpect(jsonPath("$.id",is(13L), Long.class)); Mockito.verify(requestService, Mockito.times(1)) - .getRequestById(23L); + .findRequestById(23L); } @Test @@ -112,7 +112,7 @@ void getOtherUserRequestsTest() throws Exception { RequestDto.builder().id(37L).build() ); - Mockito.when(requestService.getRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) + Mockito.when(requestService.findRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) .thenReturn(expectedRequests); mockMvc.perform(get("/requests/all") @@ -123,7 +123,7 @@ void getOtherUserRequestsTest() throws Exception { .andExpect(jsonPath("$[2].id", is(37L), Long.class)); Mockito.verify(requestService, Mockito.times(1)) - .getRequestsByUserId(7L, false); + .findRequestsByUserId(7L, false); } @Test diff --git a/server/src/test/java/ru/practicum/shareit/request/RequestServiceTest.java b/server/src/test/java/ru/practicum/shareit/request/RequestServiceTest.java index 4f109f9..94aa014 100644 --- a/server/src/test/java/ru/practicum/shareit/request/RequestServiceTest.java +++ b/server/src/test/java/ru/practicum/shareit/request/RequestServiceTest.java @@ -84,12 +84,12 @@ public void createRequestTest() { } @Test - public void getRequestsByUserIdWhileNotFoundUserTest() { + public void findRequestsByUserIdWhileNotFoundUserTest() { Mockito.when(userStorage.existsById(Mockito.anyLong())) .thenReturn(false); try { - requestService.getRequestsByUserId(1L, true); + requestService.findRequestsByUserId(1L, true); } catch (NotFoundException ex) { Assertions.assertEquals("Пользователь не найден", ex.getMessage()); return; @@ -99,7 +99,7 @@ public void getRequestsByUserIdWhileNotFoundUserTest() { } @Test - public void getRequestsByUserIdTest() { + public void findRequestsByUserIdTest() { Mockito.when(userStorage.existsById(Mockito.anyLong())) .thenReturn(true); @@ -114,10 +114,10 @@ public void getRequestsByUserIdTest() { .map(i -> RequestMapper.toEntity(i, userEntity)) .toList(); - Mockito.when(requestStorage.getRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) + Mockito.when(requestStorage.findRequestsByUserId(Mockito.anyLong())) .thenReturn(requestEntities); - var actualRequestDtos = requestService.getRequestsByUserId(11L, true); + var actualRequestDtos = requestService.findRequestsByUserId(11L, true); var expectedRequestDtos = requestEntities.stream().map(RequestEntity::toDto).toList(); @@ -127,11 +127,14 @@ public void getRequestsByUserIdTest() { .existsById(11L); Mockito.verify(requestStorage, Mockito.times(1)) - .getRequestsByUserId(11L, true); + .findRequestsByUserId(11L); + + Mockito.verify(requestStorage, Mockito.never()) + .findRequestsByNotUserId(Mockito.anyLong()); } @Test - public void getRequestsByUserIdWhileParamIsFalseTest() { + public void findRequestsByUserIdWhileParamIsFalseTest() { Mockito.when(userStorage.existsById(Mockito.anyLong())) .thenReturn(true); @@ -146,17 +149,23 @@ public void getRequestsByUserIdWhileParamIsFalseTest() { .map(i -> RequestMapper.toEntity(i, userEntity)) .toList(); - Mockito.when(requestStorage.getRequestsByUserId(Mockito.anyLong(), Mockito.anyBoolean())) + Mockito.when(requestStorage.findRequestsByNotUserId(Mockito.anyLong())) .thenReturn(requestEntities); - var actualRequestDtos = requestService.getRequestsByUserId(13L, false); + var actualRequestDtos = requestService.findRequestsByUserId(13L, false); var expectedRequestDtos = requestEntities.stream().map(RequestEntity::toDto).toList(); Assertions.assertEquals(expectedRequestDtos, actualRequestDtos); + Mockito.verify(userStorage, Mockito.never()) + .existsById(Mockito.anyLong()); + + Mockito.verify(requestStorage, Mockito.never()) + .findRequestsByUserId(Mockito.anyLong()); + Mockito.verify(requestStorage, Mockito.times(1)) - .getRequestsByUserId(13L, false); + .findRequestsByNotUserId(13L); } @Test @@ -165,7 +174,7 @@ public void getRequestsIdWhileNotFoundUserTest() { .thenReturn(Optional.empty()); try { - requestService.getRequestById(1L); + requestService.findRequestById(1L); } catch (NotFoundException ex) { Assertions.assertEquals("Запрос не найден", ex.getMessage()); return; @@ -175,14 +184,14 @@ public void getRequestsIdWhileNotFoundUserTest() { } @Test - public void getRequestByIdTest() { + public void findRequestByIdTest() { var requestEntity = new RequestEntity(); requestEntity.setId(15L); Mockito.when(requestStorage.findRequestById(Mockito.anyLong())) .thenReturn(Optional.of(requestEntity)); - var actualRequestDto = requestService.getRequestById(11L); + var actualRequestDto = requestService.findRequestById(11L); var expectedRequestDto = requestEntity.toDto();