WorkTracker/tests/WorkTracker.Tests/WorkbookAssert.cs

90 lines
3.5 KiB
C#
Raw Normal View History

using ClosedXML.Excel;
using Xunit;
namespace WorkTracker.Tests;
internal static class WorkbookAssert
{
public static void Equivalent(string expectedPath, byte[] actualContent)
{
using var expectedWorkbook = new XLWorkbook(expectedPath);
using var actualStream = new MemoryStream(actualContent);
using var actualWorkbook = new XLWorkbook(actualStream);
var expectedWorksheet = expectedWorkbook.Worksheet(1);
var actualWorksheet = actualWorkbook.Worksheet(1);
Assert.Equal(expectedWorksheet.Name, actualWorksheet.Name);
Assert.Equal(expectedWorksheet.RangeUsed()?.RangeAddress.ToString(), actualWorksheet.RangeUsed()?.RangeAddress.ToString());
Assert.Equal(expectedWorksheet.MergedRanges.Select(range => range.RangeAddress.ToString()), actualWorksheet.MergedRanges.Select(range => range.RangeAddress.ToString()));
var usedRange = expectedWorksheet.RangeUsed() ?? throw new InvalidOperationException("Expected workbook must have a used range.");
foreach (var column in Enumerable.Range(usedRange.RangeAddress.FirstAddress.ColumnNumber, usedRange.ColumnCount()))
{
Assert.Equal(Math.Round(expectedWorksheet.Column(column).Width, 5), Math.Round(actualWorksheet.Column(column).Width, 5));
}
foreach (var cell in usedRange.Cells())
{
var actualCell = actualWorksheet.Cell(cell.Address.RowNumber, cell.Address.ColumnNumber);
Assert.Equal(GetCellValue(cell), GetCellValue(actualCell));
Assert.Equal(cell.FormulaA1, actualCell.FormulaA1);
if (string.IsNullOrEmpty(cell.FormulaA1))
{
Assert.Equal(cell.DataType, actualCell.DataType);
}
var expectedStyle = DescribeStyle(cell.Style);
var actualStyle = DescribeStyle(actualCell.Style);
Assert.True(expectedStyle == actualStyle, $"Style mismatch at {cell.Address}: expected '{expectedStyle}' actual '{actualStyle}'");
}
}
private static string GetCellValue(IXLCell cell)
{
if (!string.IsNullOrEmpty(cell.FormulaA1))
{
return string.Empty;
}
return cell.Value.ToString();
}
private static string DescribeStyle(IXLStyle style)
{
return string.Join(
"|",
style.NumberFormat.NumberFormatId,
style.NumberFormat.Format,
style.Fill.PatternType,
DescribeColor(style.Fill.BackgroundColor),
DescribeColor(style.Fill.PatternColor),
style.Font.FontName,
style.Font.FontSize,
style.Font.Bold,
style.Alignment.Horizontal,
style.Alignment.Vertical,
style.Alignment.WrapText,
style.Border.LeftBorder,
DescribeColor(style.Border.LeftBorderColor),
style.Border.RightBorder,
DescribeColor(style.Border.RightBorderColor),
style.Border.TopBorder,
DescribeColor(style.Border.TopBorderColor),
style.Border.BottomBorder,
DescribeColor(style.Border.BottomBorderColor),
style.Protection.Locked);
}
private static string DescribeColor(XLColor color)
{
return color.ColorType switch
{
XLColorType.Color => $"rgb:{color.Color.ToArgb()}",
XLColorType.Indexed => $"indexed:{color.Indexed}",
XLColorType.Theme => $"theme:{color.ThemeColor}:{Math.Round(color.ThemeTint, 12)}",
_ => color.ColorType.ToString()
};
}
}