9.6 KiB
download_test_results_v1.0.py — dokumentace
Verze: 1.0 · Datum: 2026-05-29
Umístění: U:\PythonProject\Janssen\Covance_UCO3001\download_test_results_v1.0.py
1. Účel
Automatické stažení reportu Standard Test Results z portálu Labcorp Sponsor
Portal (xsp.labcorp.com) pro studii 77242113UCO3001 (interní study ID
36940). Skript projde všech 12 center studie, u každého vyexportuje grid
do CSV a uloží ho timestampovaný do adresáře Source/.
Pozn.: Stahuje se záložka Standard (ne Microbiology). URL končí
/standard-test-results.
2. Spuštění
U:\PythonProject\Janssen\.venv\Scripts\python.exe ^
U:\PythonProject\Janssen\Covance_UCO3001\download_test_results_v1.0.py
- Prohlížeč běží viditelně (
headless=False), maximalizovaný. - Používá persistent profile (
browser_profile/vedle skriptu) — session (přihlášení) přežívá mezi spuštěními.
3. Konfigurace (konstanty v hlavičce skriptu)
| Konstanta | Hodnota / význam |
|---|---|
EMAIL |
vbuzalka@its.jnj.com (login přes iMedidata/OKTA na xsp.covance.com) |
PASSWORD |
heslo k účtu (uložené přímo v kódu) |
LOGIN_URL |
https://xsp.covance.com/ — po přihlášení redirect na xsp.labcorp.com |
OUT_DIR |
U:\PythonProject\Janssen\Covance_UCO3001\Source |
PROFILE_DIR |
browser_profile/ vedle skriptu (persistent Chromium profil) |
STUDY |
36940 (interní study ID pro 77242113UCO3001) |
SITE_IDS |
seznam 12 interních čísel center — viz níže |
Interní čísla center (SITE_IDS)
930551, 930556, 930525, 930549, 930543, 930547,
930555, 930557, 930539, 930536, 930553, 930531
Zdroj: převzato z
download_equeries_report_v1.1.py(proměnnáSITES). Jsou to interní ID Labcorpu, nikoli čísla center typu CZ10001. V URL test-results se používá právě toto interní ID:…/test-results/{SITE_ID}/standard-test-results.
Generování REPORTS (DRY)
REPORTS se sestaví automaticky z SITE_IDS — URL i název souboru mají vzor
napsaný jen jednou. Přidání/odebrání centra = úprava seznamu SITE_IDS.
4. Výstupní soubory
Formát názvu (timestamp + popisný název):
{YYYY-MM-DD_HHMMSS} sponsor-study-36940-test-results-{SITE_ID}-standard.csv
Příklad:
2026-05-29_125710 sponsor-study-36940-test-results-930557-standard.csv
- Timestamp se generuje pro každý report zvlášť (v okamžiku exportu).
- Staré soubory se nikdy nemažou (verzování přes timestamp).
- Browser dočasný název se na disk neukládá —
expect_downloadzachytí download event asave_as()ho uloží pod naším názvem.
5. Průběh skriptu (kroky + logging)
Každý krok se loguje s časem ([HH:MM:SS], flush=True → vypisuje průběžně).
| Fáze | Co dělá |
|---|---|
| START | spustí prohlížeč |
| LOGIN | otevře login; pokud je session aktivní, přihlášení přeskočí |
| Pro každé centrum: | |
| KROK 1/5 | navigace na report URL |
| KROK 2/5 | čeká na řádky gridu .ag-row nebo prázdný grid; pak stabilizace počtu |
| KROK 3/5 | klik na viditelné tři tečky (more_horiz) → otevře menu |
| KROK 4/5 | klik na viditelné „Export to CSV" → zachytí download |
| KROK 5/5 | uloží soubor do OUT_DIR |
| KONEC | souhrn hotovo X/12 + seznam selhaných center |
Příklad výstupu
[12:56:35] START: prohlizec spusten.
[12:56:35] LOGIN: otviram login stranku...
[12:56:49] LOGIN: prihlaseni OK (...)
[12:56:49] === Centrum 930557 (studie 36940) ===
[12:56:59] KROK 1/5: stranka nactena (...)
[12:57:05] KROK 2/5: radky se objevily, cekam na stabilizaci poctu...
[12:57:06] ...kontrola #1: 153 radku
[12:57:08] ...kontrola #2: 153 radku
[12:57:10] KROK 2/5: data stabilni (153 radku v gridu).
[12:57:10] KROK 3/5: menu otevreno.
[12:57:11] KROK 4/5: stahovani zachyceno, ukladam soubor...
[12:57:11] KROK 5/5: HOTOVO -> ...\2026-05-29_125710 sponsor-study-36940-test-results-930557-standard.csv
6. Klíčové technické poznatky (PROČ to tak je) — ověřeno přes Chrome DevTools
Stránka test-results je Angular SPA s knihovnou MDL a tabulkou AG Grid. Tyto detaily byly zjištěny živou inspekcí DOM (Claude in Chrome MCP), ne hádáním:
6.1 Čekání na data = řádky AG Gridu
- Grid je
<covance-ag-grid>→<ag-grid-angular>(AG Grid). - Data jsou načtena, jakmile se objeví řádky
div.ag-row(count jde z 0 → N; pro 930557 to bylo 153 řádků). - Řádky jsou
position-absolute(virtuální render AG Gridu) → Playwright je nepovažuje za „visible". Proto:- ❌
wait_for_selector("div.ag-row")(defaultstate="visible") timeoutuje i když řádky existují. - ✅ čekat na přítomnost v DOM:
wait_for_function("() => document.querySelectorAll('div.ag-row').length > 0").
- ❌
- Stabilizace: počet řádků se čte opakovaně co 2 s, dokud se 2× po sobě neshodne.
6.2 „Fetching Data" / spinner — POZOR, NEPLATÍ pro tuto stránku
- Na test-results stránce NENÍ text „Fetching Data" (ten je na samples reportu, jiná stránka!).
- Je tu element
<loading-bar>, ale ten jen krátce problikne<mdl-progress>při route-loadingu, ne během načítání dat gridu → nelze na něj spoléhat. - Spolehlivý signál je výhradně objevení
.ag-row.
6.3 Tři tečky (export) — na stránce jsou DVA <ag-export>
- Na stránce existují 2×
<ag-export>: jeden skrytý, jeden viditelný. - Existují 3× ikona
more_horiz: 1 mimo export (toolbar), 1 ve skrytém ag-export, 1 ve viditelném. - Proto je nutný filtr na viditelnost:
✅
page.locator("ag-export button:visible", has_text="more_horiz").first.click()
6.4 „Export to CSV" — v DOM jsou DVĚ položky
- Po otevření menu existují 2×
mdl-menu-item„Export to CSV" (jedna skrytá z neviditelného ag-export, jedna viditelná). Stejně tak 2× „Export to Excel". - Proto:
✅
page.locator("mdl-menu-item:visible", has_text="Export to CSV").first.click()- ❌
get_by_text("Export to CSV")→ strict mode violation (2 elementy).
- ❌
6.5 Prázdné centrum (ověřeno přes Chrome MCP na centru 930551)
- AG Grid při 0 záznamech zobrazí no-rows overlay s textem „No Data".
- Struktura:
.ag-overlay→.ag-overlay-panel→.ag-overlay-no-rows-wrapper→<span>No Data</span>. - ⚠️ Třída NENÍ
.ag-overlay-no-rows-center(to byl chybný předpoklad, na který detekce nikdy nezabrala) — správně je.ag-overlay-no-rows-wrapper. - ⚠️ Text „No Data" NENÍ v
.ag-body-viewport(ten je prázdný,height: 1px) — je v samostatném overlay sourozenci. - ⚠️ Na stránce jsou 2 overlaye (jeden skrytý, jeden viditelný) — stejně
jako u
ag-export. Proto kontrola viditelnostioffsetParent !== null. - Detekce (KROK 2):
() => { if (document.querySelectorAll('div.ag-row').length > 0) return false; return [...document.querySelectorAll('.ag-overlay-no-rows-wrapper')] .some(e => e.offsetParent !== null); } - KROK 2 čeká na
.ag-rowNEBO tuto detekci → centrum bez dat necheká zbytečně 120 s a export se přeskočí.
7. Login logika (sdílená napříč Covance skripty)
page.goto(LOGIN_URL)
page.wait_for_load_state("networkidle")
if not page.get_by_label("Email").is_visible():
return # session aktivní → login přeskočit
# jinak: Email → Next → Password → Verify → wait redirect (code= zmizí z URL)
- Proč
is_visible()a ne kontrola URL: pogoto(LOGIN_URL)zůstane URLxsp.covance.comi po redirectu na dashboard, takže URL test je nespolehlivý. Spolehlivé je, zda existuje pole Email (login formulář) nebo ne. is_visible()neháže výjimku — když pole není, vrátíFalse.
8. Chrome flagy proti „Restore pages" / broken session
V args launchu:
--disable-restore-session-state # neobnovovat předchozí session
--disable-session-crashed-bubble # potlačit "Chromium didn't shut down correctly"
Důvod: při natvrdo ukončeném skriptu (kill) Chromium jinak při dalším startu nabídne „Restore pages?" dialog, který rozbil interakci.
9. Robustnost smyčky
- Každé centrum je v
try/except→ chyba u jednoho nezastaví zbytek. - Na konci souhrn:
hotovo X/12+ seznamSELHALA centra: …. - Selhané centrum v logu = snadno se dohledá a vyřadí/opraví ID.
10. Možná budoucí rozšíření
- Microbiology záložka: existuje i
…/test-results/{SITE}/microbiology…(analogická stránka, pravděpodobně stejná AG Grid logika). - Druhá studie (MDD3003, study 35472): přidat další
STUDY+SITE_IDSa obalit do vnější smyčky (vzor vizdownload_samples_reportse seznamem STUDIES). - Ověření počtu: počet
.ag-rowse loguje — dá se porovnat s počtem řádků ve staženém CSV jako sanity check.
11. Příbuzné skripty (stejná složka / portál)
| Skript | Co stahuje |
|---|---|
download_samples_report_v1.1.py |
All Samples (sampletracking, čeká na „Fetching Data") |
download_kit_inventory_v2.1.py |
Kit inventory (on-hand expiration) |
download_equeries_report_v1.1.py |
eQuery reporty (zdroj SITE_IDS) |
download_test_results_v1.0.py |
tento — Standard Test Results |
Všechny sdílejí: persistent profile, login logiku s is_visible() checkem,
ag-export + „Export to CSV" pattern (equeries/test-results).