using AvParser.Core.Parsing; namespace AvParser.Core.Tests; /// Collection helpers so the tests read as assertions rather than as loops. internal static class ParserTestExtensions { /// /// Drains a parse into memory, using the ambient test cancellation token. /// /// /// Deliberately takes no : every call site would otherwise have /// to pass TestContext.Current.CancellationToken to satisfy xUnit1051. Cancellation /// behaviour is covered by driving directly. /// internal static async Task<(List Records, List Errors)> CollectAsync( this ITextParser parser, string input, IProgress? progress = null ) { var records = new List(); var errors = new List(); await foreach (var outcome in parser.ParseAsync(input, progress, TestContext.Current.CancellationToken)) { if (outcome.IsSuccess) { records.Add(outcome.Value!); } else { errors.Add(outcome.Error); } } return (records, errors); } /// Reads a field by name, failing the test if it is absent. internal static string Field(this ParsedRecord record, string name) => record[name] ?? throw new InvalidOperationException($"Field '{name}' is missing."); /// Builds a delimited document with a header plus data rows. internal static string DelimitedDocument(int rows) => string.Join('\n', Enumerable.Range(0, rows + 1).Select(i => i == 0 ? "id,name" : $"{i},row{i}")); }