Migrate ExcelIO from ClosedXML to NPOI

This commit is contained in:
Joseph Doherty
2026-02-06 17:27:09 -05:00
parent 070d915b12
commit dd18a05408
26 changed files with 3034 additions and 2805 deletions
@@ -1,431 +1,427 @@
using ClosedXML.Excel;
using JdeScoping.ExcelIO.Options;
using JdeScoping.ExcelIO.Generators;
using JdeScoping.ExcelIO.Mapping;
using JdeScoping.ExcelIO.Mapping.Maps;
using JdeScoping.ExcelIO.Models.Reporting;
using Microsoft.Extensions.Options;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests;
public class CriteriaSheetGeneratorTests
{
private readonly CriteriaSheetGenerator _generator;
private readonly IOptions<ExcelExportOptions> _options;
public CriteriaSheetGeneratorTests()
{
_options = Microsoft.Extensions.Options.Options.Create(new ExcelExportOptions
{
CriteriaSheetPassword = "TestPassword"
});
var registry = CreateTestRegistry();
var tableWriter = new FluentTableWriter(registry);
_generator = new CriteriaSheetGenerator(_options, tableWriter);
}
private static ExcelMapRegistry CreateTestRegistry()
{
var registry = new ExcelMapRegistry();
registry.Register(new TimespanFilterMap());
registry.Register(new WorkOrderFilterEntryMap());
registry.Register(new ItemNumberFilterEntryMap());
registry.Register(new ProfitCenterFilterEntryMap());
registry.Register(new WorkCenterFilterEntryMap());
registry.Register(new OperatorFilterEntryMap());
registry.Register(new ComponentLotFilterEntryMap());
registry.Register(new ItemOperationMisFilterEntryMap());
return registry;
}
[Fact]
public void Generate_CreatesSearchCriteriaSheet()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
_generator.Generate(workbook, search);
workbook.Worksheets.TryGetWorksheet("Search Criteria", out var worksheet).ShouldBeTrue();
worksheet.ShouldNotBeNull();
}
[Fact]
public void Generate_ContainsSearchName()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
search.Name = "Test Search Name";
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
worksheet.Cell(1, 1).Value.GetText().ShouldBe("Search Name");
worksheet.Cell(1, 2).Value.GetText().ShouldBe("Test Search Name");
}
[Fact]
public void Generate_ContainsUserName()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
search.UserName = "testuser";
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
worksheet.Cell(2, 1).Value.GetText().ShouldBe("User Name");
worksheet.Cell(2, 2).Value.GetText().ShouldBe("testuser");
}
[Fact]
public void Generate_ContainsTimestamps()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
var submitDt = new DateTime(2024, 1, 15, 10, 30, 0);
var startDt = new DateTime(2024, 1, 15, 10, 31, 0);
var endDt = new DateTime(2024, 1, 15, 10, 35, 0);
search.SubmitDt = submitDt;
search.StartDt = startDt;
search.EndDt = endDt;
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
worksheet.Cell(4, 1).Value.GetText().ShouldBe("Submit timestamp");
worksheet.Cell(4, 2).Value.GetText().ShouldContain("Jan 15, 2024");
worksheet.Cell(5, 1).Value.GetText().ShouldBe("Start timestamp");
worksheet.Cell(5, 2).Value.GetText().ShouldContain("Jan 15, 2024");
worksheet.Cell(6, 1).Value.GetText().ShouldBe("Completed timestamp");
worksheet.Cell(6, 2).Value.GetText().ShouldContain("Jan 15, 2024");
}
[Fact]
public void Generate_ContainsTimespanFilterTable()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
search.MinimumDt = new DateTime(2024, 1, 1);
search.MaximumDt = new DateTime(2024, 12, 31);
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
var tables = worksheet.Tables;
tables.Any(t => t.Name == "Timespan_Filter").ShouldBeTrue();
}
[Fact]
public void Generate_ContainsWorkOrderFilterTable()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
search.WorkOrderFilter.Add(new WorkOrderFilterEntry { WorkOrderNumber = 12345, ItemNumber = "ITEM-001" });
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
var tables = worksheet.Tables;
tables.Any(t => t.Name == "Work_Order_Filter").ShouldBeTrue();
}
[Fact]
public void Generate_ContainsItemNumberFilterTable()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
search.ItemNumberFilter.Add(new ItemNumberFilterEntry { ItemNumber = "ITEM-001" });
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
var tables = worksheet.Tables;
tables.Any(t => t.Name == "Item_Number_Filter").ShouldBeTrue();
}
[Fact]
public void Generate_ContainsProfitCenterFilterTable()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
search.ProfitCenterFilter.Add(new ProfitCenterFilterEntry { Code = "PC01", Description = "Profit Center 1" });
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
var tables = worksheet.Tables;
tables.Any(t => t.Name == "Profit_Center_Filter").ShouldBeTrue();
}
[Fact]
public void Generate_ContainsWorkCenterFilterTable()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
search.WorkCenterFilter.Add(new WorkCenterFilterEntry { Code = "WC01", Description = "Work Center 1" });
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
var tables = worksheet.Tables;
tables.Any(t => t.Name == "Work_Center_Filter").ShouldBeTrue();
}
[Fact]
public void Generate_ContainsOperatorFilterTable()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
search.OperatorFilter.Add(new OperatorFilterEntry { UserId = "OP01", FullName = "Operator 1" });
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
var tables = worksheet.Tables;
tables.Any(t => t.Name == "Operator_Filter").ShouldBeTrue();
}
[Fact]
public void Generate_ContainsComponentLotFilterTable()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
search.ComponentLotFilter.Add(new ComponentLotFilterEntry { LotNumber = "LOT001" });
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
var tables = worksheet.Tables;
tables.Any(t => t.Name == "Component_Lot_Filter").ShouldBeTrue();
}
[Fact]
public void Generate_ContainsItemOperationMisFilterTable()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
search.ItemOperationMisFilter.Add(new ItemOperationMisFilterEntry
{
ItemNumber = "ITEM-001",
OperationNumber = "10",
MisNumber = "MIS-001"
});
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
var tables = worksheet.Tables;
tables.Any(t => t.Name == "Item_Operation_MIS_Filter").ShouldBeTrue();
}
[Fact]
public void Generate_ContainsExtractMisDataIndicator_WhenTrue()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
search.ExtractMisData = true;
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
// Find the "Extract MIS data?" header and check for YES
var cells = worksheet.CellsUsed();
var extractMisCell = cells.FirstOrDefault(c => c.Value.ToString() == "YES" || c.Value.ToString() == "NO");
extractMisCell.ShouldNotBeNull();
extractMisCell.Value.GetText().ShouldBe("YES");
}
[Fact]
public void Generate_ContainsExtractMisDataIndicator_WhenFalse()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
search.ExtractMisData = false;
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
// Find the "Extract MIS data?" header and check for NO
var cells = worksheet.CellsUsed();
var extractMisCell = cells.FirstOrDefault(c => c.Value.ToString() == "YES" || c.Value.ToString() == "NO");
extractMisCell.ShouldNotBeNull();
extractMisCell.Value.GetText().ShouldBe("NO");
}
[Fact]
public void Generate_AppliesHeaderFormatting()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
// Search Name header should be bold with Gainsboro background
var headerCell = worksheet.Cell(1, 1);
headerCell.Style.Font.Bold.ShouldBeTrue();
headerCell.Style.Fill.BackgroundColor.ShouldBe(XLColor.Gainsboro);
}
[Fact]
public void Generate_AppliesProtection()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
worksheet.Protection.IsProtected.ShouldBeTrue();
}
[Fact]
public void Generate_TablesHaveLight18Style()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
search.WorkOrderFilter.Add(new WorkOrderFilterEntry { WorkOrderNumber = 12345, ItemNumber = "ITEM-001" });
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
var table = worksheet.Tables.First(t => t.Name == "Work_Order_Filter");
table.Theme.ShouldBe(XLTableTheme.TableStyleLight18);
}
[Fact]
public void Generate_FilterTables_Have2BlankRowSpacing()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
search.WorkOrderFilter.Add(new WorkOrderFilterEntry { WorkOrderNumber = 12345, ItemNumber = "ITEM-001" });
search.ItemNumberFilter.Add(new ItemNumberFilterEntry { ItemNumber = "ITEM-001" });
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
var woTable = worksheet.Tables.First(t => t.Name == "Work_Order_Filter");
var itemTable = worksheet.Tables.First(t => t.Name == "Item_Number_Filter");
// There should be 2 blank rows between tables. With the header row of the next table, that's a gap of 3
// Looking at CriteriaSheetGenerator: row = table.RangeAddress.LastAddress.RowNumber + 3
// This means the next table starts 3 rows after the last row, leaving 2 blank rows in between
var gap = itemTable.RangeAddress.FirstAddress.RowNumber - woTable.RangeAddress.LastAddress.RowNumber;
// Gap includes header row of next table, so: 2 blank rows + 1 header = gap of 3
// But with table header (Timespan_Filter has ShowHeader=true), add 1 more
gap.ShouldBeGreaterThanOrEqualTo(3);
}
[Fact]
public void Generate_NullTimestamps_ShowEmptyValue()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
search.SubmitDt = null;
search.StartDt = null;
search.EndDt = null;
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
worksheet.Cell(4, 2).Value.ToString().ShouldBe(string.Empty);
worksheet.Cell(5, 2).Value.ToString().ShouldBe(string.Empty);
worksheet.Cell(6, 2).Value.ToString().ShouldBe(string.Empty);
}
[Fact]
public void Generate_ColumnsAreAutoFitWithPadding()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
search.Name = "A Very Long Search Name That Needs Extra Width";
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
// Columns should have been adjusted - verify they have non-default width
worksheet.Column(1).Width.ShouldBeGreaterThan(0);
worksheet.Column(2).Width.ShouldBeGreaterThan(0);
}
[Fact]
public void Generate_MultipleFiltersWithData_CreatesAllTables()
{
using var workbook = new XLWorkbook();
var search = CreateFullSearchModel();
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
var tables = worksheet.Tables;
// Should have 8 filter tables
tables.Count().ShouldBe(8);
tables.Any(t => t.Name == "Timespan_Filter").ShouldBeTrue();
tables.Any(t => t.Name == "Work_Order_Filter").ShouldBeTrue();
tables.Any(t => t.Name == "Item_Number_Filter").ShouldBeTrue();
tables.Any(t => t.Name == "Profit_Center_Filter").ShouldBeTrue();
tables.Any(t => t.Name == "Work_Center_Filter").ShouldBeTrue();
tables.Any(t => t.Name == "Component_Lot_Filter").ShouldBeTrue();
tables.Any(t => t.Name == "Operator_Filter").ShouldBeTrue();
tables.Any(t => t.Name == "Item_Operation_MIS_Filter").ShouldBeTrue();
}
[Fact]
public void Generate_TimestampFormat_IncludesESTSuffix()
{
using var workbook = new XLWorkbook();
var search = CreateMinimalSearchModel();
search.SubmitDt = new DateTime(2024, 1, 15, 10, 30, 45);
_generator.Generate(workbook, search);
var worksheet = workbook.Worksheet("Search Criteria");
var timestampValue = worksheet.Cell(4, 2).Value.GetText();
timestampValue.ShouldContain("EST");
timestampValue.ShouldContain("10:30:45");
}
private static SearchModel CreateMinimalSearchModel()
{
return new SearchModel
{
Id = 1,
Name = "Test Search",
UserName = "testuser",
SubmitDt = DateTime.Now.AddHours(-1),
StartDt = DateTime.Now.AddMinutes(-30),
EndDt = DateTime.Now,
ExtractMisData = false
};
}
private static SearchModel CreateFullSearchModel()
{
return new SearchModel
{
Id = 1,
Name = "Full Search",
UserName = "testuser",
SubmitDt = DateTime.Now.AddHours(-1),
StartDt = DateTime.Now.AddMinutes(-30),
EndDt = DateTime.Now,
MinimumDt = new DateTime(2024, 1, 1),
MaximumDt = new DateTime(2024, 12, 31),
ExtractMisData = true,
WorkOrderFilter = [new WorkOrderFilterEntry { WorkOrderNumber = 12345, ItemNumber = "ITEM-001" }],
ItemNumberFilter = [new ItemNumberFilterEntry { ItemNumber = "ITEM-001" }],
ProfitCenterFilter = [new ProfitCenterFilterEntry { Code = "PC01", Description = "Profit Center 1" }],
WorkCenterFilter = [new WorkCenterFilterEntry { Code = "WC01", Description = "Work Center 1" }],
OperatorFilter = [new OperatorFilterEntry { UserId = "OP01", FullName = "Operator 1" }],
ComponentLotFilter = [new ComponentLotFilterEntry { LotNumber = "LOT001" }],
ItemOperationMisFilter = [new ItemOperationMisFilterEntry { ItemNumber = "ITEM-001", OperationNumber = "10", MisNumber = "MIS-001" }]
};
}
}
using JdeScoping.ExcelIO.Options;
using JdeScoping.ExcelIO.Generators;
using JdeScoping.ExcelIO.Mapping;
using JdeScoping.ExcelIO.Mapping.Maps;
using JdeScoping.ExcelIO.Models.Reporting;
using JdeScoping.ExcelIO.Tests.Fixtures;
using Microsoft.Extensions.Options;
using NPOI.XSSF.UserModel;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests;
public class CriteriaSheetGeneratorTests
{
private readonly CriteriaSheetGenerator _generator;
public CriteriaSheetGeneratorTests()
{
var options = Microsoft.Extensions.Options.Options.Create(new ExcelExportOptions
{
CriteriaSheetPassword = "TestPassword"
});
var registry = CreateTestRegistry();
var tableWriter = new FluentTableWriter(registry);
_generator = new CriteriaSheetGenerator(options, tableWriter);
}
private static ExcelMapRegistry CreateTestRegistry()
{
var registry = new ExcelMapRegistry();
registry.Register(new TimespanFilterMap());
registry.Register(new WorkOrderFilterEntryMap());
registry.Register(new ItemNumberFilterEntryMap());
registry.Register(new ProfitCenterFilterEntryMap());
registry.Register(new WorkCenterFilterEntryMap());
registry.Register(new OperatorFilterEntryMap());
registry.Register(new ComponentLotFilterEntryMap());
registry.Register(new ItemOperationMisFilterEntryMap());
return registry;
}
[Fact]
public void Generate_CreatesSearchCriteriaSheet()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
_generator.Generate(workbook, search);
workbook.GetSheet("Search Criteria").ShouldNotBeNull();
}
[Fact]
public void Generate_ContainsSearchName()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
search.Name = "Test Search Name";
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
ExcelTestHelpers.GetCellText(worksheet, 1, 1).ShouldBe("Search Name");
ExcelTestHelpers.GetCellText(worksheet, 1, 2).ShouldBe("Test Search Name");
}
[Fact]
public void Generate_ContainsUserName()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
search.UserName = "testuser";
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
ExcelTestHelpers.GetCellText(worksheet, 2, 1).ShouldBe("User Name");
ExcelTestHelpers.GetCellText(worksheet, 2, 2).ShouldBe("testuser");
}
[Fact]
public void Generate_ContainsTimestamps()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
search.SubmitDt = new DateTime(2024, 1, 15, 10, 30, 0);
search.StartDt = new DateTime(2024, 1, 15, 10, 31, 0);
search.EndDt = new DateTime(2024, 1, 15, 10, 35, 0);
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
ExcelTestHelpers.GetCellText(worksheet, 4, 1).ShouldBe("Submit timestamp");
ExcelTestHelpers.GetCellText(worksheet, 4, 2).ShouldContain("Jan 15, 2024");
ExcelTestHelpers.GetCellText(worksheet, 5, 1).ShouldBe("Start timestamp");
ExcelTestHelpers.GetCellText(worksheet, 5, 2).ShouldContain("Jan 15, 2024");
ExcelTestHelpers.GetCellText(worksheet, 6, 1).ShouldBe("Completed timestamp");
ExcelTestHelpers.GetCellText(worksheet, 6, 2).ShouldContain("Jan 15, 2024");
}
[Fact]
public void Generate_ContainsTimespanFilterTable()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
search.MinimumDt = new DateTime(2024, 1, 1);
search.MaximumDt = new DateTime(2024, 12, 31);
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
ExcelTestHelpers.TableExists(worksheet, "Timespan_Filter").ShouldBeTrue();
}
[Fact]
public void Generate_ContainsWorkOrderFilterTable()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
search.WorkOrderFilter.Add(new WorkOrderFilterEntry { WorkOrderNumber = 12345, ItemNumber = "ITEM-001" });
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
ExcelTestHelpers.TableExists(worksheet, "Work_Order_Filter").ShouldBeTrue();
}
[Fact]
public void Generate_ContainsItemNumberFilterTable()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
search.ItemNumberFilter.Add(new ItemNumberFilterEntry { ItemNumber = "ITEM-001" });
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
ExcelTestHelpers.TableExists(worksheet, "Item_Number_Filter").ShouldBeTrue();
}
[Fact]
public void Generate_ContainsProfitCenterFilterTable()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
search.ProfitCenterFilter.Add(new ProfitCenterFilterEntry { Code = "PC01", Description = "Profit Center 1" });
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
ExcelTestHelpers.TableExists(worksheet, "Profit_Center_Filter").ShouldBeTrue();
}
[Fact]
public void Generate_ContainsWorkCenterFilterTable()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
search.WorkCenterFilter.Add(new WorkCenterFilterEntry { Code = "WC01", Description = "Work Center 1" });
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
ExcelTestHelpers.TableExists(worksheet, "Work_Center_Filter").ShouldBeTrue();
}
[Fact]
public void Generate_ContainsOperatorFilterTable()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
search.OperatorFilter.Add(new OperatorFilterEntry { UserId = "OP01", FullName = "Operator 1" });
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
ExcelTestHelpers.TableExists(worksheet, "Operator_Filter").ShouldBeTrue();
}
[Fact]
public void Generate_ContainsComponentLotFilterTable()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
search.ComponentLotFilter.Add(new ComponentLotFilterEntry { LotNumber = "LOT001" });
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
ExcelTestHelpers.TableExists(worksheet, "Component_Lot_Filter").ShouldBeTrue();
}
[Fact]
public void Generate_ContainsItemOperationMisFilterTable()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
search.ItemOperationMisFilter.Add(new ItemOperationMisFilterEntry
{
ItemNumber = "ITEM-001",
OperationNumber = "10",
MisNumber = "MIS-001"
});
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
ExcelTestHelpers.TableExists(worksheet, "Item_Operation_MIS_Filter").ShouldBeTrue();
}
[Fact]
public void Generate_ContainsExtractMisDataIndicator_WhenTrue()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
search.ExtractMisData = true;
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
var yesNo = FindYesNo(worksheet);
yesNo.ShouldBe("YES");
}
[Fact]
public void Generate_ContainsExtractMisDataIndicator_WhenFalse()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
search.ExtractMisData = false;
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
var yesNo = FindYesNo(worksheet);
yesNo.ShouldBe("NO");
}
[Fact]
public void Generate_AppliesHeaderFormatting()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
var headerCell = ExcelTestHelpers.GetCell(worksheet, 1, 1)!;
(headerCell.CellStyle.FontIndex >= 0 &&
workbook.GetFontAt(headerCell.CellStyle.FontIndex).IsBold).ShouldBeTrue();
ExcelTestHelpers.GetFillForegroundRgb(headerCell).ShouldBe([0xDC, 0xDC, 0xDC]);
}
[Fact]
public void Generate_AppliesProtection()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
ExcelTestHelpers.IsSheetProtected(worksheet).ShouldBeTrue();
}
[Fact]
public void Generate_TablesHaveLight18Style()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
search.WorkOrderFilter.Add(new WorkOrderFilterEntry { WorkOrderNumber = 12345, ItemNumber = "ITEM-001" });
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
var table = ExcelTestHelpers.GetTableByName(worksheet, "Work_Order_Filter");
table.StyleName.ShouldBe("TableStyleLight18");
}
[Fact]
public void Generate_FilterTables_Have2BlankRowSpacing()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
search.WorkOrderFilter.Add(new WorkOrderFilterEntry { WorkOrderNumber = 12345, ItemNumber = "ITEM-001" });
search.ItemNumberFilter.Add(new ItemNumberFilterEntry { ItemNumber = "ITEM-001" });
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
var woTable = ExcelTestHelpers.GetTableByName(worksheet, "Work_Order_Filter");
var itemTable = ExcelTestHelpers.GetTableByName(worksheet, "Item_Number_Filter");
var gap = itemTable.StartCellReference.Row - woTable.EndCellReference.Row;
gap.ShouldBeGreaterThanOrEqualTo(3);
}
[Fact]
public void Generate_NullTimestamps_ShowEmptyValue()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
search.SubmitDt = null;
search.StartDt = null;
search.EndDt = null;
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
ExcelTestHelpers.GetCellText(worksheet, 4, 2).ShouldBe(string.Empty);
ExcelTestHelpers.GetCellText(worksheet, 5, 2).ShouldBe(string.Empty);
ExcelTestHelpers.GetCellText(worksheet, 6, 2).ShouldBe(string.Empty);
}
[Fact]
public void Generate_ColumnsAreAutoFitWithPadding()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
search.Name = "A Very Long Search Name That Needs Extra Width";
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
ExcelTestHelpers.GetColumnWidthChars(worksheet, 1).ShouldBeGreaterThan(0);
ExcelTestHelpers.GetColumnWidthChars(worksheet, 2).ShouldBeGreaterThan(0);
}
[Fact]
public void Generate_MultipleFiltersWithData_CreatesAllTables()
{
using var workbook = new XSSFWorkbook();
var search = CreateFullSearchModel();
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
var tableCount = ((XSSFSheet)worksheet).GetTables().Count;
tableCount.ShouldBe(8);
ExcelTestHelpers.TableExists(worksheet, "Timespan_Filter").ShouldBeTrue();
ExcelTestHelpers.TableExists(worksheet, "Work_Order_Filter").ShouldBeTrue();
ExcelTestHelpers.TableExists(worksheet, "Item_Number_Filter").ShouldBeTrue();
ExcelTestHelpers.TableExists(worksheet, "Profit_Center_Filter").ShouldBeTrue();
ExcelTestHelpers.TableExists(worksheet, "Work_Center_Filter").ShouldBeTrue();
ExcelTestHelpers.TableExists(worksheet, "Component_Lot_Filter").ShouldBeTrue();
ExcelTestHelpers.TableExists(worksheet, "Operator_Filter").ShouldBeTrue();
ExcelTestHelpers.TableExists(worksheet, "Item_Operation_MIS_Filter").ShouldBeTrue();
}
[Fact]
public void Generate_TimestampFormat_IncludesESTSuffix()
{
using var workbook = new XSSFWorkbook();
var search = CreateMinimalSearchModel();
search.SubmitDt = new DateTime(2024, 1, 15, 10, 30, 45);
_generator.Generate(workbook, search);
var worksheet = workbook.GetSheet("Search Criteria");
var timestampValue = ExcelTestHelpers.GetCellText(worksheet, 4, 2);
timestampValue.ShouldContain("EST");
timestampValue.ShouldContain("10:30:45");
}
private static string FindYesNo(NPOI.SS.UserModel.ISheet worksheet)
{
for (var row = 0; row <= worksheet.LastRowNum; row++)
{
var npoiRow = worksheet.GetRow(row);
if (npoiRow == null)
{
continue;
}
for (var col = 0; col < npoiRow.LastCellNum; col++)
{
var text = ExcelTestHelpers.GetCellText(worksheet, row + 1, col + 1);
if (text == "YES" || text == "NO")
{
return text;
}
}
}
return string.Empty;
}
private static SearchModel CreateMinimalSearchModel()
{
return new SearchModel
{
Id = 1,
Name = "Test Search",
UserName = "testuser",
SubmitDt = DateTime.Now.AddHours(-1),
StartDt = DateTime.Now.AddMinutes(-30),
EndDt = DateTime.Now,
ExtractMisData = false
};
}
private static SearchModel CreateFullSearchModel()
{
return new SearchModel
{
Id = 1,
Name = "Full Search",
UserName = "testuser",
SubmitDt = DateTime.Now.AddHours(-1),
StartDt = DateTime.Now.AddMinutes(-30),
EndDt = DateTime.Now,
MinimumDt = new DateTime(2024, 1, 1),
MaximumDt = new DateTime(2024, 12, 31),
ExtractMisData = true,
WorkOrderFilter = [new WorkOrderFilterEntry { WorkOrderNumber = 12345, ItemNumber = "ITEM-001" }],
ItemNumberFilter = [new ItemNumberFilterEntry { ItemNumber = "ITEM-001" }],
ProfitCenterFilter = [new ProfitCenterFilterEntry { Code = "PC01", Description = "Profit Center 1" }],
WorkCenterFilter = [new WorkCenterFilterEntry { Code = "WC01", Description = "Work Center 1" }],
OperatorFilter = [new OperatorFilterEntry { UserId = "OP01", FullName = "Operator 1" }],
ComponentLotFilter = [new ComponentLotFilterEntry { LotNumber = "LOT001" }],
ItemOperationMisFilter = [new ItemOperationMisFilterEntry { ItemNumber = "ITEM-001", OperationNumber = "10", MisNumber = "MIS-001" }]
};
}
}
@@ -1,145 +1,137 @@
using ClosedXML.Excel;
using JdeScoping.ExcelIO.Generators;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests;
public class DataEntryTemplateGeneratorTests
{
private readonly DataEntryTemplateGenerator _generator = new();
[Fact]
public void Generate_SingleColumn_ReturnsValidExcel()
{
var result = _generator.Generate<string>(null, "Test Header");
result.ShouldNotBeNull();
result.Length.ShouldBeGreaterThan(0);
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
workbook.Worksheets.Count.ShouldBe(1);
}
[Fact]
public void Generate_SingleColumn_HasCorrectHeader()
{
var result = _generator.Generate<string>(null, "Item Numbers");
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
var worksheet = workbook.Worksheets.First();
worksheet.Cell(1, 1).Value.GetText().ShouldBe("Item Numbers");
}
[Fact]
public void Generate_SingleColumn_HasHeaderFormatting()
{
var result = _generator.Generate<string>(null, "Test Header");
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
var worksheet = workbook.Worksheets.First();
var headerCell = worksheet.Cell(1, 1);
headerCell.Style.Font.Bold.ShouldBeTrue();
headerCell.Style.Fill.BackgroundColor.ShouldBe(XLColor.Gainsboro);
}
[Fact]
public void Generate_SingleColumn_WithData_PopulatesRows()
{
var data = new List<string> { "Item1", "Item2", "Item3" };
var result = _generator.Generate(data, "Items");
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
var worksheet = workbook.Worksheets.First();
worksheet.Cell(2, 1).Value.GetText().ShouldBe("Item1");
worksheet.Cell(3, 1).Value.GetText().ShouldBe("Item2");
worksheet.Cell(4, 1).Value.GetText().ShouldBe("Item3");
}
[Fact]
public void Generate_SingleColumn_SetsTextFormat()
{
var result = _generator.Generate<string>(null, "Test");
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
var worksheet = workbook.Worksheets.First();
worksheet.Column(1).Style.NumberFormat.Format.ShouldBe("@");
}
[Fact]
public void Generate_MultiColumn_ReturnsValidExcel()
{
var headers = new[] { "Column A", "Column B", "Column C" };
var result = _generator.Generate(null, headers);
result.ShouldNotBeNull();
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
var worksheet = workbook.Worksheets.First();
worksheet.Cell(1, 1).Value.GetText().ShouldBe("Column A");
worksheet.Cell(1, 2).Value.GetText().ShouldBe("Column B");
worksheet.Cell(1, 3).Value.GetText().ShouldBe("Column C");
}
[Fact]
public void Generate_MultiColumn_WithData_PopulatesRows()
{
var headers = new[] { "Name", "Value" };
var data = new[]
{
new object[] { "Row1", 100 },
new object[] { "Row2", 200 }
};
var result = _generator.Generate(data, headers);
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
var worksheet = workbook.Worksheets.First();
worksheet.Cell(2, 1).Value.GetText().ShouldBe("Row1");
worksheet.Cell(2, 2).Value.GetNumber().ShouldBe(100);
worksheet.Cell(3, 1).Value.GetText().ShouldBe("Row2");
worksheet.Cell(3, 2).Value.GetNumber().ShouldBe(200);
}
[Fact]
public void Generate_MultiColumn_SetsColumnWidth()
{
var headers = new[] { "Column A", "Column B" };
var result = _generator.Generate(null, headers);
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
var worksheet = workbook.Worksheets.First();
worksheet.Column(1).Width.ShouldBe(65);
worksheet.Column(2).Width.ShouldBe(65);
}
[Fact]
public void Generate_SingleColumn_SetsColumnWidth()
{
var result = _generator.Generate<string>(null, "Test");
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
var worksheet = workbook.Worksheets.First();
worksheet.Column(1).Width.ShouldBe(45);
}
}
using JdeScoping.ExcelIO.Generators;
using JdeScoping.ExcelIO.Tests.Fixtures;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests;
public class DataEntryTemplateGeneratorTests
{
private readonly DataEntryTemplateGenerator _generator = new();
[Fact]
public void Generate_SingleColumn_ReturnsValidExcel()
{
var result = _generator.Generate<string>(null, "Test Header");
result.ShouldNotBeNull();
result.Length.ShouldBeGreaterThan(0);
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
workbook.NumberOfSheets.ShouldBe(1);
}
[Fact]
public void Generate_SingleColumn_HasCorrectHeader()
{
var result = _generator.Generate<string>(null, "Item Numbers");
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
var worksheet = workbook.GetSheetAt(0);
ExcelTestHelpers.GetCellText(worksheet, 1, 1).ShouldBe("Item Numbers");
}
[Fact]
public void Generate_SingleColumn_HasHeaderFormatting()
{
var result = _generator.Generate<string>(null, "Test Header");
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
var worksheet = workbook.GetSheetAt(0);
var headerCell = ExcelTestHelpers.GetCell(worksheet, 1, 1)!;
(headerCell.CellStyle.FontIndex >= 0 &&
workbook.GetFontAt(headerCell.CellStyle.FontIndex).IsBold).ShouldBeTrue();
ExcelTestHelpers.GetFillForegroundRgb(headerCell).ShouldBe([0xDC, 0xDC, 0xDC]);
}
[Fact]
public void Generate_SingleColumn_WithData_PopulatesRows()
{
var data = new List<string> { "Item1", "Item2", "Item3" };
var result = _generator.Generate(data, "Items");
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
var worksheet = workbook.GetSheetAt(0);
ExcelTestHelpers.GetCellText(worksheet, 2, 1).ShouldBe("Item1");
ExcelTestHelpers.GetCellText(worksheet, 3, 1).ShouldBe("Item2");
ExcelTestHelpers.GetCellText(worksheet, 4, 1).ShouldBe("Item3");
}
[Fact]
public void Generate_SingleColumn_SetsTextFormat()
{
var result = _generator.Generate<string>(null, "Test");
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
var worksheet = workbook.GetSheetAt(0);
worksheet.GetColumnStyle(0).GetDataFormatString().ShouldBe("@");
}
[Fact]
public void Generate_MultiColumn_ReturnsValidExcel()
{
var headers = new[] { "Column A", "Column B", "Column C" };
var result = _generator.Generate(null, headers);
result.ShouldNotBeNull();
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
var worksheet = workbook.GetSheetAt(0);
ExcelTestHelpers.GetCellText(worksheet, 1, 1).ShouldBe("Column A");
ExcelTestHelpers.GetCellText(worksheet, 1, 2).ShouldBe("Column B");
ExcelTestHelpers.GetCellText(worksheet, 1, 3).ShouldBe("Column C");
}
[Fact]
public void Generate_MultiColumn_WithData_PopulatesRows()
{
var headers = new[] { "Name", "Value" };
var data = new[]
{
new object[] { "Row1", 100 },
new object[] { "Row2", 200 }
};
var result = _generator.Generate(data, headers);
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
var worksheet = workbook.GetSheetAt(0);
ExcelTestHelpers.GetCellText(worksheet, 2, 1).ShouldBe("Row1");
ExcelTestHelpers.GetCellNumber(worksheet, 2, 2).ShouldBe(100);
ExcelTestHelpers.GetCellText(worksheet, 3, 1).ShouldBe("Row2");
ExcelTestHelpers.GetCellNumber(worksheet, 3, 2).ShouldBe(200);
}
[Fact]
public void Generate_MultiColumn_SetsColumnWidth()
{
var headers = new[] { "Column A", "Column B" };
var result = _generator.Generate(null, headers);
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
var worksheet = workbook.GetSheetAt(0);
ExcelTestHelpers.GetColumnWidthChars(worksheet, 1).ShouldBe(65);
ExcelTestHelpers.GetColumnWidthChars(worksheet, 2).ShouldBe(65);
}
[Fact]
public void Generate_SingleColumn_SetsColumnWidth()
{
var result = _generator.Generate<string>(null, "Test");
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
var worksheet = workbook.GetSheetAt(0);
ExcelTestHelpers.GetColumnWidthChars(worksheet, 1).ShouldBe(45);
}
}
@@ -1,249 +1,228 @@
using ClosedXML.Excel;
using JdeScoping.Core.Models.SearchResults;
using JdeScoping.ExcelIO.Options;
using JdeScoping.ExcelIO.Generators;
using JdeScoping.ExcelIO.Mapping;
using JdeScoping.ExcelIO.Mapping.Maps;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NSubstitute;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests;
public class ExcelExportServiceTests
{
private readonly ExcelExportService _service;
private readonly ILogger<ExcelExportService> _logger;
private readonly IOptions<ExcelExportOptions> _options;
public ExcelExportServiceTests()
{
_logger = Substitute.For<ILogger<ExcelExportService>>();
_options = Microsoft.Extensions.Options.Options.Create(new ExcelExportOptions
{
CriteriaSheetPassword = "TestCriteriaPass",
DataSheetPassword = "TestDataPass"
});
var registry = CreateTestRegistry();
var tableWriter = new FluentTableWriter(registry);
var criteriaGenerator = new CriteriaSheetGenerator(_options, tableWriter);
_service = new ExcelExportService(_logger, _options, criteriaGenerator, tableWriter, registry);
}
private static ExcelMapRegistry CreateTestRegistry()
{
var registry = new ExcelMapRegistry();
// Search result maps
registry.Register(new SearchResultMap());
registry.Register(new MisSearchResultMap());
registry.Register(new MisNonMatchSearchResultMap());
// Filter entry maps
registry.Register(new TimespanFilterMap());
registry.Register(new WorkOrderFilterEntryMap());
registry.Register(new ItemNumberFilterEntryMap());
registry.Register(new ProfitCenterFilterEntryMap());
registry.Register(new WorkCenterFilterEntryMap());
registry.Register(new OperatorFilterEntryMap());
registry.Register(new ComponentLotFilterEntryMap());
registry.Register(new ItemOperationMisFilterEntryMap());
return registry;
}
[Fact]
public async Task GenerateAsync_ReturnsValidExcelBytes()
{
var search = CreateMinimalSearchModel();
var result = await _service.GenerateAsync(search);
result.ShouldNotBeNull();
result.Length.ShouldBeGreaterThan(0);
// Verify it's a valid Excel file
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
workbook.Worksheets.Count.ShouldBeGreaterThanOrEqualTo(2);
}
[Fact]
public async Task GenerateAsync_CreatesSearchCriteriaSheet()
{
var search = CreateMinimalSearchModel();
var result = await _service.GenerateAsync(search);
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
workbook.Worksheets.TryGetWorksheet("Search Criteria", out var criteriaSheet).ShouldBeTrue();
criteriaSheet.ShouldNotBeNull();
}
[Fact]
public async Task GenerateAsync_CreatesSearchResultsSheet()
{
var search = CreateMinimalSearchModel();
var result = await _service.GenerateAsync(search);
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
workbook.Worksheets.TryGetWorksheet("Search Results", out var resultsSheet).ShouldBeTrue();
resultsSheet.ShouldNotBeNull();
}
[Fact]
public async Task GenerateAsync_WithMisData_CreatesMisInfoSheet()
{
var search = CreateSearchModelWithMisData();
var result = await _service.GenerateAsync(search);
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
workbook.Worksheets.Count.ShouldBe(4); // Criteria, Results, MIS Info, Investigation
workbook.Worksheets.TryGetWorksheet("MIS Info", out var misSheet).ShouldBeTrue();
misSheet.ShouldNotBeNull();
}
[Fact]
public async Task GenerateAsync_WithMisData_CreatesInvestigationSheet()
{
var search = CreateSearchModelWithMisData();
var result = await _service.GenerateAsync(search);
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
workbook.Worksheets.TryGetWorksheet("Investigation", out var investigationSheet).ShouldBeTrue();
investigationSheet.ShouldNotBeNull();
}
[Fact]
public async Task GenerateAsync_WithoutMisData_DoesNotCreateMisSheets()
{
var search = CreateMinimalSearchModel();
search.ExtractMisData = false;
var result = await _service.GenerateAsync(search);
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
workbook.Worksheets.Count.ShouldBe(2); // Only Criteria and Results
}
[Fact]
public async Task GenerateAsync_CancellationRequested_ThrowsOperationCanceled()
{
var search = CreateMinimalSearchModel();
var cts = new CancellationTokenSource();
cts.Cancel();
await Should.ThrowAsync<OperationCanceledException>(
() => _service.GenerateAsync(search, cts.Token));
}
[Fact]
public async Task GenerateAsync_CriteriaSheet_ContainsSearchName()
{
var search = CreateMinimalSearchModel();
search.Name = "Test Search Name";
var result = await _service.GenerateAsync(search);
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
var criteriaSheet = workbook.Worksheet("Search Criteria");
criteriaSheet.Cell(1, 2).Value.GetText().ShouldBe("Test Search Name");
}
[Fact]
public async Task GenerateAsync_CriteriaSheet_ContainsUserName()
{
var search = CreateMinimalSearchModel();
search.UserName = "testuser";
var result = await _service.GenerateAsync(search);
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
var criteriaSheet = workbook.Worksheet("Search Criteria");
criteriaSheet.Cell(2, 2).Value.GetText().ShouldBe("testuser");
}
[Fact]
public async Task GenerateAsync_ResultsSheet_ContainsResultData()
{
var search = CreateMinimalSearchModel();
search.Results.Add(new SearchResult
{
WorkOrderNumber = 12345,
ItemNumber = "ITEM-001",
LotNumber = "LOT-001",
Flagged = true
});
var result = await _service.GenerateAsync(search);
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
var resultsSheet = workbook.Worksheet("Search Results");
// Check header row
resultsSheet.Cell(1, 1).Value.GetText().ShouldBe("Work Order Number");
// Check data row
resultsSheet.Cell(2, 1).Value.GetNumber().ShouldBe(12345);
}
private static SearchModel CreateMinimalSearchModel()
{
return new SearchModel
{
Id = 1,
Name = "Test Search",
UserName = "testuser",
SubmitDt = DateTime.Now.AddHours(-1),
StartDt = DateTime.Now.AddMinutes(-30),
EndDt = DateTime.Now,
ExtractMisData = false,
Results = []
};
}
private static SearchModel CreateSearchModelWithMisData()
{
return new SearchModel
{
Id = 1,
Name = "Test Search with MIS",
UserName = "testuser",
SubmitDt = DateTime.Now.AddHours(-1),
StartDt = DateTime.Now.AddMinutes(-30),
EndDt = DateTime.Now,
ExtractMisData = true,
Results = [
new SearchResult { WorkOrderNumber = 12345, Flagged = true }
],
MisResults = [
new MisSearchResult { ItemNumber = "ITEM-001", MisNumber = "MIS-001" }
],
MisNonMatchResults = [
new MisNonMatchSearchResult { WorkOrderNumber = 12345, ItemNumber = "ITEM-001" }
]
};
}
}
using JdeScoping.Core.Models.SearchResults;
using JdeScoping.ExcelIO.Options;
using JdeScoping.ExcelIO.Generators;
using JdeScoping.ExcelIO.Mapping;
using JdeScoping.ExcelIO.Mapping.Maps;
using JdeScoping.ExcelIO.Tests.Fixtures;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NSubstitute;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests;
public class ExcelExportServiceTests
{
private readonly ExcelExportService _service;
public ExcelExportServiceTests()
{
var logger = Substitute.For<ILogger<ExcelExportService>>();
var options = Microsoft.Extensions.Options.Options.Create(new ExcelExportOptions
{
CriteriaSheetPassword = "TestCriteriaPass",
DataSheetPassword = "TestDataPass"
});
var registry = CreateTestRegistry();
var tableWriter = new FluentTableWriter(registry);
var criteriaGenerator = new CriteriaSheetGenerator(options, tableWriter);
_service = new ExcelExportService(logger, options, criteriaGenerator, tableWriter, registry);
}
private static ExcelMapRegistry CreateTestRegistry()
{
var registry = new ExcelMapRegistry();
registry.Register(new SearchResultMap());
registry.Register(new MisSearchResultMap());
registry.Register(new MisNonMatchSearchResultMap());
registry.Register(new TimespanFilterMap());
registry.Register(new WorkOrderFilterEntryMap());
registry.Register(new ItemNumberFilterEntryMap());
registry.Register(new ProfitCenterFilterEntryMap());
registry.Register(new WorkCenterFilterEntryMap());
registry.Register(new OperatorFilterEntryMap());
registry.Register(new ComponentLotFilterEntryMap());
registry.Register(new ItemOperationMisFilterEntryMap());
return registry;
}
[Fact]
public async Task GenerateAsync_ReturnsValidExcelBytes()
{
var search = CreateMinimalSearchModel();
var result = await _service.GenerateAsync(search);
result.ShouldNotBeNull();
result.Length.ShouldBeGreaterThan(0);
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
workbook.NumberOfSheets.ShouldBeGreaterThanOrEqualTo(2);
}
[Fact]
public async Task GenerateAsync_CreatesSearchCriteriaSheet()
{
var search = CreateMinimalSearchModel();
var result = await _service.GenerateAsync(search);
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
workbook.GetSheet("Search Criteria").ShouldNotBeNull();
}
[Fact]
public async Task GenerateAsync_CreatesSearchResultsSheet()
{
var search = CreateMinimalSearchModel();
var result = await _service.GenerateAsync(search);
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
workbook.GetSheet("Search Results").ShouldNotBeNull();
}
[Fact]
public async Task GenerateAsync_WithMisData_CreatesMisInfoSheet()
{
var search = CreateSearchModelWithMisData();
var result = await _service.GenerateAsync(search);
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
workbook.NumberOfSheets.ShouldBe(4);
workbook.GetSheet("MIS Info").ShouldNotBeNull();
}
[Fact]
public async Task GenerateAsync_WithMisData_CreatesInvestigationSheet()
{
var search = CreateSearchModelWithMisData();
var result = await _service.GenerateAsync(search);
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
workbook.GetSheet("Investigation").ShouldNotBeNull();
}
[Fact]
public async Task GenerateAsync_WithoutMisData_DoesNotCreateMisSheets()
{
var search = CreateMinimalSearchModel();
search.ExtractMisData = false;
var result = await _service.GenerateAsync(search);
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
workbook.NumberOfSheets.ShouldBe(2);
}
[Fact]
public async Task GenerateAsync_CancellationRequested_ThrowsOperationCanceled()
{
var search = CreateMinimalSearchModel();
var cts = new CancellationTokenSource();
cts.Cancel();
await Should.ThrowAsync<OperationCanceledException>(
() => _service.GenerateAsync(search, cts.Token));
}
[Fact]
public async Task GenerateAsync_CriteriaSheet_ContainsSearchName()
{
var search = CreateMinimalSearchModel();
search.Name = "Test Search Name";
var result = await _service.GenerateAsync(search);
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
var criteriaSheet = workbook.GetSheet("Search Criteria");
ExcelTestHelpers.GetCellText(criteriaSheet, 1, 2).ShouldBe("Test Search Name");
}
[Fact]
public async Task GenerateAsync_CriteriaSheet_ContainsUserName()
{
var search = CreateMinimalSearchModel();
search.UserName = "testuser";
var result = await _service.GenerateAsync(search);
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
var criteriaSheet = workbook.GetSheet("Search Criteria");
ExcelTestHelpers.GetCellText(criteriaSheet, 2, 2).ShouldBe("testuser");
}
[Fact]
public async Task GenerateAsync_ResultsSheet_ContainsResultData()
{
var search = CreateMinimalSearchModel();
search.Results.Add(new SearchResult
{
WorkOrderNumber = 12345,
ItemNumber = "ITEM-001",
LotNumber = "LOT-001",
Flagged = true
});
var result = await _service.GenerateAsync(search);
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
var resultsSheet = workbook.GetSheet("Search Results");
ExcelTestHelpers.GetCellText(resultsSheet, 1, 1).ShouldBe("Work Order Number");
ExcelTestHelpers.GetCellNumber(resultsSheet, 2, 1).ShouldBe(12345);
}
private static SearchModel CreateMinimalSearchModel()
{
return new SearchModel
{
Id = 1,
Name = "Test Search",
UserName = "testuser",
SubmitDt = DateTime.Now.AddHours(-1),
StartDt = DateTime.Now.AddMinutes(-30),
EndDt = DateTime.Now,
ExtractMisData = false,
Results = []
};
}
private static SearchModel CreateSearchModelWithMisData()
{
return new SearchModel
{
Id = 1,
Name = "Test Search with MIS",
UserName = "testuser",
SubmitDt = DateTime.Now.AddHours(-1),
StartDt = DateTime.Now.AddMinutes(-30),
EndDt = DateTime.Now,
ExtractMisData = true,
Results = [
new SearchResult { WorkOrderNumber = 12345, Flagged = true }
],
MisResults = [
new MisSearchResult { ItemNumber = "ITEM-001", MisNumber = "MIS-001" }
],
MisNonMatchResults = [
new MisNonMatchSearchResult { WorkOrderNumber = 12345, ItemNumber = "ITEM-001" }
]
};
}
}
@@ -1,18 +1,139 @@
using ClosedXML.Excel;
namespace JdeScoping.ExcelIO.Tests.Fixtures;
public static class ExcelTestHelpers
{
public static List<string> GetHeadersFromSheet(IXLWorksheet sheet)
{
var headers = new List<string>();
var col = 1;
while (!sheet.Cell(1, col).IsEmpty())
{
headers.Add(sheet.Cell(1, col).Value.GetText());
col++;
}
return headers;
}
}
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;
namespace JdeScoping.ExcelIO.Tests.Fixtures;
public static class ExcelTestHelpers
{
private static readonly DataFormatter Formatter = new();
public static List<string> GetHeadersFromSheet(ISheet sheet)
{
var headers = new List<string>();
var headerRow = sheet.GetRow(0);
if (headerRow == null)
{
return headers;
}
var col = 0;
while (true)
{
var cell = headerRow.GetCell(col);
var text = cell == null ? string.Empty : Formatter.FormatCellValue(cell);
if (string.IsNullOrEmpty(text))
{
break;
}
headers.Add(text);
col++;
}
return headers;
}
public static string GetCellText(ISheet sheet, int row1Based, int col1Based)
{
var cell = GetCell(sheet, row1Based, col1Based);
return cell == null ? string.Empty : Formatter.FormatCellValue(cell);
}
public static double GetCellNumber(ISheet sheet, int row1Based, int col1Based)
{
var cell = GetCell(sheet, row1Based, col1Based);
if (cell == null)
{
return 0;
}
if (cell.CellType == CellType.Numeric)
{
return cell.NumericCellValue;
}
var text = Formatter.FormatCellValue(cell);
return double.TryParse(text, out var value) ? value : 0;
}
public static ICell? GetCell(ISheet sheet, int row1Based, int col1Based)
{
return sheet.GetRow(row1Based - 1)?.GetCell(col1Based - 1);
}
public static XSSFSheet GetXssfSheet(IWorkbook workbook, string sheetName)
{
return (XSSFSheet)workbook.GetSheet(sheetName)!;
}
public static XSSFWorkbook OpenWorkbook(byte[] bytes)
{
return new XSSFWorkbook(new MemoryStream(bytes));
}
public static double GetColumnWidthChars(ISheet sheet, int col1Based)
{
return sheet.GetColumnWidth(col1Based - 1) / 256d;
}
public static bool IsSheetProtected(ISheet sheet)
{
return sheet is XSSFSheet xssf && xssf.IsSheetLocked;
}
public static byte[]? GetFillForegroundRgb(ICell cell)
{
if (cell.CellStyle is XSSFCellStyle xssfStyle)
{
return xssfStyle.FillForegroundXSSFColor?.RGB;
}
return null;
}
public static bool IsMerged(ISheet sheet, int firstRow1Based, int lastRow1Based, int firstCol1Based, int lastCol1Based)
{
for (var i = 0; i < sheet.NumMergedRegions; i++)
{
var region = sheet.GetMergedRegion(i);
if (region.FirstRow == firstRow1Based - 1 &&
region.LastRow == lastRow1Based - 1 &&
region.FirstColumn == firstCol1Based - 1 &&
region.LastColumn == lastCol1Based - 1)
{
return true;
}
}
return false;
}
public static XSSFTable GetFirstTable(ISheet sheet)
{
return ((XSSFSheet)sheet).GetTables().First();
}
public static XSSFTable GetTableByName(ISheet sheet, string name)
{
return ((XSSFSheet)sheet).GetTables().First(t => t.Name == name || t.DisplayName == name);
}
public static int GetTableRowCount(XSSFTable table)
{
// header row + data rows
return table.RowCount;
}
public static bool TableExists(ISheet sheet, string tableName)
{
return ((XSSFSheet)sheet).GetTables().Any(t => t.Name == tableName || t.DisplayName == tableName);
}
public static bool RegionIntersectsCell(CellRangeAddress region, int row1Based, int col1Based)
{
var row = row1Based - 1;
var col = col1Based - 1;
return region.IsInRange(row, col);
}
}
@@ -1,68 +1,67 @@
using ClosedXML.Excel;
using JdeScoping.Core.Models.SearchResults;
using JdeScoping.ExcelIO.Generators;
using JdeScoping.ExcelIO.Mapping;
using JdeScoping.ExcelIO.Mapping.Maps;
using JdeScoping.ExcelIO.Options;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NSubstitute;
namespace JdeScoping.ExcelIO.Tests.Fixtures;
public abstract class WorkbookFixtureBase : IDisposable
{
public XLWorkbook Workbook { get; }
public SearchModel SearchModel { get; }
protected abstract SearchModel CreateSearchModel();
protected WorkbookFixtureBase()
{
SearchModel = CreateSearchModel();
var service = CreateExportService();
var bytes = service.GenerateAsync(SearchModel).GetAwaiter().GetResult();
Workbook = new XLWorkbook(new MemoryStream(bytes));
}
private static ExcelExportService CreateExportService()
{
var logger = Substitute.For<ILogger<ExcelExportService>>();
var options = Microsoft.Extensions.Options.Options.Create(new ExcelExportOptions
{
CriteriaSheetPassword = "TestCriteriaPass",
DataSheetPassword = "TestDataPass"
});
var registry = CreateTestRegistry();
var tableWriter = new FluentTableWriter(registry);
var criteriaGenerator = new CriteriaSheetGenerator(options, tableWriter);
return new ExcelExportService(logger, options, criteriaGenerator, tableWriter, registry);
}
private static ExcelMapRegistry CreateTestRegistry()
{
var registry = new ExcelMapRegistry();
registry.Register(new SearchResultMap());
registry.Register(new MisSearchResultMap());
registry.Register(new MisNonMatchSearchResultMap());
registry.Register(new TimespanFilterMap());
registry.Register(new WorkOrderFilterEntryMap());
registry.Register(new ItemNumberFilterEntryMap());
registry.Register(new ProfitCenterFilterEntryMap());
registry.Register(new WorkCenterFilterEntryMap());
registry.Register(new OperatorFilterEntryMap());
registry.Register(new ComponentLotFilterEntryMap());
registry.Register(new ItemOperationMisFilterEntryMap());
return registry;
}
public void Dispose()
{
Workbook.Dispose();
GC.SuppressFinalize(this);
}
}
using JdeScoping.Core.Models.SearchResults;
using JdeScoping.ExcelIO.Generators;
using JdeScoping.ExcelIO.Mapping;
using JdeScoping.ExcelIO.Mapping.Maps;
using JdeScoping.ExcelIO.Options;
using Microsoft.Extensions.Logging;
using NPOI.XSSF.UserModel;
using NSubstitute;
namespace JdeScoping.ExcelIO.Tests.Fixtures;
public abstract class WorkbookFixtureBase : IDisposable
{
public XSSFWorkbook Workbook { get; }
public SearchModel SearchModel { get; }
protected abstract SearchModel CreateSearchModel();
protected WorkbookFixtureBase()
{
SearchModel = CreateSearchModel();
var service = CreateExportService();
var bytes = service.GenerateAsync(SearchModel).GetAwaiter().GetResult();
Workbook = new XSSFWorkbook(new MemoryStream(bytes));
}
private static ExcelExportService CreateExportService()
{
var logger = Substitute.For<ILogger<ExcelExportService>>();
var options = Microsoft.Extensions.Options.Options.Create(new ExcelExportOptions
{
CriteriaSheetPassword = "TestCriteriaPass",
DataSheetPassword = "TestDataPass"
});
var registry = CreateTestRegistry();
var tableWriter = new FluentTableWriter(registry);
var criteriaGenerator = new CriteriaSheetGenerator(options, tableWriter);
return new ExcelExportService(logger, options, criteriaGenerator, tableWriter, registry);
}
private static ExcelMapRegistry CreateTestRegistry()
{
var registry = new ExcelMapRegistry();
registry.Register(new SearchResultMap());
registry.Register(new MisSearchResultMap());
registry.Register(new MisNonMatchSearchResultMap());
registry.Register(new TimespanFilterMap());
registry.Register(new WorkOrderFilterEntryMap());
registry.Register(new ItemNumberFilterEntryMap());
registry.Register(new ProfitCenterFilterEntryMap());
registry.Register(new WorkCenterFilterEntryMap());
registry.Register(new OperatorFilterEntryMap());
registry.Register(new ComponentLotFilterEntryMap());
registry.Register(new ItemOperationMisFilterEntryMap());
return registry;
}
public void Dispose()
{
Workbook.Dispose();
GC.SuppressFinalize(this);
}
}
@@ -1,80 +1,81 @@
using ClosedXML.Excel;
using JdeScoping.ExcelIO.Formatting;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests;
public class HeaderFormatterTests
{
[Fact]
public void ApplyHeaderFormat_Cell_AppliesCorrectStyling()
{
using var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Test");
var cell = worksheet.Cell(1, 1);
HeaderFormatter.ApplyHeaderFormat(cell, "Test Header");
cell.Value.GetText().ShouldBe("Test Header");
cell.Style.Font.Bold.ShouldBeTrue();
cell.Style.Alignment.Horizontal.ShouldBe(XLAlignmentHorizontalValues.Center);
cell.Style.Fill.BackgroundColor.ShouldBe(XLColor.Gainsboro);
}
[Fact]
public void ApplyHeaderFormat_Cell_WithoutText_AppliesOnlyStyling()
{
using var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Test");
var cell = worksheet.Cell(1, 1);
cell.Value = "Original";
HeaderFormatter.ApplyHeaderFormat(cell);
cell.Value.GetText().ShouldBe("Original");
cell.Style.Font.Bold.ShouldBeTrue();
}
[Fact]
public void ApplyHeaderFormat_Range_AppliesCorrectStyling()
{
using var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Test");
var range = worksheet.Range(1, 1, 1, 3);
HeaderFormatter.ApplyHeaderFormat(range, "Header", merge: false);
range.FirstCell().Value.GetText().ShouldBe("Header");
foreach (var cell in range.Cells())
{
cell.Style.Font.Bold.ShouldBeTrue();
cell.Style.Fill.BackgroundColor.ShouldBe(XLColor.Gainsboro);
}
}
[Fact]
public void ApplyHeaderFormat_Range_WithMerge_MergesCells()
{
using var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Test");
var range = worksheet.Range(1, 1, 1, 3);
HeaderFormatter.ApplyHeaderFormat(range, "Merged Header", merge: true);
range.IsMerged().ShouldBeTrue();
range.FirstCell().Value.GetText().ShouldBe("Merged Header");
}
[Fact]
public void ApplyHeaderFormat_Range_WithoutMerge_DoesNotMergeCells()
{
using var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Test");
var range = worksheet.Range(1, 1, 1, 3);
HeaderFormatter.ApplyHeaderFormat(range, "Not Merged", merge: false);
range.IsMerged().ShouldBeFalse();
}
}
using JdeScoping.ExcelIO.Formatting;
using JdeScoping.ExcelIO.Tests.Fixtures;
using NPOI.XSSF.UserModel;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests;
public class HeaderFormatterTests
{
[Fact]
public void ApplyHeaderFormat_Cell_AppliesCorrectStyling()
{
using var workbook = new XSSFWorkbook();
var worksheet = workbook.CreateSheet("Test");
var row = worksheet.CreateRow(0);
var cell = row.CreateCell(0);
HeaderFormatter.ApplyHeaderFormat(cell, "Test Header");
ExcelTestHelpers.GetCellText(worksheet, 1, 1).ShouldBe("Test Header");
cell.CellStyle.GetFont(workbook).IsBold.ShouldBeTrue();
cell.CellStyle.Alignment.ShouldBe(NPOI.SS.UserModel.HorizontalAlignment.Center);
ExcelTestHelpers.GetFillForegroundRgb(cell).ShouldBe([0xDC, 0xDC, 0xDC]);
}
[Fact]
public void ApplyHeaderFormat_Cell_WithoutText_AppliesOnlyStyling()
{
using var workbook = new XSSFWorkbook();
var worksheet = workbook.CreateSheet("Test");
var row = worksheet.CreateRow(0);
var cell = row.CreateCell(0);
cell.SetCellValue("Original");
HeaderFormatter.ApplyHeaderFormat(cell);
ExcelTestHelpers.GetCellText(worksheet, 1, 1).ShouldBe("Original");
cell.CellStyle.GetFont(workbook).IsBold.ShouldBeTrue();
}
[Fact]
public void ApplyHeaderFormat_Range_AppliesCorrectStyling()
{
using var workbook = new XSSFWorkbook();
var worksheet = workbook.CreateSheet("Test");
HeaderFormatter.ApplyHeaderFormat(worksheet, 1, 1, 1, 3, "Header", merge: false);
ExcelTestHelpers.GetCellText(worksheet, 1, 1).ShouldBe("Header");
for (var col = 1; col <= 3; col++)
{
var cell = ExcelTestHelpers.GetCell(worksheet, 1, col)!;
cell.CellStyle.GetFont(workbook).IsBold.ShouldBeTrue();
ExcelTestHelpers.GetFillForegroundRgb(cell).ShouldBe([0xDC, 0xDC, 0xDC]);
}
}
[Fact]
public void ApplyHeaderFormat_Range_WithMerge_MergesCells()
{
using var workbook = new XSSFWorkbook();
var worksheet = workbook.CreateSheet("Test");
HeaderFormatter.ApplyHeaderFormat(worksheet, 1, 1, 1, 3, "Merged Header", merge: true);
ExcelTestHelpers.IsMerged(worksheet, 1, 1, 1, 3).ShouldBeTrue();
ExcelTestHelpers.GetCellText(worksheet, 1, 1).ShouldBe("Merged Header");
}
[Fact]
public void ApplyHeaderFormat_Range_WithoutMerge_DoesNotMergeCells()
{
using var workbook = new XSSFWorkbook();
var worksheet = workbook.CreateSheet("Test");
HeaderFormatter.ApplyHeaderFormat(worksheet, 1, 1, 1, 3, "Not Merged", merge: false);
ExcelTestHelpers.IsMerged(worksheet, 1, 1, 1, 3).ShouldBeFalse();
}
}
@@ -1,86 +1,87 @@
using ClosedXML.Excel;
using JdeScoping.ExcelIO.Tests.Fixtures;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests.Integration;
public class InvestigationSheetTests : IClassFixture<WithMisDataFixture>
{
private readonly XLWorkbook _workbook;
private readonly IXLWorksheet _sheet;
private readonly List<string> _headers;
public InvestigationSheetTests(WithMisDataFixture fixture)
{
_workbook = fixture.Workbook;
_sheet = _workbook.Worksheet("Investigation");
_headers = ExcelTestHelpers.GetHeadersFromSheet(_sheet);
}
[Fact]
public void InvestigationSheet_Exists()
{
_workbook.Worksheets.TryGetWorksheet("Investigation", out _).ShouldBeTrue();
}
[Fact]
public void ColumnCount_Is12()
{
_headers.Count.ShouldBe(12);
}
[Fact]
public void ColumnHeaders_MatchExpected()
{
_headers.ShouldContain("Work Center Code");
_headers.ShouldContain("Work Order Number");
_headers.ShouldContain("Work Order Start Date");
_headers.ShouldContain("Job Step Number");
_headers.ShouldContain("Function Operation Description");
_headers.ShouldContain("Job Step End Date");
_headers.ShouldContain("Function Code");
_headers.ShouldContain("Was Job Step Added?");
_headers.ShouldContain("Matched Job Step Number");
_headers.ShouldContain("Item Number");
_headers.ShouldContain("Item Description");
_headers.ShouldContain("Routing Type");
}
[Fact]
public void ColumnOrder_MatchesSpec()
{
_headers[0].ShouldBe("Work Center Code");
_headers[1].ShouldBe("Work Order Number");
_headers[2].ShouldBe("Work Order Start Date");
_headers[3].ShouldBe("Job Step Number");
_headers[4].ShouldBe("Function Operation Description");
_headers[5].ShouldBe("Job Step End Date");
_headers[6].ShouldBe("Function Code");
_headers[7].ShouldBe("Was Job Step Added?");
_headers[8].ShouldBe("Matched Job Step Number");
_headers[9].ShouldBe("Item Number");
_headers[10].ShouldBe("Item Description");
_headers[11].ShouldBe("Routing Type");
}
[Fact]
public void TableStyle_IsLight18()
{
var table = _sheet.Tables.First();
table.Theme.ShouldBe(XLTableTheme.TableStyleLight18);
}
[Fact]
public void Protection_IsEnabled()
{
_sheet.Protection.IsProtected.ShouldBeTrue();
}
[Fact]
public void DataRow_ContainsExpectedValues()
{
_sheet.Cell(2, 2).Value.GetNumber().ShouldBe(12345);
_sheet.Cell(2, 10).Value.GetText().ShouldBe("ITEM-001");
}
}
using JdeScoping.ExcelIO.Tests.Fixtures;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests.Integration;
public class InvestigationSheetTests : IClassFixture<WithMisDataFixture>
{
private readonly XSSFWorkbook _workbook;
private readonly ISheet _sheet;
private readonly List<string> _headers;
public InvestigationSheetTests(WithMisDataFixture fixture)
{
_workbook = fixture.Workbook;
_sheet = _workbook.GetSheet("Investigation")!;
_headers = ExcelTestHelpers.GetHeadersFromSheet(_sheet);
}
[Fact]
public void InvestigationSheet_Exists()
{
_workbook.GetSheet("Investigation").ShouldNotBeNull();
}
[Fact]
public void ColumnCount_Is12()
{
_headers.Count.ShouldBe(12);
}
[Fact]
public void ColumnHeaders_MatchExpected()
{
_headers.ShouldContain("Work Center Code");
_headers.ShouldContain("Work Order Number");
_headers.ShouldContain("Work Order Start Date");
_headers.ShouldContain("Job Step Number");
_headers.ShouldContain("Function Operation Description");
_headers.ShouldContain("Job Step End Date");
_headers.ShouldContain("Function Code");
_headers.ShouldContain("Was Job Step Added?");
_headers.ShouldContain("Matched Job Step Number");
_headers.ShouldContain("Item Number");
_headers.ShouldContain("Item Description");
_headers.ShouldContain("Routing Type");
}
[Fact]
public void ColumnOrder_MatchesSpec()
{
_headers[0].ShouldBe("Work Center Code");
_headers[1].ShouldBe("Work Order Number");
_headers[2].ShouldBe("Work Order Start Date");
_headers[3].ShouldBe("Job Step Number");
_headers[4].ShouldBe("Function Operation Description");
_headers[5].ShouldBe("Job Step End Date");
_headers[6].ShouldBe("Function Code");
_headers[7].ShouldBe("Was Job Step Added?");
_headers[8].ShouldBe("Matched Job Step Number");
_headers[9].ShouldBe("Item Number");
_headers[10].ShouldBe("Item Description");
_headers[11].ShouldBe("Routing Type");
}
[Fact]
public void TableStyle_IsLight18()
{
var table = ExcelTestHelpers.GetFirstTable(_sheet);
table.StyleName.ShouldBe("TableStyleLight18");
}
[Fact]
public void Protection_IsEnabled()
{
((XSSFSheet)_sheet).IsSheetLocked.ShouldBeTrue();
}
[Fact]
public void DataRow_ContainsExpectedValues()
{
ExcelTestHelpers.GetCellNumber(_sheet, 2, 2).ShouldBe(12345);
ExcelTestHelpers.GetCellText(_sheet, 2, 10).ShouldBe("ITEM-001");
}
}
@@ -1,24 +1,24 @@
using ClosedXML.Excel;
using JdeScoping.ExcelIO.Tests.Fixtures;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests.Integration;
public class LargeDataSetTests : IClassFixture<LargeDataSetFixture>
{
private readonly XLWorkbook _workbook;
public LargeDataSetTests(LargeDataSetFixture fixture)
{
_workbook = fixture.Workbook;
}
[Fact]
public void TableRowCount_Is1001()
{
var sheet = _workbook.Worksheet("Search Results");
var table = sheet.Tables.First();
table.RowCount().ShouldBe(1001); // 1 header + 1000 data rows
}
}
using JdeScoping.ExcelIO.Tests.Fixtures;
using NPOI.XSSF.UserModel;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests.Integration;
public class LargeDataSetTests : IClassFixture<LargeDataSetFixture>
{
private readonly XSSFWorkbook _workbook;
public LargeDataSetTests(LargeDataSetFixture fixture)
{
_workbook = fixture.Workbook;
}
[Fact]
public void TableRowCount_Is1001()
{
var sheet = _workbook.GetSheet("Search Results")!;
var table = ExcelTestHelpers.GetFirstTable(sheet);
ExcelTestHelpers.GetTableRowCount(table).ShouldBe(1001);
}
}
@@ -1,48 +1,48 @@
using ClosedXML.Excel;
using JdeScoping.ExcelIO.Tests.Fixtures;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests.Integration;
public class MinimalSearchTests : IClassFixture<MinimalSearchFixture>
{
private readonly XLWorkbook _workbook;
public MinimalSearchTests(MinimalSearchFixture fixture)
{
_workbook = fixture.Workbook;
}
[Fact]
public void SheetCount_IsTwo()
{
_workbook.Worksheets.Count.ShouldBe(2);
}
[Fact]
public void SearchCriteriaSheet_Exists()
{
_workbook.Worksheets.TryGetWorksheet("Search Criteria", out _).ShouldBeTrue();
}
[Fact]
public void SearchResultsSheet_Exists()
{
_workbook.Worksheets.TryGetWorksheet("Search Results", out _).ShouldBeTrue();
}
[Fact]
public void SearchCriteriaSheet_IsProtected()
{
var sheet = _workbook.Worksheet("Search Criteria");
sheet.Protection.IsProtected.ShouldBeTrue();
}
[Fact]
public void SearchResultsSheet_IsProtected()
{
var sheet = _workbook.Worksheet("Search Results");
sheet.Protection.IsProtected.ShouldBeTrue();
}
}
using JdeScoping.ExcelIO.Tests.Fixtures;
using NPOI.XSSF.UserModel;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests.Integration;
public class MinimalSearchTests : IClassFixture<MinimalSearchFixture>
{
private readonly XSSFWorkbook _workbook;
public MinimalSearchTests(MinimalSearchFixture fixture)
{
_workbook = fixture.Workbook;
}
[Fact]
public void SheetCount_IsTwo()
{
_workbook.NumberOfSheets.ShouldBe(2);
}
[Fact]
public void SearchCriteriaSheet_Exists()
{
_workbook.GetSheet("Search Criteria").ShouldNotBeNull();
}
[Fact]
public void SearchResultsSheet_Exists()
{
_workbook.GetSheet("Search Results").ShouldNotBeNull();
}
[Fact]
public void SearchCriteriaSheet_IsProtected()
{
var sheet = (XSSFSheet)_workbook.GetSheet("Search Criteria")!;
sheet.IsSheetLocked.ShouldBeTrue();
}
[Fact]
public void SearchResultsSheet_IsProtected()
{
var sheet = (XSSFSheet)_workbook.GetSheet("Search Results")!;
sheet.IsSheetLocked.ShouldBeTrue();
}
}
@@ -1,130 +1,131 @@
using ClosedXML.Excel;
using JdeScoping.ExcelIO.Tests.Fixtures;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests.Integration;
public class MisInfoSheetTests : IClassFixture<WithMisDataFixture>
{
private readonly XLWorkbook _workbook;
private readonly IXLWorksheet _sheet;
private readonly List<string> _headers;
public MisInfoSheetTests(WithMisDataFixture fixture)
{
_workbook = fixture.Workbook;
_sheet = _workbook.Worksheet("MIS Info");
_headers = ExcelTestHelpers.GetHeadersFromSheet(_sheet);
}
[Fact]
public void SheetCount_IsFour()
{
_workbook.Worksheets.Count.ShouldBe(4);
}
[Fact]
public void MisInfoSheet_Exists()
{
_workbook.Worksheets.TryGetWorksheet("MIS Info", out _).ShouldBeTrue();
}
[Fact]
public void ColumnCount_Is19()
{
_headers.Count.ShouldBe(19);
}
[Fact]
public void ColumnHeaders_MatchExpected()
{
_headers.ShouldContain("Item Number");
_headers.ShouldContain("MIS Job Step Sequence Number");
_headers.ShouldContain("MIS Number");
_headers.ShouldContain("MIS Revision");
_headers.ShouldContain("Item Description");
_headers.ShouldContain("MIS Release Status");
_headers.ShouldContain("MIS Release Date");
_headers.ShouldContain("Branch Code");
_headers.ShouldContain("Job Step Sequence Number");
_headers.ShouldContain("Matched Sequence Number");
_headers.ShouldContain("Matched to F3112Z1?");
_headers.ShouldContain("Matched to F3003?");
_headers.ShouldContain("Function Operation Description");
_headers.ShouldContain("Char Number");
_headers.ShouldContain("Test Description");
_headers.ShouldContain("Sampling Type");
_headers.ShouldContain("Sampling Value");
_headers.ShouldContain("Tools & Gauges");
_headers.ShouldContain("Work Instructions");
}
[Fact]
public void ColumnOrder_MatchesSpec()
{
_headers[0].ShouldBe("Item Number");
_headers[1].ShouldBe("MIS Job Step Sequence Number");
_headers[2].ShouldBe("MIS Number");
_headers[3].ShouldBe("MIS Revision");
_headers[4].ShouldBe("Item Description");
_headers[5].ShouldBe("MIS Release Status");
_headers[6].ShouldBe("MIS Release Date");
_headers[7].ShouldBe("Branch Code");
_headers[8].ShouldBe("Job Step Sequence Number");
_headers[9].ShouldBe("Matched Sequence Number");
_headers[10].ShouldBe("Matched to F3112Z1?");
_headers[11].ShouldBe("Matched to F3003?");
_headers[12].ShouldBe("Function Operation Description");
_headers[13].ShouldBe("Char Number");
_headers[14].ShouldBe("Test Description");
_headers[15].ShouldBe("Sampling Type");
_headers[16].ShouldBe("Sampling Value");
_headers[17].ShouldBe("Tools & Gauges");
_headers[18].ShouldBe("Work Instructions");
}
[Fact]
public void TableStyle_IsLight18()
{
var table = _sheet.Tables.First();
table.Theme.ShouldBe(XLTableTheme.TableStyleLight18);
}
[Fact]
public void Protection_IsEnabled()
{
_sheet.Protection.IsProtected.ShouldBeTrue();
}
[Fact]
public void DataRow_ContainsExpectedValues()
{
_sheet.Cell(2, 1).Value.GetText().ShouldBe("ITEM-001");
_sheet.Cell(2, 3).Value.GetText().ShouldBe("MIS-001");
}
[Fact]
public void TestDescriptionColumn_IsWrapped()
{
var colIndex = _headers.IndexOf("Test Description") + 1;
_sheet.Column(colIndex).Width.ShouldBe(65);
_sheet.Column(colIndex).Style.Alignment.WrapText.ShouldBeTrue();
}
[Fact]
public void ToolsGaugesColumn_IsWrapped()
{
var colIndex = _headers.IndexOf("Tools & Gauges") + 1;
_sheet.Column(colIndex).Width.ShouldBe(65);
_sheet.Column(colIndex).Style.Alignment.WrapText.ShouldBeTrue();
}
[Fact]
public void WorkInstructionsColumn_IsWrapped()
{
var colIndex = _headers.IndexOf("Work Instructions") + 1;
_sheet.Column(colIndex).Width.ShouldBe(65);
_sheet.Column(colIndex).Style.Alignment.WrapText.ShouldBeTrue();
}
}
using JdeScoping.ExcelIO.Tests.Fixtures;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests.Integration;
public class MisInfoSheetTests : IClassFixture<WithMisDataFixture>
{
private readonly XSSFWorkbook _workbook;
private readonly ISheet _sheet;
private readonly List<string> _headers;
public MisInfoSheetTests(WithMisDataFixture fixture)
{
_workbook = fixture.Workbook;
_sheet = _workbook.GetSheet("MIS Info")!;
_headers = ExcelTestHelpers.GetHeadersFromSheet(_sheet);
}
[Fact]
public void SheetCount_IsFour()
{
_workbook.NumberOfSheets.ShouldBe(4);
}
[Fact]
public void MisInfoSheet_Exists()
{
_workbook.GetSheet("MIS Info").ShouldNotBeNull();
}
[Fact]
public void ColumnCount_Is19()
{
_headers.Count.ShouldBe(19);
}
[Fact]
public void ColumnHeaders_MatchExpected()
{
_headers.ShouldContain("Item Number");
_headers.ShouldContain("MIS Job Step Sequence Number");
_headers.ShouldContain("MIS Number");
_headers.ShouldContain("MIS Revision");
_headers.ShouldContain("Item Description");
_headers.ShouldContain("MIS Release Status");
_headers.ShouldContain("MIS Release Date");
_headers.ShouldContain("Branch Code");
_headers.ShouldContain("Job Step Sequence Number");
_headers.ShouldContain("Matched Sequence Number");
_headers.ShouldContain("Matched to F3112Z1?");
_headers.ShouldContain("Matched to F3003?");
_headers.ShouldContain("Function Operation Description");
_headers.ShouldContain("Char Number");
_headers.ShouldContain("Test Description");
_headers.ShouldContain("Sampling Type");
_headers.ShouldContain("Sampling Value");
_headers.ShouldContain("Tools & Gauges");
_headers.ShouldContain("Work Instructions");
}
[Fact]
public void ColumnOrder_MatchesSpec()
{
_headers[0].ShouldBe("Item Number");
_headers[1].ShouldBe("MIS Job Step Sequence Number");
_headers[2].ShouldBe("MIS Number");
_headers[3].ShouldBe("MIS Revision");
_headers[4].ShouldBe("Item Description");
_headers[5].ShouldBe("MIS Release Status");
_headers[6].ShouldBe("MIS Release Date");
_headers[7].ShouldBe("Branch Code");
_headers[8].ShouldBe("Job Step Sequence Number");
_headers[9].ShouldBe("Matched Sequence Number");
_headers[10].ShouldBe("Matched to F3112Z1?");
_headers[11].ShouldBe("Matched to F3003?");
_headers[12].ShouldBe("Function Operation Description");
_headers[13].ShouldBe("Char Number");
_headers[14].ShouldBe("Test Description");
_headers[15].ShouldBe("Sampling Type");
_headers[16].ShouldBe("Sampling Value");
_headers[17].ShouldBe("Tools & Gauges");
_headers[18].ShouldBe("Work Instructions");
}
[Fact]
public void TableStyle_IsLight18()
{
var table = ExcelTestHelpers.GetFirstTable(_sheet);
table.StyleName.ShouldBe("TableStyleLight18");
}
[Fact]
public void Protection_IsEnabled()
{
((XSSFSheet)_sheet).IsSheetLocked.ShouldBeTrue();
}
[Fact]
public void DataRow_ContainsExpectedValues()
{
ExcelTestHelpers.GetCellText(_sheet, 2, 1).ShouldBe("ITEM-001");
ExcelTestHelpers.GetCellText(_sheet, 2, 3).ShouldBe("MIS-001");
}
[Fact]
public void TestDescriptionColumn_IsWrapped()
{
var colIndex = _headers.IndexOf("Test Description") + 1;
ExcelTestHelpers.GetColumnWidthChars(_sheet, colIndex).ShouldBe(65);
ExcelTestHelpers.GetCell(_sheet, 2, colIndex)!.CellStyle.WrapText.ShouldBeTrue();
}
[Fact]
public void ToolsGaugesColumn_IsWrapped()
{
var colIndex = _headers.IndexOf("Tools & Gauges") + 1;
ExcelTestHelpers.GetColumnWidthChars(_sheet, colIndex).ShouldBe(65);
ExcelTestHelpers.GetCell(_sheet, 2, colIndex)!.CellStyle.WrapText.ShouldBeTrue();
}
[Fact]
public void WorkInstructionsColumn_IsWrapped()
{
var colIndex = _headers.IndexOf("Work Instructions") + 1;
ExcelTestHelpers.GetColumnWidthChars(_sheet, colIndex).ShouldBe(65);
ExcelTestHelpers.GetCell(_sheet, 2, colIndex)!.CellStyle.WrapText.ShouldBeTrue();
}
}
@@ -1,75 +1,77 @@
using ClosedXML.Excel;
using JdeScoping.ExcelIO.Tests.Fixtures;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests.Integration;
public class ProtectionAndStyleTests : IClassFixture<WithMisDataFixture>
{
private readonly XLWorkbook _workbook;
public ProtectionAndStyleTests(WithMisDataFixture fixture)
{
_workbook = fixture.Workbook;
}
[Fact]
public void AllDataSheets_AreProtected()
{
_workbook.Worksheet("Search Results").Protection.IsProtected.ShouldBeTrue();
_workbook.Worksheet("MIS Info").Protection.IsProtected.ShouldBeTrue();
_workbook.Worksheet("Investigation").Protection.IsProtected.ShouldBeTrue();
}
[Fact]
public void Protection_AllowsFiltering()
{
var sheet = _workbook.Worksheet("Search Results");
sheet.Protection.AllowedElements.HasFlag(XLSheetProtectionElements.AutoFilter).ShouldBeTrue();
}
[Fact]
public void Protection_AllowsSorting()
{
var sheet = _workbook.Worksheet("Search Results");
sheet.Protection.AllowedElements.HasFlag(XLSheetProtectionElements.Sort).ShouldBeTrue();
}
[Fact]
public void Protection_AllowsFormatting()
{
var sheet = _workbook.Worksheet("Search Results");
sheet.Protection.AllowedElements.HasFlag(XLSheetProtectionElements.FormatCells).ShouldBeTrue();
sheet.Protection.AllowedElements.HasFlag(XLSheetProtectionElements.FormatColumns).ShouldBeTrue();
sheet.Protection.AllowedElements.HasFlag(XLSheetProtectionElements.FormatRows).ShouldBeTrue();
}
[Fact]
public void AllTables_UseLight18Style()
{
_workbook.Worksheet("Search Results").Tables.First().Theme.ShouldBe(XLTableTheme.TableStyleLight18);
_workbook.Worksheet("MIS Info").Tables.First().Theme.ShouldBe(XLTableTheme.TableStyleLight18);
_workbook.Worksheet("Investigation").Tables.First().Theme.ShouldBe(XLTableTheme.TableStyleLight18);
}
[Fact]
public void HeaderCells_HaveCorrectFormatting()
{
var sheet = _workbook.Worksheet("Search Criteria");
var headerCell = sheet.Cell(1, 1);
headerCell.Style.Font.Bold.ShouldBeTrue();
headerCell.Style.Fill.BackgroundColor.ShouldBe(XLColor.Gainsboro);
headerCell.Style.Alignment.Horizontal.ShouldBe(XLAlignmentHorizontalValues.Center);
}
[Fact]
public void CriteriaTimestamp_MatchesLegacyFormat()
{
var sheet = _workbook.Worksheet("Search Criteria");
var timestamp = sheet.Cell(4, 2).Value.GetText();
timestamp.ShouldContain("Jan 15, 2024");
timestamp.ShouldContain("02:30:45");
timestamp.ShouldContain("EST");
}
}
using JdeScoping.ExcelIO.Tests.Fixtures;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests.Integration;
public class ProtectionAndStyleTests : IClassFixture<WithMisDataFixture>
{
private readonly XSSFWorkbook _workbook;
public ProtectionAndStyleTests(WithMisDataFixture fixture)
{
_workbook = fixture.Workbook;
}
[Fact]
public void AllDataSheets_AreProtected()
{
((XSSFSheet)_workbook.GetSheet("Search Results")!).IsSheetLocked.ShouldBeTrue();
((XSSFSheet)_workbook.GetSheet("MIS Info")!).IsSheetLocked.ShouldBeTrue();
((XSSFSheet)_workbook.GetSheet("Investigation")!).IsSheetLocked.ShouldBeTrue();
}
[Fact]
public void Protection_AllowsFiltering()
{
var sheet = (XSSFSheet)_workbook.GetSheet("Search Results")!;
sheet.IsAutoFilterLocked.ShouldBeFalse();
}
[Fact]
public void Protection_AllowsSorting()
{
var sheet = (XSSFSheet)_workbook.GetSheet("Search Results")!;
sheet.IsSortLocked.ShouldBeFalse();
}
[Fact]
public void Protection_AllowsFormatting()
{
var sheet = (XSSFSheet)_workbook.GetSheet("Search Results")!;
sheet.IsFormatCellsLocked.ShouldBeFalse();
sheet.IsFormatColumnsLocked.ShouldBeFalse();
sheet.IsFormatRowsLocked.ShouldBeFalse();
}
[Fact]
public void AllTables_UseLight18Style()
{
ExcelTestHelpers.GetFirstTable(_workbook.GetSheet("Search Results")!).StyleName.ShouldBe("TableStyleLight18");
ExcelTestHelpers.GetFirstTable(_workbook.GetSheet("MIS Info")!).StyleName.ShouldBe("TableStyleLight18");
ExcelTestHelpers.GetFirstTable(_workbook.GetSheet("Investigation")!).StyleName.ShouldBe("TableStyleLight18");
}
[Fact]
public void HeaderCells_HaveCorrectFormatting()
{
var sheet = _workbook.GetSheet("Search Criteria")!;
var headerCell = ExcelTestHelpers.GetCell(sheet, 1, 1)!;
(headerCell.CellStyle.FontIndex >= 0 &&
_workbook.GetFontAt(headerCell.CellStyle.FontIndex).IsBold).ShouldBeTrue();
ExcelTestHelpers.GetFillForegroundRgb(headerCell).ShouldBe([0xDC, 0xDC, 0xDC]);
headerCell.CellStyle.Alignment.ShouldBe(HorizontalAlignment.Center);
}
[Fact]
public void CriteriaTimestamp_MatchesLegacyFormat()
{
var sheet = _workbook.GetSheet("Search Criteria")!;
var timestamp = ExcelTestHelpers.GetCellText(sheet, 4, 2);
timestamp.ShouldContain("Jan 15, 2024");
timestamp.ShouldContain("02:30:45");
timestamp.ShouldContain("EST");
}
}
@@ -1,89 +1,90 @@
using ClosedXML.Excel;
using JdeScoping.ExcelIO.Tests.Fixtures;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests.Integration;
public class SearchResultsSheetTests : IClassFixture<WithResultsFixture>
{
private readonly XLWorkbook _workbook;
private readonly IXLWorksheet _sheet;
private readonly List<string> _headers;
public SearchResultsSheetTests(WithResultsFixture fixture)
{
_workbook = fixture.Workbook;
_sheet = _workbook.Worksheet("Search Results");
_headers = ExcelTestHelpers.GetHeadersFromSheet(_sheet);
}
[Fact]
public void ColumnCount_Is19()
{
_headers.Count.ShouldBe(19);
}
[Fact]
public void ColumnHeaders_MatchExpected()
{
_headers.ShouldContain("Work Order Number");
_headers.ShouldContain("Work Order Branch Code");
_headers.ShouldContain("Lot Number");
_headers.ShouldContain("Item Number");
_headers.ShouldContain("Planning Family");
_headers.ShouldContain("Stocking Type");
_headers.ShouldContain("Order Quantity");
_headers.ShouldContain("Held Quantity");
_headers.ShouldContain("Scrapped Quantity");
_headers.ShouldContain("Shipped Quantity");
_headers.ShouldContain("Operation Step Branch Code");
_headers.ShouldContain("Operation Step");
_headers.ShouldContain("Operation Step Description");
_headers.ShouldContain("Function Operation Description");
_headers.ShouldContain("Operation Step Update Timestamp");
_headers.ShouldContain("Status Code");
_headers.ShouldContain("Status Description");
_headers.ShouldContain("Status Update Timestamp");
_headers.ShouldContain("Inclusion Reason");
}
[Fact]
public void ColumnOrder_MatchesSpec()
{
_headers[0].ShouldBe("Work Order Number");
_headers[1].ShouldBe("Work Order Branch Code");
_headers[2].ShouldBe("Lot Number");
_headers[3].ShouldBe("Item Number");
_headers[4].ShouldBe("Planning Family");
_headers[5].ShouldBe("Stocking Type");
_headers[6].ShouldBe("Order Quantity");
_headers[7].ShouldBe("Held Quantity");
_headers[8].ShouldBe("Scrapped Quantity");
_headers[9].ShouldBe("Shipped Quantity");
_headers[10].ShouldBe("Operation Step Branch Code");
_headers[11].ShouldBe("Operation Step");
_headers[12].ShouldBe("Operation Step Description");
_headers[13].ShouldBe("Function Operation Description");
_headers[14].ShouldBe("Operation Step Update Timestamp");
_headers[15].ShouldBe("Status Code");
_headers[16].ShouldBe("Status Description");
_headers[17].ShouldBe("Status Update Timestamp");
_headers[18].ShouldBe("Inclusion Reason");
}
[Fact]
public void TableStyle_IsLight18()
{
var table = _sheet.Tables.First();
table.Theme.ShouldBe(XLTableTheme.TableStyleLight18);
}
[Fact]
public void DataRow_ContainsExpectedValues()
{
_sheet.Cell(2, 1).Value.GetNumber().ShouldBe(12345);
_sheet.Cell(2, 3).Value.GetText().ShouldBe("LOT-001");
_sheet.Cell(2, 4).Value.GetText().ShouldBe("ITEM-001");
}
}
using JdeScoping.ExcelIO.Tests.Fixtures;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests.Integration;
public class SearchResultsSheetTests : IClassFixture<WithResultsFixture>
{
private readonly XSSFWorkbook _workbook;
private readonly ISheet _sheet;
private readonly List<string> _headers;
public SearchResultsSheetTests(WithResultsFixture fixture)
{
_workbook = fixture.Workbook;
_sheet = _workbook.GetSheet("Search Results")!;
_headers = ExcelTestHelpers.GetHeadersFromSheet(_sheet);
}
[Fact]
public void ColumnCount_Is19()
{
_headers.Count.ShouldBe(19);
}
[Fact]
public void ColumnHeaders_MatchExpected()
{
_headers.ShouldContain("Work Order Number");
_headers.ShouldContain("Work Order Branch Code");
_headers.ShouldContain("Lot Number");
_headers.ShouldContain("Item Number");
_headers.ShouldContain("Planning Family");
_headers.ShouldContain("Stocking Type");
_headers.ShouldContain("Order Quantity");
_headers.ShouldContain("Held Quantity");
_headers.ShouldContain("Scrapped Quantity");
_headers.ShouldContain("Shipped Quantity");
_headers.ShouldContain("Operation Step Branch Code");
_headers.ShouldContain("Operation Step");
_headers.ShouldContain("Operation Step Description");
_headers.ShouldContain("Function Operation Description");
_headers.ShouldContain("Operation Step Update Timestamp");
_headers.ShouldContain("Status Code");
_headers.ShouldContain("Status Description");
_headers.ShouldContain("Status Update Timestamp");
_headers.ShouldContain("Inclusion Reason");
}
[Fact]
public void ColumnOrder_MatchesSpec()
{
_headers[0].ShouldBe("Work Order Number");
_headers[1].ShouldBe("Work Order Branch Code");
_headers[2].ShouldBe("Lot Number");
_headers[3].ShouldBe("Item Number");
_headers[4].ShouldBe("Planning Family");
_headers[5].ShouldBe("Stocking Type");
_headers[6].ShouldBe("Order Quantity");
_headers[7].ShouldBe("Held Quantity");
_headers[8].ShouldBe("Scrapped Quantity");
_headers[9].ShouldBe("Shipped Quantity");
_headers[10].ShouldBe("Operation Step Branch Code");
_headers[11].ShouldBe("Operation Step");
_headers[12].ShouldBe("Operation Step Description");
_headers[13].ShouldBe("Function Operation Description");
_headers[14].ShouldBe("Operation Step Update Timestamp");
_headers[15].ShouldBe("Status Code");
_headers[16].ShouldBe("Status Description");
_headers[17].ShouldBe("Status Update Timestamp");
_headers[18].ShouldBe("Inclusion Reason");
}
[Fact]
public void TableStyle_IsLight18()
{
var table = ExcelTestHelpers.GetFirstTable(_sheet);
table.StyleName.ShouldBe("TableStyleLight18");
}
[Fact]
public void DataRow_ContainsExpectedValues()
{
ExcelTestHelpers.GetCellNumber(_sheet, 2, 1).ShouldBe(12345);
ExcelTestHelpers.GetCellText(_sheet, 2, 3).ShouldBe("LOT-001");
ExcelTestHelpers.GetCellText(_sheet, 2, 4).ShouldBe("ITEM-001");
}
}
@@ -8,10 +8,11 @@
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.2">
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="NPOI" Version="2.7.5" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
@@ -1,179 +1,171 @@
using ClosedXML.Excel;
using JdeScoping.ExcelIO.Parsing;
using Microsoft.Extensions.Logging.Abstractions;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests.Parsing;
public class ExcelParserServiceTests
{
private readonly ExcelParserService _service = new(NullLogger<ExcelParserService>.Instance);
[Fact]
public void ParseWorkOrders_ReturnsWorkOrderNumbers()
{
// Arrange
var excelData = CreateWorkOrderExcel([12345, 67890, 11111]);
// Act
using var stream = new MemoryStream(excelData);
var result = _service.ParseWorkOrders(stream);
// Assert
result.Count.ShouldBe(3);
result.ShouldContain(12345);
result.ShouldContain(67890);
result.ShouldContain(11111);
}
[Fact]
public void ParseWorkOrders_SkipsInvalidNumbers()
{
// Arrange
using var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Sheet1");
worksheet.Cell(1, 1).Value = "Work Order";
worksheet.Cell(2, 1).Value = "12345";
worksheet.Cell(3, 1).Value = "not-a-number";
worksheet.Cell(4, 1).Value = "67890";
using var ms = new MemoryStream();
workbook.SaveAs(ms);
ms.Position = 0;
// Act
var result = _service.ParseWorkOrders(ms);
// Assert
result.Count.ShouldBe(2);
}
[Fact]
public void ParseItems_ReturnsItemNumbers()
{
// Arrange
var excelData = CreateItemExcel(["ITEM-001", "ITEM-002"]);
// Act
using var stream = new MemoryStream(excelData);
var result = _service.ParseItems(stream);
// Assert
result.Count.ShouldBe(2);
result.ShouldContain("ITEM-001");
result.ShouldContain("ITEM-002");
}
[Fact]
public void ParseComponentLots_ReturnsLotViewModels()
{
// Arrange
var excelData = CreateComponentLotExcel([("LOT001", "ITEM-001"), ("LOT002", "ITEM-002")]);
// Act
using var stream = new MemoryStream(excelData);
var result = _service.ParseComponentLots(stream);
// Assert
result.Count.ShouldBe(2);
result[0].LotNumber.ShouldBe("LOT001");
result[0].ItemNumber.ShouldBe("ITEM-001");
}
[Fact]
public void ParsePartOperations_ReturnsPartOperations()
{
// Arrange
var excelData = CreatePartOperationExcel([("ITEM-001", "100", "MIS001", "A")]);
// Act
using var stream = new MemoryStream(excelData);
var result = _service.ParsePartOperations(stream);
// Assert
result.Count.ShouldBe(1);
result[0].ItemNumber.ShouldBe("ITEM-001");
result[0].OperationNumber.ShouldBe("100");
result[0].MisNumber.ShouldBe("MIS001");
result[0].MisRevision.ShouldBe("A");
}
[Fact]
public void ParsePartOperations_TruncatesDecimalOperationNumbers()
{
// Arrange
var excelData = CreatePartOperationExcel([("ITEM-001", "100.5", "MIS001", "A")]);
// Act
using var stream = new MemoryStream(excelData);
var result = _service.ParsePartOperations(stream);
// Assert
result[0].OperationNumber.ShouldBe("100");
}
private static byte[] CreateWorkOrderExcel(long[] workOrderNumbers)
{
using var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Sheet1");
worksheet.Cell(1, 1).Value = "Work Order Number";
for (var i = 0; i < workOrderNumbers.Length; i++)
{
worksheet.Cell(i + 2, 1).Value = workOrderNumbers[i];
}
using var stream = new MemoryStream();
workbook.SaveAs(stream);
return stream.ToArray();
}
private static byte[] CreateItemExcel(string[] itemNumbers)
{
using var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Sheet1");
worksheet.Cell(1, 1).Value = "Item Number";
for (var i = 0; i < itemNumbers.Length; i++)
{
worksheet.Cell(i + 2, 1).Value = itemNumbers[i];
}
using var stream = new MemoryStream();
workbook.SaveAs(stream);
return stream.ToArray();
}
private static byte[] CreateComponentLotExcel((string LotNumber, string ItemNumber)[] lots)
{
using var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Sheet1");
worksheet.Cell(1, 1).Value = "Lot Number";
worksheet.Cell(1, 2).Value = "Item Number";
for (var i = 0; i < lots.Length; i++)
{
worksheet.Cell(i + 2, 1).Value = lots[i].LotNumber;
worksheet.Cell(i + 2, 2).Value = lots[i].ItemNumber;
}
using var stream = new MemoryStream();
workbook.SaveAs(stream);
return stream.ToArray();
}
private static byte[] CreatePartOperationExcel((string ItemNumber, string OpNumber, string MisNumber, string MisRevision)[] operations)
{
using var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Sheet1");
worksheet.Cell(1, 1).Value = "Item Number";
worksheet.Cell(1, 2).Value = "Operation Number";
worksheet.Cell(1, 3).Value = "MIS Number";
worksheet.Cell(1, 4).Value = "MIS Revision";
for (var i = 0; i < operations.Length; i++)
{
worksheet.Cell(i + 2, 1).Value = operations[i].ItemNumber;
worksheet.Cell(i + 2, 2).Value = operations[i].OpNumber;
worksheet.Cell(i + 2, 3).Value = operations[i].MisNumber;
worksheet.Cell(i + 2, 4).Value = operations[i].MisRevision;
}
using var stream = new MemoryStream();
workbook.SaveAs(stream);
return stream.ToArray();
}
}
using JdeScoping.ExcelIO.Parsing;
using Microsoft.Extensions.Logging.Abstractions;
using NPOI.XSSF.UserModel;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests.Parsing;
public class ExcelParserServiceTests
{
private readonly ExcelParserService _service = new(NullLogger<ExcelParserService>.Instance);
[Fact]
public void ParseWorkOrders_ReturnsWorkOrderNumbers()
{
var excelData = CreateWorkOrderExcel([12345, 67890, 11111]);
using var stream = new MemoryStream(excelData);
var result = _service.ParseWorkOrders(stream);
result.Count.ShouldBe(3);
result.ShouldContain(12345);
result.ShouldContain(67890);
result.ShouldContain(11111);
}
[Fact]
public void ParseWorkOrders_SkipsInvalidNumbers()
{
using var workbook = new XSSFWorkbook();
var worksheet = workbook.CreateSheet("Sheet1");
worksheet.CreateRow(0).CreateCell(0).SetCellValue("Work Order");
worksheet.CreateRow(1).CreateCell(0).SetCellValue("12345");
worksheet.CreateRow(2).CreateCell(0).SetCellValue("not-a-number");
worksheet.CreateRow(3).CreateCell(0).SetCellValue("67890");
using var ms = new MemoryStream();
workbook.Write(ms, leaveOpen: true);
ms.Position = 0;
var result = _service.ParseWorkOrders(ms);
result.Count.ShouldBe(2);
}
[Fact]
public void ParseItems_ReturnsItemNumbers()
{
var excelData = CreateItemExcel(["ITEM-001", "ITEM-002"]);
using var stream = new MemoryStream(excelData);
var result = _service.ParseItems(stream);
result.Count.ShouldBe(2);
result.ShouldContain("ITEM-001");
result.ShouldContain("ITEM-002");
}
[Fact]
public void ParseComponentLots_ReturnsLotViewModels()
{
var excelData = CreateComponentLotExcel([("LOT001", "ITEM-001"), ("LOT002", "ITEM-002")]);
using var stream = new MemoryStream(excelData);
var result = _service.ParseComponentLots(stream);
result.Count.ShouldBe(2);
result[0].LotNumber.ShouldBe("LOT001");
result[0].ItemNumber.ShouldBe("ITEM-001");
}
[Fact]
public void ParsePartOperations_ReturnsPartOperations()
{
var excelData = CreatePartOperationExcel([("ITEM-001", "100", "MIS001", "A")]);
using var stream = new MemoryStream(excelData);
var result = _service.ParsePartOperations(stream);
result.Count.ShouldBe(1);
result[0].ItemNumber.ShouldBe("ITEM-001");
result[0].OperationNumber.ShouldBe("100");
result[0].MisNumber.ShouldBe("MIS001");
result[0].MisRevision.ShouldBe("A");
}
[Fact]
public void ParsePartOperations_TruncatesDecimalOperationNumbers()
{
var excelData = CreatePartOperationExcel([("ITEM-001", "100.5", "MIS001", "A")]);
using var stream = new MemoryStream(excelData);
var result = _service.ParsePartOperations(stream);
result[0].OperationNumber.ShouldBe("100");
}
private static byte[] CreateWorkOrderExcel(long[] workOrderNumbers)
{
using var workbook = new XSSFWorkbook();
var worksheet = workbook.CreateSheet("Sheet1");
worksheet.CreateRow(0).CreateCell(0).SetCellValue("Work Order Number");
for (var i = 0; i < workOrderNumbers.Length; i++)
{
worksheet.CreateRow(i + 1).CreateCell(0).SetCellValue(workOrderNumbers[i]);
}
using var stream = new MemoryStream();
workbook.Write(stream, leaveOpen: true);
return stream.ToArray();
}
private static byte[] CreateItemExcel(string[] itemNumbers)
{
using var workbook = new XSSFWorkbook();
var worksheet = workbook.CreateSheet("Sheet1");
worksheet.CreateRow(0).CreateCell(0).SetCellValue("Item Number");
for (var i = 0; i < itemNumbers.Length; i++)
{
worksheet.CreateRow(i + 1).CreateCell(0).SetCellValue(itemNumbers[i]);
}
using var stream = new MemoryStream();
workbook.Write(stream, leaveOpen: true);
return stream.ToArray();
}
private static byte[] CreateComponentLotExcel((string LotNumber, string ItemNumber)[] lots)
{
using var workbook = new XSSFWorkbook();
var worksheet = workbook.CreateSheet("Sheet1");
var header = worksheet.CreateRow(0);
header.CreateCell(0).SetCellValue("Lot Number");
header.CreateCell(1).SetCellValue("Item Number");
for (var i = 0; i < lots.Length; i++)
{
var row = worksheet.CreateRow(i + 1);
row.CreateCell(0).SetCellValue(lots[i].LotNumber);
row.CreateCell(1).SetCellValue(lots[i].ItemNumber);
}
using var stream = new MemoryStream();
workbook.Write(stream, leaveOpen: true);
return stream.ToArray();
}
private static byte[] CreatePartOperationExcel((string ItemNumber, string OpNumber, string MisNumber, string MisRevision)[] operations)
{
using var workbook = new XSSFWorkbook();
var worksheet = workbook.CreateSheet("Sheet1");
var header = worksheet.CreateRow(0);
header.CreateCell(0).SetCellValue("Item Number");
header.CreateCell(1).SetCellValue("Operation Number");
header.CreateCell(2).SetCellValue("MIS Number");
header.CreateCell(3).SetCellValue("MIS Revision");
for (var i = 0; i < operations.Length; i++)
{
var row = worksheet.CreateRow(i + 1);
row.CreateCell(0).SetCellValue(operations[i].ItemNumber);
row.CreateCell(1).SetCellValue(operations[i].OpNumber);
row.CreateCell(2).SetCellValue(operations[i].MisNumber);
row.CreateCell(3).SetCellValue(operations[i].MisRevision);
}
using var stream = new MemoryStream();
workbook.Write(stream, leaveOpen: true);
return stream.ToArray();
}
}
@@ -1,96 +1,80 @@
using ClosedXML.Excel;
using JdeScoping.ExcelIO.Templates;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests.Templates;
public class ExcelTemplateServiceTests
{
private readonly ExcelTemplateService _service = new();
[Fact]
public void GenerateSingleColumn_CreatesValidExcel()
{
// Arrange
var data = new[] { 12345L, 67890L };
// Act
var result = _service.GenerateSingleColumn(data, "Work Order Number");
// Assert
result.ShouldNotBeNull();
result.Length.ShouldBeGreaterThan(0);
// Verify content
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
var worksheet = workbook.Worksheet(1);
worksheet.Cell(1, 1).GetString().ShouldBe("Work Order Number");
worksheet.Cell(2, 1).GetString().ShouldBe("12345");
worksheet.Cell(3, 1).GetString().ShouldBe("67890");
}
[Fact]
public void GenerateMultiColumn_CreatesValidExcel()
{
// Arrange
var data = new[]
{
new object?[] { "ITEM-001", "Description 1" },
new object?[] { "ITEM-002", "Description 2" }
};
var headers = new[] { "Item Number", "Description" };
// Act
var result = _service.GenerateMultiColumn(data, headers);
// Assert
result.ShouldNotBeNull();
result.Length.ShouldBeGreaterThan(0);
// Verify content
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
var worksheet = workbook.Worksheet(1);
worksheet.Cell(1, 1).GetString().ShouldBe("Item Number");
worksheet.Cell(1, 2).GetString().ShouldBe("Description");
worksheet.Cell(2, 1).GetString().ShouldBe("ITEM-001");
worksheet.Cell(2, 2).GetString().ShouldBe("Description 1");
}
[Fact]
public void GenerateSingleColumn_HandlesEmptyData()
{
// Act
var result = _service.GenerateSingleColumn(Array.Empty<string>(), "Header");
// Assert
result.ShouldNotBeNull();
result.Length.ShouldBeGreaterThan(0);
}
[Fact]
public void GenerateMultiColumn_HandlesNullValues()
{
// Arrange
var data = new[]
{
new object?[] { "ITEM-001", null }
};
var headers = new[] { "Item", "Value" };
// Act
var result = _service.GenerateMultiColumn(data, headers);
// Assert
result.ShouldNotBeNull();
using var stream = new MemoryStream(result);
using var workbook = new XLWorkbook(stream);
var worksheet = workbook.Worksheet(1);
worksheet.Cell(2, 2).GetString().ShouldBe(string.Empty);
}
}
using JdeScoping.ExcelIO.Templates;
using JdeScoping.ExcelIO.Tests.Fixtures;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests.Templates;
public class ExcelTemplateServiceTests
{
private readonly ExcelTemplateService _service = new();
[Fact]
public void GenerateSingleColumn_CreatesValidExcel()
{
var data = new[] { 12345L, 67890L };
var result = _service.GenerateSingleColumn(data, "Work Order Number");
result.ShouldNotBeNull();
result.Length.ShouldBeGreaterThan(0);
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
var worksheet = workbook.GetSheetAt(0);
ExcelTestHelpers.GetCellText(worksheet, 1, 1).ShouldBe("Work Order Number");
ExcelTestHelpers.GetCellText(worksheet, 2, 1).ShouldBe("12345");
ExcelTestHelpers.GetCellText(worksheet, 3, 1).ShouldBe("67890");
}
[Fact]
public void GenerateMultiColumn_CreatesValidExcel()
{
var data = new[]
{
new object?[] { "ITEM-001", "Description 1" },
new object?[] { "ITEM-002", "Description 2" }
};
var headers = new[] { "Item Number", "Description" };
var result = _service.GenerateMultiColumn(data, headers);
result.ShouldNotBeNull();
result.Length.ShouldBeGreaterThan(0);
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
var worksheet = workbook.GetSheetAt(0);
ExcelTestHelpers.GetCellText(worksheet, 1, 1).ShouldBe("Item Number");
ExcelTestHelpers.GetCellText(worksheet, 1, 2).ShouldBe("Description");
ExcelTestHelpers.GetCellText(worksheet, 2, 1).ShouldBe("ITEM-001");
ExcelTestHelpers.GetCellText(worksheet, 2, 2).ShouldBe("Description 1");
}
[Fact]
public void GenerateSingleColumn_HandlesEmptyData()
{
var result = _service.GenerateSingleColumn(Array.Empty<string>(), "Header");
result.ShouldNotBeNull();
result.Length.ShouldBeGreaterThan(0);
}
[Fact]
public void GenerateMultiColumn_HandlesNullValues()
{
var data = new[]
{
new object?[] { "ITEM-001", null }
};
var headers = new[] { "Item", "Value" };
var result = _service.GenerateMultiColumn(data, headers);
result.ShouldNotBeNull();
using var workbook = ExcelTestHelpers.OpenWorkbook(result);
var worksheet = workbook.GetSheetAt(0);
ExcelTestHelpers.GetCellText(worksheet, 2, 2).ShouldBe(string.Empty);
}
}
@@ -1,80 +1,78 @@
using ClosedXML.Excel;
using JdeScoping.ExcelIO.Formatting;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests;
public class WorksheetProtectorTests
{
[Fact]
public void ApplyProtection_ProtectsWorksheet()
{
using var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Test");
WorksheetProtector.ApplyProtection(worksheet, "TestPassword");
worksheet.Protection.IsProtected.ShouldBeTrue();
}
[Fact]
public void ApplyProtection_AllowsSpecifiedOperations()
{
using var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Test");
WorksheetProtector.ApplyProtection(worksheet, "TestPassword");
// Check that specified operations are allowed
worksheet.Protection.AllowedElements.HasFlag(XLSheetProtectionElements.DeleteColumns).ShouldBeTrue();
worksheet.Protection.AllowedElements.HasFlag(XLSheetProtectionElements.DeleteRows).ShouldBeTrue();
worksheet.Protection.AllowedElements.HasFlag(XLSheetProtectionElements.AutoFilter).ShouldBeTrue();
worksheet.Protection.AllowedElements.HasFlag(XLSheetProtectionElements.FormatCells).ShouldBeTrue();
worksheet.Protection.AllowedElements.HasFlag(XLSheetProtectionElements.FormatColumns).ShouldBeTrue();
worksheet.Protection.AllowedElements.HasFlag(XLSheetProtectionElements.FormatRows).ShouldBeTrue();
worksheet.Protection.AllowedElements.HasFlag(XLSheetProtectionElements.SelectLockedCells).ShouldBeTrue();
worksheet.Protection.AllowedElements.HasFlag(XLSheetProtectionElements.SelectUnlockedCells).ShouldBeTrue();
worksheet.Protection.AllowedElements.HasFlag(XLSheetProtectionElements.EditObjects).ShouldBeTrue();
worksheet.Protection.AllowedElements.HasFlag(XLSheetProtectionElements.Sort).ShouldBeTrue();
}
[Fact]
public void ApplyProtection_AllowsDeleteRows()
{
using var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Test");
WorksheetProtector.ApplyProtection(worksheet, "TestPassword");
// DeleteRows should be allowed
worksheet.Protection.AllowedElements.HasFlag(XLSheetProtectionElements.DeleteRows).ShouldBeTrue();
}
[Fact]
public void ApplyCriteriaProtection_ProtectsWorksheet()
{
using var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Test");
WorksheetProtector.ApplyCriteriaProtection(worksheet, "CriteriaPassword");
worksheet.Protection.IsProtected.ShouldBeTrue();
}
[Fact]
public void UnlockExtensionArea_UnlocksSpecifiedRange()
{
using var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Test");
// First, set some cells to locked (default)
worksheet.Range(1, 1, 10, 5).Style.Protection.Locked = true;
WorksheetProtector.UnlockExtensionArea(worksheet, 10, 5, 100, 100);
// Extension area should be unlocked
var extensionCell = worksheet.Cell(1, 6);
extensionCell.Style.Protection.Locked.ShouldBeFalse();
}
}
using JdeScoping.ExcelIO.Formatting;
using JdeScoping.ExcelIO.Tests.Fixtures;
using NPOI.XSSF.UserModel;
using Shouldly;
using Xunit;
namespace JdeScoping.ExcelIO.Tests;
public class WorksheetProtectorTests
{
[Fact]
public void ApplyProtection_ProtectsWorksheet()
{
using var workbook = new XSSFWorkbook();
var worksheet = (XSSFSheet)workbook.CreateSheet("Test");
WorksheetProtector.ApplyProtection(worksheet, "TestPassword");
worksheet.IsSheetLocked.ShouldBeTrue();
}
[Fact]
public void ApplyProtection_AllowsSpecifiedOperations()
{
using var workbook = new XSSFWorkbook();
var worksheet = (XSSFSheet)workbook.CreateSheet("Test");
WorksheetProtector.ApplyProtection(worksheet, "TestPassword");
worksheet.IsDeleteColumnsLocked.ShouldBeFalse();
worksheet.IsDeleteRowsLocked.ShouldBeFalse();
worksheet.IsAutoFilterLocked.ShouldBeFalse();
worksheet.IsFormatCellsLocked.ShouldBeFalse();
worksheet.IsFormatColumnsLocked.ShouldBeFalse();
worksheet.IsFormatRowsLocked.ShouldBeFalse();
worksheet.IsSelectLockedCellsLocked.ShouldBeFalse();
worksheet.IsSelectUnlockedCellsLocked.ShouldBeFalse();
worksheet.IsObjectsLocked.ShouldBeFalse();
worksheet.IsSortLocked.ShouldBeFalse();
}
[Fact]
public void ApplyProtection_AllowsDeleteRows()
{
using var workbook = new XSSFWorkbook();
var worksheet = (XSSFSheet)workbook.CreateSheet("Test");
WorksheetProtector.ApplyProtection(worksheet, "TestPassword");
worksheet.IsDeleteRowsLocked.ShouldBeFalse();
}
[Fact]
public void ApplyCriteriaProtection_ProtectsWorksheet()
{
using var workbook = new XSSFWorkbook();
var worksheet = (XSSFSheet)workbook.CreateSheet("Test");
WorksheetProtector.ApplyCriteriaProtection(worksheet, "CriteriaPassword");
worksheet.IsSheetLocked.ShouldBeTrue();
}
[Fact]
public void UnlockExtensionArea_UnlocksSpecifiedRange()
{
using var workbook = new XSSFWorkbook();
var worksheet = (XSSFSheet)workbook.CreateSheet("Test");
WorksheetProtector.UnlockExtensionArea(worksheet, 10, 5, 100, 100);
var extensionStyle = worksheet.GetColumnStyle(5);
extensionStyle.IsLocked.ShouldBeFalse();
var extensionCell = ExcelTestHelpers.GetCell(worksheet, 1, 6)!;
extensionCell.CellStyle.IsLocked.ShouldBeFalse();
}
}