Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ public class RequestController {
public ResponseEntity<ApiResult<RequestDetailDTO>> save(
@Valid @RequestBody SaveRequestDTO dto) {
log.info("Saving request: {}", dto.getName());

RequestDetailDTO saved = requestService.save(dto);
return ResponseEntity.status(HttpStatus.CREATED)
.body(ApiResult.success(saved, "Request saved successfully"));
Expand Down Expand Up @@ -72,7 +71,6 @@ public ResponseEntity<ApiResult<RequestDetailDTO>> update(
@PathVariable Long id,
@Valid @RequestBody SaveRequestDTO dto) {
log.info("Updating request: {}", id);

RequestDetailDTO updated = requestService.update(id, dto);
return ResponseEntity.ok(ApiResult.success(updated, "Request updated successfully"));
}
Expand All @@ -81,7 +79,6 @@ public ResponseEntity<ApiResult<RequestDetailDTO>> update(
@Operation(summary = "Delete request", description = "Delete a saved request")
public ResponseEntity<ApiResult<Void>> delete(@PathVariable Long id) {
log.info("Deleting request: {}", id);

requestService.delete(id);
return ResponseEntity.ok(ApiResult.success(null, "Request deleted successfully"));
}
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/com/akash/embedqa/controller/TestController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.akash.embedqa.controller;

import com.akash.embedqa.model.dtos.test.TestRequestDTO;
import com.akash.embedqa.model.dtos.test.TestResultDTO;
import com.akash.embedqa.service.TestRunnerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;


@Slf4j
@RestController
@RequestMapping("/api/v1/test")

public class TestController {

private final TestRunnerService testRunnerService;

@Autowired
public TestController(TestRunnerService testRunnerService) {
this.testRunnerService = testRunnerService;
}

@PostMapping("/run")
public TestResultDTO runTest(@RequestBody TestRequestDTO request) {
return testRunnerService.runSingleTest(request);
}

}
15 changes: 15 additions & 0 deletions src/main/java/com/akash/embedqa/model/dtos/test/AssertionDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.akash.embedqa.model.dtos.test;

import lombok.*;

@Getter
@Setter
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AssertionDTO {
private String type;
private String key;
private String value;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.akash.embedqa.model.dtos.test;

import lombok.*;

import java.util.List;
import java.util.Map;

@Getter
@Setter
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TestRequestDTO {
private String name;
private String method;
private String url;
private Map<String, String> headers;
private List<AssertionDTO> assertions;
}
19 changes: 19 additions & 0 deletions src/main/java/com/akash/embedqa/model/dtos/test/TestResultDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.akash.embedqa.model.dtos.test;

import lombok.*;

import java.util.ArrayList;
import java.util.List;

@Getter
@Setter
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TestResultDTO {
private String requestName;
private boolean passed;
private int statusCode;
private List<String> messages = new ArrayList<>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.akash.embedqa.service;

import com.akash.embedqa.model.dtos.test.TestRequestDTO;
import com.akash.embedqa.model.dtos.test.TestResultDTO;


public interface TestRunnerService {
TestResultDTO runSingleTest(TestRequestDTO request);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package com.akash.embedqa.service.impl;

import com.akash.embedqa.model.dtos.test.AssertionDTO;
import com.akash.embedqa.model.dtos.test.TestRequestDTO;
import com.akash.embedqa.model.dtos.test.TestResultDTO;
import com.akash.embedqa.service.TestRunnerService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;

@Slf4j
@Service
@RequiredArgsConstructor
public class TestRunnerServiceImpl implements TestRunnerService {

private final RestTemplate restTemplate = new RestTemplate();

@Override
public TestResultDTO runSingleTest(TestRequestDTO request) {

TestResultDTO result = new TestResultDTO();
result.setRequestName(result.getRequestName());
result.setMessages(new ArrayList<>());

try {
String url = normalizerUrl(request.getUrl());

HttpHeaders headers = new HttpHeaders();
if (request.getHeaders() != null) {
request.getHeaders().forEach(headers::add);
}

HttpEntity<?> entity = new HttpEntity<>(headers);

ResponseEntity<String> response =
restTemplate.exchange(
url,
HttpMethod.valueOf(request.getMethod()),
entity,
String.class
);

result.setStatusCode(response.getStatusCodeValue());
boolean allPassed = true;

if (request.getAssertions() != null && !request.getAssertions().isEmpty()) {
for (AssertionDTO assertion : request.getAssertions()) {
boolean passed = false;

switch (assertion.getType().toLowerCase()) {
case "statuscode":
int expected = Integer.parseInt(assertion.getValue());
int actual = response.getStatusCodeValue();
passed = actual == expected;

result.getMessages().add(
"Excepted status " + expected +
", actual " + actual +
" -> " + (passed ? "PASS" : "FAIL")
);
break;
case "header":
String key = assertion.getKey();
String actualHeader = response.getHeaders().getFirst(key);
passed = assertion.getValue().equals(actualHeader);
result.getMessages().add(
"Header" + key + "expected=" + assertion.getValue() +
", actual=" + actualHeader + " -> " + (passed ? "PASS" : "FAIL")
);
break;
case "bodycontains":
String body = response.getBody() != null ? response.getBody() : "";
passed = body.contains(assertion.getValue());
result.getMessages().add(
"Body contains \"" + assertion.getValue() + "\" -> " + (passed ? "PASS" : "FAIL")
);
break;
default:
result.getMessages().add("Unknown assertion type: " + assertion.getType());
break;
}

if ("StatusCode".equalsIgnoreCase(assertion.getType())) {
int expected = Integer.parseInt(assertion.getValue());
int actual = response.getStatusCodeValue();
passed = actual == expected;

result.getMessages().add(
"Excepted status " + expected +
", actual " + actual +
" -> " + (passed ? "PASS" : "FAIL")
);
}

allPassed = allPassed && passed;

}
} else {
allPassed = response.getStatusCodeValue() == 200;
result.getMessages().add("Default check status == 200");
}

result.setPassed(allPassed);

} catch (Exception e) {
result.setPassed(false);
result.getMessages().add("Exception: " + e.getMessage());
}
return result;
}

private String normalizerUrl(String url) {
if (!url.startsWith("http://") && !url.startsWith("https://")) {
url = "https://" + url;
}
return url;
}
}
59 changes: 59 additions & 0 deletions src/test/java/com/akash/embedqa/TestRunnerServiceUnitTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.akash.embedqa;

import com.akash.embedqa.model.dtos.test.AssertionDTO;
import com.akash.embedqa.model.dtos.test.TestRequestDTO;
import com.akash.embedqa.model.dtos.test.TestResultDTO;
import com.akash.embedqa.service.TestRunnerService;
import com.akash.embedqa.service.impl.TestRunnerServiceImpl;
import org.hibernate.validator.internal.constraintvalidators.bv.AssertTrueValidator;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

import static org.junit.Assert.*;


@SpringBootTest
public class TestRunnerServiceUnitTest {

@Autowired
private TestRunnerService service;


@Test
void testGoogleHomepage_StatusCode200() {
TestRequestDTO request = new TestRequestDTO();
request.setName("Google Test");
request.setMethod("GET");
request.setUrl("google.com");

AssertionDTO assertion = new AssertionDTO();
assertion.setType("statusCode");
assertion.setValue("200");

request.setAssertions(List.of(assertion));

TestResultDTO result = service.runSingleTest(request);

Assertions.assertTrue(result.isPassed());
Assertions.assertEquals(200, result.getStatusCode());
Assertions.assertTrue(result.getMessages().stream().anyMatch(m -> m.contains("PASS")));
}

@Test
void testInvalidUrl_ShouldFail() {
TestRequestDTO request = new TestRequestDTO();
request.setName("Invalid URL Test");
request.setMethod("GET");
request.setUrl("http://invalid.url.test");

TestResultDTO result = service.runSingleTest(request);

Assertions.assertFalse(result.isPassed());
Assertions.assertTrue(result.getMessages().stream().anyMatch(m -> m.contains("Exception")));
}
}