using System.Text.Json; using MBN_STOCK_WEBVIEW.LegacyApplication; namespace MBN_STOCK_WEBVIEW.LegacyBridge.Tests; public sealed class LegacyComparisonBridgeTests { [Theory] [InlineData("search-comparison-domestic", "{\"query\":\"삼성\"}", typeof(LegacySearchComparisonDomesticIntent))] [InlineData("search-comparison-world", "{\"query\":\"APPLE\"}", typeof(LegacySearchComparisonWorldIntent))] [InlineData("select-comparison-domestic", "{\"selectionId\":\"comparison-domestic-0001-0001\"}", typeof(LegacySelectComparisonDomesticIntent))] [InlineData("select-comparison-world", "{\"selectionId\":\"comparison-world-0001-0001\"}", typeof(LegacySelectComparisonWorldIntent))] [InlineData("select-comparison-fixed", "{\"targetId\":\"kospi\"}", typeof(LegacySelectComparisonFixedIntent))] [InlineData("choose-comparison-domestic", "{\"selectionId\":\"comparison-domestic-0001-0001\"}", typeof(LegacyChooseComparisonDomesticIntent))] [InlineData("choose-comparison-world", "{\"selectionId\":\"comparison-world-0001-0001\"}", typeof(LegacyChooseComparisonWorldIntent))] [InlineData("choose-comparison-fixed", "{\"targetId\":\"kospi\"}", typeof(LegacyChooseComparisonFixedIntent))] [InlineData("swap-comparison-targets", "{}", typeof(LegacySwapComparisonTargetsIntent))] [InlineData("clear-comparison-targets", "{}", typeof(LegacyClearComparisonTargetsIntent))] [InlineData("add-comparison-pair", "{}", typeof(LegacyAddComparisonPairIntent))] [InlineData("import-legacy-comparison-pairs", "{}", typeof(LegacyImportComparisonPairsIntent))] [InlineData("select-comparison-pair", "{\"rowId\":\"comparison-pair-00000001\"}", typeof(LegacySelectComparisonPairIntent))] [InlineData("move-comparison-pair", "{\"direction\":\"up\"}", typeof(LegacyMoveComparisonPairIntent))] [InlineData("delete-selected-comparison-pair", "{}", typeof(LegacyDeleteSelectedComparisonPairIntent))] [InlineData("delete-all-comparison-pairs", "{}", typeof(LegacyDeleteAllComparisonPairsIntent))] [InlineData("activate-comparison-action", "{\"actionId\":\"comparison-candle\"}", typeof(LegacyActivateComparisonActionIntent))] public void ComparisonIntentsAreClosed(string type, string payload, Type expected) { Assert.True(LegacyBridgeProtocol.TryParseIntent( $"{{\"type\":\"{type}\",\"payload\":{payload}}}", out var intent, out _)); Assert.IsType(expected, intent); } [Fact] public void ComparisonIntentRejectsUnexpectedOrRawIdentityFields() { Assert.False(LegacyBridgeProtocol.TryParseIntent( "{\"type\":\"choose-comparison-domestic\",\"payload\":{\"selectionId\":\"comparison-domestic-0001-0001\",\"stockCode\":\"005930\"}}", out _, out _)); Assert.False(LegacyBridgeProtocol.TryParseIntent( "{\"type\":\"move-comparison-pair\",\"payload\":{\"direction\":\"sideways\"}}", out _, out _)); Assert.False(LegacyBridgeProtocol.TryParseIntent( "{\"type\":\"import-legacy-comparison-pairs\",\"payload\":{\"path\":\"C:\\\\untrusted.dat\"}}", out _, out _)); } [Fact] public void State_projects_truncation_and_isolated_row_diagnostics() { var domestic = new LegacyComparisonSearchSnapshot( string.Empty, LegacyComparisonSearchStatus.Ready, Array.Empty(), null, 0, string.Empty); var world = new LegacyComparisonSearchSnapshot( string.Empty, LegacyComparisonSearchStatus.Ready, [new LegacyComparisonTargetView( "comparison-world-0001-0001", "ACME, INC", "US · ACME", LegacyComparisonTargetKind.WorldStock) { CanSelect = false, UnavailableReason = "쉼표 이름은 선택할 수 없습니다." }], null, 1_474, string.Empty) { IsTruncated = true, IsolatedInvalidRowCount = 16, DeferredUnsafeRowCount = 1 }; var comparison = new LegacyComparisonWorkflowSnapshot( 1, false, domestic, world, Array.Empty(), null, null, null, Array.Empty(), null, Array.Empty(), string.Empty, LegacyOperatorStatusKind.Neutral) { CanImportLegacyPairs = true, LastImport = new LegacyComparisonImportReceipt( new string('A', 64), 8, 7, 1, 8, DateTimeOffset.Parse("2026-07-22T12:00:00+09:00")) }; var snapshot = new LegacyOperatorSnapshot( 1, string.Empty, Array.Empty(), null, Array.Empty(), Array.Empty(), null, string.Empty, LegacyOperatorStatusKind.Neutral, Comparison: comparison); using var document = JsonDocument.Parse(LegacyBridgeProtocol.SerializeState(snapshot)); var projected = document.RootElement .GetProperty("payload") .GetProperty("comparison") .GetProperty("worldSearch"); Assert.True(projected.GetProperty("isTruncated").GetBoolean()); Assert.Equal(16, projected.GetProperty("isolatedInvalidRowCount").GetInt32()); Assert.Equal(1, projected.GetProperty("deferredUnsafeRowCount").GetInt32()); Assert.Equal(1_474, projected.GetProperty("totalRowCount").GetInt32()); var deferred = projected.GetProperty("results")[0]; Assert.False(deferred.GetProperty("canSelect").GetBoolean()); var comparisonWire = document.RootElement .GetProperty("payload") .GetProperty("comparison"); Assert.True(comparisonWire.GetProperty("canImportLegacyPairs").GetBoolean()); Assert.Equal(7, comparisonWire.GetProperty("lastImport") .GetProperty("addedPairCount").GetInt32()); Assert.Contains( "쉼표", deferred.GetProperty("unavailableReason").GetString(), StringComparison.Ordinal); } }