- 카드 = 로직 이름 · 결과단위 묶음 아래 입력 줄(이름 · 설명 · 단위 · 고르기/범위 · 자동값 흐리게) + 자리 상자 · 처음은 모두 안 씀 - 저장 = 집계표 [저장]에 이어 PUT input-links(자동저장 없음) · 읽기만 층은 상자 잠금 - 면적 · 재료로 고른 입력은 그 시트 알약 줄에 「로직 이름 · 입력 이름」 · 자재 모드에서도 [목록에서 빼기] 막음(고정) - 알약 줄 시험을 합계 줄 아래 자리에 맞춤(25-0 뒤 어긋난 것) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D2nUMUMTsqm93PbQtipo6c
152 lines
4.3 KiB
Python
152 lines
4.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_links_bar_sits_under_statusbar():
|
|
# 알약 막대 = 시트 · 합계 줄(상태줄) 아래 맨 끝 · 자재 고르기 창은 막대 위로 엶
|
|
with open(
|
|
os.path.join(HERE, "../../../A00_Common/spreadsheet/spreadsheet_links.ts"), encoding="utf-8"
|
|
) as f:
|
|
src = f.read()
|
|
assert 'ctx.root.querySelector(":scope > .ss-statusbar")?.after(bar)' in src
|
|
assert "pick.style.bottom = `${o.bottom - bar.getBoundingClientRect().top + 4}px`" in src
|
|
|
|
|
|
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)']
|
|
|
|
|
|
def test_spill(r):
|
|
sp = r["spill"]
|
|
assert sp["left"] is None # 오른 칸(3)에 값 → 못 넘침
|
|
assert sp["leftFree"] == [0, 100, 2, 4, 0, 0] # 빈 칸 둘 덮음
|
|
assert sp["right"] == [100, 0, 0, 2, 0, 0]
|
|
assert sp["center"] == [40, 40, 1, 3, 0, 0]
|
|
assert sp["centerBlocked"] == [40, 40, 1, 2, 0, 40] # 오른쪽 막힘 → 오른쪽 반 잘라 냄
|
|
assert sp["fits"] is None
|
|
assert sp["edge"] is None # 판 끝(그린 칸 없음)
|