미리보기가 거짓말을 멈춘다, 그리고 9번째 컨트롤이 1번째를 덮지 않는다
3단계 시작 — 실사용 버그 두 건. <b>① 미리보기·인쇄가 인쇄 필터를 무시하고 있었다.</b> 레거시 런타임은 인쇄에서 이렇게 걸러낸다 — If Me.Visible = False OrElse mbPrintOutPut = False Then Return False 그 문장이 ControlRegistry.cs:17 에 인용까지 되어 있는데, 렌더 경로가 두 키를 아무도 읽지 않았다. 대신 걸러낸 것은 ControlElement.Hidden 뿐이고 그건 [JsonIgnore] 디자이너 전용 플래그다 (주석에도 "레거시 Visible 과 별개"라고 적혀 있다). 그래서 인스펙터에서 '인쇄 출력'을 꺼도 미리보기에 그대로 나왔다 — 서식을 저장하기 전에 결과를 확인할 유일한 수단이 거짓말을 하고 있었다. <b>키 이름이 타입마다 다르다.</b> 라벨만 소문자 visible 이다 (Label.vb 가 Shadows Property visible 로 Control.Visible 을 가리고 직렬화기가 그림자를 쓴다). 운영에서 소문자 58,864건(99.7%) 대 대문자 196건이다. 그래서 관용으로 둘 다 읽지 않는다 — 타입이 선언한 키를 카탈로그에서 찾아 그것만 읽는다. 둘 다 읽으면 대문자 Visible=False 인 라벨이 우리 인쇄에서만 빠지고, 그건 호환이 아니라 새 차이다. 모르는 값과 없는 키는 인쇄한다 — 내용을 조용히 빼는 것이 조용히 넣는 것보다 나쁘다. 캔버스는 그대로 다 보여 준다. 편집 중인 것을 못 보면 고칠 수 없다. --db-render 는 이 경로를 쓰지 않아 종이 렌더 md5 는 불변이다(확인했다). <b>② 팔레트 즉시 배치가 9번째부터 겹쳤다.</b> (page.Controls.Count % 8) * 16 이라 두 가지가 틀렸다 — 9번째가 1번째와 정확히 같은 자리에 떨어지고, 하나 지우고 다시 놓으면 지운 자리로 갔다. 단조 증가 카운터로 바꿨다. 계단은 종이를 벗어나기 전에 옆으로 비킨다. <b>순수 함수 테스트만으로는 배선을 증명하지 못한다.</b> PrintFilter 단위 테스트 8건은 판정이 옳다는 것만 말한다. 렌더 경로가 그 판정을 부르는지는 다른 문제이고, 이 앱에서 "코드는 맞아 보이는데 화면은 다른" 일이 이번 세션에만 세 번 있었다. 그래서 --edit-smoke 에서 BuildPageVisual 의 자식 수를 실제로 세는 검사 3건을 더했다. 게이트: 테스트 285/285(신규 8), --edit-smoke 0실패(신규 5), --dialog-shots 넘침 0(대조군 4/4), --scale-budget 5/5, --maxrect 0실패, --cleartype 11/11, --modal-check 0실패, 빌드 경고 0, --db-smoke 1271건 diff 0, --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 동일. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
d55ca39e6a
commit
1b49f07dd9
@@ -0,0 +1,94 @@
|
||||
using SheetMe.Core.Catalog;
|
||||
using SheetMe.Core.Models;
|
||||
|
||||
namespace SheetMe.Core.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// 인쇄·미리보기 필터 고정.
|
||||
///
|
||||
/// 이 판정이 틀리면 <b>미리보기가 사용자에게 거짓말을 한다</b> — 인쇄에서 빠질 것을 보여 주거나,
|
||||
/// 나올 것을 감춘다. 저장 전에 결과를 확인할 유일한 수단이라 틀린 값이 곧 잘못된 서식이 된다.
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public sealed class PrintFilterTests
|
||||
{
|
||||
#region Methods
|
||||
private static ControlElement Make(string type, params (string Key, string Value)[] props)
|
||||
{
|
||||
var control = new ControlElement { Type = type, Id = type + "1" };
|
||||
foreach (var (key, value) in props)
|
||||
{
|
||||
control.Props.SetText(key, value);
|
||||
}
|
||||
return control;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void 아무_설정도_없으면_인쇄된다()
|
||||
{
|
||||
// 키가 없을 때의 기본값은 True 다(레거시 컨트롤 필드 선언 기준).
|
||||
// 여기서 false 를 내면 서식 대부분이 빈 종이로 나온다.
|
||||
Assert.IsTrue(PrintFilter.IsPrinted(Make("Label")));
|
||||
Assert.IsTrue(PrintFilter.IsPrinted(Make("TextBox")));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void 인쇄_출력을_끄면_빠진다()
|
||||
{
|
||||
Assert.IsFalse(PrintFilter.IsPrinted(Make("TextBox", ("PrintOutPut", "False"))));
|
||||
Assert.IsFalse(PrintFilter.IsPrinted(Make("Label", ("PrintOutPut", "False"))));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void 라벨은_소문자_visible_을_본다()
|
||||
{
|
||||
// Label.vb 가 Shadows Property visible 로 Control.Visible 을 가리고 직렬화기가 그림자를 쓴다.
|
||||
// 운영에서 소문자 58,864건(99.7%) 대 대문자 196건이다.
|
||||
Assert.AreEqual("visible", PrintFilter.VisibleKeyOf("Label"));
|
||||
Assert.IsFalse(PrintFilter.IsPrinted(Make("Label", ("visible", "False"))));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void 라벨의_대문자_Visible_은_인쇄를_막지_못한다()
|
||||
{
|
||||
// 레거시 런타임이 읽지 않는 키다. 관용으로 둘 다 읽으면 레거시가 인쇄하는 라벨을
|
||||
// 우리만 빼먹는 <b>새 차이</b>가 생긴다 — 그건 호환이 아니다.
|
||||
Assert.IsTrue(PrintFilter.IsPrinted(Make("Label", ("Visible", "False"))));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void 라벨이_아닌_타입은_대문자_Visible_을_본다()
|
||||
{
|
||||
Assert.AreEqual("Visible", PrintFilter.VisibleKeyOf("TextBox"));
|
||||
Assert.IsFalse(PrintFilter.IsPrinted(Make("TextBox", ("Visible", "False"))));
|
||||
// 그쪽에서는 소문자가 무시된다
|
||||
Assert.IsTrue(PrintFilter.IsPrinted(Make("TextBox", ("visible", "False"))));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void 대소문자와_공백을_관용으로_읽는다()
|
||||
{
|
||||
Assert.IsFalse(PrintFilter.IsPrinted(Make("TextBox", ("PrintOutPut", " false "))));
|
||||
Assert.IsFalse(PrintFilter.IsPrinted(Make("TextBox", ("PrintOutPut", "FALSE"))));
|
||||
Assert.IsFalse(PrintFilter.IsPrinted(Make("TextBox", ("PrintOutPut", "0"))));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void 해석할_수_없는_값은_인쇄한다()
|
||||
{
|
||||
// 내용을 조용히 빼는 것이 조용히 넣는 것보다 나쁘다 — 빠진 것은 아무도 못 본다.
|
||||
Assert.IsTrue(PrintFilter.IsPrinted(Make("TextBox", ("PrintOutPut", "알수없는값"))));
|
||||
Assert.IsTrue(PrintFilter.IsPrinted(Make("TextBox", ("PrintOutPut", ""))));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void 모르는_타입도_판정을_거부하지_않는다()
|
||||
{
|
||||
// 카탈로그에 없는 타입(Spread·MSign 처럼 미지원으로 살아남은 242건)이 들어와도
|
||||
// 예외를 던지지 않고 대문자 Visible 규약으로 판정한다.
|
||||
Assert.AreEqual("Visible", PrintFilter.VisibleKeyOf("Spread"));
|
||||
Assert.IsTrue(PrintFilter.IsPrinted(Make("Spread")));
|
||||
Assert.IsFalse(PrintFilter.IsPrinted(Make("Spread", ("PrintOutPut", "False"))));
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user