using FluentAssertions; using Marathon.Application.Export; namespace Marathon.Application.Tests.Export; public sealed class CsvTests { [Theory] [InlineData("plain", "plain")] [InlineData("", "")] [InlineData("a,b", "\"a,b\"")] [InlineData("he said \"hi\"", "\"he said \"\"hi\"\"\"")] [InlineData("line1\nline2", "\"line1\nline2\"")] public void Escape_QuotesOnlyWhenNeeded(string input, string expected) { Csv.Escape(input).Should().Be(expected); } [Fact] public void Escape_Null_IsEmpty() { Csv.Escape(null).Should().BeEmpty(); } [Fact] public void Document_JoinsHeaderAndRows_WithCrlf_AndEscapes() { var csv = Csv.Document( new[] { "Name", "Note" }, new[] { (IReadOnlyList)new[] { "Kelly", "ok" }, new[] { "Flat, fixed", "say \"hi\"" }, }); csv.Should().Be( "Name,Note\r\n" + "Kelly,ok\r\n" + "\"Flat, fixed\",\"say \"\"hi\"\"\"\r\n"); } [Theory] [InlineData("=cmd|'/c calc'!A1")] [InlineData("+1+1")] [InlineData("-2+3")] [InlineData("@SUM(A1)")] [InlineData("\ttab")] [InlineData("\rcr")] public void NeutralizeFormula_PrefixesLeadingFormulaTriggers(string dangerous) { Csv.NeutralizeFormula(dangerous).Should().Be("'" + dangerous); } [Theory] [InlineData("Home vs Away")] [InlineData("normal note")] [InlineData("3-1 win")] [InlineData("")] public void NeutralizeFormula_LeavesSafeValuesUntouched(string safe) { Csv.NeutralizeFormula(safe).Should().Be(safe); } [Fact] public void NeutralizeFormula_Null_IsEmpty() { Csv.NeutralizeFormula(null).Should().BeEmpty(); } }