diff --git a/src/main/java/cat/udl/eps/softarch/demo/config/DBInitialization.java b/src/main/java/cat/udl/eps/softarch/demo/config/DBInitialization.java index b9b8ad6..db6b5f3 100644 --- a/src/main/java/cat/udl/eps/softarch/demo/config/DBInitialization.java +++ b/src/main/java/cat/udl/eps/softarch/demo/config/DBInitialization.java @@ -1,12 +1,18 @@ package cat.udl.eps.softarch.demo.config; import cat.udl.eps.softarch.demo.domain.Owner; +import cat.udl.eps.softarch.demo.domain.Advertisement; import cat.udl.eps.softarch.demo.domain.User; import cat.udl.eps.softarch.demo.repository.OwnerRepository; +import cat.udl.eps.softarch.demo.repository.AdvertisementRepository; import cat.udl.eps.softarch.demo.repository.UserRepository; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import jakarta.annotation.PostConstruct; + +import java.math.BigDecimal; import java.util.Arrays; +import cat.udl.eps.softarch.demo.domain.Advertisement; +import cat.udl.eps.softarch.demo.repository.AdvertisementRepository; import java.util.Set; @Configuration @@ -17,10 +23,12 @@ public class DBInitialization { @Value("${spring.profiles.active:}") private String activeProfiles; private final UserRepository userRepository; + private final AdvertisementRepository advertisementRepository; - public DBInitialization(UserRepository userRepository, OwnerRepository ownerRepository) { + public DBInitialization(UserRepository userRepository, OwnerRepository ownerRepository, AdvertisementRepository advertisementRepository) { this.userRepository = userRepository; this.ownerRepository = ownerRepository; + this.advertisementRepository = advertisementRepository; } @PostConstruct @@ -45,6 +53,7 @@ public void initializeDatabase() { owner.encodePassword(); ownerRepository.save(owner); } + if (!ownerRepository.existsById("owner1")) { Owner owner = new Owner(); owner.setEmail("owner1@sample.app"); diff --git a/src/main/java/cat/udl/eps/softarch/demo/config/WebSecurityConfig.java b/src/main/java/cat/udl/eps/softarch/demo/config/WebSecurityConfig.java index 8dbeb9b..2cfc3a7 100644 --- a/src/main/java/cat/udl/eps/softarch/demo/config/WebSecurityConfig.java +++ b/src/main/java/cat/udl/eps/softarch/demo/config/WebSecurityConfig.java @@ -41,6 +41,8 @@ protected SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exce .requestMatchers(HttpMethod.POST, "/properties").hasAuthority("ROLE_OWNER") .requestMatchers(HttpMethod.PUT, "/properties/*").hasAuthority("ROLE_OWNER") .requestMatchers(HttpMethod.DELETE, "/properties/*").hasAuthority("ROLE_OWNER") + .requestMatchers(HttpMethod.POST, "/visits").authenticated() + .requestMatchers(HttpMethod.DELETE, "/visits/*").authenticated() .requestMatchers(HttpMethod.POST, "/*/*").authenticated() .requestMatchers(HttpMethod.PUT, "/*/*").authenticated() .requestMatchers(HttpMethod.PATCH, "/*/*").authenticated() diff --git a/src/main/java/cat/udl/eps/softarch/demo/domain/Visit.java b/src/main/java/cat/udl/eps/softarch/demo/domain/Visit.java index 94908c8..5070dc0 100644 --- a/src/main/java/cat/udl/eps/softarch/demo/domain/Visit.java +++ b/src/main/java/cat/udl/eps/softarch/demo/domain/Visit.java @@ -1,26 +1,37 @@ package cat.udl.eps.softarch.demo.domain; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import com.fasterxml.jackson.annotation.JsonIdentityReference; +import jakarta.persistence.*; +import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.EqualsAndHashCode; +import lombok.*; import java.time.ZonedDateTime; @EqualsAndHashCode(callSuper = true) -@Entity +@Entity(name = "visit") @Data -public class Visit extends UriEntity{ +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class Visit extends UriEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @NotNull + @Column(name = "visit_date") private ZonedDateTime when; -} + + @ManyToOne + @NotNull + @JsonIdentityReference(alwaysAsId = true) + private Advertisement advertisement; + + public void setVisitDateTime(ZonedDateTime parse) { + this.when = parse; + } +} \ No newline at end of file diff --git a/src/main/java/cat/udl/eps/softarch/demo/repository/VisitRepository.java b/src/main/java/cat/udl/eps/softarch/demo/repository/VisitRepository.java index 48b93e0..326f174 100644 --- a/src/main/java/cat/udl/eps/softarch/demo/repository/VisitRepository.java +++ b/src/main/java/cat/udl/eps/softarch/demo/repository/VisitRepository.java @@ -1,6 +1,7 @@ package cat.udl.eps.softarch.demo.repository; +import cat.udl.eps.softarch.demo.domain.Advertisement; import cat.udl.eps.softarch.demo.domain.Visit; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; @@ -14,4 +15,5 @@ public interface VisitRepository extends CrudRepository, PagingAndS Optional findById(@Param("id") Long id); List findByWhen(@Param("when") ZonedDateTime when); + List findByAdvertisement(@Param("advertisement") Advertisement advertisement); } diff --git a/src/test/java/cat/udl/eps/softarch/demo/steps/DeleteVisitSteps.java b/src/test/java/cat/udl/eps/softarch/demo/steps/DeleteVisitSteps.java new file mode 100644 index 0000000..162bb1c --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/demo/steps/DeleteVisitSteps.java @@ -0,0 +1,56 @@ +package cat.udl.eps.softarch.demo.steps; + +import cat.udl.eps.softarch.demo.domain.Advertisement; +import cat.udl.eps.softarch.demo.domain.Visit; +import cat.udl.eps.softarch.demo.repository.AdvertisementRepository; +import cat.udl.eps.softarch.demo.repository.VisitRepository; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import org.junit.jupiter.api.Assertions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MvcResult; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +public class DeleteVisitSteps { + + @Autowired + private StepDefs stepDefs; + + @Autowired + private VisitRepository visitRepository; + + @Autowired + private AdvertisementRepository advertisementRepository; + + private MvcResult result; + + + + @When("I delete the visit request to the advertisement with title {string}") + public void iDeleteTheVisitRequestToTheAdvertisementWithTitle(String title) throws Exception { + + Advertisement advertisement = advertisementRepository.findByTitle(title).get(0); + Visit visit = visitRepository.findByAdvertisement(advertisement).get(0); + + result = stepDefs.mockMvc.perform(delete( "/visits/" + visit.getId() ) + .contentType(MediaType.APPLICATION_JSON) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()) + .andExpect(status().isNoContent()) + .andReturn(); + + + + } + + @Then("The visit is successfully deleted") + public void theVisitIsSuccessfullyDeleted() { + assertNotNull(result, "Result should not be null after visit deletion"); + Assertions.assertEquals(204, result.getResponse().getStatus(), "Expected HTTP status 200 OK"); + } +} diff --git a/src/test/java/cat/udl/eps/softarch/demo/steps/GetAdvertismentStepDefs.java b/src/test/java/cat/udl/eps/softarch/demo/steps/GetAdvertismentStepDefs.java new file mode 100644 index 0000000..959d9e4 --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/demo/steps/GetAdvertismentStepDefs.java @@ -0,0 +1,56 @@ +package cat.udl.eps.softarch.demo.steps; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; + +import cat.udl.eps.softarch.demo.repository.ApartmentRepository; +import io.cucumber.java.en.And; +import org.springframework.http.MediaType; +import cat.udl.eps.softarch.demo.domain.*; +import cat.udl.eps.softarch.demo.repository.AdvertisementRepository; +import cat.udl.eps.softarch.demo.repository.AdvertisementStatusRepository; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.When; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; + +import java.math.BigDecimal; +import java.time.ZonedDateTime; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class GetAdvertismentStepDefs { + + @Autowired + private AdvertisementRepository advertisementRepository; + + @Autowired + private ApartmentRepository apartmentRepository; + @Autowired + private AdvertisementStatusRepository advertisementStatusRepository; + private AdvertisementStatus status; + private ResponseEntity response; + @Autowired + private StepDefs stepDefs; + + @When("I get the apartment advertisement with title {string}") + public void iGetTheApartmentAdvertisement(String title) throws Exception { + Advertisement ad = advertisementRepository.findByTitle(title).stream().findFirst().orElse(null); + + if (ad == null) { + stepDefs.result = stepDefs.mockMvc.perform( + get("/advertisements/{id}", 9999) + .accept(MediaType.APPLICATION_JSON) + ).andDo(print()); + } else { + stepDefs.result = stepDefs.mockMvc.perform( + get("/advertisements/{id}", ad.getId()) + .accept(MediaType.APPLICATION_JSON) + ).andDo(print()); + } + } + +} diff --git a/src/test/java/cat/udl/eps/softarch/demo/steps/PatchAdvStepDefs.java b/src/test/java/cat/udl/eps/softarch/demo/steps/PatchAdvStepDefs.java new file mode 100644 index 0000000..d1e17fb --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/demo/steps/PatchAdvStepDefs.java @@ -0,0 +1,50 @@ +package cat.udl.eps.softarch.demo.steps; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; + +import cat.udl.eps.softarch.demo.domain.Advertisement; +import cat.udl.eps.softarch.demo.repository.AdvertisementRepository; +import io.cucumber.core.internal.com.fasterxml.jackson.databind.ObjectMapper; +import io.cucumber.java.en.When; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; + + + +import java.util.HashMap; +import java.util.Map; + +public class PatchAdvStepDefs { + + @Autowired + private AdvertisementRepository advertisementRepository; + + @Autowired + private StepDefs stepDefs; + + @When("I patch the apartment advertisement with title {string} and new description {string}") + public void iPatchTheApartmentAdvertisement(String title, String newDescription) throws Exception { + Advertisement ad = advertisementRepository.findByTitle(title).stream().findFirst().orElse(null); + + Map updatedFields = new HashMap<>(); + updatedFields.put("description", newDescription); + String jsonContent = new ObjectMapper().writeValueAsString(updatedFields); + + if (ad == null) { + stepDefs.result = stepDefs.mockMvc.perform( + patch("/advertisements/{id}", 9999) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonContent) + .with(AuthenticationStepDefs.authenticate()) + ).andDo(print()); + } else { + stepDefs.result = stepDefs.mockMvc.perform( + patch("/advertisements/{id}", ad.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonContent) + .with(AuthenticationStepDefs.authenticate()) + ).andDo(print()); + } + } +} diff --git a/src/test/java/cat/udl/eps/softarch/demo/steps/RequestVisitStepDefs.java b/src/test/java/cat/udl/eps/softarch/demo/steps/RequestVisitStepDefs.java new file mode 100644 index 0000000..6b33c59 --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/demo/steps/RequestVisitStepDefs.java @@ -0,0 +1,140 @@ +package cat.udl.eps.softarch.demo.steps; + +import cat.udl.eps.softarch.demo.domain.Advertisement; +import cat.udl.eps.softarch.demo.domain.AdvertisementStatus; +import cat.udl.eps.softarch.demo.domain.Apartment; +import cat.udl.eps.softarch.demo.domain.Visit; +import cat.udl.eps.softarch.demo.repository.AdvertisementRepository; +import cat.udl.eps.softarch.demo.repository.AdvertisementStatusRepository; +import cat.udl.eps.softarch.demo.repository.ApartmentRepository; +import cat.udl.eps.softarch.demo.repository.VisitRepository; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import org.checkerframework.checker.units.qual.A; +import org.junit.jupiter.api.Assertions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MvcResult; + +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.time.ZonedDateTime; +import java.util.Objects; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +public class RequestVisitStepDefs { + + @Autowired + private StepDefs stepDefs; + + @Autowired + private VisitRepository visitRepository; + + @Autowired + private ApartmentRepository apartmentRepository; + + @Autowired + private AdvertisementRepository advertisementRepository; + @Autowired + private AdvertisementStatusRepository advertisementStatusRepository; + + private MvcResult result; + private Advertisement advertisement; + + + public void createAdvertisementStatus(String status) { + AdvertisementStatus advertisementStatus = new AdvertisementStatus(); + advertisementStatus.setStatus(status); + advertisementStatusRepository.save(advertisementStatus); + + } + @Given("There is an advertisement with title {string} and address {string}") + public void thereIsAnAdvertisementWithTitleAndAddress(String title, String address) { + advertisement = new Advertisement(); + advertisement.setTitle(title); + advertisement.setAddress(address); + advertisement.setDescription("A cozy loft in the center of Barcelona"); + advertisement.setPrice(new BigDecimal("1000.00")); + advertisement.setZipCode("08001"); + advertisement.setCountry("Spain"); + advertisement.setCreationDate(ZonedDateTime.now()); + String visitDateTime = ZonedDateTime.now().plusDays(30).toString(); + Apartment apartment = ApartmentUtils.buildApartment("Apartment", "2", "Apartment", "25182", "Lleida", "Spain", "Apartment", visitDateTime); + apartmentRepository.save(apartment); + advertisement.setApartment(apartment); + createAdvertisementStatus("Available"); + AdvertisementStatus cur_status = advertisementStatusRepository.findByStatus("Available").stream().findFirst().orElse(null); + advertisement.setAdStatus(cur_status); + + advertisement = advertisementRepository.save(advertisement); + } + + @When("I request a visit to the advertisement with title {string}") + public void iRequestAVisitToTheAdvertisementWithTitle(String title) throws Exception { + + Advertisement advertisement; + + if(title.equals("Invalid Advertisement")) + advertisement = null; + else { + advertisement = advertisementRepository.findByTitle(title).get(0); + } + + String visitDateTime = ZonedDateTime.now().plusDays(30).toString(); + Visit visit = new Visit(); + visit.setVisitDateTime(ZonedDateTime.parse(visitDateTime)); + visit.setAdvertisement(advertisement); + + + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + + + String jsonContent = objectMapper.writeValueAsString(visit); + + if(advertisement != null) { + result = stepDefs.mockMvc.perform(post("/visits") + .contentType(MediaType.APPLICATION_JSON) + .content(jsonContent) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()) + .andExpect(status().isCreated()) + .andReturn(); + } else if (advertisement == null) { + + result = stepDefs.mockMvc.perform(post("/visits") + .contentType(MediaType.APPLICATION_JSON) + .content(jsonContent) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()) + .andExpect(status().isBadRequest()) + .andReturn(); + } + + + } + + @Then("The visit is successfully requested") + public void theVisitIsSuccessfullyRequested() { + assertNotNull(result, "Result should not be null after visit request"); + Assertions.assertEquals(201, result.getResponse().getStatus(), "Expected HTTP status 201 Created"); + } + + + @Then("The visit is not successfully requested") + public void theVisitIsNotSuccessfullyRequested() { + assertNotNull(result, "Result should not be null after visit request"); + Assertions.assertEquals(400, result.getResponse().getStatus(), "Expected HTTP status 400 Bad Request"); + } + + +} diff --git a/src/test/java/cat/udl/eps/softarch/demo/steps/UpdateAdvertisementStepDefs.java b/src/test/java/cat/udl/eps/softarch/demo/steps/UpdateAdvertisementStepDefs.java new file mode 100644 index 0000000..78df593 --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/demo/steps/UpdateAdvertisementStepDefs.java @@ -0,0 +1,200 @@ +package cat.udl.eps.softarch.demo.steps; + +import cat.udl.eps.softarch.demo.domain.*; +import cat.udl.eps.softarch.demo.repository.AdvertisementRepository; +import cat.udl.eps.softarch.demo.repository.AdvertisementStatusRepository; +import cat.udl.eps.softarch.demo.repository.ApartmentRepository; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; + +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; + +public class UpdateAdvertisementStepDefs { + + @Autowired + private AdvertisementStatusRepository advertisementStatusRepository; + + @Autowired + private AdvertisementRepository advertisementRepository; + + @Autowired + private ApartmentRepository apartmentRepository; + + @Autowired + private StepDefs stepDefs; + + + @When("I update an advertisement with title {string} to have name {string} and address {string}") + public void iUpdateAdvertisement(String title, String newTitle, String newAddress) throws Exception { + List ads = advertisementRepository.findByTitle(title); + + if (ads.isEmpty()) { + throw new IllegalArgumentException("Advertisement with title " + title + " not found"); + } + + Advertisement advertisement = ads.get(0); + advertisement.setTitle(newTitle); + advertisement.setAddress(newAddress); + advertisementRepository.save(advertisement); + + stepDefs.result = stepDefs.mockMvc.perform(put("/advertisements/" + advertisement.getId()) + .with(AuthenticationStepDefs.authenticate()) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(stepDefs.mapper.writeValueAsString(advertisement)) + .characterEncoding(StandardCharsets.UTF_8)) + .andDo(print()); + } + + + + @Then("The advertisement with title {string} should have name {string} and address {string}") + public void theAdvertisementWithTitleShouldHaveNameAndAddress(String title, String expectedName, String expectedAddress) throws Exception { + Advertisement updatedAdvertisement = advertisementRepository.findByTitle(title).stream().findFirst().orElse(null); + + if (updatedAdvertisement == null) { + throw new IllegalArgumentException("Advertisement with title " + title + " not found"); + } + + assertEquals(expectedName, updatedAdvertisement.getTitle()); + assertEquals(expectedAddress, updatedAdvertisement.getAddress()); + } + + @When("I update the advertisement with title {string} to have price {string}") + public void iUpdateAdvertisementPrice(String title, String newPrice) throws Exception { + List ads = advertisementRepository.findByTitle(title); + + if (ads.isEmpty()) { + throw new IllegalArgumentException("Advertisement with title " + title + " not found"); + } + + Advertisement advertisement = ads.get(0); + advertisement.setPrice(new BigDecimal(newPrice)); + + stepDefs.result = stepDefs.mockMvc.perform(put("/advertisements/" + advertisement.getId()) + .with(AuthenticationStepDefs.authenticate()) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(stepDefs.mapper.writeValueAsString(advertisement)) + .characterEncoding(StandardCharsets.UTF_8)) + .andDo(print()); + } + + @Then("The advertisement with title {string} should have price {string}") + public void theAdvertisementWithTitleShouldHavePrice(String title, String expectedPrice) throws Exception { + Advertisement updatedAdvertisement = advertisementRepository.findByTitle(title).stream().findFirst().orElse(null); + + if (updatedAdvertisement == null) { + throw new IllegalArgumentException("Advertisement with title " + title + " not found"); + } + + assertEquals(new BigDecimal(expectedPrice), updatedAdvertisement.getPrice()); + } + + @When("I update the advertisement with title {string} to have zipCode {string}") + public void iUpdateAdvertisementZipCode(String title, String newZipCode) throws Exception { + List ads = advertisementRepository.findByTitle(title); + + if (ads.isEmpty()) { + throw new IllegalArgumentException("Advertisement with title " + title + " not found"); + } + + Advertisement advertisement = ads.get(0); + advertisement.setZipCode(newZipCode); + advertisementRepository.save(advertisement); + + stepDefs.result = stepDefs.mockMvc.perform(put("/advertisements/" + advertisement.getId()) + .with(AuthenticationStepDefs.authenticate()) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(stepDefs.mapper.writeValueAsString(advertisement)) + .characterEncoding(StandardCharsets.UTF_8)) + .andDo(print()); + } + + @Then("The advertisement with title {string} should have zipCode {string}") + public void theAdvertisementWithTitleShouldHaveZipCode(String title, String expectedZipCode) throws Exception { + Advertisement updatedAdvertisement = advertisementRepository.findByTitle(title).stream().findFirst().orElse(null); + + if (updatedAdvertisement == null) { + throw new IllegalArgumentException("Advertisement with title " + title + " not found"); + } + + assertEquals(expectedZipCode, updatedAdvertisement.getZipCode()); + } + + @When("I update the advertisement with title {string} to have country {string}") + public void iUpdateAdvertisementCountry(String title, String newCountry) throws Exception { + List ads = advertisementRepository.findByTitle(title); + + if (ads.isEmpty()) { + throw new IllegalArgumentException("Advertisement with title " + title + " not found"); + } + + Advertisement advertisement = ads.get(0); + advertisement.setCountry(newCountry); + advertisementRepository.save(advertisement); + + stepDefs.result = stepDefs.mockMvc.perform(put("/advertisements/" + advertisement.getId()) + .with(AuthenticationStepDefs.authenticate()) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(stepDefs.mapper.writeValueAsString(advertisement)) + .characterEncoding(StandardCharsets.UTF_8)) + .andDo(print()); + } + + @Then("The advertisement with title {string} should have country {string}") + public void theAdvertisementWithTitleShouldHaveCountry(String title, String expectedCountry) throws Exception { + Advertisement updatedAdvertisement = advertisementRepository.findByTitle(title).stream().findFirst().orElse(null); + + if (updatedAdvertisement == null) { + throw new IllegalArgumentException("Advertisement with title " + title + " not found"); + } + + assertEquals(expectedCountry, updatedAdvertisement.getCountry()); + } + + @When("I update the advertisement with title {string} to have description {string}") + public void iUpdateAdvertisementDescription(String title, String newDescription) throws Exception { + List ads = advertisementRepository.findByTitle(title); + + if (ads.isEmpty()) { + throw new IllegalArgumentException("Advertisement with title " + title + " not found"); + } + + Advertisement advertisement = ads.get(0); + advertisement.setDescription(newDescription); + advertisementRepository.save(advertisement); + + stepDefs.result = stepDefs.mockMvc.perform(put("/advertisements/" + advertisement.getId()) + .with(AuthenticationStepDefs.authenticate()) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(stepDefs.mapper.writeValueAsString(advertisement)) + .characterEncoding(StandardCharsets.UTF_8)) + .andDo(print()); + } + + @Then("The advertisement with title {string} should have description {string}") + public void theAdvertisementWithTitleShouldHaveDescription(String title, String expectedDescription) throws Exception { + Advertisement updatedAdvertisement = advertisementRepository.findByTitle(title).stream().findFirst().orElse(null); + + if (updatedAdvertisement == null) { + throw new IllegalArgumentException("Advertisement with title " + title + " not found"); + } + + assertEquals(expectedDescription, updatedAdvertisement.getDescription()); + } + + +} diff --git a/src/test/resources/features/DeleteVisit.feature b/src/test/resources/features/DeleteVisit.feature new file mode 100644 index 0000000..77c7577 --- /dev/null +++ b/src/test/resources/features/DeleteVisit.feature @@ -0,0 +1,13 @@ +# Created by abdee at 31/10/24 +# Created by abdee at 17/10/24 +Feature: Delete Visit + As a user + I want to delete a visit to an advertisement + So that I can cancel the visit request + +Scenario: Delete visit request + Given There is an advertisement with title "Cozy Loft" and address "Carrer de les Flors 10" + And I login as "demo" with password "password" + And I request a visit to the advertisement with title "Cozy Loft" + When I delete the visit request to the advertisement with title "Cozy Loft" + Then The visit is successfully deleted \ No newline at end of file diff --git a/src/test/resources/features/GetAdvertisment.feature b/src/test/resources/features/GetAdvertisment.feature new file mode 100644 index 0000000..419c05c --- /dev/null +++ b/src/test/resources/features/GetAdvertisment.feature @@ -0,0 +1,28 @@ +Feature: Get Advertisement + In order to use the app + users can retrieve advertisement details for existing apartments + + Scenario: Get an existing apartment advertisement by title + Given There is an existing apartment with id "1" named "Cozy Apartment" + And I login as "owner" with password "password" + And There is an existing advertisement status "Available" + And There is an advertisement with title "Apartment for rent", description "A beautiful apartment", price "1200", zipCode "12345", address "456 Elm St", country "Spain", status "Available", apartment title "Cozy Apartment" + When I get the apartment advertisement with title "Apartment for rent" + Then The response code is 200 + + Scenario: Get a non-existing apartment advertisement by title + Given There is an existing apartment with id "1" named "Cozy Apartment" + And I login as "owner" with password "password" + And There is an existing advertisement status "Available" + And There is an advertisement with title "Apartment for rent", description "A beautiful apartment", price "1200", zipCode "12345", address "456 Elm St", country "Spain", status "Available", apartment title "Cozy Apartment" + When I get the apartment advertisement with title "non existing title" + Then The response code is 404 + + + Scenario: Get apartment advertisement when not authenticated + Given There is an existing apartment with id "1" named "Cozy Apartment" + And There is an existing advertisement status "Available" + And There is an advertisement with title "Apartment for rent", description "A beautiful apartment", price "1200", zipCode "12345", address "456 Elm St", country "Spain", status "Available", apartment title "Cozy Apartment" + Given I'm not logged in + When I get the apartment advertisement with title "Apartment for rent" + Then The response code is 200 diff --git a/src/test/resources/features/PatchAdvertisment.feature b/src/test/resources/features/PatchAdvertisment.feature new file mode 100644 index 0000000..da27387 --- /dev/null +++ b/src/test/resources/features/PatchAdvertisment.feature @@ -0,0 +1,28 @@ +Feature: Patch Advertisement + In order to update advertisement details + as an authenticated owner + I want to patch an existing advertisement's data + + Scenario: Patch an existing apartment advertisement + Given There is an existing apartment with id "1" named "Cozy Apartment" + And I login as "owner" with password "password" + And There is an existing advertisement status "Available" + And There is an advertisement with title "Apartment for rent", description "Old description", price "1200", zipCode "12345", address "456 Elm St", country "Spain", status "Available", apartment title "Cozy Apartment" + When I patch the apartment advertisement with title "Apartment for rent" and new description "Updated description" + Then The response code is 204 + + + Scenario: Patch a non-existing apartment advertisement + Given There is an existing apartment with id "1" named "Cozy Apartment" + Given I login as "owner" with password "password" + And There is an existing advertisement status "Available" + When I patch the apartment advertisement with title "Non-existing title" and new description "Should not update" + Then The response code is 404 + + Scenario: Patch an advertisement when not authenticated + Given There is an existing apartment with id "1" named "Cozy Apartment" + And There is an existing advertisement status "Available" + And There is an advertisement with title "Apartment for rent", description "Old description", price "1200", zipCode "12345", address "456 Elm St", country "Spain", status "Available", apartment title "Cozy Apartment" + Given I'm not logged in + When I patch the apartment advertisement with title "Apartment for rent" and new description "Updated description" + Then The response code is 401 diff --git a/src/test/resources/features/RequestVisit.feature b/src/test/resources/features/RequestVisit.feature new file mode 100644 index 0000000..31ba485 --- /dev/null +++ b/src/test/resources/features/RequestVisit.feature @@ -0,0 +1,18 @@ +# Created by abdee at 17/10/24 +Feature: Request Visit + As a user + I want to request a visit to an advertisement + So that I can see the advertisement in person + + Scenario: Successful visit request + Given There is an advertisement with title "Cozy Loft" and address "Carrer de les Flors 10" + And I login as "demo" with password "password" + When I request a visit to the advertisement with title "Cozy Loft" + Then The visit is successfully requested + + Scenario: Visit request with invalid advertisement + Given There is an advertisement with title "Cozy Loft" and address "Carrer de les Flors 10" + And I login as "demo" with password "password" + When I request a visit to the advertisement with title "Invalid Advertisement" + Then The visit is not successfully requested + diff --git a/src/test/resources/features/UpdateAdvertisement.feature b/src/test/resources/features/UpdateAdvertisement.feature new file mode 100644 index 0000000..45371ca --- /dev/null +++ b/src/test/resources/features/UpdateAdvertisement.feature @@ -0,0 +1,60 @@ +Feature: Update Advertisement + In order to update advertisements in the system + As a user + I want to be able to create and update advertisements + + Background: + Given There is a registered user with username "owner" and password "password" and email "test@test.com" + Given There is an existing apartment with id "1" named "Luxury Suite" + And There is an existing advertisement status "Active" + + Scenario: Create and update an advertisement without logged in + Given I'm not logged in + Given There is an advertisement with title "Luxury Suite Ad", description "A beautiful suite", price "2000", zipCode "12345", address "High Street 123", country "Wonderland", status "Active", apartment title "Luxury Suite" + When I update an advertisement with title "Luxury Suite Ad" to have name "Updated Suite Ad" and address "Updated Street 123" + Then The advertisement with title "Updated Suite Ad" should have name "Updated Suite Ad" and address "Updated Street 123" + And The response code is 401 + + Scenario: Create and update an advertisement + Given I login as "owner" with password "password" + Given There is an advertisement with title "Luxury Suite Ad", description "A beautiful suite", price "2000", zipCode "12345", address "High Street 123", country "Wonderland", status "Active", apartment title "Luxury Suite" + When I update an advertisement with title "Luxury Suite Ad" to have name "Updated Suite Ad" and address "Updated Street 123" + Then The advertisement with title "Updated Suite Ad" should have name "Updated Suite Ad" and address "Updated Street 123" + And The response code is 200 + + Scenario: Update advertisement price + Given I login as "owner" with password "password" + Given There is an advertisement with title "Luxury Suite Ad", description "A beautiful suite", price "2000", zipCode "12345", address "High Street 123", country "Wonderland", status "Active", apartment title "Luxury Suite" + When I update the advertisement with title "Luxury Suite Ad" to have price "2500" + Then The advertisement with title "Luxury Suite Ad" should have price "2500.00" + And The response code is 200 + + Scenario: Attempt to update advertisement with invalid data + Given I login as "owner" with password "password" + Given There is an advertisement with title "Luxury Suite Ad", description "A beautiful suite", price "2000", zipCode "12345", address "High Street 123", country "Wonderland", status "Active", apartment title "Luxury Suite" + When I update the advertisement with title "Luxury Suite Ad" to have price "-100.00" + Then The response code is 400 + And The error message is "must be greater than or equal to 0.01" + + Scenario: Update advertisement zip code + Given I login as "owner" with password "password" + Given There is an advertisement with title "Luxury Suite Ad", description "A beautiful suite", price "2000", zipCode "12345", address "High Street 123", country "Wonderland", status "Active", apartment title "Luxury Suite" + When I update the advertisement with title "Luxury Suite Ad" to have zipCode "54321" + Then The advertisement with title "Luxury Suite Ad" should have zipCode "54321" + And The response code is 200 + + Scenario: Update advertisement country + Given I login as "owner" with password "password" + Given There is an advertisement with title "Luxury Suite Ad", description "A beautiful suite", price "2000", zipCode "12345", address "High Street 123", country "Wonderland", status "Active", apartment title "Luxury Suite" + When I update the advertisement with title "Luxury Suite Ad" to have country "Dreamland" + Then The advertisement with title "Luxury Suite Ad" should have country "Dreamland" + And The response code is 200 + + Scenario: Update advertisement description + Given I login as "owner" with password "password" + Given There is an advertisement with title "Luxury Suite Ad", description "A beautiful suite", price "2000", zipCode "12345", address "High Street 123", country "Wonderland", status "Active", apartment title "Luxury Suite" + When I update the advertisement with title "Luxury Suite Ad" to have description "An updated beautiful suite" + Then The advertisement with title "Luxury Suite Ad" should have description "An updated beautiful suite" + And The response code is 200 + +