Prendere in giro un utente in javascript?

Sto cercando un modo per cambiare al volo navigator.userAgent al volo. Nel mio tentativo fallito di ottenere un tester di unità javascript automatizzato, ho rinunciato e ho tentato di iniziare a usare l’unità antincendio. Immediatamente, mi sono imbattuto in una delle pareti di usare un vero browser per i test di javascript.

Nello specifico, ho bisogno di cambiare navigator.userAgent per simulare alcune centinaia di stringhe userAgent per garantire un rilevamento e una copertura adeguati su una determinata funzione. navigator.userAgent è di sola lettura, quindi mi sembra bloccato! Come posso prendere in giro navigator.userAgent? User Agent Switcher (plugin) può cambiare useragent di FF, ma posso farlo all’interno di javascript?

Provare:

navigator.__defineGetter__('userAgent', function(){ return 'foo' // customized user agent }); navigator.userAgent; // 'foo' 

Provato in FF2 e FF3.

Aggiungendo alla soluzione di Crescent Fresh , la ridefinizione del getter navigator.userAgent non sembra funzionare in Safari 5.0.5 (su Windows 7 e Mac OS X 10.6.7).

È necessario creare un nuovo object che erediti dall’object navigator e definire un nuovo getter userAgent per hide il getter userAgent originale nel navigator :

 var __originalNavigator = navigator; navigator = new Object(); navigator.__proto__ = __originalNavigator; navigator.__defineGetter__('userAgent', function () { return 'Custom'; }); 

La seguente soluzione funziona in Chrome, Firefox, Safari, IE9 + e anche con iframe:

 function setUserAgent(window, userAgent) { if (window.navigator.userAgent != userAgent) { var userAgentProp = { get: function () { return userAgent; } }; try { Object.defineProperty(window.navigator, 'userAgent', userAgentProp); } catch (e) { window.navigator = Object.create(navigator, { userAgent: userAgentProp }); } } } 

Esempi:

 setUserAgent(window, 'new user agent'); setUserAgent(document.querySelector('iframe').contentWindow, 'new user agent'); 

L’uso di Object.defineProperty dovrebbe aggiungere molti altri browser al mix:

 if (navigator.__defineGetter__) { navigator.__defineGetter__("userAgent", function () { return "ua"; }); } else if (Object.defineProperty) { Object.defineProperty(navigator, "userAgent", { get: function () { return "ua"; } }); } 

Questo codice dovrebbe funzionare (ed è stato testato) in Firefox 1.5+ , Chrome 6+ , Opera 10.5+ e IE9 + . Purtroppo Safari su qualsiasi piattaforma non consente di modificare l’utenteAgent.

Modifica: Safari non consente la modifica di userAgent, ma è ansible sostituire l’intero object navigator , come indicato in un’altra soluzione sopra.

La risposta di Crescent Fresh è corretta. Ma c’è un problema: __defineGetter__ è deprecato:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/ defineGetter

Deprecato Questa funzione è stata rimossa dagli standard Web. Sebbene alcuni browser possano ancora supportarlo, è in fase di rilascio. Non usarlo in progetti vecchi o nuovi. Le pagine o le app Web che lo utilizzano potrebbero interrompersi in qualsiasi momento.

Dovresti usare defineProperty invece:

 Object.defineProperty(navigator, "userAgent", { get: function () { return "foo"; // customized user agent } }); navigator.userAgent; // 'foo' 

Per aggiornare questo thread, defineGetter non funziona più in Jasmine dato che era deprecato. Tuttavia ho trovato questo mi permette di modificare il getter per navigator.userAgent in jasmine:

 navigator = { get userAgent() { return 'agent'; } } console.log(navigator.userAgent); // returns 'agent' 

Ricordati di resettare l’object navigator una volta che hai finito i test in jasmine

Per coloro che cercano di fare la stessa cosa in TypeScript, ecco la soluzione:

 (navigator)['__defineGetter__']('userAgent', function(){ return 'foo'; }); navigator.userAgent; // 'foo' 

O stessa cosa per il linguaggio:

 (navigator)['__defineGetter__']('language', function(){ return 'de-DE'; }); 

Immagino che prenderei un approccio di iniezione di dipendenza. Invece di:

 function myFunction() { var userAgent = navigator.userAgent; // do stuff with userAgent } 

Forse fare qualcosa come:

 function myFunction(userAgent) { // do stuff with userAgent } function getUserAgent() { window.userAgentReal = +window.userAgentReal || 0; return [ navigator.userAgent ][window.userAgentReal++]; } function getUserAgentMock() { window.nextUserAgentMock = +window.nextUserAgentMock || 0; return [ 'test user agent1', 'test user agent2', 'test user agent3' ][window.nextUserAgentMock++]; } var userAgent; while (userAgent = getUserAgent()) { myFunction(userAgent); } 

Quindi puoi “deridere” getUserAgent() facendo:

 function getUserAgentReal() { // formsrly not 'Real' // ... } function getUserAgent() { // formsrly 'Mock' // ... } 

Questo design non è ancora completamente automatizzato (è necessario rinominare manualmente il getter per eseguire i test) e aggiunge un po ‘di complessità a qualcosa di semplice come operare su navigator.userAgent , e non sono sicuro di come in realtà identifico eventuali bug in myFunction , ma ho appena pensato di buttarlo lì fuori per darti qualche idea su come questo potrebbe essere affrontato.

Forse l’idea di “iniezione di dipendenza” qui presentata può essere in qualche modo integrata con FireUnit.

navigator.userAgent è una proprietà stringa di sola lettura, quindi non è ansible modificarla

Le risposte sopra non funzionavano per PhantomJS + TypeScript. Sotto il codice ha funzionato per me:

 var __originalNavigator = navigator; (window as any).navigator = new Object(); navigator["__proto__"] = __originalNavigator["__proto__"]; navigator["__defineGetter__"]('userAgent', function () { return 'Custom'; }); 

In ritardo su questo argomento, ma per Karma + Jasmin e Typescript e voglio impostare la proprietà userAgent, lo farò:

 describe('should validate YYYY-MM-dd format only on IE browser', () => { // this validator has a specific condition to work only in IE11 and down (window as any).navigator.__defineGetter__('userAgent', function () { return 'MSIE'; }); ... // rest of the test }); 

Questo articolo ha aiutato: https://www.codeproject.com/Tips/1036762/Mocking-userAgent-with-JavaScript

No, dubito che tu possa farlo in javascript. Ma con lo User Agent Switcher di Firefox puoi testare qualsiasi useragent tu voglia, quindi perché non usarlo?

Cambia navigator.userAgent su Firefox e Opera tramite defineGetter

 navigator.__defineGetter__('userAgent', function(){ return( "iPhone 5" ); }); alert( navigator.userAgent ); //iPhone 5 

Cambia navigator.userAgent su IE e Opera tramite l’istanza dell’object

 var navigator = new Object; navigator.userAgent = 'iPhone 5'; alert( navigator.userAgent ); //iPhone5 

La cosa buona è che, se si lavora con il controllo webbrowser di IE, è ansible raddoppiare sia la richiesta HTTP che JavaScript navigator.userAgent tramite execScript

 WebBrowser1.Navigate "http://example.com", , , , "User-Agent: iPhone 5" & vbCrLf WebBrowser1.Document.parentWindow.execScript ("var navigator=new Object;navigator.userAgent='iPhone 5';") WebBrowser1.Document.parentWindow.execScript ("alert(navigator.userAgent);") 'iPhone 5