using Microsoft.VisualStudio.TestTools.UnitTesting; using SheetMe.Core.Catalog; using SheetMe.Core.Models; namespace SheetMe.Core.Tests; /// /// 미리보기 클릭 — 라디오 배타가 직계 부모 안에서만 일어나는지가 핵심이다. /// 레거시 RadioButton 은 GroupName 이 없어 부모 컨테이너가 문항 단위이고, /// 운영 서식의 라디오 98.96% 가 그 형태다. /// [TestClass] public class PreviewCheckStateTests { #region Helpers private static ControlElement Radio(string id, bool checkedOn = false) { var element = new ControlElement { Id = id, Type = "RadioButton" }; element.Props.SetText("Checked", checkedOn ? "True" : "False"); return element; } private static ControlElement Check(string id, bool checkedOn = false) { var element = new ControlElement { Id = id, Type = "CheckBox" }; element.Props.SetText("Checked", checkedOn ? "True" : "False"); return element; } #endregion #region Tests [TestMethod] public void 누르지_않았으면_서식의_기본값을_그대로_읽는다() { var state = new PreviewCheckState(); Assert.IsTrue(state.IsChecked(Radio("a", checkedOn: true))); Assert.IsFalse(state.IsChecked(Radio("b"))); Assert.IsFalse(state.HasAny); } [TestMethod] public void 라디오를_누르면_같은_부모의_다른_라디오가_꺼진다() { var first = Radio("a", checkedOn: true); var second = Radio("b"); var third = Radio("c"); var siblings = new[] { first, second, third }; var state = new PreviewCheckState(); state.Click(second, siblings); Assert.IsFalse(state.IsChecked(first)); Assert.IsTrue(state.IsChecked(second)); Assert.IsFalse(state.IsChecked(third)); } [TestMethod] public void 다른_부모의_라디오는_영향을_받지_않는다() { // 패널 1개 = 문항 1개. 옆 문항의 답이 지워지면 그 서식은 못 쓴다. var mine = Radio("a"); var neighbour = Radio("z", checkedOn: true); var state = new PreviewCheckState(); state.Click(mine, new[] { mine, Radio("b") }); Assert.IsTrue(state.IsChecked(neighbour)); } [TestMethod] public void 라디오는_다시_눌러도_꺼지지_않는다() { // WinForms 라디오는 자기를 눌러 해제하는 동작이 없다 — 끄는 것은 형제를 누르는 것뿐이다. var radio = Radio("a"); var state = new PreviewCheckState(); state.Click(radio, new[] { radio }); state.Click(radio, new[] { radio }); Assert.IsTrue(state.IsChecked(radio)); } [TestMethod] public void 체크박스는_누를_때마다_반전한다() { var box = Check("a"); var state = new PreviewCheckState(); state.Click(box, new[] { box }); Assert.IsTrue(state.IsChecked(box)); state.Click(box, new[] { box }); Assert.IsFalse(state.IsChecked(box)); } [TestMethod] public void 체크박스는_형제_라디오를_끄지_않는다() { // 한 패널에 체크박스와 라디오가 섞인 서식이 있다(기타 항목 + 자유 입력). var radio = Radio("r", checkedOn: true); var box = Check("c"); var state = new PreviewCheckState(); state.Click(box, new[] { radio, box }); Assert.IsTrue(state.IsChecked(radio)); Assert.IsTrue(state.IsChecked(box)); } [TestMethod] public void 기본값이_체크인_체크박스를_누르면_풀린다() { var box = Check("a", checkedOn: true); var state = new PreviewCheckState(); state.Click(box, new[] { box }); Assert.IsFalse(state.IsChecked(box)); } [TestMethod] public void 읽기전용은_눌리지_않는다() { // 레거시는 PreventEditing=True 면 OnClick 을 무시한다 — 값 대입만 가능하다. var locked = Radio("a"); locked.Props.SetText("PreventEditing", "True"); var mate = Radio("b", checkedOn: true); var state = new PreviewCheckState(); state.Click(locked, new[] { locked, mate }); Assert.IsFalse(PreviewCheckState.IsClickable(locked)); Assert.IsFalse(state.IsChecked(locked)); Assert.IsTrue(state.IsChecked(mate)); Assert.IsFalse(state.HasAny); } [TestMethod] public void 누를_수_있는_타입은_체크류뿐이다() { Assert.IsTrue(PreviewCheckState.IsClickable(Radio("a"))); Assert.IsTrue(PreviewCheckState.IsClickable(Check("b"))); Assert.IsFalse(PreviewCheckState.IsClickable(new ControlElement { Id = "c", Type = "Label" })); Assert.IsFalse(PreviewCheckState.IsClickable(new ControlElement { Id = "d", Type = "TextBox" })); Assert.IsFalse(PreviewCheckState.IsClickable(new ControlElement { Id = "e", Type = "Panel" })); } [TestMethod] public void 초기화하면_서식의_기본값으로_돌아간다() { var first = Radio("a", checkedOn: true); var second = Radio("b"); var state = new PreviewCheckState(); state.Click(second, new[] { first, second }); state.Clear(); Assert.IsFalse(state.HasAny); Assert.IsTrue(state.IsChecked(first)); Assert.IsFalse(state.IsChecked(second)); } #endregion }