using Books.Api.AiBookkeeper; using AwesomeAssertions; namespace Books.Api.Tests.AiBookkeeper; /// /// Unit tests for ToonFormatConverter. /// Verifies that ChartOfAccountsDto is correctly converted to .toon format. /// [Trait("Category", "Unit")] public class ToonFormatConverterTests { [Fact] public void ConvertToToon_EuGoodsAccount_HasEuRegion() { // Arrange var chartOfAccounts = CreateChartOfAccounts( CreateAccount("2050", "EU-erhvervelser varer", "cogs", "IEUV")); // Act var result = ToonFormatConverter.ConvertToToon(chartOfAccounts); // Assert - Account 2050 should have region EU result.Should().Contain("2050,EU-erhvervelser varer,Variable omkostninger,IEUV,EU,,"); } [Fact] public void ConvertToToon_EuServicesAccount_HasEuRegion() { // Arrange var chartOfAccounts = CreateChartOfAccounts( CreateAccount("2100", "EU-erhvervelser ydelser", "cogs", "IEUY")); // Act var result = ToonFormatConverter.ConvertToToon(chartOfAccounts); // Assert - Account 2100 should have region EU result.Should().Contain("2100,EU-erhvervelser ydelser,Variable omkostninger,IEUY,EU,,"); } [Fact] public void ConvertToToon_WorldGoodsAccount_HasWorldRegion() { // Arrange var chartOfAccounts = CreateChartOfAccounts( CreateAccount("2150", "Varekøb verden", "cogs", "IVV")); // Act var result = ToonFormatConverter.ConvertToToon(chartOfAccounts); // Assert - Account 2150 should have region WORLD result.Should().Contain("2150,Varekøb verden,Variable omkostninger,IVV,WORLD,,"); } [Fact] public void ConvertToToon_WorldServicesAccount_HasWorldRegion() { // Arrange var chartOfAccounts = CreateChartOfAccounts( CreateAccount("2200", "Ydelseskøb verden", "cogs", "IVY")); // Act var result = ToonFormatConverter.ConvertToToon(chartOfAccounts); // Assert - Account 2200 should have region WORLD result.Should().Contain("2200,Ydelseskøb verden,Variable omkostninger,IVY,WORLD,,"); } [Fact] public void ConvertToToon_DomesticAccount_HasEmptyRegion() { // Arrange var chartOfAccounts = CreateChartOfAccounts( CreateAccount("7320", "Køb af software", "expense", "I25")); // Act var result = ToonFormatConverter.ConvertToToon(chartOfAccounts); // Assert - Account 7320 should have empty region (available for all regions) result.Should().Contain("7320,Køb af software,Administrationsomkostninger,I25,,,"); } [Fact] public void ConvertToToon_AccountWithNoVatCode_HasEmptyRegion() { // Arrange var chartOfAccounts = CreateChartOfAccounts( CreateAccount("7000", "Kontorartikler", "expense", null)); // Act var result = ToonFormatConverter.ConvertToToon(chartOfAccounts); // Assert - Account with no VAT code should have empty region result.Should().Contain("7000,Kontorartikler,Administrationsomkostninger,,,,"); } [Fact] public void ConvertToToon_MixedAccounts_CorrectRegionsAssigned() { // Arrange var chartOfAccounts = CreateChartOfAccounts( CreateAccount("2000", "Vareforbrug", "cogs", "I25"), CreateAccount("2050", "EU-erhvervelser varer", "cogs", "IEUV"), CreateAccount("2150", "Varekøb verden", "cogs", "IVV"), CreateAccount("7320", "Køb af software", "expense", "I25")); // Act var result = ToonFormatConverter.ConvertToToon(chartOfAccounts); // Assert result.Should().Contain("2000,Vareforbrug,Variable omkostninger,I25,,,"); // Empty region result.Should().Contain("2050,EU-erhvervelser varer,Variable omkostninger,IEUV,EU,,"); // EU result.Should().Contain("2150,Varekøb verden,Variable omkostninger,IVV,WORLD,,"); // WORLD result.Should().Contain("7320,Køb af software,Administrationsomkostninger,I25,,,"); // Empty region } [Fact] public void ConvertToToon_ContainsMetaSection() { // Arrange var chartOfAccounts = CreateChartOfAccounts( CreateAccount("7000", "Kontorartikler", "expense", "I25")); // Act var result = ToonFormatConverter.ConvertToToon(chartOfAccounts); // Assert result.Should().Contain("meta:"); result.Should().Contain("source: Books API"); result.Should().Contain("organizationId: company-1"); result.Should().Contain("accountType: expense"); result.Should().Contain("totalAccounts: 1"); } [Fact] public void ConvertToToon_ContainsAccountsHeader() { // Arrange var chartOfAccounts = CreateChartOfAccounts( CreateAccount("7000", "Kontorartikler", "expense", "I25"), CreateAccount("7100", "Porto", "expense", "I25")); // Act var result = ToonFormatConverter.ConvertToToon(chartOfAccounts); // Assert result.Should().Contain("accounts[2]{number,name,category,vatCode,region,vatRubric,suggestions}:"); } [Fact] public void MapCategory_ExpenseAccount_ReturnsAdministrationsomkostninger() { var result = ToonFormatConverter.MapCategory("expense"); result.Should().Be("Administrationsomkostninger"); } [Fact] public void MapCategory_CogsAccount_ReturnsVariableOmkostninger() { var result = ToonFormatConverter.MapCategory("cogs"); result.Should().Be("Variable omkostninger"); } [Fact] public void MapCategory_PersonnelAccount_ReturnsLønomkostninger() { var result = ToonFormatConverter.MapCategory("personnel"); result.Should().Be("Lønomkostninger"); } [Fact] public void MapCategory_FinancialAccount_ReturnsRenteudgifter() { var result = ToonFormatConverter.MapCategory("financial"); result.Should().Be("Renteudgifter"); } [Fact] public void GenerateSuggestions_IncludesWordsFromName() { var result = ToonFormatConverter.GenerateSuggestions("Køb af software", "7320"); result.Should().Contain("køb"); result.Should().Contain("software"); result.Should().Contain("7320"); } [Fact] public void GenerateSuggestions_ExcludesShortWords() { var result = ToonFormatConverter.GenerateSuggestions("IT og software", "7320"); result.Should().NotContain("og"); // "og" has only 2 characters result.Should().Contain("software"); } private static ChartOfAccountsDto CreateChartOfAccounts(params AiAccountDto[] accounts) { return new ChartOfAccountsDto { CompanyId = "company-1", Accounts = accounts.ToList() }; } private static AiAccountDto CreateAccount(string number, string name, string type, string? vatCode) { return new AiAccountDto { AccountNumber = number, Name = name, AccountType = type, VatCodeId = vatCode }; } }