195 lines
6.5 KiB
C#
195 lines
6.5 KiB
C#
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.Extensions.Logging;
|
|
using RobotNet10.NavigationTune.Shared.Interfaces;
|
|
using RobotNet10.NavigationTune.Shared.Models;
|
|
|
|
namespace RobotNet10.NavigationTune.Controllers;
|
|
|
|
/// <summary>
|
|
/// REST API controller for test runs (test history)
|
|
/// </summary>
|
|
[ApiController]
|
|
[Route("api/[controller]")]
|
|
public class TestRunsController : ControllerBase
|
|
{
|
|
private readonly ITestRepository _testRepository;
|
|
private readonly ILogger<TestRunsController> _logger;
|
|
|
|
public TestRunsController(
|
|
ITestRepository testRepository,
|
|
ILogger<TestRunsController> logger)
|
|
{
|
|
_testRepository = testRepository;
|
|
_logger = logger;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get test runs with optional pagination (returns DTO to avoid abstract TestScenario deserialization on client).
|
|
/// Use skip/take for paging; totalCount is returned for paginator.
|
|
/// </summary>
|
|
[HttpGet]
|
|
public async Task<ActionResult<PagedResult<TestRunDto>>> GetAll(
|
|
[FromQuery] int? skip = null,
|
|
[FromQuery] int? take = null,
|
|
[FromQuery] int? limit = null)
|
|
{
|
|
try
|
|
{
|
|
int skipVal = skip ?? 0;
|
|
int takeVal;
|
|
if (limit.HasValue && limit.Value > 0 && !take.HasValue)
|
|
takeVal = limit.Value;
|
|
else
|
|
takeVal = Math.Min(take ?? 50, 500);
|
|
|
|
var totalCount = await _testRepository.GetCountAsync();
|
|
var testRuns = await _testRepository.GetPagedAsync(skipVal, takeVal);
|
|
var items = testRuns.Select(ToDto).ToList();
|
|
return Ok(new PagedResult<TestRunDto> { TotalCount = totalCount, Items = items });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error getting all test runs");
|
|
return StatusCode(500, new { error = "Failed to retrieve test runs" });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get test run by ID
|
|
/// </summary>
|
|
[HttpGet("{id:guid}")]
|
|
public async Task<ActionResult<TestRunDto>> GetById(Guid id)
|
|
{
|
|
try
|
|
{
|
|
var testRun = await _testRepository.GetByIdAsync(id);
|
|
if (testRun == null)
|
|
return NotFound(new { error = $"Test run with ID {id} not found" });
|
|
return Ok(ToDto(testRun));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error getting test run {Id}", id);
|
|
return StatusCode(500, new { error = "Failed to retrieve test run" });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get test runs by scenario ID
|
|
/// </summary>
|
|
[HttpGet("scenario/{scenarioId}")]
|
|
public async Task<ActionResult<List<TestRunDto>>> GetByScenario(Guid scenarioId)
|
|
{
|
|
try
|
|
{
|
|
var testRuns = await _testRepository.GetByScenarioAsync(scenarioId);
|
|
return Ok(testRuns.Select(ToDto).ToList());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error getting test runs for scenario {ScenarioId}", scenarioId);
|
|
return StatusCode(500, new { error = "Failed to retrieve test runs" });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get test runs by parameter set ID
|
|
/// </summary>
|
|
[HttpGet("parameterset/{parameterSetId}")]
|
|
public async Task<ActionResult<List<TestRunDto>>> GetByParameterSet(Guid parameterSetId)
|
|
{
|
|
try
|
|
{
|
|
var testRuns = await _testRepository.GetByParameterSetAsync(parameterSetId);
|
|
return Ok(testRuns.Select(ToDto).ToList());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error getting test runs for parameter set {ParameterSetId}", parameterSetId);
|
|
return StatusCode(500, new { error = "Failed to retrieve test runs" });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get test runs by date range
|
|
/// </summary>
|
|
[HttpGet("daterange")]
|
|
public async Task<ActionResult<List<TestRunDto>>> GetByDateRange(
|
|
[FromQuery] DateTime from,
|
|
[FromQuery] DateTime to)
|
|
{
|
|
try
|
|
{
|
|
var testRuns = await _testRepository.GetByDateRangeAsync(from, to);
|
|
return Ok(testRuns.Select(ToDto).ToList());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error getting test runs for date range {From} to {To}", from, to);
|
|
return StatusCode(500, new { error = "Failed to retrieve test runs" });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Delete test run
|
|
/// </summary>
|
|
[HttpDelete("{id}")]
|
|
public async Task<ActionResult> Delete(Guid id)
|
|
{
|
|
try
|
|
{
|
|
var existing = await _testRepository.GetByIdAsync(id);
|
|
if (existing == null)
|
|
return NotFound(new { error = $"Test run with ID {id} not found" });
|
|
|
|
await _testRepository.DeleteAsync(id);
|
|
return NoContent();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error deleting test run {Id}", id);
|
|
return StatusCode(500, new { error = "Failed to delete test run" });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Delete multiple test runs by IDs
|
|
/// </summary>
|
|
[HttpPost("delete-batch")]
|
|
public async Task<ActionResult> DeleteBatch([FromBody] DeleteBatchRequest request)
|
|
{
|
|
if (request?.Ids == null || request.Ids.Count == 0)
|
|
return BadRequest(new { error = "Ids is required and must not be empty" });
|
|
try
|
|
{
|
|
await _testRepository.DeleteManyAsync(request.Ids);
|
|
return NoContent();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error deleting test runs batch");
|
|
return StatusCode(500, new { error = "Failed to delete test runs" });
|
|
}
|
|
}
|
|
|
|
private static TestRunDto ToDto(TestRun r)
|
|
{
|
|
return new TestRunDto
|
|
{
|
|
Id = r.Id,
|
|
ScenarioId = r.ScenarioId,
|
|
ScenarioName = r.Scenario?.Name ?? string.Empty,
|
|
ParameterSetId = r.ParameterSetId,
|
|
ParameterSetName = r.ParameterSet?.Name ?? string.Empty,
|
|
StartTime = r.StartTime,
|
|
EndTime = r.EndTime,
|
|
Status = r.Status,
|
|
Duration = r.Duration,
|
|
Notes = r.Notes,
|
|
ErrorMessage = r.ErrorMessage,
|
|
Metrics = r.Metrics,
|
|
SafetyViolations = r.SafetyViolations ?? new List<SafetyViolation>()
|
|
};
|
|
}
|
|
}
|