43bbcece7a
Backend: adds JDBC session support, login/status/logout endpoints, and new DTOs (AuthResponse, ConnectionStatusResponse, LoginResult). Frontend replaces the Vite boilerplate with a Dashboard, ServiceCard, and ConnectModal backed by a typed API client. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
210 lines
7.8 KiB
Java
210 lines
7.8 KiB
Java
package com.vaessl.app.connection;
|
|
|
|
import org.junit.jupiter.api.Test;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.boot.resttestclient.TestRestTemplate;
|
|
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate;
|
|
import org.springframework.boot.test.context.SpringBootTest;
|
|
import org.springframework.http.HttpStatus;
|
|
import org.springframework.http.ResponseEntity;
|
|
|
|
import com.github.tomakehurst.wiremock.http.Fault;
|
|
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
|
|
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
|
|
|
|
import com.jayway.jsonpath.DocumentContext;
|
|
import com.jayway.jsonpath.JsonPath;
|
|
import com.vaessl.app.dto.ConnectionRequest;
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
|
|
import static com.github.tomakehurst.wiremock.client.WireMock.*;
|
|
import static com.vaessl.app.connection.Endpoint.*;
|
|
import static com.vaessl.app.exception.ErrorMessage.*;
|
|
import static com.vaessl.app.connection.ServiceType.*;
|
|
|
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
|
@AutoConfigureTestRestTemplate
|
|
@WireMockTest
|
|
class HomeboxIntegrationTest {
|
|
|
|
@Autowired
|
|
TestRestTemplate restTemplate;
|
|
|
|
@Autowired
|
|
ConnectionRepository cRepository;
|
|
|
|
String okJsonHomeboxResponse = """
|
|
{
|
|
"token": "fake-jwt-token",
|
|
"attachmentToken": "fake-attach",
|
|
"expiresAt": "2026-04-26T02:23:13Z"
|
|
}
|
|
""";
|
|
|
|
private static final String TEST_USER = "admin";
|
|
private static final String TEST_PASS = "pw";
|
|
|
|
/**
|
|
* Returns Token and status code OK when login is successful.
|
|
*
|
|
* @param wm the WiremockRuntimeInfo object
|
|
*/
|
|
@Test
|
|
void shouldReturnStatusOkWhenHomeboxCredentialsAreValid(WireMockRuntimeInfo wm) {
|
|
|
|
stubFor(post(HOMEBOX_LOGIN.getValue())
|
|
.willReturn(okJson(okJsonHomeboxResponse)));
|
|
|
|
ResponseEntity<String> response = restTemplate.postForEntity(LOGIN.getValue(), connectionRequest(wm),
|
|
String.class);
|
|
|
|
DocumentContext documentContext = JsonPath.parse(response.getBody());
|
|
|
|
String serviceType = documentContext.read("$.serviceType");
|
|
assertThat(serviceType).isEqualTo("HOMEBOX");
|
|
|
|
String expiresAt = documentContext.read("$.expiresAt", String.class);
|
|
assertThat(expiresAt).isEqualTo("2026-04-26T02:23:13Z");
|
|
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
|
|
}
|
|
|
|
/**
|
|
* Tests the Unauthorized custom exception.
|
|
*
|
|
* @param wm the WiremockRuntimeInfo object
|
|
*/
|
|
@Test
|
|
void shouldFailToConnectWhenHomeboxReturnsUnauthorized(WireMockRuntimeInfo wm) {
|
|
|
|
stubFor(post(HOMEBOX_LOGIN.getValue()).willReturn(unauthorized()));
|
|
|
|
ResponseEntity<String> response = restTemplate.postForEntity(LOGIN.getValue(), connectionRequest(wm),
|
|
String.class);
|
|
|
|
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
|
|
assertThat(response.getBody()).contains(UNAUTHORIZED_WRONG_LOGIN.getMessage());
|
|
}
|
|
|
|
/**
|
|
* Tests a server error from the external api.
|
|
*
|
|
* @param wm the WiremockRuntimeInfo object
|
|
*/
|
|
@Test
|
|
void shouldFailToConnectWhenHomeboxReturnsServiceUnavailable(WireMockRuntimeInfo wm) {
|
|
|
|
stubFor(post(HOMEBOX_LOGIN.getValue()).willReturn(serviceUnavailable()));
|
|
|
|
ResponseEntity<String> response = restTemplate.postForEntity(LOGIN.getValue(), connectionRequest(wm),
|
|
String.class);
|
|
|
|
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.SERVICE_UNAVAILABLE);
|
|
assertThat(response.getBody()).contains(SERVER_ERROR_GENERAL.getMessage());
|
|
}
|
|
|
|
/**
|
|
* Checks when the service is unavailable or the app URL is wrong.
|
|
*/
|
|
@Test
|
|
void shouldReturnServiceUnavailableWhenHomeboxUrlIsWrong(WireMockRuntimeInfo wm) {
|
|
|
|
stubFor(post(HOMEBOX_LOGIN.getValue())
|
|
.willReturn(aResponse().withFault(Fault.CONNECTION_RESET_BY_PEER)));
|
|
|
|
ConnectionRequest badRequest = connectionRequest(wm);
|
|
ResponseEntity<String> response = restTemplate.postForEntity(LOGIN.getValue(), badRequest, String.class);
|
|
|
|
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.SERVICE_UNAVAILABLE);
|
|
assertThat(response.getBody()).contains(SERVICE_UNAVAILABLE_UNREACHABLE_URL.getMessage());
|
|
}
|
|
|
|
/**
|
|
* Checks if any login fields are empty since all of them are mandatory.
|
|
*/
|
|
@Test
|
|
void shouldReturnBadRequestWhenHomeboxFieldsAreEmpty() {
|
|
|
|
ConnectionRequest emtpyRequest = new ConnectionRequest("", "", "", "", false);
|
|
|
|
ResponseEntity<String> response = restTemplate.postForEntity(LOGIN.getValue(), emtpyRequest, String.class);
|
|
|
|
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
|
|
assertThat(response.getBody()).contains(BAD_REQUEST_EMPTY_FIELDS.getMessage());
|
|
}
|
|
|
|
/**
|
|
* Test the exception when there is an input for serviceType but it's
|
|
* unsupported.
|
|
*/
|
|
@Test
|
|
void shouldReturnWrongServiceTypeException(WireMockRuntimeInfo wm) {
|
|
ConnectionRequest wrongServiceTypeReq = new ConnectionRequest(
|
|
wm.getHttpBaseUrl(),
|
|
"wrong-service-type",
|
|
TEST_USER, TEST_PASS,
|
|
false);
|
|
|
|
ResponseEntity<String> response = restTemplate.postForEntity(LOGIN.getValue(), wrongServiceTypeReq,
|
|
String.class);
|
|
|
|
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND);
|
|
assertThat(response.getBody()).contains(WRONG_SERVICE_TYPE.getMessage());
|
|
}
|
|
|
|
/**
|
|
* Tests the succesfull persistance of Homebox credential response to the
|
|
* database.
|
|
*
|
|
* @param wm the WiremockRuntimeInfo object
|
|
*/
|
|
@Test
|
|
void shouldSaveHomeboxConnectionResponseToDb(WireMockRuntimeInfo wm) {
|
|
|
|
stubFor(post(urlEqualTo(HOMEBOX_LOGIN.getValue()))
|
|
.willReturn(okJson(okJsonHomeboxResponse)));
|
|
|
|
ConnectionRequest request = connectionRequest(wm);
|
|
|
|
ResponseEntity<String> response = restTemplate.postForEntity(LOGIN.getValue(), request, String.class);
|
|
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
|
|
|
|
ConnectionEntity dbEntry = cRepository.findByAppUrlAndUsername(request.appUrl(), request.username());
|
|
|
|
assertThat(dbEntry).isNotNull();
|
|
assertThat(dbEntry.getAppUrl()).isEqualTo(request.appUrl());
|
|
assertThat(dbEntry.getUsername()).isEqualTo(request.username());
|
|
|
|
if (dbEntry instanceof HomeboxEntity hbE) {
|
|
assertThat(hbE.getToken()).isEqualTo("fake-jwt-token");
|
|
assertThat(hbE.getAttachmentToken()).isEqualTo("fake-attach");
|
|
assertThat(hbE.getExpiresAt().toString()).hasToString("2026-04-26T02:23:13Z");
|
|
}
|
|
}
|
|
|
|
@Test
|
|
void shouldReturnEmptyCredentialsExceptionWhenCredsAreMissing(WireMockRuntimeInfo wm) {
|
|
ConnectionRequest missingCredentials = new ConnectionRequest(wm.getHttpBaseUrl(), HOMEBOX.getValue(), TEST_USER,
|
|
null,
|
|
false);
|
|
|
|
ResponseEntity<String> response = restTemplate.postForEntity(LOGIN.getValue(), missingCredentials,
|
|
String.class);
|
|
|
|
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
|
|
assertThat(response.getBody()).contains(BAD_REQUEST_EMPTY_FIELDS.getMessage());
|
|
}
|
|
|
|
/**
|
|
* Creates a valid connection request with a mock Api through
|
|
* WireMockRuntimeInfo.
|
|
*
|
|
* @param wm the WiremockRuntimeInfo object
|
|
* @return a mock api connection request.
|
|
*/
|
|
private ConnectionRequest connectionRequest(WireMockRuntimeInfo wm) {
|
|
return new ConnectionRequest(wm.getHttpBaseUrl(), HOMEBOX.getValue(), TEST_USER, TEST_PASS,
|
|
null);
|
|
}
|
|
}
|