Falsificarea datei într-o aplicație Electron
Caută asta și fiecare răspuns este despre schimbarea propriului cod - mock pentru obiectul
Date, temporizatoare false din framework-ul tău de testare. Nimic din toate astea nu
ajută când ai o aplicație deja compilată. Aici rulezi aplicația pe care o ai deja.
De ce nu ajunge injecția la ea
Acest mod există din cauza unui eșec concret. Un cronometru Pomodoro construit pe Electron a fost
rulat într-o sesiune x60 și numărătoarea lui inversă nu s-a mișcat deloc. Desfacerea
pachetului aplicației a arătat două motive independente, iar niciunul nu avea o soluție pe partea
nativă:
- Numărătoarea inversă nu citea un ceas. Era un contor incrementat de
setInterval, care rula într-un Web Worker. Nu exista niciun apel de timp de interceptat, pentru că aplicația nu întreba niciodată cât este ceasul. - Acel worker trăiește într-un proces renderer izolat, adică exact locul în care o bibliotecă injectată din afară nu pătrunde.
Așadar mecanismul de pe partea Windows nu poate ajuta aici, iar răspunsul este să vorbești în schimb cu motorul JavaScript propriu al aplicației.
Ce se întâmplă în schimb
Aplicația este lansată cu un port de depanare și cu un profil curat, de unică folosință, iar
propriile ei API-uri de timp sunt puse pe ceasul sesiunii prin protocolul DevTools -
Date.now, constructorul new Date(),
performance.now, setTimeout și setInterval.
Înlocuirea este instalată în fiecare context pe care îl deschide aplicația, inclusiv în Web Worker-ele ei - acolo unde se dovedește de obicei că trăiește cronometrul și singurul loc la care injecția nativă nu avea cum să ajungă.
Nimic din felul în care îl folosești nu se schimbă. Aceeași comandă, aceeași fereastră, același panou de sesiune cu cele două ceasuri și verdictul.
# Aceeași comandă ca pentru o aplicație nativă - modul este detectat chrono run "%LOCALAPPDATA%\Programs\your-app\YourApp.exe" --at 2038-01-01T00:00:00 --mode x60
Două limite bune de știut înainte să începi
Lansarea este invazivă și spune asta deschis, în mod deliberat.
Aplicația este pornită cu un port de depanare la distanță deschis și cu un profil nou, izolat, în
%TEMP% - nu rulează pe profilul tău real și nu este exemplarul care se află deja în
bara de sistem. Profilul este șters când se încheie sesiunea, iar dacă nu a putut fi șters,
rezumatul sesiunii spune asta, în loc să-l lase pe tăcute în urmă.
Transmiterea propriului --user-data-dir sau --remote-debugging-port
este refuzată, nu suprascrisă, pentru că accidentul evident - îndreptarea sesiunii spre profilul
tău real de browser - nu merită permis.
Paginile citesc fusul orar al sesiunii.
Fiecare pagină și fiecare worker este mutat pe fusul
orar al sesiunii, o decalare fixă fără ora de vară, și verifică decalarea pe care o
citește, așa că o pagină care a citit alt fus este raportată. Două limite: Intl
numește acel fus printr-o decalare precum GMT+02:00, nu printr-un oraș, iar
procesul principal al unei aplicații Electron rulează JavaScript în Node, la care sesiunea
nu ajunge, deci păstrează ceasul real - raportul spune asta.
Încă un lucru care îi surprinde pe oameni: un interval deja programat își păstrează
vechiul ritm când schimbi viteza în timpul sesiunii. Date.now,
new Date() și performance.now reacționează imediat, un
setInterval aflat în execuție nu, iar sesiunea te avertizează în loc să te lase să
concluzionezi că schimbarea nu a făcut nimic.
Cât de bine este testat
Experimental, iar cuvântul acesta are aici un sens definit: funcționează pe țintele pentru care a fost construit, nu a fost testat pe scară largă, iar auditul încorporat este sursa ta de adevăr, nu această pagină. A fost verificat manual, nu prin suita automată, pe o aplicație Electron reală, pe Windows pe 64 de biți.
Acoperirea este raportată pe context JavaScript, nu pe proces, deoarece asta este unitatea care există aici. O aplicație aflată în repaus, care nu întreabă niciodată ora, produce în mod onest nedeterminat - nu a citit un ceas, deci nu se poate afirma nimic despre dacă ar fi văzut unul corect. Ce înseamnă verdictele →