using System.IO; using System.Text.Json; using AxCopilot.Services.Agent; using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Spreadsheet; using FluentAssertions; using Xunit; namespace AxCopilot.Tests.Services; public class ExcelSkillConditionalFormattingTests { [Fact] public async Task ExecuteAsync_WithConditionalFormats_ShouldPersistFormattingRules() { var workDir = Path.Combine(Path.GetTempPath(), "ax-xlsx-conditional-" + Guid.NewGuid().ToString("N")); Directory.CreateDirectory(workDir); try { var tool = new ExcelSkill(); var context = new AgentContext { WorkFolder = workDir, Permission = "Auto", OperationMode = "external", }; var args = JsonDocument.Parse( """ { "path": "conditional.xlsx", "sheet_name": "Tracker", "headers": ["Metric", "Score", "Trend"], "rows": [ ["Margin", 42, 12], ["Retention", 61, 8], ["Cycle Time", 19, -3] ], "conditional_formats": [ { "range": "B2:B10", "type": "color_scale", "low": "FEE2E2", "mid": "FEF3C7", "high": "DCFCE7" }, { "range": "C2:C10", "type": "data_bar", "color": "2563EB" } ] } """).RootElement; var result = await tool.ExecuteAsync(args, context, CancellationToken.None); result.Success.Should().BeTrue(); result.Output.Should().Contain("Quality score"); var outputPath = Path.Combine(workDir, "conditional.xlsx"); File.Exists(outputPath).Should().BeTrue(); using var doc = SpreadsheetDocument.Open(outputPath, false); var firstSheet = doc.WorkbookPart!.Workbook.Sheets!.Elements().First(); var worksheetPart = (WorksheetPart)doc.WorkbookPart.GetPartById(firstSheet.Id!); worksheetPart.Worksheet.Elements().Count().Should().Be(2); var ruleTypes = worksheetPart.Worksheet.Descendants() .Select(rule => rule.Type?.Value) .ToList(); ruleTypes.Should().Contain(ConditionalFormatValues.ColorScale); ruleTypes.Should().Contain(ConditionalFormatValues.DataBar); } finally { try { if (Directory.Exists(workDir)) Directory.Delete(workDir, true); } catch { } } } }