using System.ComponentModel.DataAnnotations;
using System.Net;
using System.Text;
using AyCode.Services.Nav;
using AyCode.Services.Nav.Ekaer;
using AyCode.Services.Nav.Ekaer.Models;
using TradeType = AyCode.Services.Nav.Ekaer.Models.Common.TradeType;
namespace AyCode.Services.Tests.Nav;
///
/// Az tesztjei: a validate → send sorrend a valódi
/// fölött, fake -rel (nincs valódi hálózat) és stub validátorral.
///
[TestClass]
public sealed class EkaerSubmitServiceTests
{
// ---- Test doubles -------------------------------------------------------
private sealed class FakeHttpMessageHandler(HttpStatusCode status, string body) : HttpMessageHandler
{
public int CallCount { get; private set; }
public string? LastRequestBody { get; private set; }
protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
CallCount++;
if (request.Content is not null)
LastRequestBody = await request.Content.ReadAsStringAsync(cancellationToken);
return new HttpResponseMessage(status) { Content = new StringContent(body, Encoding.UTF8, "text/xml") };
}
}
private sealed class StubValidator(IReadOnlyList errors) : IEkaerTradeCardValidator
{
public IReadOnlyList Validate(TradeCardOperationType operation) => errors;
public IReadOnlyList Validate(IEnumerable operations) => errors;
}
private sealed class FakeCredentials : INavCredentials
{
public string User => "u";
public string Password => "p";
public string SigningKey => "k";
public string TaxNumber => "12345678";
public string BaseUrl => "https://test.example";
}
// ---- Helpers ------------------------------------------------------------
private static EkaerSubmitService CreateSut(IReadOnlyList validationErrors, FakeHttpMessageHandler handler)
{
var manageService = new EkaerManageService(new HttpClient(handler), new FakeCredentials());
return new EkaerSubmitService(manageService, new StubValidator(validationErrors));
}
private static string OkResponseXml()
=> NavXmlHelper.Serialize(new ManageTradeCardsResponse { Result = new BaseResultType { FuncCode = FunctionCodeType.Ok } });
private static TradeCardOperationType SomeOperation()
=> new() { Index = 1, Operation = OperationType.Create, TradeCard = new TradeCardType { TradeType = TradeType.I } };
// ---- Tesztek ------------------------------------------------------------
[TestMethod]
public async Task SubmitAsync_ValidationFails_DoesNotSend()
{
var handler = new FakeHttpMessageHandler(HttpStatusCode.OK, OkResponseXml());
var sut = CreateSut([new ValidationResult("teszthiba")], handler);
var result = await sut.SubmitAsync([SomeOperation()]);
Assert.IsFalse(result.IsValid);
Assert.AreEqual(1, result.ValidationErrors.Count);
Assert.IsNull(result.Response);
Assert.AreEqual(0, handler.CallCount, "validációs hiba esetén NEM mehet ki kérés a NAV-nak");
}
[TestMethod]
public async Task SubmitAsync_Valid_SendsAndReturnsResponse()
{
var handler = new FakeHttpMessageHandler(HttpStatusCode.OK, OkResponseXml());
var sut = CreateSut([], handler);
var result = await sut.SubmitAsync([SomeOperation()]);
Assert.IsTrue(result.IsValid);
Assert.AreEqual(1, handler.CallCount, "érvényes esetben egy kérés megy ki");
Assert.IsNotNull(result.Response);
Assert.AreEqual(0, result.ValidationErrors.Count);
}
[TestMethod]
public async Task SubmitAsync_Valid_RequestContainsOperations()
{
var handler = new FakeHttpMessageHandler(HttpStatusCode.OK, OkResponseXml());
var sut = CreateSut([], handler);
await sut.SubmitAsync([SomeOperation()]);
Assert.IsNotNull(handler.LastRequestBody);
StringAssert.Contains(handler.LastRequestBody, "tradeCardOperation", "a beküldött XML tartalmazza a műveleteket");
}
[TestMethod]
public async Task SubmitAsync_NavHttpError_PropagatesNavReportException()
{
var handler = new FakeHttpMessageHandler(HttpStatusCode.InternalServerError, "boom");
var sut = CreateSut([], handler);
await Assert.ThrowsExactlyAsync(() => sut.SubmitAsync([SomeOperation()]));
}
[TestMethod]
public async Task SubmitAsync_NullOperations_Throws()
{
var handler = new FakeHttpMessageHandler(HttpStatusCode.OK, OkResponseXml());
var sut = CreateSut([], handler);
await Assert.ThrowsExactlyAsync(() => sut.SubmitAsync(null!));
}
}