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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions .github/workflows/complete-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,11 @@ jobs:
DB_PASSWORD: password
run: |
cd ../backend/pcmod
./mvnw spring-boot:run > /dev/null 2>&1 < /dev/null &
sudo -E ./mvnw spring-boot:run > /dev/null 2>&1 < /dev/null &

npx wait-on https-get://localhost:8443/api/v1/components/
npx wait-on https-get://localhost:443/api/v1/components/

sudo chown -R $USER:$USER target/

cd ../../frontend
npm run test:coverage
Expand Down Expand Up @@ -186,10 +188,12 @@ jobs:
npm run dev > /dev/null 2>&1 < /dev/null &

cd ../backend/pcmod
./mvnw spring-boot:run > /dev/null 2>&1 < /dev/null &
sudo -E ./mvnw spring-boot:run > /dev/null 2>&1 < /dev/null &

npx wait-on http-get://localhost:5173 https-get://localhost:8443/api/v1/components/
npx wait-on http-get://localhost:5173 https-get://localhost:443/api/v1/components/

sudo chown -R $USER:$USER target/

./mvnw test -Dgroups="client-system"

# SonarCloud Analysis
Expand Down
2 changes: 1 addition & 1 deletion backend/pcmod/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@
</execution>
</executions>
<configuration>
<apiDocsUrl>http://127.0.0.1:8443/v3/api-docs.yaml</apiDocsUrl>
<apiDocsUrl>http://127.0.0.1:443/v3/api-docs.yaml</apiDocsUrl>
<outputFileName>api-docs.yaml</outputFileName>
<outputDir>${project.basedir}/docs/api</outputDir>
</configuration>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
Expand All @@ -23,4 +25,9 @@ public Page<ComponentDTO> findAll(Pageable pageable) {
return componentService.findAll(pageable).map(component -> componentService.toDTO(component));
}

@GetMapping("/recent")
public List<ComponentDTO> findTop3MoreRecent() {
return componentService.findTop3MoreRecent().stream().map(componentService::toDTO).toList();
}

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package es.codeurjcstudents.pcmod.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;

import es.codeurjcstudents.pcmod.model.Component;

