Replace import_orders (insert-per-run) with orders table (one row per order, upsert on conflict). Eliminates dedup CTE on every dashboard query and prevents unbounded row growth at 4-500 orders/sync. Key changes: - orders table: PK order_number, upsert via ON CONFLICT DO UPDATE; COALESCE preserves id_comanda once set; times_skipped auto-increments - sync_run_orders: lightweight junction (sync_run_id, order_number) replaces sync_run_id column on orders - order_items: PK changed to (order_number, sku), INSERT OR IGNORE - Auto-migration in init_sqlite(): import_orders → orders on first boot, old table renamed to import_orders_bak - /api/dashboard/orders: period_days param (3/7/30/0=all, default 7) - Dashboard: period selector buttons in orders card header - start.sh: stop existing process on port 5003 before restart; remove --reload (broken on WSL2 /mnt/e/) - Add invoice_service, E2E Playwright tests, Oracle package updates Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
83 lines
2.1 KiB
Python
83 lines
2.1 KiB
Python
"""
|
|
Playwright E2E test fixtures.
|
|
Starts the FastAPI app on a random port with test SQLite, no Oracle.
|
|
"""
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
import pytest
|
|
import subprocess
|
|
import time
|
|
import socket
|
|
|
|
|
|
def _free_port():
|
|
with socket.socket() as s:
|
|
s.bind(('', 0))
|
|
return s.getsockname()[1]
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def app_url():
|
|
"""Start the FastAPI app as a subprocess and return its URL."""
|
|
port = _free_port()
|
|
tmpdir = tempfile.mkdtemp()
|
|
sqlite_path = os.path.join(tmpdir, "e2e_test.db")
|
|
|
|
env = os.environ.copy()
|
|
env.update({
|
|
"FORCE_THIN_MODE": "true",
|
|
"SQLITE_DB_PATH": sqlite_path,
|
|
"ORACLE_DSN": "dummy",
|
|
"ORACLE_USER": "dummy",
|
|
"ORACLE_PASSWORD": "dummy",
|
|
"JSON_OUTPUT_DIR": tmpdir,
|
|
})
|
|
|
|
api_dir = os.path.join(os.path.dirname(__file__), "..", "..")
|
|
proc = subprocess.Popen(
|
|
[sys.executable, "-m", "uvicorn", "app.main:app", "--host", "127.0.0.1", "--port", str(port)],
|
|
cwd=api_dir,
|
|
env=env,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
)
|
|
|
|
# Wait for startup (up to 15 seconds)
|
|
url = f"http://127.0.0.1:{port}"
|
|
for _ in range(30):
|
|
try:
|
|
import urllib.request
|
|
urllib.request.urlopen(f"{url}/health", timeout=1)
|
|
break
|
|
except Exception:
|
|
time.sleep(0.5)
|
|
else:
|
|
proc.kill()
|
|
stdout, stderr = proc.communicate()
|
|
raise RuntimeError(
|
|
f"App failed to start on port {port}.\n"
|
|
f"STDOUT: {stdout.decode()[-2000:]}\n"
|
|
f"STDERR: {stderr.decode()[-2000:]}"
|
|
)
|
|
|
|
yield url
|
|
|
|
proc.terminate()
|
|
try:
|
|
proc.wait(timeout=5)
|
|
except subprocess.TimeoutExpired:
|
|
proc.kill()
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def seed_test_data(app_url):
|
|
"""
|
|
Seed SQLite with test data via API calls.
|
|
|
|
Oracle is unavailable in E2E tests — only SQLite-backed pages are
|
|
fully functional. This fixture exists as a hook for future seeding;
|
|
for now E2E tests validate UI structure on empty-state pages.
|
|
"""
|
|
return app_url
|