Files
Aislo/resources/tester/spreadsheet/test_spreadsheet_d_input.py
T
eomsangdonandClaude Opus 5.5 52d441e3a9 fix(spreadsheet): 칸 다루기 전수 점검 흠 11 고침 — 고름 테두리 · 채우기 손잡이 · 틀고정 빈 띠 · 입력 형식 · 잘라 붙이기 옮김
- 격자: 고름을 옮겨도 옛 활성 칸 파란 테두리가 남던 것 · 채우기 손잡이가 범위 오른아래가 아니라
  활성 칸 모서리에 있던 것(여러 범위 · 읽기 전용 카드에서는 손잡이 없음) · 틀 고정 뒤 본문 판
  아래 · 오른 끝(틀 고정 크기만큼)이 안 그려져 비던 것(보이는 행열을 틀 고정만큼 밀어 잼) ·
  오류 칸 글자색을 테마 토큰으로(어두운 테마 대비 2.7 → 5.0)
- 입력: `50%` → 0% 형식 · `1,234.5` → #,##0.0 형식을 함께 붙임(엑셀 · 되돌리기 한 번) · 식의
  함수 · 참조 · 참거짓을 대문자로 · 닫는 괄호만 모자라면 채움 · 「식이 덜 끝남」 알림 글
- 클립보드: 잘라낸 칸을 같은 문서에 처음 붙이면 `옮기기` 로 — 그 칸을 가리키던 식도 따라감
  (전에는 식이 0 · 빈 칸을 가리킴) · 그 사이 잘라낸 자리에 새로 쓰면 보통 붙여넣기
- 시험: test_spreadsheet_saved_values.py(면적 · 재료 저장본 102 권 서버 재계산 = 저장 계산값) ·
  d_input 에 형식 · 대문자 · 괄호 규칙 · ORCA M02 면적산출 편집 창 목록 38 항목 재실행 통과

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BYN9gMie8e6pXzSxJNb6Xt
2026-09-28 22:20:35 +09:00

131 lines
3.3 KiB
Python

# -*- coding: utf-8 -*-
"""스프레드시트 D 입력 — 고름 · 입력 글 규칙 · 참조 가리키기 자리 · 채우기 끌기 목표(엑셀 동작 기준).
Node 도우미(helper_spreadsheet_d.cjs)가 TS 를 풀어 돌리고 JSON 을 줌 — 남의 몫이 빈 몸이면 가짜 부품.
화면 조작(한글 첫 글자 · 수식 입력줄 · 끌기)은 harness_spreadsheet_d.html 을 ORCA 로.
"""
import json
import os
import subprocess
import pytest
HERE = os.path.dirname(os.path.abspath(__file__))
@pytest.fixture(scope="module")
def r():
proc = subprocess.run(
["node", os.path.join(HERE, "helper_spreadsheet_d.cjs")],
capture_output=True,
text=True,
encoding="utf-8",
timeout=60,
)
assert proc.returncode == 0, proc.stderr
return json.loads(proc.stdout)
def test_merge_selection(r):
assert r["mergeClick"] == "C4|C4:F4"
assert r["mergeMove"] == ["G4|G4", "C4|C4:F4", "B4|B4"]
assert r["colHead"] == "A:H" # 걸친 병합(A1:H1 · C3:F3 · A6:G6)만큼 늘림
def test_shift_ctrl_arrows(r):
assert r["shiftExtend"] == ["A4|A4:B4", "A4|A4:F4", "A4|A4:B4", "A4|A4:B5"]
assert r["ctrlJump"] == ["A6|A6:G6", "A1048576|A1048576", "A6|A6:G6"]
assert r["hiddenSkip"] == ["K1"]
assert r["usedEnd"] == "J6"
def test_cycle_in_selection(r):
assert r["cycleEnter"] == ["K12", "L11", "L12", "K11"]
assert r["cycleTab"] == ["L11", "K12", "L12"]
assert r["cycleSingle"] is None
def test_text_to_cell(r):
got = r["textToCell"]
assert [c.get("값", c.get("식")) for c in got] == [
12,
1234.5,
0.5,
-1000,
True,
"=12",
"=",
"A1+1",
None,
"1,23",
"abc",
]
assert "식" in got[7] and all(c["서식"] == 4 for c in got)
assert r["textToCellNoStyle"] is None
def test_cell_to_text(r):
assert r["cellToText"] == ["'=12", "'12", "abc", "1.5", "FALSE", "=A1*2", ""]
def test_pointing(r):
assert r["insertable"] == [True, True, False, True, True, True, False, False]
assert r["highlights"] == ["s1:A1:0", "s1:B2:C3:1", "s1:A1:0", "s2:B1:2"]
def test_fill_target(r):
assert r["fill"] == [
["B2:C10", None],
["B2:G4", None],
["B2:B4", "C2:C4"],
["B2:C3", "B4:C4"],
]
def test_formula_hint(r):
assert r["hint"] == [
{"prefix": "su"},
{"prefix": "ro"},
None,
{"func": "ROUND", "arg": 1},
{"func": "SUM", "arg": 2},
{"func": "IF", "arg": 1},
None,
]
def test_abs_cycle_and_fold(r):
assert r["abs"] == [
"=$A$1+B2",
"=A$1+B2",
"=$A1+B2",
"=A1+B2",
"=SUM(Sheet2!$A$1:$B$3)|21",
None,
None,
]
assert r["foldSkip"] == "L5"
def test_links_follow_rows_cols(r):
# 행 넣기 → 밀림 · 연결 칸 열 지움 → 빠짐 · 되돌리기 → 제자리
assert r["links"] == ["L:B7,W:D5", "L:B7", "L:B7,W:D5", "L:B5,W:D3", "D1"]
def test_typed_format(r):
assert r["typedFormat"] == ["0%", "0.0%", "#,##0.0", "#,##0", None, None, None]
def test_upper_formula(r):
assert r["upperFormula"] == [
"SUM(A1:B2)+ROUND(C3,0)",
"'시트 a'!A1*TRUE",
'"abc"&A1',
"내이름*2",
]
def test_close_parens(r):
assert r["closeParens"] == ["=(1+2)", "=SUM(1,ROUND(2,0))", None, None, '=")"&(1)']