using System.Text; using FluentAssertions; using AxCopilot.Handlers; using Xunit; namespace AxCopilot.Tests.Handlers; public class ClipboardTransformTests { // ─── 대소문자 변환 ──────────────────────────────────────────────────────── [Fact] public void Upper_ConvertsToUppercase() { ClipboardHandler.ExecuteBuiltin("$upper", "hello world").Should().Be("HELLO WORLD"); } [Fact] public void Lower_ConvertsToLowercase() { ClipboardHandler.ExecuteBuiltin("$lower", "HELLO WORLD").Should().Be("hello world"); } // ─── Base64 ────────────────────────────────────────────────────────────── [Fact] public void Base64Encode_EncodesCorrectly() { ClipboardHandler.ExecuteBuiltin("$b64e", "hello").Should().Be("aGVsbG8="); } [Fact] public void Base64Decode_DecodesCorrectly() { ClipboardHandler.ExecuteBuiltin("$b64d", "aGVsbG8=").Should().Be("hello"); } [Fact] public void Base64_RoundTrip() { var original = "AX Copilot 테스트"; var encoded = ClipboardHandler.ExecuteBuiltin("$b64e", original)!; var decoded = ClipboardHandler.ExecuteBuiltin("$b64d", encoded); decoded.Should().Be(original); } // ─── URL 인코딩 ────────────────────────────────────────────────────────── [Fact] public void UrlEncode_EncodesSpaces() { ClipboardHandler.ExecuteBuiltin("$urle", "hello world").Should().Be("hello%20world"); } [Fact] public void UrlDecode_DecodesSpaces() { ClipboardHandler.ExecuteBuiltin("$urld", "hello%20world").Should().Be("hello world"); } [Fact] public void UrlEncode_EncodesSpecialChars() { var result = ClipboardHandler.ExecuteBuiltin("$urle", "a=b&c=d"); result.Should().Be("a%3Db%26c%3Dd"); } [Fact] public void UrlDecode_DecodesSpecialChars() { var result = ClipboardHandler.ExecuteBuiltin("$urld", "a%3Db%26c%3Dd"); result.Should().Be("a=b&c=d"); } // ─── 문자열 처리 ───────────────────────────────────────────────────────── [Fact] public void Trim_RemovesLeadingTrailingWhitespace() { ClipboardHandler.ExecuteBuiltin("$trim", " hello ").Should().Be("hello"); } [Fact] public void Trim_PreservesInternalSpaces() { ClipboardHandler.ExecuteBuiltin("$trim", " hello world ").Should().Be("hello world"); } [Fact] public void Lines_RemovesEmptyLines() { var input = "a\n\nb\n \nc"; var result = ClipboardHandler.ExecuteBuiltin("$lines", input); result.Should().NotContain("\n\n"); result.Should().Contain("a"); result.Should().Contain("b"); result.Should().Contain("c"); } [Fact] public void Lines_TrimsEachLine() { var input = " hello \n world "; var result = ClipboardHandler.ExecuteBuiltin("$lines", input)!; result.Should().Contain("hello"); result.Should().Contain("world"); result.Should().NotContain(" hello"); } // ─── 타임스탬프 ────────────────────────────────────────────────────────── [Fact] public void Timestamp_EpochZero_Returns1970() { var result = ClipboardHandler.ExecuteBuiltin("$ts", "0"); result.Should().NotBeNullOrEmpty(); result.Should().Contain("1970"); } [Fact] public void Timestamp_ValidEpoch_ReturnsDateString() { var result = ClipboardHandler.ExecuteBuiltin("$ts", "1700000000"); result.Should().NotBeNullOrEmpty(); result.Should().MatchRegex(@"\d{4}-\d{2}-\d{2}"); } [Fact] public void Timestamp_InvalidInput_ReturnsNull() { ClipboardHandler.ExecuteBuiltin("$ts", "not-a-number").Should().BeNull(); } [Fact] public void Epoch_ValidDate_ReturnsNumber() { var result = ClipboardHandler.ExecuteBuiltin("$epoch", "1970-01-01"); result.Should().NotBeNullOrEmpty(); long.TryParse(result, out _).Should().BeTrue(); } [Fact] public void Epoch_InvalidDate_ReturnsNull() { ClipboardHandler.ExecuteBuiltin("$epoch", "not-a-date").Should().BeNull(); } // ─── JSON 포맷팅 ───────────────────────────────────────────────────────── [Fact] public void JsonFormat_MinifiedJson_AddsIndentation() { var result = ClipboardHandler.ExecuteBuiltin("$json", "{\"a\":1,\"b\":2}"); result.Should().NotBeNullOrEmpty(); result.Should().Contain("\n"); result.Should().Contain("\"a\""); } [Fact] public void JsonFormat_AlreadyFormatted_StaysValid() { var formatted = "{\n \"a\": 1\n}"; var result = ClipboardHandler.ExecuteBuiltin("$json", formatted); result.Should().NotBeNullOrEmpty(); result.Should().Contain("\"a\""); } [Fact] public void JsonFormat_InvalidJson_ReturnsOriginal() { var invalid = "not json"; var result = ClipboardHandler.ExecuteBuiltin("$json", invalid); result.Should().Be(invalid); // 파싱 실패 시 원본 반환 } // ─── 마크다운 제거 ─────────────────────────────────────────────────────── [Fact] public void StripMarkdown_RemovesBold() { var result = ClipboardHandler.ExecuteBuiltin("$md", "**bold text**"); result.Should().NotContain("**"); result.Should().Contain("bold text"); } [Fact] public void StripMarkdown_RemovesItalic() { var result = ClipboardHandler.ExecuteBuiltin("$md", "*italic*"); result.Should().NotContain("*italic*"); result.Should().Contain("italic"); } [Fact] public void StripMarkdown_RemovesInlineCode() { var result = ClipboardHandler.ExecuteBuiltin("$md", "`code`"); result.Should().NotContain("`"); result.Should().Contain("code"); } // ─── 알 수 없는 키 ────────────────────────────────────────────────────── [Fact] public void UnknownKey_ReturnsNull() { ClipboardHandler.ExecuteBuiltin("$unknown", "input").Should().BeNull(); } [Fact] public void EmptyKey_ReturnsNull() { ClipboardHandler.ExecuteBuiltin("", "input").Should().BeNull(); } }