182 lines
8.0 KiB
Python
182 lines
8.0 KiB
Python
import os
|
|
from pathlib import Path
|
|
import pytest
|
|
from playwright.sync_api import sync_playwright
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
|
|
|
|
def test_edge_indexeddb_cache_and_tab_isolation_when_server_running():
|
|
with sync_playwright() as p:
|
|
browser = p.chromium.launch(channel="msedge", headless=True)
|
|
context = browser.new_context()
|
|
page1 = context.new_page()
|
|
try:
|
|
page1.goto("http://100.65.141.15:5175", timeout=5000)
|
|
except Exception:
|
|
pytest.skip("EST 5175 server not reachable")
|
|
|
|
page1.wait_for_function("() => Boolean(EstApp.state.project)")
|
|
|
|
# 1. 탭 1에서 프로젝트 이름 수정 및 비동기 캐시 완료 대기
|
|
page1.evaluate("""async () => {
|
|
EstApp.change(p => { p.name = '탭 1 프로젝트 수정'; });
|
|
await new Promise(r => setTimeout(r, 100));
|
|
}""")
|
|
|
|
# 2. 탭 1 새로고침 후 복원 확인
|
|
page1.reload()
|
|
page1.wait_for_function("() => Boolean(EstApp.state.project)")
|
|
name1 = page1.evaluate("EstApp.state.project.name")
|
|
assert name1 == "탭 1 프로젝트 수정"
|
|
|
|
# 3. 탭 2 독립 생성
|
|
page2 = context.new_page()
|
|
page2.goto("http://100.65.141.15:5175")
|
|
page2.wait_for_function("() => Boolean(EstApp.state.project)")
|
|
|
|
# 탭 2는 탭 1의 세션 스토리지를 공유하지 않고 독립적으로 시작
|
|
page2.evaluate("EstApp.change(p => { p.name = '탭 2 독자 프로젝트'; })")
|
|
name2 = page2.evaluate("EstApp.state.project.name")
|
|
assert name2 == "탭 2 독자 프로젝트"
|
|
|
|
# 4. 탭 1 다시 새로고침 시 탭 2에 의해 덮어써지지 않는지 확인
|
|
page1.reload()
|
|
page1.wait_for_function("() => Boolean(EstApp.state.project)")
|
|
assert page1.evaluate("EstApp.state.project.name") == "탭 1 프로젝트 수정"
|
|
|
|
browser.close()
|
|
|
|
|
|
def test_edge_indexeddb_large_main_estx_reload_restore_when_server_running():
|
|
sample = Path("C:/Dasansoft/Est Plus 2/Data/ProjectData/main.estx")
|
|
if not sample.exists():
|
|
sample = Path("resources/knowledge/original/원가계산/다산소프트/2026-07-main.estx")
|
|
if not sample.exists():
|
|
pytest.skip("main.estx sample not available")
|
|
|
|
with sync_playwright() as p:
|
|
browser = p.chromium.launch(channel="msedge", headless=True)
|
|
page = browser.new_page()
|
|
try:
|
|
page.goto("http://100.65.141.15:5175", timeout=5000)
|
|
except Exception:
|
|
pytest.skip("EST 5175 server not reachable")
|
|
|
|
page.wait_for_function("() => Boolean(EstApp.state.project)")
|
|
|
|
# 대용량 main.estx 업로드
|
|
page.locator("#open-file").set_input_files(str(sample))
|
|
page.wait_for_function(
|
|
"() => EstApp.state.project.tables.EstMainDat.length > 50", timeout=30000
|
|
)
|
|
|
|
# 수정 후 캐시 대기
|
|
page.evaluate("EstApp.change(p => { p.name = '대용량 main 수정본'; })")
|
|
page.wait_for_timeout(2000)
|
|
|
|
# 새로고침 후 복원 확인
|
|
page.reload()
|
|
page.wait_for_function("() => Boolean(EstApp.state.project)", timeout=30000)
|
|
|
|
restored_name = page.evaluate("EstApp.state.project.name")
|
|
restored_rows = page.evaluate("EstApp.state.project.tables?.EstMainDat?.length || 0")
|
|
|
|
assert restored_name == "대용량 main 수정본"
|
|
assert restored_rows > 50
|
|
|
|
# 대용량 캐시 저장 실패 시 안내 메시지 검증
|
|
notice = page.evaluate("""async () => {
|
|
const originalSave = EstApp.cache;
|
|
// 인위적으로 IndexedDB 에러 유발 모의
|
|
const db = await (new Promise(r => {
|
|
const req = indexedDB.open("est-independent-cache", 1);
|
|
req.onsuccess = () => r(req.result);
|
|
}));
|
|
// 읽기 전용 모드로 변경 시도하거나 sessionStorage 차단 모의
|
|
const res = await EstApp.cache("x".repeat(100));
|
|
return EstApp.state.notice;
|
|
}""")
|
|
assert isinstance(notice, str)
|
|
|
|
browser.close()
|
|
|
|
|
|
def test_edge_duplicate_tab_isolation_and_inheritance_when_server_running():
|
|
with sync_playwright() as p:
|
|
browser = p.chromium.launch(channel="msedge", headless=True)
|
|
context = browser.new_context()
|
|
page1 = context.new_page()
|
|
try:
|
|
page1.goto("http://100.65.141.15:5175", timeout=5000)
|
|
except Exception:
|
|
pytest.skip("EST 5175 server not reachable")
|
|
|
|
page1.wait_for_function("() => Boolean(EstApp.state.project)")
|
|
|
|
# 탭 1에서 이름 수정
|
|
page1.evaluate("""async () => {
|
|
EstApp.change(p => { p.name = '원래 탭 프로젝트'; });
|
|
await new Promise(r => setTimeout(r, 200));
|
|
}""")
|
|
|
|
tab1_id = page1.evaluate("sessionStorage.getItem('est-tab-instance-id')")
|
|
assert tab1_id == page1.evaluate("window.name")
|
|
|
|
# 브라우저의 "탭 복제(Duplicate Tab)" 시뮬레이션:
|
|
# Chromium 복제 탭은 이전 탭의 sessionStorage 전체를 복제받지만, window.name은 빈 문자열("")로 시작합니다.
|
|
tab1_data = page1.evaluate(f"sessionStorage.getItem('est-web-v2-working-{tab1_id}')")
|
|
page_dup = context.new_page()
|
|
# 1회성 init script: 최초 로드 시 복제 순간 모의 후 플래그로 1회만 동작하도록 제어
|
|
# 브라우저 실제 환경에서는 복제 순간 1회만 window.name이 빈 문자열이고 sessionStorage에 부모 데이터가 복제됨.
|
|
# page_dup.reload() 시 add_init_script가 다시 실행되어 window.name을 지우거나 부모 id로 되돌리는 현상을 방지하기 위해 sessionStorage 플래그 사용
|
|
page_dup.add_init_script(f"""
|
|
if (!sessionStorage.getItem('__test_cloned_injected')) {{
|
|
sessionStorage.setItem('__test_cloned_injected', '1');
|
|
sessionStorage.setItem('est-tab-instance-id', '{tab1_id}');
|
|
if ({"true" if tab1_data else "false"}) {{
|
|
sessionStorage.setItem('est-web-v2-working-{tab1_id}', {repr(tab1_data) if tab1_data else '""'});
|
|
}}
|
|
window.name = '';
|
|
}}
|
|
""")
|
|
page_dup.goto("http://100.65.141.15:5175")
|
|
page_dup.wait_for_function("() => Boolean(EstApp.state.project)")
|
|
|
|
# 1) 복제 탭은 부모 탭의 데이터('원래 탭 프로젝트')를 성공적으로 상속받았는지 확인
|
|
info = page_dup.evaluate("""() => {
|
|
return {
|
|
windowName: window.name,
|
|
sessionTab: sessionStorage.getItem('est-tab-instance-id'),
|
|
parentTabId: EstApp.parentTabId,
|
|
name: EstApp.state.project.name,
|
|
keys: Object.keys(sessionStorage)
|
|
};
|
|
}""")
|
|
print("DEBUG INFO:", info)
|
|
dup_name = info["name"]
|
|
assert dup_name == "원래 탭 프로젝트"
|
|
|
|
# 2) 복제 탭은 부모 탭과 다른 새 고유 인스턴스 ID를 발급받았는지 확인
|
|
dup_tab_id = page_dup.evaluate("sessionStorage.getItem('est-tab-instance-id')")
|
|
assert dup_tab_id != tab1_id
|
|
assert dup_tab_id == page_dup.evaluate("window.name")
|
|
|
|
# 3) 복제 탭에서 데이터를 독립적으로 수정했을 때 원래 탭에 영향을 주지 않는지 확인
|
|
page_dup.evaluate("""async () => {
|
|
EstApp.change(p => { p.name = '복제 탭에서만 변경'; });
|
|
await new Promise(r => setTimeout(r, 200));
|
|
}""")
|
|
|
|
# 원래 탭 1 새로고침 시 원래 데이터 유지 확인
|
|
page1.reload()
|
|
page1.wait_for_function("() => Boolean(EstApp.state.project)")
|
|
assert page1.evaluate("EstApp.state.project.name") == "원래 탭 프로젝트"
|
|
|
|
# 복제 탭 새로고침 시 복제 탭 변경 사항 유지 확인
|
|
page_dup.reload()
|
|
page_dup.wait_for_function("() => Boolean(EstApp.state.project)")
|
|
assert page_dup.evaluate("EstApp.state.project.name") == "복제 탭에서만 변경"
|
|
|
|
browser.close()
|