Falsificare la data in un'app Electron
Cercalo e ogni risposta riguarda la modifica del tuo codice - simulare l'oggetto Date,
usare i timer finti del tuo framework di test. Niente di tutto questo aiuta quando quello che hai è
un'applicazione già compilata. Questo esegue l'applicazione che hai già.
Perché l'iniezione non la raggiunge
Questa modalità esiste per un fallimento preciso. Un timer Pomodoro costruito su Electron è stato
eseguito con una sessione x60 e il suo conto alla rovescia non si è mosso affatto.
Smontare il bundle dell'applicazione ha mostrato due motivi indipendenti, e nessuno dei due aveva
una soluzione dal lato nativo:
- Il conto alla rovescia non leggeva alcun orologio. Era un contatore incrementato da
setInterval, in esecuzione dentro un Web Worker. Non c'era alcuna chiamata di tempo da intercettare, perché l'applicazione non chiedeva mai che ora fosse. - Quel worker vive in un processo di rendering isolato, che è proprio il posto in cui una libreria iniettata dall'esterno non entra.
Quindi il meccanismo lato Windows non può aiutare qui, e la risposta è parlare invece con il motore JavaScript dell'applicazione stessa.
Che cosa succede invece
L'applicazione viene avviata con una porta di debug e un profilo pulito e usa e getta, e le sue
stesse API di tempo vengono portate sull'orologio della sessione tramite il protocollo DevTools -
Date.now, il costruttore new Date(), performance.now,
setTimeout e setInterval.
La sostituzione viene installata in ogni contesto che l'applicazione apre, compresi i suoi Web Worker - dove il timer di solito si trova, e l'unico posto che l'iniezione nativa non avrebbe mai raggiunto.
Nulla cambia nel modo di pilotarla. Lo stesso comando, la stessa finestra, lo stesso pannello di sessione con i due orologi e il verdetto.
# Lo stesso comando di un'applicazione nativa - la modalità viene rilevata chrono run "%LOCALAPPDATA%\Programs\your-app\YourApp.exe" --at 2038-01-01T00:00:00 --mode x60
Due limiti da conoscere prima di cominciare
L'avvio è invasivo, e volutamente rumoroso al riguardo.
L'applicazione viene avviata con una porta di debug remoto aperta e un profilo nuovo e isolato in
%TEMP% - non gira sul tuo vero profilo, e non è la copia già presente nell'area di
notifica. Il profilo viene eliminato alla fine della sessione, e se non è stato possibile il
riepilogo della sessione lo dice invece di lasciarlo lì in silenzio.
Passare il tuo --user-data-dir o --remote-debugging-port viene rifiutato
invece di essere sovrascritto, perché l'incidente più ovvio - puntare la sessione sul tuo vero
profilo del browser - non è uno che valga la pena consentire.
Le pagine leggono il fuso orario della sessione.
Ogni pagina e ogni worker viene portato sul fuso orario
della sessione, uno scostamento fisso senza ora legale, e controlla lo scostamento che
legge, così una pagina che ha letto un altro fuso viene segnalata. Due limiti:
Intl chiama quel fuso con uno scostamento come GMT+02:00 e non con
una città, e il processo principale di un'applicazione Electron esegue JavaScript in Node,
che la sessione non raggiunge, quindi mantiene l'orologio reale - il rapporto lo dice.
Un'altra cosa che sorprende: un intervallo già programmato mantiene il vecchio ritmo
quando cambi la velocità a sessione in corso. Date.now, new Date() e
performance.now reagiscono subito, un setInterval in corso no, e la
sessione lo segnala invece di lasciarti concludere che la modifica non ha fatto nulla.
Quanto è testato
Sperimentale, e questa parola ha qui un significato definito: funziona sui target per cui è stato costruito, non è stato testato in modo ampio, e l'audit integrato è la tua fonte di verità, non questa pagina. È stato verificato a mano e non con la suite automatica, su una vera applicazione Electron su Windows a 64 bit.
La copertura viene riportata per contesto JavaScript e non per processo, perché è l'unità che qui esiste. Un'applicazione inattiva che non chiede mai l'ora produce onestamente indeterminato - non ha letto alcun orologio, quindi non si può affermare nulla su se avrebbe visto quello giusto. Cosa significano i verdetti →