Domanda

Sto cercando un modo per modificare a livello di navigator.userAgent al volo. Nel mio tentativo fallito di ottenere un tester unità javascript automatizzato, ho rinunciato e ha tentato di iniziare a utilizzare fireunit. Immediatamente, ho sbattuto in una delle pareti di utilizzare un browser attuale per javascript test.

In particolare, ho bisogno di cambiare navigator.userAgent per simulare alcune centinaia di stringhe UserAgent per garantire una corretta individuazione e la copertura su una data funzione. navigator.userAgent è di sola lettura, quindi mi sembra bloccato! Come faccio a deridere navigator.userAgent? User Agent Switcher (plugin) può passare useragent di FF, ma posso farlo all'interno di javascript?

È stato utile?

Soluzione

Prova:

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

navigator.userAgent; // 'foo'

provato in FF2 e FF3.

Altri suggerimenti

L'aggiunta a soluzione Crescent Fresh , ridefinendo il getter navigator.userAgent non sembra funzionare in Safari 5.0.5 (su Windows 7 e Mac OS X 10.6.7).

Hai bisogno di creare un nuovo oggetto che eredita dall'oggetto navigator e definire un nuovo getter userAgent per nascondere il getter userAgent originale in navigator:

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

Il seguente soluzione funziona in Chrome, Firefox, Safari, IE9 + e anche con gli 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');

Utilizzando Object.defineProperty dovrebbe aggiungere diversi 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 permette di cambiare l'userAgent.

Edit. Safari non permette di cambiare l'userAgent, ma può sostituire l'intero navigatore oggetto, come sottolineato in un'altra soluzione sopra

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

https: //developer.mozilla. org / it-IT / docs / Web / JavaScript / Reference / Global_Objects / oggetto / defineGetter

  

Deprecato   Questa caratteristica è stata rimossa dagli standard Web.   Anche se alcuni browser possono ancora sostenerlo, è in procinto di   cadute. Non usare in progetti vecchi o nuovi. Pagine o applicazioni web   usando si può rompere in qualsiasi momento.

Si dovrebbe usare defineProperty invece:

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

navigator.userAgent; // 'foo'

Per aggiornare questa discussione, defineGetter non funziona più in Jasmine come è stata sconsigliata. Tuttavia ho trovato questo mi permette di modificare il getter per navigator.userAgent in gelsomino:

navigator = {
  get userAgent() {
    return 'agent';
  }
}

console.log(navigator.userAgent); // returns 'agent'

Basta ricordare resettare l'oggetto del navigatore, una volta che si è fatto il test in gelsomino

Per coloro che cercano di fare la stessa cosa a macchina ecco la soluzione:

(<any>navigator)['__defineGetter__']('userAgent', function(){
    return 'foo';
});

navigator.userAgent; // 'foo'

O stessa cosa per la lingua:

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

Credo che mi piacerebbe prendere un approccio iniezione di dipendenza. Invece di:

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

Forse fare qualcosa di simile:

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);
}

Poi si può "prendere in giro fuori" getUserAgent() facendo:

function getUserAgentReal() { // formerly not 'Real'
    // ...
}

function getUserAgent() { // formerly 'Mock'
    // ...
}

Questo progetto ancora non è completamente automatizzata (si deve rinominare manualmente il getter per eseguire il test), e aggiunge un po 'di complessità qualcosa di semplice come operano su navigator.userAgent, e io non sono sicuro di come si' d realtà individuare eventuali bug nel myFunction, ma ho solo pensato che avrei butto là fuori per darvi alcune idee come questo potrebbe essere affrontato.

Forse l'idea di "Dependency Injection" presentato qui possa in qualche modo essere integrato con FireUnit.

Per coloro che sono qui perché hanno bisogno di modificare il valore userAgent in unit test, la soluzione di Tyler lungo funziona, ma se si desidera ripristinare l'userAgent iniziale o modificare più di una volta, si avrà probabilmente bisogno di impostare la proprietà come configurabile:

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

// Now in your setup phase:
// Keep the initial value
var initialUserAgent = navigator.userAgent;
setUserAgent('foo');

// In your tearDown:
// Restore the initial value
setUserAgent(initialUserAgent);

In caso contrario, si potrebbe incorrere in un errore di TypeError: Cannot redefine property. Lavora per me su Chrome senza testa.

navigator.userAgent è una proprietà di stringa di sola lettura, quindi non è possibile modificarlo

Sopra risposte non stavano lavorando per PhantomJS + dattiloscritto. Qui di seguito 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'; });

tardi per questo argomento, ma per il Karma + Jasmin e tipografico e si desidera impostare la proprietà userAgent questo 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 / Consigli / 1036762 / Mocking-userAgent-con-JavaScript

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 istanza di oggetto

var navigator = new Object; 
navigator.userAgent = 'iPhone 5';

alert( navigator.userAgent ); //iPhone5

Buona cosa è, se si lavora su controllo WebBrowser Internet Explorer, è possibile raddoppiare parodia sia HTTP di richiesta e 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

No, dubito che si può fare all'interno di javascript. Ma con l'utente di Firefox Agent Switcher è possibile verificare tutto quello che vuoi useragent, quindi perché non basta usare questo?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top