From 0bad5ae978a8ae53c0d6866800d9ef431c29377d Mon Sep 17 00:00:00 2001 From: mairess Date: Thu, 11 Jul 2024 16:56:52 -0300 Subject: [PATCH 01/17] chore: add jacoco-check coveredratio --- pom.xml | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d1aad5e..25133f8 100644 --- a/pom.xml +++ b/pom.xml @@ -32,14 +32,18 @@ + true + + **/controller/UserController.* + PACKAGE LINE - 0.0 + 0.80 COVEREDRATIO @@ -168,6 +172,29 @@ org.junit.jupiter test + + junit-jupiter + org.testcontainers + test + 1.19.8 + + + postgresql + org.testcontainers + test + 1.19.8 + + + kafka + org.testcontainers + test + 1.19.8 + + + jjwt + io.jsonwebtoken + 0.9.1 + A simple API for internet provider From 12e6f3f2c1654d721009fa1b6a945867eb52d676 Mon Sep 17 00:00:00 2001 From: mairess Date: Thu, 11 Jul 2024 16:57:21 -0300 Subject: [PATCH 02/17] test(integration): add user test --- src/main/resources/application-dev.properties | 2 +- .../wnet/WnetInternetApplicationTests.java | 27 --- .../wnet/integration/UserIntegrationTest.java | 208 ++++++++++++++++++ src/test/resources/import.sql | 14 -- 4 files changed, 209 insertions(+), 42 deletions(-) delete mode 100644 src/test/java/com/maires/wnet/WnetInternetApplicationTests.java create mode 100644 src/test/java/com/maires/wnet/integration/UserIntegrationTest.java delete mode 100644 src/test/resources/import.sql diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index 78b917c..ef47f2a 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -5,7 +5,7 @@ spring.datasource.username=${SPRING_DATASOURCE_USERNAME:postgres} spring.datasource.password=${SPRING_DATASOURCE_PASSWORD:postgres} spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect # Hibernate configuration -spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.hibernate.ddl-auto=update #spring.jpa.hibernate.ddl-auto=updateUser spring.jpa.show-sql=true spring.application.name=w-net-internet diff --git a/src/test/java/com/maires/wnet/WnetInternetApplicationTests.java b/src/test/java/com/maires/wnet/WnetInternetApplicationTests.java deleted file mode 100644 index 7fd17db..0000000 --- a/src/test/java/com/maires/wnet/WnetInternetApplicationTests.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.maires.wnet; - -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.kafka.test.EmbeddedKafkaBroker; -import org.springframework.kafka.test.context.EmbeddedKafka; -import org.springframework.test.context.ActiveProfiles; - -@SpringBootTest -@ActiveProfiles("test") -@EmbeddedKafka(partitions = 1, topics = {"installation-completed"}) -class WnetInternetApplicationTests { - - - private final EmbeddedKafkaBroker embeddedKafkaBroker; - - @Autowired - WnetInternetApplicationTests(EmbeddedKafkaBroker embeddedKafkaBroker) { - this.embeddedKafkaBroker = embeddedKafkaBroker; - } - - @Test - void contextLoads() { - } - -} \ No newline at end of file diff --git a/src/test/java/com/maires/wnet/integration/UserIntegrationTest.java b/src/test/java/com/maires/wnet/integration/UserIntegrationTest.java new file mode 100644 index 0000000..c4dd588 --- /dev/null +++ b/src/test/java/com/maires/wnet/integration/UserIntegrationTest.java @@ -0,0 +1,208 @@ +package com.maires.wnet.integration; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.maires.wnet.entity.User; +import com.maires.wnet.repository.UserRepository; +import com.maires.wnet.security.Role; +import com.maires.wnet.service.TokenService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.springframework.test.web.servlet.MockMvc; +import org.testcontainers.containers.KafkaContainer; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper; + +@SpringBootTest +@AutoConfigureMockMvc +@Testcontainers +@DisplayName("User Integration Tests") +public class UserIntegrationTest { + + @Container + public static PostgreSQLContainer POSTGRES_CONTAINER = new PostgreSQLContainer("postgres") + .withDatabaseName("wnetdb"); + @Container + public static KafkaContainer kafkaContainer = new KafkaContainer(); + @Autowired + UserRepository userRepository; + @Autowired + MockMvc mockMvc; + @Autowired + private TokenService tokenService; + private User userAdmin; + private String tokenAdmin; + + + @DynamicPropertySource + public static void overrideProperties(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.url", POSTGRES_CONTAINER::getJdbcUrl); + registry.add("spring.datasource.username", POSTGRES_CONTAINER::getUsername); + registry.add("spring.datasource.password", POSTGRES_CONTAINER::getPassword); + } + + @DynamicPropertySource + public static void kafkaProperties(DynamicPropertyRegistry registry) { + registry.add("spring.kafka.bootstrap-servers", kafkaContainer::getBootstrapServers); + } + + @BeforeEach + public void cleanUp() { + userRepository.deleteAll(); + User admin = new User(null, "System Manager Administrator", "admin@mail.com", "admin", + "segredo123", + Role.ADMIN); + userAdmin = userRepository.save(admin); + tokenAdmin = tokenService.generateToken(userAdmin.getUsername()); + } + + @Test + @DisplayName("Retrieval all users") + public void testUserRetrievalAll() throws Exception { + User Juca = new User(null, "Juca Rosa de Souza", "juquinha@mail.com", "juca", "segredo123", + Role.TECHNICIAN); + + User Rogerio = new User(null, "Rogerio Cardoso da Sena", "rogerSena@mail.com", "rogerio", + "segredo123", + Role.TECHNICIAN); + + userRepository.save(Juca); + userRepository.save(Rogerio); + String userUrl = "/users"; + + mockMvc.perform(get(userUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$").isArray()) + .andExpect(jsonPath("$.length()").value(3)) + .andExpect(jsonPath("$[0].id").exists()) + .andExpect(jsonPath("$[0].fullName").value("System Manager Administrator")) + .andExpect(jsonPath("$[1].id").exists()) + .andExpect(jsonPath("$[1].fullName").value("Juca Rosa de Souza")) + .andExpect(jsonPath("$[2].id").exists()) + .andExpect(jsonPath("$[2].fullName").value("Rogerio Cardoso da Sena")); + } + + @Test + @DisplayName("Retrieval user by id") + public void testUserRetrievalById() throws Exception { + + String userUrl = "/users/%s".formatted(userAdmin.getId()); + + mockMvc.perform(get(userUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.fullName").value("System Manager Administrator")) + .andExpect(jsonPath("$.email").value("admin@mail.com")) + .andExpect(jsonPath("$.username").value("admin")) + .andExpect(jsonPath("$.role").value("ADMIN")); + } + + @Test + @DisplayName("Retrieval user by username") + public void testUserRetrievalByUsername() throws Exception { + + String userUrl = "/users/find?username=%s".formatted("admin"); + + mockMvc.perform(get(userUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.fullName").value("System Manager Administrator")) + .andExpect(jsonPath("$.email").value("admin@mail.com")) + .andExpect(jsonPath("$.username").value("admin")) + .andExpect(jsonPath("$.role").value("ADMIN")); + } + + @Test + @DisplayName("Create user") + public void testCreateUser() throws Exception { + + User newUser = new User(null, "Edcarlos Saraiva Bragança", "edcarlos@mail.com", "edcarlos", + "password123", Role.TECHNICIAN); + + ObjectMapper objectMapper = new ObjectMapper(); + String newUserJson = objectMapper.writeValueAsString(newUser); + String userUrl = "/users"; + + mockMvc.perform(post(userUrl) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(newUserJson)) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.fullName").value("Edcarlos Saraiva Bragança")) + .andExpect(jsonPath("$.email").value("edcarlos@mail.com")) + .andExpect(jsonPath("$.username").value("edcarlos")) + .andExpect(jsonPath("$.role").value("TECHNICIAN")); + } + + @Test + @DisplayName("Update user") + public void testUpdateUser() throws Exception { + + User updatedUser = new User(null, "System Manager aka Administrator", "admin@mail.com", "admin", + "segredo123", + Role.ADMIN); + + ObjectMapper objectMapper = new ObjectMapper(); + String updatedUserJson = objectMapper.writeValueAsString(updatedUser); + String userUrl = "/users/%s".formatted(userAdmin.getId()); + + mockMvc.perform(put(userUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(updatedUserJson)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.fullName").value("System Manager aka Administrator")) + .andExpect(jsonPath("$.email").value("admin@mail.com")) + .andExpect(jsonPath("$.username").value("admin")) + .andExpect(jsonPath("$.role").value("ADMIN")); + } + + @Test + @DisplayName("Delete user") + public void testDeleteUser() throws Exception { + + User userToDelete = new User(null, "Please Remove Me From Your Database", "removeme@mail.com", + "removeme", + "segredo123", + Role.TECHNICIAN); + + userRepository.save(userToDelete); + String userUrl = "/users/%s".formatted(userToDelete.getId()); + + mockMvc.perform(delete(userUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.fullName").value("Please Remove Me From Your Database")) + .andExpect(jsonPath("$.email").value("removeme@mail.com")) + .andExpect(jsonPath("$.username").value("removeme")) + .andExpect(jsonPath("$.role").value("TECHNICIAN")); + } + + +} \ No newline at end of file diff --git a/src/test/resources/import.sql b/src/test/resources/import.sql deleted file mode 100644 index d81359d..0000000 --- a/src/test/resources/import.sql +++ /dev/null @@ -1,14 +0,0 @@ - -insert into "PLANS" ("NAME", "SPEED", "PRICE") values ('Starter Plan', 100, 99.99), ('Deluxe Plan', 300, 199.99), ('Platinum Plan', 500, 299.99); - -insert into "TECHNICIANS" ("FULL_NAME", "PHONE", "EMAIL") values ('Marcos Oliveira', '21987654321', 'marcos@wnet.com'), ('João Silva', '21987654322', 'joao@wnet.com'), ('Ana Souza', '21987654323', 'ana@wnet.com'), ('Pedro Santos', '21987654324', 'pedro@wnet.com'); - -insert into "CUSTOMERS" ("FULL_NAME", "CPF", "PHONE", "EMAIL", "REGISTRATION_DATE") values ('João Silva', '12345678900', '21999999999', 'joao.silva@example.com', current_date), ('Maria Oliveira', '23456789001', '21888888888', 'maria.oliveira@example.com', current_date), ('Pedro Souza', '34567890123', '21777777777', 'pedro.souza@example.com', current_date), ('Ana Santos', '45678901224', '21666666666', 'ana.santos@example.com', current_date), ('Carlos Lima', '56789012145', '21555555555', 'carlos.lima@example.com', current_date), ('Mariana Costa', '67890123456', '21444444444', 'mariana.costa@example.com', current_date), ('José Pereira', '78901234567', '21333333333', 'jose.pereira@example.com', current_date), ('Luiza Gomes', '89002345678', '21222222222', 'luiza.gomes@example.com', current_date), ('Fernando Martins', '90123456289', '21111111111', 'fernando.martins@example.com', current_date), ('Aline Mendes', '01214567890', '21999999998', 'aline.mendes@example.com', current_date), ('Rafaela Almeida', '12345678901', '21888888887', 'rafaela.almeida@example.com', current_date), ('Rodrigo Santos', '23456789012', '21777777776', 'rodrigo.santos@example.com', current_date), ('Juliana Lima', '34563790123', '21666666665', 'juliana.lima@example.com', current_date), ('Gustavo Oliveira', '45678901234', '21555555554', 'gustavo.oliveira@example.com', current_date), ('Camila Silva', '56789012345', '21444444443', 'camila.silva@example.com', current_date), ('Marcos Costa', '37890123456', '21333333332', 'marcos.costa@example.com', current_date), ('Carolina Pereira', '70901234567', '21222222221', 'carolina.pereira@example.com', current_date), ('Paulo Gomes', '89012345678', '21111111110', 'paulo.gomes@example.com', current_date), ('Isabela Martins', '90123456789', '21999999997', 'isabela.martins@example.com', current_date), ('Renato Mendes', '01234567890', '21888888886', 'renato.mendes@example.com', current_date); - -insert into "INSTALLATIONS" ("IS_ACTIVE", "PLAN_ID", "TECHNICIAN_ID", "INSTALLATION_DATE") values (true, 2, 2, current_date), (true, 3, 1, current_date), (true, 1, 3, current_date), (true, 2, 4, current_date), (true, 1, 2, current_date), (true, 3, 3, current_date), (true, 1, 1, current_date), (true, 2, 4, current_date), (true, 3, 2, current_date), (true, 1, 3, current_date), (true, 2, 1, current_date), (true, 3, 4, current_date), (true, 1, 2, current_date), (true, 2, 3, current_date), (true, 3, 4, current_date), (true, 1, 1, current_date), (true, 2, 2, current_date), (true, 3, 3, current_date), (true, 1, 4, current_date), (true, 2, 1, current_date); - -insert into "ADDRESSES" ("CITY", "STATE", "ZIP_CODE", "STREET", "STREET_NUMBER", "COMPLEMENT", "NEIGHBORHOOD", "INSTALLATION_ID", "CUSTOMER_ID") values ('São Paulo', 'São Paulo', '01000-000', 'Avenida Paulista', 1023, 'Próximo ao Parque Trianon', 'Bela Vista', 1, 1), ('Rio de Janeiro', 'Rio de Janeiro', '20000-000', 'Rua do Ouvidor', 50, 'Centro Histórico', 'Centro', 2, 2), ('Belo Horizonte', 'Minas Gerais', '30000-000', 'Avenida Afonso Pena', 1234, 'Em frente ao Parque Municipal', 'Centro', 3, 3), ('Porto Alegre', 'Rio Grande do Sul', '90000-000', 'Rua dos Andradas', 500, 'Próximo ao Mercado Público', 'Centro Histórico', 4, 4), ('Curitiba', 'Paraná', '80000-000', 'Rua XV de Novembro', 1500, 'Próximo ao Passeio Público', 'Centro', 5, 5), ('Salvador', 'Bahia', '40000-000', 'Avenida Sete de Setembro', 300, 'Próximo ao Elevador Lacerda', 'Comércio', 6, 6), ('Brasília', 'Distrito Federal', '70000-000', 'Eixo Monumental', 100, 'Próximo à Esplanada dos Ministérios', 'Zona Cívico-Administrativa', 7, 7), ('Fortaleza', 'Ceará', '60000-000', 'Avenida Beira Mar', 2000, 'Próximo ao Mercado Central', 'Praia de Iracema', 8, 8), ('Recife', 'Pernambuco', '50000-000', 'Rua da Aurora', 1200, 'Próximo ao Parque Treze de Maio', 'Boa Vista', 9, 9), ('Manaus', 'Amazonas', '69000-000', 'Avenida Eduardo Ribeiro', 400, 'Próximo ao Teatro Amazonas', 'Centro', 10, 10), ('São José dos Campos', 'São Paulo', '12200-000', 'Fazenda Boa Esperança', NULL, 'Próximo ao Rio Paraíba', 'Zona Rural', 11, 11), ('Piracicaba', 'São Paulo', '13400-000', 'Sítio das Palmeiras', NULL, 'Perto da Estrada Municipal', 'Zona Rural', 12, 12), ('Ribeirão Preto', 'São Paulo', '14000-000', 'Chácara Santa Maria', NULL, 'Ao lado da Igreja São João', 'Zona Rural', 13, 13), ('Campinas', 'São Paulo', '13000-000', 'Fazenda Santo Antônio', NULL, 'Próximo ao Lago Azul', 'Zona Rural', 14, 14), ('Sorocaba', 'São Paulo', '18000-000', 'Sítio São José', NULL, 'Cerca de 5 km da Rodovia Raposo Tavares', 'Zona Rural', 15, 15), ('Jundiaí', 'São Paulo', '13200-000', 'Chácara Bela Vista', NULL, 'Depois da Ponte Velha', 'Zona Rural', 16, 16), ('Bauru', 'São Paulo', '17000-000', 'Fazenda Primavera', NULL, 'Na Estrada do Barreiro', 'Zona Rural', 17, 17), ('Taubaté', 'São Paulo', '12000-000', 'Sítio Boa Vista', NULL, 'Perto do Posto de Saúde', 'Zona Rural', 18, 18), ('Marília', 'São Paulo', '17500-000', 'Chácara Sol Nascente', NULL, 'Próximo ao Campo de Futebol', 'Zona Rural', 19, 19), ('Presidente Prudente', 'São Paulo', '19000-000', 'Fazenda São Pedro', NULL, 'A 3 km do Centro', 'Zona Rural', 20, 20); - -insert into "EQUIPMENTS" ("TYPE", "MODEL", "SERIAL_NUMBER", "MANUFACTURER", "INSTALLATION_ID") values ('ROUTER', 'TP-Link Deco M5', 'SN031', 'TP-Link', 1), ('MODEM', 'Arris SURFboard SBG6700AC', 'SN032', 'Arris', 1), ('ROUTER', 'Linksys Velop', 'SN033', 'Linksys', 2), ('MODEM', 'Netgear Nighthawk AC1900', 'SN034', 'Netgear', 2), ('ROUTER', 'Asus RT-AC88U', 'SN035', 'Asus', 3), ('MODEM', 'Motorola MG7700', 'SN036', 'Motorola', 3), ('ROUTER', 'Google Nest Wifi', 'SN037', 'Google', 4), ('MODEM', 'Zoom Telephonics AC1900', 'SN038', 'Zoom', 4), ('ROUTER', 'D-Link DIR-867', 'SN039', 'D-Link', 5), ('MODEM', 'Actiontec C3000A', 'SN040', 'Actiontec', 5), ('ROUTER', 'Synology RT2600ac', 'SN041', 'Synology', 6), ('MODEM', 'Hitron CODA-4582', 'SN042', 'Hitron', 6), ('ROUTER', 'Tenda AC10U', 'SN043', 'Tenda', 7), ('MODEM', 'Technicolor TC4400', 'SN044', 'Technicolor', 7), ('ROUTER', 'Buffalo AirStation', 'SN045', 'Buffalo', 8), ('MODEM', 'Cisco DPC3941T', 'SN046', 'Cisco', 8), ('ROUTER', 'TP-Link Archer C7', 'SN047', 'TP-Link', 9), ('MODEM', 'Zyxel C1100Z', 'SN048', 'Zyxel', 9), ('ROUTER', 'Apple AirPort Extreme', 'SN049', 'Apple', 10), ('MODEM', 'Hitron CGNM-2250', 'SN050', 'Hitron', 10), ('ROUTER', 'Huawei WS5200', 'SN051', 'Huawei', 11), ('MODEM', 'UBEE DDW36C', 'SN052', 'UBEE', 11), ('ROUTER', 'MikroTik RB3011UiAS-RM', 'SN053', 'MikroTik', 12), ('MODEM', 'Zoom 5370', 'SN054', 'Zoom', 12), ('ROUTER', 'Linksys EA7500', 'SN055', 'Linksys', 13), ('MODEM', 'Motorola MB7621', 'SN056', 'Motorola', 13), ('ROUTER', 'Asus RT-AX88U', 'SN057', 'Asus', 14), ('MODEM', 'Netgear CM500', 'SN058', 'Netgear', 14), ('ROUTER', 'Google Wifi', 'SN059', 'Google', 15), ('MODEM', 'Arris SB6190', 'SN060', 'Arris', 15), ('ROUTER', 'D-Link EXO AC2600', 'SN061', 'D-Link', 16), ('MODEM', 'TP-Link TC-7610', 'SN062', 'TP-Link', 16), ('ROUTER', 'Synology MR2200ac', 'SN063', 'Synology', 17), ('MODEM', 'Actiontec GT784WN', 'SN064', 'Actiontec', 17), ('ROUTER', 'Netgear Nighthawk X6', 'SN065', 'Netgear', 18), ('MODEM', 'Technicolor TC8717T', 'SN066', 'Technicolor', 18), ('ROUTER', 'Buffalo WZR-1750DHP', 'SN067', 'Buffalo', 19), ('MODEM', 'Cisco DPC3010', 'SN068', 'Cisco', 19); - -insert into "USERS" ("ROLE", "EMAIL", "FULL_NAME", "PASSWORD", "USERNAME") values ('ADMIN', 'juca@provedor.com', 'Juca Almeida', '$2a$10$mI4JPFBW4sE2zseRF7yC1OjsIcmZf8Wa5RkiZin5slC7lSfOwqC26', 'juca'), ('TECHNICIAN', 'osvaldo@provedor.com', 'Osvaldo Ferreira', '$2a$10$mI4JPFBW4sE2zseRF7yC1OjsIcmZf8Wa5RkiZin5slC7lSfOwqC26', 'osvaldo'), ('TECHNICIAN', 'mirosmar@provedor.com', 'Mirosmar Fernandes', '$2a$10$mI4JPFBW4sE2zseRF7yC1OjsIcmZf8Wa5RkiZin5slC7lSfOwqC26', 'mirosmar'); \ No newline at end of file From 50b5b8e36a2ea86462ee8caddd65bd3bb322a2c0 Mon Sep 17 00:00:00 2001 From: mairess Date: Thu, 11 Jul 2024 17:57:41 -0300 Subject: [PATCH 03/17] test(integration): add technician test --- pom.xml | 1 + .../wnet/controller/dto/TechnicianDto.java | 2 +- .../com/maires/wnet/entity/Technician.java | 10 +- .../TechnicianIntegrationTest.java | 191 ++++++++++++++++++ 4 files changed, 198 insertions(+), 6 deletions(-) create mode 100644 src/test/java/com/maires/wnet/integration/TechnicianIntegrationTest.java diff --git a/pom.xml b/pom.xml index 25133f8..c32c551 100644 --- a/pom.xml +++ b/pom.xml @@ -36,6 +36,7 @@ true **/controller/UserController.* + **/controller/TechnicianController.* diff --git a/src/main/java/com/maires/wnet/controller/dto/TechnicianDto.java b/src/main/java/com/maires/wnet/controller/dto/TechnicianDto.java index 4d42db0..81eb9f9 100644 --- a/src/main/java/com/maires/wnet/controller/dto/TechnicianDto.java +++ b/src/main/java/com/maires/wnet/controller/dto/TechnicianDto.java @@ -5,7 +5,7 @@ /** * The type Technician dto. */ -public record TechnicianDto(Long id, String name, String phone, String email) { +public record TechnicianDto(Long id, String fullName, String phone, String email) { /** * From entity technician dto. diff --git a/src/main/java/com/maires/wnet/entity/Technician.java b/src/main/java/com/maires/wnet/entity/Technician.java index 86292c2..8cae075 100644 --- a/src/main/java/com/maires/wnet/entity/Technician.java +++ b/src/main/java/com/maires/wnet/entity/Technician.java @@ -42,12 +42,12 @@ public Technician() { /** * Instantiates a new Technician. * - * @param name the fullName - * @param phone the phone - * @param email the email + * @param fullName the fullName + * @param phone the phone + * @param email the email */ - public Technician(String name, String phone, String email) { - this.fullName = name; + public Technician(String fullName, String phone, String email) { + this.fullName = fullName; this.phone = phone; this.email = email; } diff --git a/src/test/java/com/maires/wnet/integration/TechnicianIntegrationTest.java b/src/test/java/com/maires/wnet/integration/TechnicianIntegrationTest.java new file mode 100644 index 0000000..a4334a8 --- /dev/null +++ b/src/test/java/com/maires/wnet/integration/TechnicianIntegrationTest.java @@ -0,0 +1,191 @@ +package com.maires.wnet.integration; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.maires.wnet.entity.Technician; +import com.maires.wnet.entity.User; +import com.maires.wnet.repository.TechnicianRepository; +import com.maires.wnet.repository.UserRepository; +import com.maires.wnet.security.Role; +import com.maires.wnet.service.TokenService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.springframework.test.web.servlet.MockMvc; +import org.testcontainers.containers.KafkaContainer; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper; + +@SpringBootTest +@AutoConfigureMockMvc +@Testcontainers +@DisplayName("Technician integration Tests") +public class TechnicianIntegrationTest { + + @Container + public static PostgreSQLContainer POSTGRES_CONTAINER = new PostgreSQLContainer("postgres") + .withDatabaseName("wnetdb"); + @Container + public static KafkaContainer kafkaContainer = new KafkaContainer(); + @Autowired + TechnicianRepository technicianRepository; + @Autowired + UserRepository userRepository; + @Autowired + MockMvc mockMvc; + @Autowired + private TokenService tokenService; + private String tokenAdmin; + + + @DynamicPropertySource + public static void overrideProperties(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.url", POSTGRES_CONTAINER::getJdbcUrl); + registry.add("spring.datasource.username", POSTGRES_CONTAINER::getUsername); + registry.add("spring.datasource.password", POSTGRES_CONTAINER::getPassword); + } + + @DynamicPropertySource + public static void kafkaProperties(DynamicPropertyRegistry registry) { + registry.add("spring.kafka.bootstrap-servers", kafkaContainer::getBootstrapServers); + } + + @BeforeEach + public void cleanUp() { + userRepository.deleteAll(); + technicianRepository.deleteAll(); + User admin = new User(null, "System Manager Administrator", "admin@mail.com", "admin", + "segredo123", + Role.ADMIN); + User userAdmin = userRepository.save(admin); + tokenAdmin = tokenService.generateToken(userAdmin.getUsername()); + } + + @Test + @DisplayName("Retrieval all technicians") + public void testTechnicianRetrievalAll() throws Exception { + Technician Alberto = new Technician("Alberto Benevides de Castro", "7799000000000", + "alberto@mail.com"); + Technician Amarildo = new Technician("Amarildo Xavier da Costa", "7799111111111", + "amarildo@mail.com"); + + technicianRepository.save(Alberto); + technicianRepository.save(Amarildo); + String technicianUrl = "/technicians"; + + mockMvc.perform(get(technicianUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$").isArray()) + .andExpect(jsonPath("$.length()").value(2)) + .andExpect(jsonPath("$[0].id").exists()) + .andExpect(jsonPath("$[0].fullName").value("Alberto Benevides de Castro")) + .andExpect(jsonPath("$[1].id").exists()) + .andExpect(jsonPath("$[1].fullName").value("Amarildo Xavier da Costa")); + } + + @Test + @DisplayName("Retrieval technician by id") + public void testTechnicianRetrievalById() throws Exception { + Technician Amarildo = new Technician("Amarildo Xavier da Costa", "7799111111111", + "amarildo@mail.com"); + technicianRepository.save(Amarildo); + + String technicianUrl = "/technicians/%s".formatted(Amarildo.getId()); + + mockMvc.perform(get(technicianUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.fullName").value("Amarildo Xavier da Costa")) + .andExpect(jsonPath("$.phone").value("7799111111111")) + .andExpect(jsonPath("$.email").value("amarildo@mail.com")); + } + + @Test + @DisplayName("Create technician") + public void testCreateTechnician() throws Exception { + + Technician Amarildo = new Technician("Amarildo Xavier da Costa", "7799111111111", + "amarildo@mail.com"); + + ObjectMapper objectMapper = new ObjectMapper(); + String newTechnicianJson = objectMapper.writeValueAsString(Amarildo); + String technicianUrl = "/technicians"; + + mockMvc.perform(post(technicianUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(newTechnicianJson)) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.fullName").value("Amarildo Xavier da Costa")) + .andExpect(jsonPath("$.phone").value("7799111111111")) + .andExpect(jsonPath("$.email").value("amarildo@mail.com")); + } + + @Test + @DisplayName("Update technician") + public void testUpdateTechnician() throws Exception { + + Technician technicianToUpdate = new Technician("Amarildo Xavier da Costa", "7799111111111", + "amarildo@mail.com"); + technicianRepository.save(technicianToUpdate); + + technicianToUpdate.setFullName("Amarildo Candido Xavier"); + technicianToUpdate.setPhone("7799222222222"); + + ObjectMapper objectMapper = new ObjectMapper(); + String updatedTechnicianJson = objectMapper.writeValueAsString(technicianToUpdate); + String technicianUrl = "/technicians/%s".formatted(technicianToUpdate.getId()); + + mockMvc.perform(put(technicianUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(updatedTechnicianJson)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.fullName").value("Amarildo Candido Xavier")) + .andExpect(jsonPath("$.phone").value("7799222222222")) + .andExpect(jsonPath("$.email").value("amarildo@mail.com")); + } + + @Test + @DisplayName("Delete technician") + public void testDeleteTechnician() throws Exception { + + Technician technicianToDelete = new Technician("Amarildo Xavier da Costa", "7799111111111", + "amarildo@mail.com"); + + technicianRepository.save(technicianToDelete); + String technicianUrl = "/technicians/%s".formatted(technicianToDelete.getId()); + + mockMvc.perform(delete(technicianUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.fullName").value("Amarildo Xavier da Costa")) + .andExpect(jsonPath("$.phone").value("7799111111111")) + .andExpect(jsonPath("$.email").value("amarildo@mail.com")); + } + +} \ No newline at end of file From f413b3f837e584a90a8cd51b96411c9f624e0674 Mon Sep 17 00:00:00 2001 From: mairess Date: Thu, 11 Jul 2024 18:17:27 -0300 Subject: [PATCH 04/17] feat: permit GET request on route /plans --- src/main/java/com/maires/wnet/security/SecurityConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/maires/wnet/security/SecurityConfig.java b/src/main/java/com/maires/wnet/security/SecurityConfig.java index d6a7dc1..cbca879 100644 --- a/src/main/java/com/maires/wnet/security/SecurityConfig.java +++ b/src/main/java/com/maires/wnet/security/SecurityConfig.java @@ -47,6 +47,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws ).authorizeHttpRequests(authorize -> authorize .requestMatchers(HttpMethod.GET, "/swagger-ui/**").permitAll() .requestMatchers(HttpMethod.GET, "/v3/**").permitAll() + .requestMatchers(HttpMethod.GET, "/plans").permitAll() .requestMatchers(HttpMethod.POST, "/users").permitAll() .requestMatchers(HttpMethod.POST, "/auth/login").permitAll() .anyRequest().authenticated() From ec6c5788cdba8157dc183e0649657f6ed82ac4c9 Mon Sep 17 00:00:00 2001 From: mairess Date: Thu, 11 Jul 2024 18:46:26 -0300 Subject: [PATCH 05/17] feat: permit all GET request on route /plans/id --- src/main/java/com/maires/wnet/controller/PlanController.java | 1 - src/main/java/com/maires/wnet/security/SecurityConfig.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/maires/wnet/controller/PlanController.java b/src/main/java/com/maires/wnet/controller/PlanController.java index 7058385..0c46280 100644 --- a/src/main/java/com/maires/wnet/controller/PlanController.java +++ b/src/main/java/com/maires/wnet/controller/PlanController.java @@ -58,7 +58,6 @@ public List findAllPlans() { * @throws PlanNotFoundException the plan not found exception */ @GetMapping("/{planId}") - @PreAuthorize("hasAnyAuthority('ADMIN', 'TECHNICIAN')") public PlanDto findPlanById(@PathVariable Long planId) throws PlanNotFoundException { return PlanDto.fromEntity(planService.findPlanById(planId)); diff --git a/src/main/java/com/maires/wnet/security/SecurityConfig.java b/src/main/java/com/maires/wnet/security/SecurityConfig.java index cbca879..e916251 100644 --- a/src/main/java/com/maires/wnet/security/SecurityConfig.java +++ b/src/main/java/com/maires/wnet/security/SecurityConfig.java @@ -47,7 +47,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws ).authorizeHttpRequests(authorize -> authorize .requestMatchers(HttpMethod.GET, "/swagger-ui/**").permitAll() .requestMatchers(HttpMethod.GET, "/v3/**").permitAll() - .requestMatchers(HttpMethod.GET, "/plans").permitAll() + .requestMatchers(HttpMethod.GET, "/plans", "/plans/{planId}").permitAll() .requestMatchers(HttpMethod.POST, "/users").permitAll() .requestMatchers(HttpMethod.POST, "/auth/login").permitAll() .anyRequest().authenticated() From b760ba9b2a6f8fe88627354bdf122241f3b613e9 Mon Sep 17 00:00:00 2001 From: mairess Date: Thu, 11 Jul 2024 18:47:00 -0300 Subject: [PATCH 06/17] test(integration): add plan test --- pom.xml | 1 + .../java/com/maires/wnet/entity/Plan.java | 10 +- .../wnet/integration/PlanIntegrationTest.java | 183 ++++++++++++++++++ .../TechnicianIntegrationTest.java | 2 +- .../wnet/integration/UserIntegrationTest.java | 2 +- 5 files changed, 191 insertions(+), 7 deletions(-) create mode 100644 src/test/java/com/maires/wnet/integration/PlanIntegrationTest.java diff --git a/pom.xml b/pom.xml index c32c551..e08d534 100644 --- a/pom.xml +++ b/pom.xml @@ -37,6 +37,7 @@ **/controller/UserController.* **/controller/TechnicianController.* + **/controller/PlanController.* diff --git a/src/main/java/com/maires/wnet/entity/Plan.java b/src/main/java/com/maires/wnet/entity/Plan.java index 16dbf0a..b9ef313 100644 --- a/src/main/java/com/maires/wnet/entity/Plan.java +++ b/src/main/java/com/maires/wnet/entity/Plan.java @@ -42,12 +42,12 @@ public Plan() { /** * Instantiates a new Plan. * - * @param fullName the full name - * @param speed the speed - * @param price the price + * @param name the name + * @param speed the speed + * @param price the price */ - public Plan(String fullName, Integer speed, Double price) { - this.name = fullName; + public Plan(String name, Integer speed, Double price) { + this.name = name; this.speed = speed; this.price = price; } diff --git a/src/test/java/com/maires/wnet/integration/PlanIntegrationTest.java b/src/test/java/com/maires/wnet/integration/PlanIntegrationTest.java new file mode 100644 index 0000000..fff748a --- /dev/null +++ b/src/test/java/com/maires/wnet/integration/PlanIntegrationTest.java @@ -0,0 +1,183 @@ +package com.maires.wnet.integration; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.maires.wnet.entity.Plan; +import com.maires.wnet.entity.User; +import com.maires.wnet.repository.PlanRepository; +import com.maires.wnet.repository.UserRepository; +import com.maires.wnet.security.Role; +import com.maires.wnet.service.TokenService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.springframework.test.web.servlet.MockMvc; +import org.testcontainers.containers.KafkaContainer; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper; + +@SpringBootTest +@AutoConfigureMockMvc +@Testcontainers +@DisplayName("Plan integration tests") +public class PlanIntegrationTest { + + @Container + public static PostgreSQLContainer POSTGRES_CONTAINER = new PostgreSQLContainer("postgres") + .withDatabaseName("wnetdb"); + @Container + public static KafkaContainer kafkaContainer = new KafkaContainer(); + @Autowired + PlanRepository planRepository; + @Autowired + UserRepository userRepository; + @Autowired + MockMvc mockMvc; + @Autowired + private TokenService tokenService; + private String tokenAdmin; + + @DynamicPropertySource + public static void overrideProperties(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.url", POSTGRES_CONTAINER::getJdbcUrl); + registry.add("spring.datasource.username", POSTGRES_CONTAINER::getUsername); + registry.add("spring.datasource.password", POSTGRES_CONTAINER::getPassword); + } + + @DynamicPropertySource + public static void kafkaProperties(DynamicPropertyRegistry registry) { + registry.add("spring.kafka.bootstrap-servers", kafkaContainer::getBootstrapServers); + } + + @BeforeEach + public void cleanUp() { + userRepository.deleteAll(); + planRepository.deleteAll(); + User admin = new User(null, "System Manager Administrator", "admin@mail.com", "admin", + "segredo123", + Role.ADMIN); + User userAdmin = userRepository.save(admin); + tokenAdmin = tokenService.generateToken(userAdmin.getUsername()); + } + + @Test + @DisplayName("Retrieval all plans") + public void testTechnicianRetrievalAll() throws Exception { + Plan planOne = new Plan("Speed of Light", 299, 100.0); + Plan planTwe = new Plan("Low Connection", 10, 50.0); + + planRepository.save(planOne); + planRepository.save(planTwe); + String planUrl = "/plans"; + + mockMvc.perform(get(planUrl) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$").isArray()) + .andExpect(jsonPath("$.length()").value(2)) + .andExpect(jsonPath("$[0].id").exists()) + .andExpect(jsonPath("$[0].name").value("Speed of Light")) + .andExpect(jsonPath("$[1].id").exists()) + .andExpect(jsonPath("$[1].name").value("Low Connection")); + } + + @Test + @DisplayName("Retrieval plan by id") + public void testPlanRetrievalById() throws Exception { + Plan plan = new Plan("Speed of Light", 299, 100.0); + + planRepository.save(plan); + String planUrl = "/plans/%s".formatted(plan.getId()); + + mockMvc.perform(get(planUrl) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.name").value("Speed of Light")) + .andExpect(jsonPath("$.speed").value(299)) + .andExpect(jsonPath("$.price").value(100.0)); + } + + @Test + @DisplayName("Create plan") + public void testCreatePlan() throws Exception { + + Plan newPlan = new Plan("Speed of Light", 299, 100.0); + + ObjectMapper objectMapper = new ObjectMapper(); + String newPlanJson = objectMapper.writeValueAsString(newPlan); + String planUrl = "/plans"; + + mockMvc.perform(post(planUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(newPlanJson)) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.name").value("Speed of Light")) + .andExpect(jsonPath("$.speed").value(299)) + .andExpect(jsonPath("$.price").value(100.0)); + } + + @Test + @DisplayName("Update plan") + public void testUpdateTechnician() throws Exception { + + Plan planToUpdate = new Plan("Speed of Light", 299, 100.0); + planRepository.save(planToUpdate); + + planToUpdate.setName("Speed of Thunder"); + planToUpdate.setSpeed(150); + planToUpdate.setPrice(70.0); + + ObjectMapper objectMapper = new ObjectMapper(); + String updatedPlanJson = objectMapper.writeValueAsString(planToUpdate); + String planUrl = "/plans/%s".formatted(planToUpdate.getId()); + + mockMvc.perform(put(planUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(updatedPlanJson)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.name").value("Speed of Thunder")) + .andExpect(jsonPath("$.speed").value(150)) + .andExpect(jsonPath("$.price").value(70.0)); + } + + @Test + @DisplayName("Delete plan") + public void testDeletePlan() throws Exception { + + Plan planToDelete = new Plan("Speed of Light", 299, 100.0); + planRepository.save(planToDelete); + + String planUrl = "/plans/%s".formatted(planToDelete.getId()); + + mockMvc.perform(delete(planUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.name").value("Speed of Light")) + .andExpect(jsonPath("$.speed").value(299)) + .andExpect(jsonPath("$.price").value(100.0)); + } + +} \ No newline at end of file diff --git a/src/test/java/com/maires/wnet/integration/TechnicianIntegrationTest.java b/src/test/java/com/maires/wnet/integration/TechnicianIntegrationTest.java index a4334a8..8149186 100644 --- a/src/test/java/com/maires/wnet/integration/TechnicianIntegrationTest.java +++ b/src/test/java/com/maires/wnet/integration/TechnicianIntegrationTest.java @@ -33,7 +33,7 @@ @SpringBootTest @AutoConfigureMockMvc @Testcontainers -@DisplayName("Technician integration Tests") +@DisplayName("Technician integration tests") public class TechnicianIntegrationTest { @Container diff --git a/src/test/java/com/maires/wnet/integration/UserIntegrationTest.java b/src/test/java/com/maires/wnet/integration/UserIntegrationTest.java index c4dd588..32221fd 100644 --- a/src/test/java/com/maires/wnet/integration/UserIntegrationTest.java +++ b/src/test/java/com/maires/wnet/integration/UserIntegrationTest.java @@ -31,7 +31,7 @@ @SpringBootTest @AutoConfigureMockMvc @Testcontainers -@DisplayName("User Integration Tests") +@DisplayName("User integration tests") public class UserIntegrationTest { @Container From 1fd50ccfeaebadf47504349ae5af56d3b326dab0 Mon Sep 17 00:00:00 2001 From: mairess Date: Fri, 12 Jul 2024 10:11:28 -0300 Subject: [PATCH 07/17] test(integration): add equipment test --- .../integration/EquipmentIntegrationTest.java | 190 ++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 src/test/java/com/maires/wnet/integration/EquipmentIntegrationTest.java diff --git a/src/test/java/com/maires/wnet/integration/EquipmentIntegrationTest.java b/src/test/java/com/maires/wnet/integration/EquipmentIntegrationTest.java new file mode 100644 index 0000000..eb54eda --- /dev/null +++ b/src/test/java/com/maires/wnet/integration/EquipmentIntegrationTest.java @@ -0,0 +1,190 @@ +package com.maires.wnet.integration; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.maires.wnet.entity.Equipment; +import com.maires.wnet.entity.EquipmentType; +import com.maires.wnet.entity.User; +import com.maires.wnet.repository.EquipmentRepository; +import com.maires.wnet.repository.UserRepository; +import com.maires.wnet.security.Role; +import com.maires.wnet.service.TokenService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.springframework.test.web.servlet.MockMvc; +import org.testcontainers.containers.KafkaContainer; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper; + +@SpringBootTest +@AutoConfigureMockMvc +@Testcontainers +@DisplayName("Equipment integration tests") +public class EquipmentIntegrationTest { + + @Container + public static PostgreSQLContainer POSTGRES_CONTAINER = new PostgreSQLContainer("postgres") + .withDatabaseName("wnetdb"); + @Container + public static KafkaContainer kafkaContainer = new KafkaContainer(); + @Autowired + EquipmentRepository equipmentRepository; + @Autowired + UserRepository userRepository; + @Autowired + MockMvc mockMvc; + @Autowired + private TokenService tokenService; + private String tokenAdmin; + + @DynamicPropertySource + public static void overrideProperties(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.url", POSTGRES_CONTAINER::getJdbcUrl); + registry.add("spring.datasource.username", POSTGRES_CONTAINER::getUsername); + registry.add("spring.datasource.password", POSTGRES_CONTAINER::getPassword); + } + + @DynamicPropertySource + public static void kafkaProperties(DynamicPropertyRegistry registry) { + registry.add("spring.kafka.bootstrap-servers", kafkaContainer::getBootstrapServers); + } + + @BeforeEach + public void cleanUp() { + userRepository.deleteAll(); + equipmentRepository.deleteAll(); + User admin = new User(null, "System Manager Administrator", "admin@mail.com", "admin", + "segredo123", + Role.ADMIN); + User userAdmin = userRepository.save(admin); + tokenAdmin = tokenService.generateToken(userAdmin.getUsername()); + } + + @Test + @DisplayName("Retrieval all equipments") + public void testEquipmentRetrievalAll() throws Exception { + Equipment router = new Equipment(EquipmentType.ROUTER, "TP-Link Deco M4", "SN5332", "TP-Link"); + Equipment modem = new Equipment(EquipmentType.MODEM, "Motorola MG7700", "SN5333", "Motorola"); + + equipmentRepository.save(router); + equipmentRepository.save(modem); + String equipmentUrl = "/equipments"; + + mockMvc.perform(get(equipmentUrl) + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$").isArray()) + .andExpect(jsonPath("$.length()").value(2)) + .andExpect(jsonPath("$[0].id").exists()) + .andExpect(jsonPath("$[0].model").value("TP-Link Deco M4")) + .andExpect(jsonPath("$[1].id").exists()) + .andExpect(jsonPath("$[1].model").value("Motorola MG7700")); + } + + @Test + @DisplayName("Retrieval equipment by id") + public void testEquipmentRetrievalById() throws Exception { + Equipment router = new Equipment(EquipmentType.ROUTER, "TP-Link Deco M4", "SN5332", "TP-Link"); + + equipmentRepository.save(router); + String equipmentUrl = "/equipments/%s".formatted(router.getId()); + + mockMvc.perform(get(equipmentUrl) + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.model").value("TP-Link Deco M4")); + } + + @Test + @DisplayName("Create equipment") + public void testCreateEquipment() throws Exception { + + Equipment newEquipment = new Equipment(EquipmentType.ROUTER, "TP-Link Deco M4", "SN5332", + "TP-Link"); + + ObjectMapper objectMapper = new ObjectMapper(); + String newEquipmentJson = objectMapper.writeValueAsString(newEquipment); + String equipmentUrl = "/equipments"; + + mockMvc.perform(post(equipmentUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(newEquipmentJson)) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.type").value("ROUTER")) + .andExpect(jsonPath("$.model").value("TP-Link Deco M4")) + .andExpect(jsonPath("$.serialNumber").value("SN5332")) + .andExpect(jsonPath("$.manufacturer").value("TP-Link")); + } + + @Test + @DisplayName("Update equipment") + public void testUpdateEquipment() throws Exception { + + Equipment equipmentToUpdate = new Equipment(EquipmentType.ROUTER, "TP-Link Deco M4", "SN5332", + "TP-Link"); + equipmentRepository.save(equipmentToUpdate); + + equipmentToUpdate.setType(EquipmentType.MODEM); + equipmentToUpdate.setModel("Netgear Nighthawk AC1900"); + equipmentToUpdate.setManufacturer("Netgear"); + + ObjectMapper objectMapper = new ObjectMapper(); + String updatedPlanJson = objectMapper.writeValueAsString(equipmentToUpdate); + String equipmentUrl = "/equipments/%s".formatted(equipmentToUpdate.getId()); + + mockMvc.perform(put(equipmentUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(updatedPlanJson)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.type").value("MODEM")) + .andExpect(jsonPath("$.model").value("Netgear Nighthawk AC1900")) + .andExpect(jsonPath("$.serialNumber").value("SN5332")) + .andExpect(jsonPath("$.manufacturer").value("Netgear")); + } + + @Test + @DisplayName("Delete equipment") + public void testDeleteEquipment() throws Exception { + + Equipment equipmentToDelete = new Equipment(EquipmentType.ROUTER, "TP-Link Deco M4", "SN5332", + "TP-Link"); + equipmentRepository.save(equipmentToDelete); + + String equipmentUrl = "/equipments/%s".formatted(equipmentToDelete.getId()); + + mockMvc.perform(delete(equipmentUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.type").value("ROUTER")) + .andExpect(jsonPath("$.model").value("TP-Link Deco M4")) + .andExpect(jsonPath("$.serialNumber").value("SN5332")) + .andExpect(jsonPath("$.manufacturer").value("TP-Link")); + } + +} \ No newline at end of file From f9fdad475d8646c635861664fb819199339fe427 Mon Sep 17 00:00:00 2001 From: mairess Date: Fri, 12 Jul 2024 10:12:36 -0300 Subject: [PATCH 08/17] chore: add EquipmentController to jacoco-check --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index e08d534..1dc7577 100644 --- a/pom.xml +++ b/pom.xml @@ -38,6 +38,7 @@ **/controller/UserController.* **/controller/TechnicianController.* **/controller/PlanController.* + **/controller/EquipmentController.* From 3f361f096b68b175f8ae6724ded8cddd383d6700 Mon Sep 17 00:00:00 2001 From: mairess Date: Fri, 12 Jul 2024 11:41:20 -0300 Subject: [PATCH 09/17] test(integration): add customer test --- pom.xml | 1 + .../integration/CustomerIntegrationTest.java | 291 ++++++++++++++++++ 2 files changed, 292 insertions(+) create mode 100644 src/test/java/com/maires/wnet/integration/CustomerIntegrationTest.java diff --git a/pom.xml b/pom.xml index 1dc7577..7913d4f 100644 --- a/pom.xml +++ b/pom.xml @@ -39,6 +39,7 @@ **/controller/TechnicianController.* **/controller/PlanController.* **/controller/EquipmentController.* + **/controller/CustomerController.* diff --git a/src/test/java/com/maires/wnet/integration/CustomerIntegrationTest.java b/src/test/java/com/maires/wnet/integration/CustomerIntegrationTest.java new file mode 100644 index 0000000..dc56a9e --- /dev/null +++ b/src/test/java/com/maires/wnet/integration/CustomerIntegrationTest.java @@ -0,0 +1,291 @@ +package com.maires.wnet.integration; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.maires.wnet.entity.Address; +import com.maires.wnet.entity.Customer; +import com.maires.wnet.entity.User; +import com.maires.wnet.repository.AddressRepository; +import com.maires.wnet.repository.CustomerRepository; +import com.maires.wnet.repository.UserRepository; +import com.maires.wnet.security.Role; +import com.maires.wnet.service.TokenService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.springframework.test.web.servlet.MockMvc; +import org.testcontainers.containers.KafkaContainer; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper; + +@SpringBootTest +@AutoConfigureMockMvc +@Testcontainers +@DisplayName("Customer integration tests") +public class CustomerIntegrationTest { + + @Container + public static PostgreSQLContainer POSTGRES_CONTAINER = new PostgreSQLContainer("postgres") + .withDatabaseName("wnetdb"); + @Container + public static KafkaContainer kafkaContainer = new KafkaContainer(); + @Autowired + CustomerRepository customerRepository; + @Autowired + AddressRepository addressRepository; + @Autowired + UserRepository userRepository; + @Autowired + MockMvc mockMvc; + @Autowired + private TokenService tokenService; + private String tokenAdmin; + + @DynamicPropertySource + public static void overrideProperties(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.url", POSTGRES_CONTAINER::getJdbcUrl); + registry.add("spring.datasource.username", POSTGRES_CONTAINER::getUsername); + registry.add("spring.datasource.password", POSTGRES_CONTAINER::getPassword); + } + + @DynamicPropertySource + public static void kafkaProperties(DynamicPropertyRegistry registry) { + registry.add("spring.kafka.bootstrap-servers", kafkaContainer::getBootstrapServers); + } + + @BeforeEach + public void cleanUp() { + userRepository.deleteAll(); + customerRepository.deleteAll(); + User admin = new User(null, "System Manager Administrator", "admin@mail.com", "admin", + "segredo123", + Role.ADMIN); + User userAdmin = userRepository.save(admin); + tokenAdmin = tokenService.generateToken(userAdmin.getUsername()); + } + + @Test + @DisplayName("Retrieval all Customers") + public void testCustomerRetrievalAll() throws Exception { + Customer everaldo = new Customer("Everaldo Soares Cordeiro", "00011122233", "77000001111", + "everaldo@mail.com"); + Customer machado = new Customer("Joaquim Maria Machado de Assis", "93684193020", + "77009901111", + "machado@mail.com"); + + customerRepository.save(everaldo); + customerRepository.save(machado); + String customerUrl = "/customers"; + + mockMvc.perform(get(customerUrl) + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$").isArray()) + .andExpect(jsonPath("$.length()").value(2)) + .andExpect(jsonPath("$[0].id").exists()) + .andExpect(jsonPath("$[0].fullName").value("Everaldo Soares Cordeiro")) + .andExpect(jsonPath("$[1].id").exists()) + .andExpect(jsonPath("$[1].fullName").value("Joaquim Maria Machado de Assis")); + } + + @Test + @DisplayName("Retrieval customer by id") + public void testCustomerRetrievalById() throws Exception { + Customer machado = new Customer("Joaquim Maria Machado de Assis", "93684193020", + "77009901111", + "machado@mail.com"); + + customerRepository.save(machado); + String customerUrl = "/customers/%s".formatted(machado.getId()); + + mockMvc.perform(get(customerUrl) + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.fullName").value("Joaquim Maria Machado de Assis")) + .andExpect(jsonPath("$.cpf").value("93684193020")) + .andExpect(jsonPath("$.phone").value("77009901111")) + .andExpect(jsonPath("$.email").value("machado@mail.com")); + } + + @Test + @DisplayName("Retrieval all addresses by customer") + public void testAddressesRetrievalByCustomer() throws Exception { + Customer machado = new Customer("Joaquim Maria Machado de Assis", "93684193020", + "77009901111", + "machado@mail.com"); + + customerRepository.save(machado); + + Address home = new Address( + "São Paulo", + "São Paulo", + "01000000", + "Avenida Paulista", + 1023, + "Próximo ao Parque Trianon", + "Bela Vista" + ); + Address work = new Address( + "São Paulo", + "São Paulo", + "13000000", + "Fazenda Santo Antônio", + null, + "Próximo ao Lago Azul", + "Zona Rural" + ); + + home.setCustomer(machado); + work.setCustomer(machado); + addressRepository.save(home); + addressRepository.save(work); + + String customerUrl = "/customers/%s/addresses".formatted(machado.getId()); + + mockMvc.perform(get(customerUrl) + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$").isArray()) + .andExpect(jsonPath("$.length()").value(2)) + .andExpect(jsonPath("$[0].street").value("Avenida Paulista")) + .andExpect(jsonPath("$[0].streetNumber").value(1023)) + .andExpect(jsonPath("$[1].street").value("Fazenda Santo Antônio")) + .andExpect(jsonPath("$[1].streetNumber").doesNotExist()); + } + + @Test + @DisplayName("Create customer") + public void testCreateCustomer() throws Exception { + + Customer newCustomer = new Customer("Joaquim Maria Machado de Assis", "93684193020", + "77009901111", + "machado@mail.com"); + + ObjectMapper objectMapper = new ObjectMapper(); + String newCustomerJson = objectMapper.writeValueAsString(newCustomer); + String customerUrl = "/customers"; + + mockMvc.perform(post(customerUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(newCustomerJson)) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.fullName").value("Joaquim Maria Machado de Assis")) + .andExpect(jsonPath("$.cpf").value("93684193020")) + .andExpect(jsonPath("$.phone").value("77009901111")) + .andExpect(jsonPath("$.email").value("machado@mail.com")); + } + + @Test + @DisplayName("Update customer") + public void testUpdateCustomer() throws Exception { + + Customer customerToUpdate = new Customer("Joaquim Maria Machado de Assis", "93684193020", + "77009901111", + "machadodexango@mail.com"); + + customerRepository.save(customerToUpdate); + + customerToUpdate.setFullName("Joaquim Maria Machado de Assis de Xangô"); + customerToUpdate.setEmail("machadodexango@mail.com"); + + ObjectMapper objectMapper = new ObjectMapper(); + String updatedCustomerJson = objectMapper.writeValueAsString(customerToUpdate); + String equipmentUrl = "/customers/%s".formatted(customerToUpdate.getId()); + + mockMvc.perform(put(equipmentUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(updatedCustomerJson)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.fullName").value("Joaquim Maria Machado de Assis de Xangô")) + .andExpect(jsonPath("$.cpf").value("93684193020")) + .andExpect(jsonPath("$.phone").value("77009901111")) + .andExpect(jsonPath("$.email").value("machadodexango@mail.com")); + } + + @Test + @DisplayName("Create customer address") + public void testCreateCustomerAddress() throws Exception { + + Customer customer = new Customer("Joaquim Maria Machado de Assis", "93684193020", + "77009901111", + "machado@mail.com"); + + customerRepository.save(customer); + + Address newAddress = new Address( + "São Paulo", + "São Paulo", + "01000000", + "Avenida Paulista", + 1023, + "Bela Vista", + "Próximo ao Parque Trianon" + + ); + + ObjectMapper objectMapper = new ObjectMapper(); + String newAddressJson = objectMapper.writeValueAsString(newAddress); + String customerUrl = "/customers/%s/addresses".formatted(customer.getId()); + + mockMvc.perform(post(customerUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(newAddressJson)) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.city").value("São Paulo")) + .andExpect(jsonPath("$.state").value("São Paulo")) + .andExpect(jsonPath("$.zipCode").value("01000000")) + .andExpect(jsonPath("$.street").value("Avenida Paulista")) + .andExpect(jsonPath("$.streetNumber").value(1023)) + .andExpect(jsonPath("$.neighborhood").value("Bela Vista")) + .andExpect(jsonPath("$.complement").value("Próximo ao Parque Trianon")); + } + + @Test + @DisplayName("Delete Customer") + public void testDeleteEquipment() throws Exception { + + Customer customerToDelete = new Customer("Gilvan Carlos Ferreira", "93684193020", + "77009901111", + "ferreira@mail.com"); + customerRepository.save(customerToDelete); + + String customerUrl = "/customers/%s".formatted(customerToDelete.getId()); + + mockMvc.perform(delete(customerUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.fullName").value("Gilvan Carlos Ferreira")) + .andExpect(jsonPath("$.cpf").value("93684193020")) + .andExpect(jsonPath("$.phone").value("77009901111")) + .andExpect(jsonPath("$.email").value("ferreira@mail.com")); + } + +} \ No newline at end of file From c3d8017b637b326549c8e730331e7d9a4ca6b5cf Mon Sep 17 00:00:00 2001 From: mairess Date: Fri, 12 Jul 2024 16:00:17 -0300 Subject: [PATCH 10/17] fix(test): replace matcher from doesNotExist to nullValue on testAddressesRetrievalByCustomer streetNumber assertion --- .../com/maires/wnet/integration/CustomerIntegrationTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/maires/wnet/integration/CustomerIntegrationTest.java b/src/test/java/com/maires/wnet/integration/CustomerIntegrationTest.java index dc56a9e..a707750 100644 --- a/src/test/java/com/maires/wnet/integration/CustomerIntegrationTest.java +++ b/src/test/java/com/maires/wnet/integration/CustomerIntegrationTest.java @@ -1,5 +1,6 @@ package com.maires.wnet.integration; +import static org.hamcrest.Matchers.nullValue; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; @@ -168,7 +169,7 @@ public void testAddressesRetrievalByCustomer() throws Exception { .andExpect(jsonPath("$[0].street").value("Avenida Paulista")) .andExpect(jsonPath("$[0].streetNumber").value(1023)) .andExpect(jsonPath("$[1].street").value("Fazenda Santo Antônio")) - .andExpect(jsonPath("$[1].streetNumber").doesNotExist()); + .andExpect(jsonPath("$[1].streetNumber").value(nullValue())); } @Test From 312bd062c250006e3105831919fee7ce942f42e1 Mon Sep 17 00:00:00 2001 From: mairess Date: Fri, 12 Jul 2024 18:25:05 -0300 Subject: [PATCH 11/17] fix: update of street on method updateAddress --- src/main/java/com/maires/wnet/service/AddressService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/maires/wnet/service/AddressService.java b/src/main/java/com/maires/wnet/service/AddressService.java index f869aee..ea071d2 100644 --- a/src/main/java/com/maires/wnet/service/AddressService.java +++ b/src/main/java/com/maires/wnet/service/AddressService.java @@ -173,7 +173,7 @@ public Address updateAddress(Long addressId, Address address) throws AddressNotF addressToUpdate.setCity(address.getCity()); addressToUpdate.setState(address.getState()); addressToUpdate.setZipCode(address.getZipCode()); - addressToUpdate.setStreet(addressToUpdate.getStreet()); + addressToUpdate.setStreet(address.getStreet()); addressToUpdate.setStreetNumber(address.getStreetNumber()); addressToUpdate.setNeighborhood(address.getNeighborhood()); addressToUpdate.setComplement(address.getComplement()); From cbf6899b290d7920fbf553216d1f04c9922563cb Mon Sep 17 00:00:00 2001 From: mairess Date: Fri, 12 Jul 2024 18:26:09 -0300 Subject: [PATCH 12/17] test(integration): add address test --- .../integration/AddressIntegrationTest.java | 276 ++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 src/test/java/com/maires/wnet/integration/AddressIntegrationTest.java diff --git a/src/test/java/com/maires/wnet/integration/AddressIntegrationTest.java b/src/test/java/com/maires/wnet/integration/AddressIntegrationTest.java new file mode 100644 index 0000000..3c35015 --- /dev/null +++ b/src/test/java/com/maires/wnet/integration/AddressIntegrationTest.java @@ -0,0 +1,276 @@ +package com.maires.wnet.integration; + +import static org.hamcrest.Matchers.nullValue; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.maires.wnet.controller.dto.InstallationCreationDto; +import com.maires.wnet.entity.Address; +import com.maires.wnet.entity.Customer; +import com.maires.wnet.entity.Equipment; +import com.maires.wnet.entity.EquipmentType; +import com.maires.wnet.entity.Plan; +import com.maires.wnet.entity.Technician; +import com.maires.wnet.entity.User; +import com.maires.wnet.repository.AddressRepository; +import com.maires.wnet.repository.CustomerRepository; +import com.maires.wnet.repository.EquipmentRepository; +import com.maires.wnet.repository.PlanRepository; +import com.maires.wnet.repository.TechnicianRepository; +import com.maires.wnet.repository.UserRepository; +import com.maires.wnet.security.Role; +import com.maires.wnet.service.TokenService; +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.springframework.test.web.servlet.MockMvc; +import org.testcontainers.containers.KafkaContainer; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@SpringBootTest +@AutoConfigureMockMvc +@Testcontainers +@DisplayName("Address integration tests") +public class AddressIntegrationTest { + + @Container + public static PostgreSQLContainer POSTGRES_CONTAINER = new PostgreSQLContainer("postgres") + .withDatabaseName("wnetdb"); + @Container + public static KafkaContainer kafkaContainer = new KafkaContainer(); + @Autowired + AddressRepository addressRepository; + @Autowired + TechnicianRepository technicianRepository; + @Autowired + EquipmentRepository equipmentRepository; + @Autowired + PlanRepository planRepository; + @Autowired + UserRepository userRepository; + @Autowired + CustomerRepository customerRepository; + @Autowired + MockMvc mockMvc; + @Autowired + private TokenService tokenService; + private String tokenAdmin; + + @DynamicPropertySource + public static void overrideProperties(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.url", POSTGRES_CONTAINER::getJdbcUrl); + registry.add("spring.datasource.username", POSTGRES_CONTAINER::getUsername); + registry.add("spring.datasource.password", POSTGRES_CONTAINER::getPassword); + } + + @DynamicPropertySource + public static void kafkaProperties(DynamicPropertyRegistry registry) { + registry.add("spring.kafka.bootstrap-servers", kafkaContainer::getBootstrapServers); + } + + @BeforeEach + public void cleanUp() { + userRepository.deleteAll(); + addressRepository.deleteAll(); + User admin = new User(null, "System Manager Administrator", "admin@mail.com", "admin", + "segredo123", + Role.ADMIN); + User userAdmin = userRepository.save(admin); + tokenAdmin = tokenService.generateToken(userAdmin.getUsername()); + } + + @Test + @DisplayName("Retrieval all addresses") + public void testAddressRetrievalAll() throws Exception { + Address home = new Address( + "São Paulo", + "São Paulo", + "01000000", + "Avenida Paulista", + 1023, + "Próximo ao Parque Trianon", + "Bela Vista" + ); + + Address work = new Address( + "São Paulo", + "São Paulo", + "13000000", + "Fazenda Santo Antônio", + null, + "Próximo ao Lago Azul", + "Zona Rural" + ); + + addressRepository.save(home); + addressRepository.save(work); + String addressUrl = "/addresses"; + + mockMvc.perform(get(addressUrl) + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$").isArray()) + .andExpect(jsonPath("$.length()").value(2)) + .andExpect(jsonPath("$[0].street").value("Avenida Paulista")) + .andExpect(jsonPath("$[0].streetNumber").value(1023)) + .andExpect(jsonPath("$[1].street").value("Fazenda Santo Antônio")) + .andExpect(jsonPath("$[1].streetNumber").value(nullValue())); + } + + @Test + @DisplayName("Retrieval customer by id") + public void testCustomerRetrievalById() throws Exception { + Address home = new Address( + "São Paulo", + "São Paulo", + "01000000", + "Avenida Paulista", + 1023, + "Bela Vista", + "Próximo ao Parque Trianon" + ); + + addressRepository.save(home); + String addressUrl = "/addresses/%s".formatted(home.getId()); + + mockMvc.perform(get(addressUrl) + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.city").value("São Paulo")) + .andExpect(jsonPath("$.state").value("São Paulo")) + .andExpect(jsonPath("$.zipCode").value("01000000")) + .andExpect(jsonPath("$.street").value("Avenida Paulista")) + .andExpect(jsonPath("$.streetNumber").value(1023)) + .andExpect(jsonPath("$.neighborhood").value("Bela Vista")) + .andExpect(jsonPath("$.complement").value("Próximo ao Parque Trianon")); + } + + @Test + @DisplayName("Create address installation") + public void testCreateAddressInstallation() throws Exception { + + Customer customer = new Customer( + "Graciliano Ramos de Oliveira", + "00011122233", + "77011223344", + "gracit@example.com" + ); + + Address home = new Address( + "São Paulo", "São Paulo", "01000000", "Avenida Paulista", 1023, "Bela Vista", + "Próximo ao Parque Trianon"); + + Technician technician = new Technician("João Antônio Benevides Faria", "77011114444", + "joao@example.com"); + + Plan plan = new Plan("Speed og Thunder", 300, 70.0); + + Equipment router = new Equipment(EquipmentType.ROUTER, "Asus RT-AC88U", "SN035", "Asus"); + Equipment modem = new Equipment(EquipmentType.MODEM, "Motorola MG7700", "SN036", "Motorola"); + + home.setCustomer(customer); + customerRepository.save(customer); + addressRepository.save(home); + technicianRepository.save(technician); + planRepository.save(plan); + equipmentRepository.save(router); + equipmentRepository.save(modem); + + List equipmentList = new ArrayList<>(); + equipmentList.add(router.getId()); + equipmentList.add(modem.getId()); + + InstallationCreationDto installationDto = new InstallationCreationDto(plan.getId(), + technician.getId(), equipmentList); + + ObjectMapper objectMapper = new ObjectMapper(); + String newInstallationJson = objectMapper.writeValueAsString(installationDto); + String addressUrl = "/addresses/%s/installations".formatted(home.getId()); + + mockMvc.perform(post(addressUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(newInstallationJson)) + .andExpect(status().isCreated()); + } + + @Test + @DisplayName("Update address") + public void testUpdateAddress() throws Exception { + + Address addressToUpdate = new Address( + "São Paulo", "São Paulo", "01000000", "Avenida Paulista", 1023, "Bela Vista", + "Próximo ao Parque Trianon"); + + addressRepository.save(addressToUpdate); + + addressToUpdate.setCity("Guarulhos"); + addressToUpdate.setZipCode("11111111"); + addressToUpdate.setStreet("Rua das Flores"); + addressToUpdate.setStreetNumber(41); + addressToUpdate.setNeighborhood("Jardim Verde"); + + ObjectMapper objectMapper = new ObjectMapper(); + String updatedAddressJson = objectMapper.writeValueAsString(addressToUpdate); + String addressUrl = "/addresses/%s".formatted(addressToUpdate.getId()); + + mockMvc.perform(put(addressUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(updatedAddressJson)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.city").value("Guarulhos")) + .andExpect(jsonPath("$.zipCode").value("11111111")) + .andExpect(jsonPath("$.street").value("Rua das Flores")) + .andExpect(jsonPath("$.streetNumber").value(41)) + .andExpect(jsonPath("$.neighborhood").value("Jardim Verde")); + } + + @Test + @DisplayName("Delete Customer") + public void testDeleteEquipment() throws Exception { + + Address addressToDelete = new Address( + "São Paulo", "São Paulo", "01000000", "Avenida Paulista", 1023, "Bela Vista", + "Próximo ao Parque Trianon"); + + addressRepository.save(addressToDelete); + + String addressUrl = "/addresses/%s".formatted(addressToDelete.getId()); + + mockMvc.perform(delete(addressUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.city").value("São Paulo")) + .andExpect(jsonPath("$.zipCode").value("01000000")) + .andExpect(jsonPath("$.street").value("Avenida Paulista")) + .andExpect(jsonPath("$.streetNumber").value(1023)) + .andExpect(jsonPath("$.neighborhood").value("Bela Vista")) + .andExpect(jsonPath("$.complement").value("Próximo ao Parque Trianon")); + } + +} \ No newline at end of file From cc4d6415d275213e27deba13522bfe9d93485f91 Mon Sep 17 00:00:00 2001 From: mairess Date: Fri, 12 Jul 2024 18:38:16 -0300 Subject: [PATCH 13/17] fix(addressIntegrationTest): clean up equipmentRepository to remove installation equipment association constraint before delete address --- pom.xml | 1 + .../maires/wnet/integration/AddressIntegrationTest.java | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 7913d4f..2f0515a 100644 --- a/pom.xml +++ b/pom.xml @@ -40,6 +40,7 @@ **/controller/PlanController.* **/controller/EquipmentController.* **/controller/CustomerController.* + **/controller/AddressController.* diff --git a/src/test/java/com/maires/wnet/integration/AddressIntegrationTest.java b/src/test/java/com/maires/wnet/integration/AddressIntegrationTest.java index 3c35015..f437721 100644 --- a/src/test/java/com/maires/wnet/integration/AddressIntegrationTest.java +++ b/src/test/java/com/maires/wnet/integration/AddressIntegrationTest.java @@ -87,6 +87,7 @@ public static void kafkaProperties(DynamicPropertyRegistry registry) { @BeforeEach public void cleanUp() { userRepository.deleteAll(); + equipmentRepository.deleteAll(); addressRepository.deleteAll(); User admin = new User(null, "System Manager Administrator", "admin@mail.com", "admin", "segredo123", @@ -135,8 +136,8 @@ public void testAddressRetrievalAll() throws Exception { } @Test - @DisplayName("Retrieval customer by id") - public void testCustomerRetrievalById() throws Exception { + @DisplayName("Retrieval addresses by id") + public void testAddressRetrievalById() throws Exception { Address home = new Address( "São Paulo", "São Paulo", @@ -249,8 +250,8 @@ public void testUpdateAddress() throws Exception { } @Test - @DisplayName("Delete Customer") - public void testDeleteEquipment() throws Exception { + @DisplayName("Delete Address") + public void testDeleteAddress() throws Exception { Address addressToDelete = new Address( "São Paulo", "São Paulo", "01000000", "Avenida Paulista", 1023, "Bela Vista", From 38a678b20dfa4f2317d3e212fb8c33cad2c81812 Mon Sep 17 00:00:00 2001 From: mairess Date: Sat, 13 Jul 2024 05:49:48 -0300 Subject: [PATCH 14/17] test(integration): add installation test --- .../com/maires/wnet/entity/Installation.java | 26 +- .../integration/AddressIntegrationTest.java | 8 +- .../integration/CustomerIntegrationTest.java | 14 +- .../integration/EquipmentIntegrationTest.java | 12 +- .../InstallationIntegrationTest.java | 291 ++++++++++++++++++ .../wnet/integration/PlanIntegrationTest.java | 12 +- .../TechnicianIntegrationTest.java | 8 +- .../wnet/integration/UserIntegrationTest.java | 8 +- 8 files changed, 333 insertions(+), 46 deletions(-) create mode 100644 src/test/java/com/maires/wnet/integration/InstallationIntegrationTest.java diff --git a/src/main/java/com/maires/wnet/entity/Installation.java b/src/main/java/com/maires/wnet/entity/Installation.java index 89d111d..a7e6752 100644 --- a/src/main/java/com/maires/wnet/entity/Installation.java +++ b/src/main/java/com/maires/wnet/entity/Installation.java @@ -53,9 +53,9 @@ public Installation() { /** * Instantiates a new Installation. * - * @param address the address id - * @param plan the plan id - * @param technician the technician id + * @param address the address + * @param plan the plan + * @param technician the technician * @param equipments the equipments */ public Installation(Address address, Plan plan, Technician technician, @@ -68,6 +68,26 @@ public Installation(Address address, Plan plan, Technician technician, this.installationDate = DateUtil.formatCurrentDate(); } + + /** + * Instantiates a new Installation. + * + * @param isActive the is active + * @param address the address + * @param plan the plan + * @param technician the technician + * @param equipments the equipments + */ + public Installation(boolean isActive, Address address, Plan plan, Technician technician, + List equipments) { + this.isActive = isActive; + this.address = address; + this.plan = plan; + this.technician = technician; + this.equipments = equipments; + this.installationDate = DateUtil.formatCurrentDate(); + } + /** * Gets id. * diff --git a/src/test/java/com/maires/wnet/integration/AddressIntegrationTest.java b/src/test/java/com/maires/wnet/integration/AddressIntegrationTest.java index f437721..b7cad30 100644 --- a/src/test/java/com/maires/wnet/integration/AddressIntegrationTest.java +++ b/src/test/java/com/maires/wnet/integration/AddressIntegrationTest.java @@ -53,7 +53,7 @@ public class AddressIntegrationTest { public static PostgreSQLContainer POSTGRES_CONTAINER = new PostgreSQLContainer("postgres") .withDatabaseName("wnetdb"); @Container - public static KafkaContainer kafkaContainer = new KafkaContainer(); + public static KafkaContainer KAFKA_CONTAINER = new KafkaContainer(); @Autowired AddressRepository addressRepository; @Autowired @@ -77,11 +77,7 @@ public static void overrideProperties(DynamicPropertyRegistry registry) { registry.add("spring.datasource.url", POSTGRES_CONTAINER::getJdbcUrl); registry.add("spring.datasource.username", POSTGRES_CONTAINER::getUsername); registry.add("spring.datasource.password", POSTGRES_CONTAINER::getPassword); - } - - @DynamicPropertySource - public static void kafkaProperties(DynamicPropertyRegistry registry) { - registry.add("spring.kafka.bootstrap-servers", kafkaContainer::getBootstrapServers); + registry.add("spring.kafka.bootstrap-servers", KAFKA_CONTAINER::getBootstrapServers); } @BeforeEach diff --git a/src/test/java/com/maires/wnet/integration/CustomerIntegrationTest.java b/src/test/java/com/maires/wnet/integration/CustomerIntegrationTest.java index a707750..f466a21 100644 --- a/src/test/java/com/maires/wnet/integration/CustomerIntegrationTest.java +++ b/src/test/java/com/maires/wnet/integration/CustomerIntegrationTest.java @@ -43,7 +43,7 @@ public class CustomerIntegrationTest { public static PostgreSQLContainer POSTGRES_CONTAINER = new PostgreSQLContainer("postgres") .withDatabaseName("wnetdb"); @Container - public static KafkaContainer kafkaContainer = new KafkaContainer(); + public static KafkaContainer KAFKA_CONTAINER = new KafkaContainer(); @Autowired CustomerRepository customerRepository; @Autowired @@ -61,11 +61,7 @@ public static void overrideProperties(DynamicPropertyRegistry registry) { registry.add("spring.datasource.url", POSTGRES_CONTAINER::getJdbcUrl); registry.add("spring.datasource.username", POSTGRES_CONTAINER::getUsername); registry.add("spring.datasource.password", POSTGRES_CONTAINER::getPassword); - } - - @DynamicPropertySource - public static void kafkaProperties(DynamicPropertyRegistry registry) { - registry.add("spring.kafka.bootstrap-servers", kafkaContainer::getBootstrapServers); + registry.add("spring.kafka.bootstrap-servers", KAFKA_CONTAINER::getBootstrapServers); } @BeforeEach @@ -212,9 +208,9 @@ public void testUpdateCustomer() throws Exception { ObjectMapper objectMapper = new ObjectMapper(); String updatedCustomerJson = objectMapper.writeValueAsString(customerToUpdate); - String equipmentUrl = "/customers/%s".formatted(customerToUpdate.getId()); + String customerUrl = "/customers/%s".formatted(customerToUpdate.getId()); - mockMvc.perform(put(equipmentUrl) + mockMvc.perform(put(customerUrl) .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) @@ -269,7 +265,7 @@ public void testCreateCustomerAddress() throws Exception { @Test @DisplayName("Delete Customer") - public void testDeleteEquipment() throws Exception { + public void testDeleteCustomer() throws Exception { Customer customerToDelete = new Customer("Gilvan Carlos Ferreira", "93684193020", "77009901111", diff --git a/src/test/java/com/maires/wnet/integration/EquipmentIntegrationTest.java b/src/test/java/com/maires/wnet/integration/EquipmentIntegrationTest.java index eb54eda..e4e065e 100644 --- a/src/test/java/com/maires/wnet/integration/EquipmentIntegrationTest.java +++ b/src/test/java/com/maires/wnet/integration/EquipmentIntegrationTest.java @@ -41,7 +41,7 @@ public class EquipmentIntegrationTest { public static PostgreSQLContainer POSTGRES_CONTAINER = new PostgreSQLContainer("postgres") .withDatabaseName("wnetdb"); @Container - public static KafkaContainer kafkaContainer = new KafkaContainer(); + public static KafkaContainer KAFKA_CONTAINER = new KafkaContainer(); @Autowired EquipmentRepository equipmentRepository; @Autowired @@ -57,11 +57,7 @@ public static void overrideProperties(DynamicPropertyRegistry registry) { registry.add("spring.datasource.url", POSTGRES_CONTAINER::getJdbcUrl); registry.add("spring.datasource.username", POSTGRES_CONTAINER::getUsername); registry.add("spring.datasource.password", POSTGRES_CONTAINER::getPassword); - } - - @DynamicPropertySource - public static void kafkaProperties(DynamicPropertyRegistry registry) { - registry.add("spring.kafka.bootstrap-servers", kafkaContainer::getBootstrapServers); + registry.add("spring.kafka.bootstrap-servers", KAFKA_CONTAINER::getBootstrapServers); } @BeforeEach @@ -150,14 +146,14 @@ public void testUpdateEquipment() throws Exception { equipmentToUpdate.setManufacturer("Netgear"); ObjectMapper objectMapper = new ObjectMapper(); - String updatedPlanJson = objectMapper.writeValueAsString(equipmentToUpdate); + String updatedEquipmentJson = objectMapper.writeValueAsString(equipmentToUpdate); String equipmentUrl = "/equipments/%s".formatted(equipmentToUpdate.getId()); mockMvc.perform(put(equipmentUrl) .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) - .content(updatedPlanJson)) + .content(updatedEquipmentJson)) .andExpect(status().isOk()) .andExpect(jsonPath("$.id").exists()) .andExpect(jsonPath("$.type").value("MODEM")) diff --git a/src/test/java/com/maires/wnet/integration/InstallationIntegrationTest.java b/src/test/java/com/maires/wnet/integration/InstallationIntegrationTest.java new file mode 100644 index 0000000..baefb68 --- /dev/null +++ b/src/test/java/com/maires/wnet/integration/InstallationIntegrationTest.java @@ -0,0 +1,291 @@ +package com.maires.wnet.integration; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.maires.wnet.controller.dto.InstallationCreationDto; +import com.maires.wnet.entity.Address; +import com.maires.wnet.entity.Equipment; +import com.maires.wnet.entity.EquipmentType; +import com.maires.wnet.entity.Installation; +import com.maires.wnet.entity.Plan; +import com.maires.wnet.entity.Technician; +import com.maires.wnet.entity.User; +import com.maires.wnet.repository.AddressRepository; +import com.maires.wnet.repository.CustomerRepository; +import com.maires.wnet.repository.EquipmentRepository; +import com.maires.wnet.repository.InstallationRepository; +import com.maires.wnet.repository.PlanRepository; +import com.maires.wnet.repository.TechnicianRepository; +import com.maires.wnet.repository.UserRepository; +import com.maires.wnet.security.Role; +import com.maires.wnet.service.TokenService; +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.springframework.test.web.servlet.MockMvc; +import org.testcontainers.containers.KafkaContainer; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@SpringBootTest +@AutoConfigureMockMvc +@Testcontainers +@DisplayName("Installation integration tests") +public class InstallationIntegrationTest { + + @Container + public static PostgreSQLContainer POSTGRES_CONTAINER = new PostgreSQLContainer("postgres") + .withDatabaseName("wnetdb"); + @Container + public static KafkaContainer KAFKA_CONTAINER = new KafkaContainer(); + @Autowired + PlanRepository planRepository; + @Autowired + UserRepository userRepository; + @Autowired + InstallationRepository installationRepository; + @Autowired + CustomerRepository customerRepository; + @Autowired + TechnicianRepository technicianRepository; + @Autowired + AddressRepository addressRepository; + @Autowired + EquipmentRepository equipmentRepository; + @Autowired + MockMvc mockMvc; + @Autowired + private TokenService tokenService; + private String tokenAdmin; + + @DynamicPropertySource + public static void overrideProperties(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.url", POSTGRES_CONTAINER::getJdbcUrl); + registry.add("spring.datasource.username", POSTGRES_CONTAINER::getUsername); + registry.add("spring.datasource.password", POSTGRES_CONTAINER::getPassword); + registry.add("spring.kafka.bootstrap-servers", KAFKA_CONTAINER::getBootstrapServers); + } + + @BeforeEach + public void cleanUp() { + userRepository.deleteAll(); + installationRepository.deleteAll(); + technicianRepository.deleteAll(); + planRepository.deleteAll(); + equipmentRepository.deleteAll(); + User admin = new User(null, "System Manager Administrator", "admin@mail.com", "admin", + "segredo123", + Role.ADMIN); + User userAdmin = userRepository.save(admin); + tokenAdmin = tokenService.generateToken(userAdmin.getUsername()); + } + + @Test + @DisplayName("Retrieval all installations") + public void testInstallationRetrievalAll() throws Exception { + + Address home = new Address( + "São Paulo", "São Paulo", "01000000", "Avenida Paulista", 1023, "Bela Vista", + "Próximo ao Parque Trianon"); + + Address work = new Address( + "Campinas", "São Paulo", "02000022", "Avenida Rosalita Fagundes", 152, "Bosque", + "Ao lado da padaria"); + + Technician technician = new Technician("João Antônio Benevides Faria", "77011114444", + "joao@example.com"); + + Plan plan = new Plan("Speed og Thunder", 300, 70.0); + + Equipment router = new Equipment(EquipmentType.ROUTER, "Asus RT-AC88U", "SN035", "Asus"); + Equipment modem = new Equipment(EquipmentType.MODEM, "Motorola MG7700", "SN036", "Motorola"); + + Equipment routerWork = new Equipment(EquipmentType.ROUTER, "Asus RT-AC88U", "SN099", "Asus"); + Equipment modemWork = new Equipment(EquipmentType.MODEM, "Motorola MG7700", "SN098", + "Motorola"); + + addressRepository.save(home); + addressRepository.save(work); + technicianRepository.save(technician); + planRepository.save(plan); + equipmentRepository.save(router); + equipmentRepository.save(modem); + equipmentRepository.save(routerWork); + equipmentRepository.save(modemWork); + + List equipmentListHome = new ArrayList<>(); + equipmentListHome.add(router); + equipmentListHome.add(modem); + + List equipmentListWork = new ArrayList<>(); + equipmentListWork.add(router); + equipmentListWork.add(modem); + + Installation newInstallationHome = new Installation(home, plan, technician, equipmentListHome); + Installation newInstallationWork = new Installation(work, plan, technician, equipmentListWork); + + installationRepository.save(newInstallationHome); + installationRepository.save(newInstallationWork); + + String installationUrl = "/installations"; + + mockMvc.perform(get(installationUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$").isArray()) + .andExpect(jsonPath("$.length()").value(2)) + .andExpect(jsonPath("$[0].isActive").value(true)) + .andExpect(jsonPath("$[0].id").value(newInstallationHome.getId())) + .andExpect(jsonPath("$[1].isActive").value(true)) + .andExpect(jsonPath("$[1].id").value(newInstallationWork.getId())); + } + + @Test + @DisplayName("Retrieval installation by id") + public void testInstallationRetrievalById() throws Exception { + Address home = new Address( + "São Paulo", "São Paulo", "01000000", "Avenida Paulista", 1023, "Bela Vista", + "Próximo ao Parque Trianon"); + + Technician technician = new Technician("João Antônio Benevides Faria", "77011114444", + "joao@example.com"); + + Plan plan = new Plan("Speed og Thunder", 300, 70.0); + + Equipment router = new Equipment(EquipmentType.ROUTER, "Asus RT-AC88U", "SN035", "Asus"); + Equipment modem = new Equipment(EquipmentType.MODEM, "Motorola MG7700", "SN036", "Motorola"); + + addressRepository.save(home); + technicianRepository.save(technician); + planRepository.save(plan); + equipmentRepository.save(router); + equipmentRepository.save(modem); + + List equipmentListHome = new ArrayList<>(); + equipmentListHome.add(router); + equipmentListHome.add(modem); + + Installation newInstallationHome = new Installation(home, plan, technician, equipmentListHome); + + installationRepository.save(newInstallationHome); + + String installationUrl = "/installations/%s".formatted(newInstallationHome.getId()); + + mockMvc.perform(get(installationUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").value(newInstallationHome.getId())) + .andExpect(jsonPath("$.isActive").value(true)) + .andExpect(jsonPath("$.plan").exists()) + .andExpect(jsonPath("$.technician").exists()) + .andExpect(jsonPath("$.equipments").exists()); + } + + @Test + @DisplayName("Update installation") + public void testUpdateInstallation() throws Exception { + + Address home = new Address( + "São Paulo", "São Paulo", "01000000", "Avenida Paulista", 1023, "Bela Vista", + "Próximo ao Parque Trianon"); + + Technician technician = new Technician("João Antônio Benevides Faria", "77011114444", + "joao@example.com"); + + Plan plan = new Plan("Speed og Thunder", 300, 70.0); + + Equipment router = new Equipment(EquipmentType.ROUTER, "Asus RT-AC88U", "SN035", "Asus"); + Equipment modem = new Equipment(EquipmentType.MODEM, "Motorola MG7700", "SN036", "Motorola"); + + addressRepository.save(home); + technicianRepository.save(technician); + planRepository.save(plan); + equipmentRepository.save(router); + equipmentRepository.save(modem); + + List equipmentListHome = new ArrayList<>(); + equipmentListHome.add(router); + equipmentListHome.add(modem); + + List blankList = new ArrayList<>(); + + Installation installationToUpdate = new Installation(home, plan, technician, equipmentListHome); + installationRepository.save(installationToUpdate); + + InstallationCreationDto installationDto = new InstallationCreationDto(plan.getId(), + technician.getId(), blankList); + + ObjectMapper objectMapper = new ObjectMapper(); + String updatedInstallationJson = objectMapper.writeValueAsString(installationDto); + + String installationUrl = "/installations/%s".formatted(installationToUpdate.getId()); + + mockMvc.perform(put(installationUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(updatedInstallationJson)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.equipments").isEmpty()); + } + + @Test + @DisplayName("Delete installation") + public void testDeleteInstallation() throws Exception { + + Address home = new Address( + "São Paulo", "São Paulo", "01000000", "Avenida Paulista", 1023, "Bela Vista", + "Próximo ao Parque Trianon"); + + Technician technician = new Technician("João Antônio Benevides Faria", "77011114444", + "joao@example.com"); + + Plan plan = new Plan("Speed og Thunder", 300, 70.0); + + Equipment router = new Equipment(EquipmentType.ROUTER, "Asus RT-AC88U", "SN035", "Asus"); + Equipment modem = new Equipment(EquipmentType.MODEM, "Motorola MG7700", "SN036", "Motorola"); + + addressRepository.save(home); + technicianRepository.save(technician); + planRepository.save(plan); + equipmentRepository.save(router); + equipmentRepository.save(modem); + + List equipmentListHome = new ArrayList<>(); + equipmentListHome.add(router); + equipmentListHome.add(modem); + + Installation installationToDelete = new Installation(home, plan, technician, equipmentListHome); + installationRepository.save(installationToDelete); + + String installationUrl = "/installations/%s".formatted(installationToDelete.getId()); + + mockMvc.perform(delete(installationUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenAdmin) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").value(installationToDelete.getId())) + .andExpect(jsonPath("$.plan").exists()) + .andExpect(jsonPath("$.technician").exists()) + .andExpect(jsonPath("$.equipments").exists()); + ; + } + +} \ No newline at end of file diff --git a/src/test/java/com/maires/wnet/integration/PlanIntegrationTest.java b/src/test/java/com/maires/wnet/integration/PlanIntegrationTest.java index fff748a..6623424 100644 --- a/src/test/java/com/maires/wnet/integration/PlanIntegrationTest.java +++ b/src/test/java/com/maires/wnet/integration/PlanIntegrationTest.java @@ -40,7 +40,7 @@ public class PlanIntegrationTest { public static PostgreSQLContainer POSTGRES_CONTAINER = new PostgreSQLContainer("postgres") .withDatabaseName("wnetdb"); @Container - public static KafkaContainer kafkaContainer = new KafkaContainer(); + public static KafkaContainer KAFKA_CONTAINER = new KafkaContainer(); @Autowired PlanRepository planRepository; @Autowired @@ -56,11 +56,7 @@ public static void overrideProperties(DynamicPropertyRegistry registry) { registry.add("spring.datasource.url", POSTGRES_CONTAINER::getJdbcUrl); registry.add("spring.datasource.username", POSTGRES_CONTAINER::getUsername); registry.add("spring.datasource.password", POSTGRES_CONTAINER::getPassword); - } - - @DynamicPropertySource - public static void kafkaProperties(DynamicPropertyRegistry registry) { - registry.add("spring.kafka.bootstrap-servers", kafkaContainer::getBootstrapServers); + registry.add("spring.kafka.bootstrap-servers", KAFKA_CONTAINER::getBootstrapServers); } @BeforeEach @@ -76,7 +72,7 @@ public void cleanUp() { @Test @DisplayName("Retrieval all plans") - public void testTechnicianRetrievalAll() throws Exception { + public void testPlanRetrievalAll() throws Exception { Plan planOne = new Plan("Speed of Light", 299, 100.0); Plan planTwe = new Plan("Low Connection", 10, 50.0); @@ -136,7 +132,7 @@ public void testCreatePlan() throws Exception { @Test @DisplayName("Update plan") - public void testUpdateTechnician() throws Exception { + public void testUpdatePlan() throws Exception { Plan planToUpdate = new Plan("Speed of Light", 299, 100.0); planRepository.save(planToUpdate); diff --git a/src/test/java/com/maires/wnet/integration/TechnicianIntegrationTest.java b/src/test/java/com/maires/wnet/integration/TechnicianIntegrationTest.java index 8149186..ad64382 100644 --- a/src/test/java/com/maires/wnet/integration/TechnicianIntegrationTest.java +++ b/src/test/java/com/maires/wnet/integration/TechnicianIntegrationTest.java @@ -40,7 +40,7 @@ public class TechnicianIntegrationTest { public static PostgreSQLContainer POSTGRES_CONTAINER = new PostgreSQLContainer("postgres") .withDatabaseName("wnetdb"); @Container - public static KafkaContainer kafkaContainer = new KafkaContainer(); + public static KafkaContainer KAFKA_CONTAINER = new KafkaContainer(); @Autowired TechnicianRepository technicianRepository; @Autowired @@ -57,11 +57,7 @@ public static void overrideProperties(DynamicPropertyRegistry registry) { registry.add("spring.datasource.url", POSTGRES_CONTAINER::getJdbcUrl); registry.add("spring.datasource.username", POSTGRES_CONTAINER::getUsername); registry.add("spring.datasource.password", POSTGRES_CONTAINER::getPassword); - } - - @DynamicPropertySource - public static void kafkaProperties(DynamicPropertyRegistry registry) { - registry.add("spring.kafka.bootstrap-servers", kafkaContainer::getBootstrapServers); + registry.add("spring.kafka.bootstrap-servers", KAFKA_CONTAINER::getBootstrapServers); } @BeforeEach diff --git a/src/test/java/com/maires/wnet/integration/UserIntegrationTest.java b/src/test/java/com/maires/wnet/integration/UserIntegrationTest.java index 32221fd..a62427d 100644 --- a/src/test/java/com/maires/wnet/integration/UserIntegrationTest.java +++ b/src/test/java/com/maires/wnet/integration/UserIntegrationTest.java @@ -38,7 +38,7 @@ public class UserIntegrationTest { public static PostgreSQLContainer POSTGRES_CONTAINER = new PostgreSQLContainer("postgres") .withDatabaseName("wnetdb"); @Container - public static KafkaContainer kafkaContainer = new KafkaContainer(); + public static KafkaContainer KAFKA_CONTAINER = new KafkaContainer(); @Autowired UserRepository userRepository; @Autowired @@ -54,11 +54,7 @@ public static void overrideProperties(DynamicPropertyRegistry registry) { registry.add("spring.datasource.url", POSTGRES_CONTAINER::getJdbcUrl); registry.add("spring.datasource.username", POSTGRES_CONTAINER::getUsername); registry.add("spring.datasource.password", POSTGRES_CONTAINER::getPassword); - } - - @DynamicPropertySource - public static void kafkaProperties(DynamicPropertyRegistry registry) { - registry.add("spring.kafka.bootstrap-servers", kafkaContainer::getBootstrapServers); + registry.add("spring.kafka.bootstrap-servers", KAFKA_CONTAINER::getBootstrapServers); } @BeforeEach From 17624378172d8eb00056bf8d491e08ee8e9c8570 Mon Sep 17 00:00:00 2001 From: mairess Date: Sat, 13 Jul 2024 12:46:39 -0300 Subject: [PATCH 15/17] test(integration): add auth test --- .../wnet/integration/AuthIntegrationTest.java | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 src/test/java/com/maires/wnet/integration/AuthIntegrationTest.java diff --git a/src/test/java/com/maires/wnet/integration/AuthIntegrationTest.java b/src/test/java/com/maires/wnet/integration/AuthIntegrationTest.java new file mode 100644 index 0000000..5f89997 --- /dev/null +++ b/src/test/java/com/maires/wnet/integration/AuthIntegrationTest.java @@ -0,0 +1,111 @@ +package com.maires.wnet.integration; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.maires.wnet.controller.dto.AuthDto; +import com.maires.wnet.entity.User; +import com.maires.wnet.repository.EquipmentRepository; +import com.maires.wnet.repository.InstallationRepository; +import com.maires.wnet.repository.PlanRepository; +import com.maires.wnet.repository.TechnicianRepository; +import com.maires.wnet.repository.UserRepository; +import com.maires.wnet.security.Role; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.springframework.test.web.servlet.MockMvc; +import org.testcontainers.containers.KafkaContainer; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@SpringBootTest +@AutoConfigureMockMvc +@Testcontainers +@DisplayName("Authentication integration tests") +public class AuthIntegrationTest { + + @Container + public static PostgreSQLContainer POSTGRES_CONTAINER = new PostgreSQLContainer("postgres") + .withDatabaseName("wnetdb"); + @Container + public static KafkaContainer KAFKA_CONTAINER = new KafkaContainer(); + + @Autowired + UserRepository userRepository; + + @Autowired + PlanRepository planRepository; + + @Autowired + InstallationRepository installationRepository; + + @Autowired + TechnicianRepository technicianRepository; + + @Autowired + EquipmentRepository equipmentRepository; + + @Autowired + MockMvc mockMvc; + + @Autowired + private PasswordEncoder passwordEncoder; + + + @DynamicPropertySource + public static void overrideProperties(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.url", POSTGRES_CONTAINER::getJdbcUrl); + registry.add("spring.datasource.username", POSTGRES_CONTAINER::getUsername); + registry.add("spring.datasource.password", POSTGRES_CONTAINER::getPassword); + registry.add("spring.kafka.bootstrap-servers", KAFKA_CONTAINER::getBootstrapServers); + } + + @BeforeEach + public void cleanUp() { + userRepository.deleteAll(); + installationRepository.deleteAll(); + technicianRepository.deleteAll(); + planRepository.deleteAll(); + equipmentRepository.deleteAll(); + + User admin = new User( + null, + "System Manager Administrator", + "admin@mail.com", + "admin", + passwordEncoder.encode("segredo123"), + Role.ADMIN); + + userRepository.save(admin); + } + + @Test + @DisplayName("Login successfully") + public void testAuthentication() throws Exception { + + AuthDto login = new AuthDto("admin", "segredo123"); + + ObjectMapper objectMapper = new ObjectMapper(); + String loginJson = objectMapper.writeValueAsString(login); + String authUrl = "/auth/login"; + + mockMvc.perform(post(authUrl) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(loginJson)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.token").exists()); + } + +} \ No newline at end of file From 7e7dffa309b7ae97345bd2c9faa12be0ca12605a Mon Sep 17 00:00:00 2001 From: mairess Date: Sat, 13 Jul 2024 12:47:27 -0300 Subject: [PATCH 16/17] chore: separate test profile --- src/main/resources/application-dev.properties | 5 +++-- .../resources/application-test.properties | 21 ------------------ src/main/resources/application.properties | 4 +--- .../resources/application-test.properties | 22 +++++++++++++++++++ src/test/resources/application.properties | 1 + 5 files changed, 27 insertions(+), 26 deletions(-) delete mode 100644 src/main/resources/application-test.properties create mode 100644 src/test/resources/application-test.properties create mode 100644 src/test/resources/application.properties diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index ef47f2a..9847784 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -5,10 +5,11 @@ spring.datasource.username=${SPRING_DATASOURCE_USERNAME:postgres} spring.datasource.password=${SPRING_DATASOURCE_PASSWORD:postgres} spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect # Hibernate configuration -spring.jpa.hibernate.ddl-auto=update -#spring.jpa.hibernate.ddl-auto=updateUser +spring.jpa.hibernate.ddl-auto=create-drop spring.jpa.show-sql=true spring.application.name=w-net-internet +# JWT configuration +api.security.token.secret=${JWT_SECRET:mySuperSuperSecret} # Kafka configuration kafka.topic=installation-completed spring.kafka.bootstrap-servers=${KAFKA_HOST:localhost}:9092 diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties deleted file mode 100644 index 87d655c..0000000 --- a/src/main/resources/application-test.properties +++ /dev/null @@ -1,21 +0,0 @@ -# Configuracao do DataSource -spring.datasource.url=jdbc:h2:mem:testdb -spring.datasource.driverClassName=org.h2.Driver -spring.datasource.username=sa -spring.datasource.password= -spring.jpa.database-platform=org.hibernate.dialect.H2Dialect -# Hibernate configuration -spring.jpa.hibernate.ddl-auto=create-drop -# Configuracao da JPA -spring.jpa.show-sql=true -spring.jpa.properties.hibernate.format_sql=true -# Kafka configuration -kafka.topic=installation-completed -#spring.kafka.bootstrap-servers=${KAFKA_HOST:localhost}:9092 -# JavaMailSender configurations -spring.mail.host=${MAIL_HOST} -spring.mail.port=${MAIL_PORT} -spring.mail.username=${MAIL_USERNAME} -spring.mail.password=${MAIL_PASSWORD} -spring.mail.properties.mail.smtp.auth=true -spring.mail.properties.mail.smtp.starttls.enable=true \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index c633ddb..257b306 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,3 +1 @@ -spring.profiles.active=dev -api.security.token.secret=${JWT_SECRET:mySuperSuperSecret} -spring.jpa.hibernate.ddl-auto=create-drop \ No newline at end of file +spring.profiles.active=dev \ No newline at end of file diff --git a/src/test/resources/application-test.properties b/src/test/resources/application-test.properties new file mode 100644 index 0000000..d99ce0f --- /dev/null +++ b/src/test/resources/application-test.properties @@ -0,0 +1,22 @@ +# DataSource configuration +spring.datasource.url=jdbc:postgresql://${POSTGRES_HOST:localhost}:5432/wnetdb +spring.datasource.driver-class-name=org.postgresql.Driver +spring.datasource.username=${SPRING_DATASOURCE_USERNAME:postgres} +spring.datasource.password=${SPRING_DATASOURCE_PASSWORD:postgres} +spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect +# Hibernate configuration +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=true +spring.application.name=w-net-internet +# JWT configuration +api.security.token.secret=${JWT_SECRET:mySuperSuperSecret} +# Kafka configuration +kafka.topic=installation-completed +spring.kafka.bootstrap-servers=${KAFKA_HOST:localhost}:9092 +# JavaMailSender configurations +spring.mail.host=${MAIL_HOST} +spring.mail.port=${MAIL_PORT} +spring.mail.username=${MAIL_USERNAME} +spring.mail.password=${MAIL_PASSWORD} +spring.mail.properties.mail.smtp.auth=true +spring.mail.properties.mail.smtp.starttls.enable=true \ No newline at end of file diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100644 index 0000000..b2d2a5a --- /dev/null +++ b/src/test/resources/application.properties @@ -0,0 +1 @@ +spring.profiles.active=test \ No newline at end of file From af86ae0fb0672a404e73a68c770364d03f19bde9 Mon Sep 17 00:00:00 2001 From: mairess Date: Sat, 13 Jul 2024 12:55:26 -0300 Subject: [PATCH 17/17] chore: change jacoco execution configuration, refactor includes to get controller/ directory instead of each individually one --- pom.xml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 2f0515a..d618873 100644 --- a/pom.xml +++ b/pom.xml @@ -35,12 +35,7 @@ true - **/controller/UserController.* - **/controller/TechnicianController.* - **/controller/PlanController.* - **/controller/EquipmentController.* - **/controller/CustomerController.* - **/controller/AddressController.* + **/controller/*