public interface ComponentsRepository extends JpaRepository<Component, Long> {

List<Component> findTop3ByOrderByIdDesc();

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package es.codeurjcstudents.pcmod.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
Expand Down Expand Up @@ -29,4 +31,8 @@ public Page<Component> findAll(Pageable pageable) {
public ComponentDTO toDTO(Component component) {
return componentMapper.toDTO(component);
}

public List<Component> findTop3MoreRecent() {
return componentRepository.findTop3ByOrderByIdDesc();
}
}
2 changes: 1 addition & 1 deletion backend/pcmod/src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
spring.application.name=pcmod

server.port=8443
server.port=443
server.ssl.enabled=true
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=password
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package es.codeurjcstudents.pcmod.e2e.api;

import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.*;

@Tag("server-system")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HomePageSystemTests {

@LocalServerPort
private int port;

@BeforeEach
public void setup() {
RestAssured.port = port;
RestAssured.baseURI = "https://localhost";
RestAssured.basePath = "/api/v1";
RestAssured.useRelaxedHTTPSValidation();
}

@Test
public void getComponents() {
given().header("Content-Type", "application/json")
.when().get("/components/recent")
.then().statusCode(200).contentType(ContentType.JSON)
// Global checks
.body("size()", equalTo(3))
// Specific checks
.body("[0].name", equalTo("Kingston FURY Beast"))
.body("[1].name", equalTo("Seagate BarraCuda 3.5"))
.body("[2].name", equalTo("AMD Radeon RX 9060 XT DUAL WHITE"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public void teardown() {
@Test
public void loadComponentsTest() throws InterruptedException {

driver.get("http://localhost:5173/");
driver.get("http://localhost:5173/components");

wait.until(ExpectedConditions.presenceOfElementLocated(By.id("name-1")));
String componentName = driver.findElement(By.id("name-1")).getText();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package es.codeurjcstudents.pcmod.e2e.ui;

import static org.assertj.core.api.Assertions.assertThat;

import java.time.Duration;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

@Tag("client-system")
public class HomePageSystemTests {

private WebDriver driver;

private WebDriverWait wait;

@BeforeEach
public void setupTest() {
ChromeOptions options = new ChromeOptions();
options.addArguments("--incognito");
options.addArguments("--disable-notifications");
options.addArguments("--disable-features=PasswordLeakDetection");
options.addArguments("--headless");
options.addArguments("--no-sandbox");
options.addArguments("--disable-dev-shm-usage");

driver = new ChromeDriver(options);
wait = new WebDriverWait(driver, Duration.ofSeconds(10));
}

@AfterEach
public void teardown() {
if (driver != null) {
driver.quit();
}
}

@Test
public void loadHomePage() throws InterruptedException {

driver.get("http://localhost:5173/");

wait.until(ExpectedConditions.presenceOfElementLocated(By.id("welcome")));
String welcomeMessage = driver.findElement(By.id("welcome")).getText();
assertThat(welcomeMessage).isEqualTo("Bienvenido a PCMod");

wait.until(ExpectedConditions.presenceOfElementLocated(By.id("logo")));
String logoMessage = driver.findElement(By.id("logo")).getAttribute("alt");
assertThat(logoMessage).isEqualTo("PCMod Logo");

wait.until(ExpectedConditions.presenceOfElementLocated(By.id("component-9")));
String componentName9 = driver.findElement(By.id("component-9")).getText();
assertThat(componentName9).isEqualTo("AMD Radeon RX 9060 XT DUAL WHITE");
wait.until(ExpectedConditions.presenceOfElementLocated(By.id("component-10")));
String componentName10 = driver.findElement(By.id("component-10")).getText();
assertThat(componentName10).isEqualTo("Seagate BarraCuda 3.5");
wait.until(ExpectedConditions.presenceOfElementLocated(By.id("component-11")));
String componentName11 = driver.findElement(By.id("component-11")).getText();
assertThat(componentName11).isEqualTo("Kingston FURY Beast");

wait.until(ExpectedConditions.presenceOfElementLocated(By.name("componentsButton")));
assertThat(driver.findElements(By.name("componentsButton"))).isNotEmpty();

}

@Test
public void navigateToComponentsPage() throws InterruptedException {

driver.get("http://localhost:5173/");

wait.until(ExpectedConditions.presenceOfElementLocated(By.name("componentsButton")));
WebElement componentsButton = driver.findElement(By.name("componentsButton"));
componentsButton.click();

wait.until(ExpectedConditions.urlToBe("http://localhost:5173/components"));

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
public class ComponentsIntegrationTests {

@Container
private static final MySQLContainer<?> mysqlContainer = new MySQLContainer<>("mysql:8.0")
private static final MySQLContainer<?> mysqlContainer = new MySQLContainer<>("mysql:8.4")
.withDatabaseName("TestDB")
.withUsername("TestDBUser")
.withPassword("TestDBPassword");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package es.codeurjcstudents.pcmod.integration;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.math.BigDecimal;
import java.util.List;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;

import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

import es.codeurjcstudents.pcmod.enums.ComponentType;
import es.codeurjcstudents.pcmod.model.Component;
import es.codeurjcstudents.pcmod.repository.ComponentsRepository;
import es.codeurjcstudents.pcmod.service.ComponentsService;

@Tag("server-integration")
@SpringBootTest
@Testcontainers
public class HomePageIntegrationTests {

@Container
private static final MySQLContainer<?> mysqlContainer = new MySQLContainer<>("mysql:8.4")
.withDatabaseName("TestDB")
.withUsername("TestDBUser")
.withPassword("TestDBPassword");

@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url",
() -> mysqlContainer.getJdbcUrl() + "?useSSL=false&allowPublicKeyRetrieval=true");

registry.add("spring.datasource.username", mysqlContainer::getUsername);
registry.add("spring.datasource.password", mysqlContainer::getPassword);
registry.add("spring.datasource.driver-class-name", mysqlContainer::getDriverClassName);
}

@Autowired
private ComponentsService componentsService;

@Autowired
private ComponentsRepository componentsRepository;

@BeforeEach
void setUp() {
componentsRepository.deleteAll();
componentsRepository.save(new Component("AMD Ryzen 7 7800X3D",
"8 núcleos y 16 hilos ideales para gaming\r\n" + //
"96 MB de caché L3 3D V-Cache, baja latencia\r\n" + //
"Compatible con memorias DDR5, doble canal\r\n" + //
"Frecuencia base 4.2 GHz y turbo hasta 5.0 GHz",
ComponentType.CPU, "AMD", BigDecimal.valueOf(350.00), 5));
componentsRepository.save(new Component("NVIDIA GeForce RTX 5060 WINDFORCE MAX OC",
"Ray Tracing y DLSS 4 para gaming fluido\r\n" + //
"8GB GDDR7 y arquitectura Blackwell\r\n" + //
"WINDFORCE 2X: refrigeración eficiente y silenciosa\r\n" + //
"DisplayPort 2.1 y HDMI 2.1b hasta 8K\r\n" + //
"Tensor Cores 5ª gen y Reflex 2 para IA avanzada",
ComponentType.GPU, "Gigabyte", BigDecimal.valueOf(359.85), 2));
componentsRepository.save(new Component("Kingston NV3",
"Capacidad: 1 TB\r\n" + //
"Factor de forma de disco SSD: M.2\r\n" + //
"Interfaz: PCI Express 4.0\r\n" + //
"NVMe: Si\r\n" + //
"Tipo de memoria: 3D NAND",
ComponentType.STORAGE, "Kingston", BigDecimal.valueOf(149.95), 15));
}

@Test
void loadRecentComponents() {

List<Component> componentList = componentsService.findTop3MoreRecent();

assertEquals(3, componentList.size());
assertEquals("Kingston NV3", componentList.get(0).getName());
assertEquals("NVIDIA GeForce RTX 5060 WINDFORCE MAX OC", componentList.get(1).getName());
assertEquals("AMD Ryzen 7 7800X3D", componentList.get(2).getName());
}

@Test
void loadWithoutRecentComponents() {

componentsRepository.deleteAll();

List<Component> componentList = componentsService.findTop3MoreRecent();

assertTrue(componentList.isEmpty());
}
}
Loading
Loading