using System.Text.Json; using MBN_STOCK_WEBVIEW.LegacyApplication; using MBN_STOCK_WEBVIEW.LegacyBridge; namespace MBN_STOCK_WEBVIEW.LegacyBridge.Tests; public sealed class LegacyOperatorSettingsBridgeTests { [Theory] [InlineData("design", LegacyOperatorFolderKind.Design)] [InlineData("resource", LegacyOperatorFolderKind.Resource)] [InlineData("background", LegacyOperatorFolderKind.Background)] public void ParseChooseFolder_AcceptsOnlyClosedFolderKinds( string wireKind, LegacyOperatorFolderKind expectedKind) { var json = $"{{\"type\":\"choose-operator-folder\",\"payload\":{{\"kind\":\"{wireKind}\"}}}}"; Assert.True(LegacyBridgeProtocol.TryParseIntent(json, out var parsed, out var error)); Assert.Null(error); var intent = Assert.IsType(parsed); Assert.Equal(expectedKind, intent.Kind); } [Theory] [InlineData("design", LegacyOperatorFolderKind.Design)] [InlineData("resource", LegacyOperatorFolderKind.Resource)] [InlineData("background", LegacyOperatorFolderKind.Background)] public void ParseResetFolder_AcceptsOnlyClosedFolderKinds( string wireKind, LegacyOperatorFolderKind expectedKind) { var json = $"{{\"type\":\"reset-operator-folder\",\"payload\":{{\"kind\":\"{wireKind}\"}}}}"; Assert.True(LegacyBridgeProtocol.TryParseIntent(json, out var parsed, out var error)); Assert.Null(error); var intent = Assert.IsType(parsed); Assert.Equal(expectedKind, intent.Kind); } [Theory] [InlineData(true)] [InlineData(false)] public void ParseNavigationExpanded_RequiresAnExactBoolean(bool expanded) { var json = $"{{\"type\":\"set-operator-navigation-expanded\",\"payload\":{{\"expanded\":{expanded.ToString().ToLowerInvariant()}}}}}"; Assert.True(LegacyBridgeProtocol.TryParseIntent(json, out var parsed, out var error)); Assert.Null(error); var intent = Assert.IsType(parsed); Assert.Equal(expanded, intent.Expanded); } [Theory] [InlineData( "system", "automatic", "stockCut", LegacyOperatorColorTheme.System, LegacyOperatorViewMode.Automatic, LegacyOperatorStartWorkspace.StockCut)] [InlineData( "light", "compact", "lastWorkspace", LegacyOperatorColorTheme.Light, LegacyOperatorViewMode.Compact, LegacyOperatorStartWorkspace.LastWorkspace)] [InlineData( "dark", "cards", "stockCut", LegacyOperatorColorTheme.Dark, LegacyOperatorViewMode.Cards, LegacyOperatorStartWorkspace.StockCut)] public void ParseAppearance_AcceptsOnlyClosedValues( string colorTheme, string viewMode, string startWorkspace, LegacyOperatorColorTheme expectedColorTheme, LegacyOperatorViewMode expectedViewMode, LegacyOperatorStartWorkspace expectedStartWorkspace) { var json = $"{{\"type\":\"set-operator-appearance\",\"payload\":{{\"viewMode\":\"{viewMode}\",\"startWorkspace\":\"{startWorkspace}\",\"colorTheme\":\"{colorTheme}\"}}}}"; Assert.True(LegacyBridgeProtocol.TryParseIntent(json, out var parsed, out var error)); Assert.Null(error); var intent = Assert.IsType(parsed); Assert.Equal(expectedColorTheme, intent.ColorTheme); Assert.Equal(expectedViewMode, intent.ViewMode); Assert.Equal(expectedStartWorkspace, intent.StartWorkspace); } [Theory] [InlineData("{\"type\":\"choose-operator-folder\",\"payload\":{}}")] [InlineData("{\"type\":\"choose-operator-folder\",\"payload\":{\"kind\":\"settings\"}}")] [InlineData("{\"type\":\"choose-operator-folder\",\"payload\":{\"kind\":\"Design\"}}")] [InlineData("{\"type\":\"choose-operator-folder\",\"payload\":{\"kind\":1}}")] [InlineData("{\"type\":\"choose-operator-folder\",\"payload\":{\"kind\":\"design\",\"path\":\"C:\\\\Cuts\"}}")] [InlineData("{\"type\":\"reset-operator-folder\",\"payload\":{\"kind\":\"resource\",\"extra\":false}}")] [InlineData("{\"type\":\"reset-operator-folder\",\"payload\":{\"kind\":\"resource\",\"kind\":\"design\"}}")] [InlineData("{\"type\":\"set-operator-navigation-expanded\",\"payload\":{}}")] [InlineData("{\"type\":\"set-operator-navigation-expanded\",\"payload\":{\"expanded\":\"true\"}}")] [InlineData("{\"type\":\"set-operator-navigation-expanded\",\"payload\":{\"expanded\":true,\"path\":\"C:\\\\Config\"}}")] [InlineData("{\"type\":\"set-operator-appearance\",\"payload\":{\"colorTheme\":\"system\",\"viewMode\":\"automatic\"}}")] [InlineData("{\"type\":\"set-operator-appearance\",\"payload\":{\"colorTheme\":\"mbn\",\"viewMode\":\"automatic\",\"startWorkspace\":\"stockCut\"}}")] [InlineData("{\"type\":\"set-operator-appearance\",\"payload\":{\"colorTheme\":\"system\",\"viewMode\":\"grid\",\"startWorkspace\":\"stockCut\"}}")] [InlineData("{\"type\":\"set-operator-appearance\",\"payload\":{\"colorTheme\":\"system\",\"viewMode\":\"automatic\",\"startWorkspace\":\"other\"}}")] [InlineData("{\"type\":\"set-operator-appearance\",\"payload\":{\"colorTheme\":\"system\",\"viewMode\":\"automatic\",\"startWorkspace\":\"stockCut\",\"extra\":true}}")] [InlineData("{\"type\":\"set-operator-appearance\",\"payload\":{\"colorTheme\":\"system\",\"colorTheme\":\"dark\",\"viewMode\":\"automatic\",\"startWorkspace\":\"stockCut\"}}")] public void ParseSettingsIntents_RejectsMissingUnknownAndExtraAuthority(string json) { Assert.False(LegacyBridgeProtocol.TryParseIntent(json, out var parsed, out _)); Assert.Null(parsed); } [Fact] public void SerializeState_ProjectsOperatorSettingsWithClosedWireNames() { var settings = new LegacyOperatorSettingsSnapshot( 17, new LegacyOperatorFolderSnapshot("D:\\Design", true, true, "사용 가능"), new LegacyOperatorFolderSnapshot("D:\\Resource", true, false, "Res 폴더 없음"), new LegacyOperatorFolderSnapshot("앱 기본 배경", false, true, "기본값"), NavigationExpanded: false, ColorTheme: LegacyOperatorColorTheme.Dark, ViewMode: LegacyOperatorViewMode.Cards, StartWorkspace: LegacyOperatorStartWorkspace.LastWorkspace, RestartRequired: true, Message: "재시작 후 적용됩니다.", MessageKind: LegacyOperatorSettingsMessageKind.Warning, AppVersion: "0.1.0.0", OracleState: "연결됨", MariaState: "연결 끊김", DatabasePollingSeconds: 10); var json = LegacyBridgeProtocol.SerializeState( CreateSnapshot(), operatorSettings: settings); using var document = JsonDocument.Parse(json); var projected = document.RootElement .GetProperty("payload") .GetProperty("operatorSettings"); Assert.Equal(17, projected.GetProperty("revision").GetInt64()); Assert.Equal("D:\\Design", projected.GetProperty("design") .GetProperty("displayName").GetString()); Assert.True(projected.GetProperty("design").GetProperty("isCustom").GetBoolean()); Assert.True(projected.GetProperty("design").GetProperty("isValid").GetBoolean()); Assert.Equal("사용 가능", projected.GetProperty("design") .GetProperty("status").GetString()); Assert.False(projected.GetProperty("resource").GetProperty("isValid").GetBoolean()); Assert.False(projected.GetProperty("background").GetProperty("isCustom").GetBoolean()); Assert.False(projected.GetProperty("navigationExpanded").GetBoolean()); Assert.Equal("dark", projected.GetProperty("colorTheme").GetString()); Assert.Equal("cards", projected.GetProperty("viewMode").GetString()); Assert.Equal( "lastWorkspace", projected.GetProperty("startWorkspace").GetString()); Assert.True(projected.GetProperty("restartRequired").GetBoolean()); Assert.Equal("재시작 후 적용됩니다.", projected.GetProperty("message").GetString()); Assert.Equal("warning", projected.GetProperty("messageKind").GetString()); Assert.Equal("0.1.0.0", projected.GetProperty("appVersion").GetString()); Assert.Equal("연결됨", projected.GetProperty("oracleState").GetString()); Assert.Equal("연결 끊김", projected.GetProperty("mariaState").GetString()); Assert.Equal(10, projected.GetProperty("databasePollingSeconds").GetInt32()); Assert.False(projected.TryGetProperty("Design", out _)); Assert.False(projected.GetProperty("design").TryGetProperty("DisplayName", out _)); } [Fact] public void SerializeState_UsesNullOperatorSettingsWhenNotProvided() { using var document = JsonDocument.Parse( LegacyBridgeProtocol.SerializeState(CreateSnapshot())); Assert.Equal( JsonValueKind.Null, document.RootElement.GetProperty("payload") .GetProperty("operatorSettings").ValueKind); } private static LegacyOperatorSnapshot CreateSnapshot() => new( 1, string.Empty, [], null, [], [], null, string.Empty, LegacyOperatorStatusKind.Neutral); }