Ich suche nach einer Möglichkeit, navigator.userAgent im laufenden Betrieb programmgesteuert zu ändern. Bei meinem fehlgeschlagenen Versuch, einen automatisierten Javascript-Unit-Tester zu erhalten, gab ich auf und versuchte, Fireunit zu verwenden. Sofort bin ich in eine der Wände geraten, in denen ein tatsächlicher Browser für Javascript-Tests verwendet wurde.
Insbesondere muss ich navigator.userAgent ändern, um einige hundert userAgent-Zeichenfolgen zu simulieren und eine ordnungsgemäße Erkennung und Abdeckung einer bestimmten Funktion sicherzustellen. navigator.userAgent ist schreibgeschützt, also stecke ich fest! Wie kann ich navigator.userAgent verspotten? User Agent Switcher (Plugin) kann den Useragent von FF wechseln, aber kann ich dies in Javascript tun?
quelle
Antworten:
Versuchen:
navigator.__defineGetter__('userAgent', function(){ return 'foo' // customized user agent }); navigator.userAgent; // 'foo'
Versuchte es in FF2 und FF3.
quelle
__defineGetter__
ist veraltet, verwenden SiedefineProperty
stattdessen. Überprüfen Sie meine Antwort unten.Hinzufügen auf Crescent Frische-Lösung , die Neudefinition
navigator.userAgent
nicht Getter scheint nicht zu Arbeit in Safari 5.0.5 (auf Windows 7 und Mac OS X 10.6.7).Sie müssen ein neues Objekt erstellen, das vom Objekt erbt,
navigator
und einen neuenuserAgent
Getter definieren , um den ursprünglichenuserAgent
Getter auszublendennavigator
:var __originalNavigator = navigator; navigator = new Object(); navigator.__proto__ = __originalNavigator; navigator.__defineGetter__('userAgent', function () { return 'Custom'; });
quelle
navigator.__proto__ = __originalNavigator;
heißt es:cyclic __proto__ value
oder so. Durch Entfernen dieser Zeile wird der Benutzeragent "lokal arbeiten", was bedeutetnavigator.userAgent
, dass er das zurückerhält, was Sie festgelegt haben. Bei XMLHttpRequest-Aufrufen wird jedoch nur die Standard-UA verwendet.Die folgende Lösung funktioniert in Chrome, Firefox, Safari, IE9 + und auch mit Iframes:
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 }); } } }
Beispiele:
setUserAgent(window, 'new user agent'); setUserAgent(document.querySelector('iframe').contentWindow, 'new user agent');
quelle
the iframe sent the default user agent to the server before the script applies a new user agent to it.
Wenn Sie Object.defineProperty verwenden, sollten Sie dem Mix mehrere weitere Browser hinzufügen:
if (navigator.__defineGetter__) { navigator.__defineGetter__("userAgent", function () { return "ua"; }); } else if (Object.defineProperty) { Object.defineProperty(navigator, "userAgent", { get: function () { return "ua"; } }); }
Dieser Code sollte in Firefox 1.5+ , Chrome 6+ , Opera 10.5+ und IE9 + funktionieren (und wurde getestet) . Leider erlaubt Safari auf keiner Plattform das Ändern des userAgent.
Bearbeiten: Safari erlaubt nicht das Ändern des userAgent, aber man kann das gesamte Navigatorobjekt ersetzen , wie in einer anderen Lösung oben ausgeführt.
quelle
Für diejenigen hier, die den userAgent-Wert in Komponententests ändern müssen, funktioniert die Lösung von Tyler Long. Wenn Sie jedoch den anfänglichen userAgent wiederherstellen oder mehrmals ändern möchten, müssen Sie die Eigenschaft wahrscheinlich als konfigurierbar festlegen:
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);
Andernfalls könnte ein
TypeError: Cannot redefine property
Fehler auftreten. Funktioniert für mich auf Chrome Headless.quelle
const setUserAgent = (userAgent: 'Chrome' | 'Android') => { Object.defineProperty(navigator, 'userAgent', { get: () => userAgent, configurable: true, }); };
Die Antwort von Crescent Fresh ist richtig. Aber es gibt ein Problem:
__defineGetter__
ist veraltet:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/ defineGetter
Sie sollten
defineProperty
stattdessen verwenden:Object.defineProperty(navigator, "userAgent", { get: function () { return "foo"; // customized user agent } }); navigator.userAgent; // 'foo'
quelle
Um diesen Thread zu aktualisieren, funktioniert defineGetter in Jasmine nicht mehr, da es veraltet ist. Ich habe jedoch festgestellt, dass ich damit den Getter für navigator.userAgent in Jasmin ändern kann:
navigator = { get userAgent() { return 'agent'; } } console.log(navigator.userAgent); // returns 'agent'
Denken Sie daran, das Navigatorobjekt zurückzusetzen, wenn Sie mit dem Testen in Jasmin fertig sind
quelle
__defineGetter__
unter NodeJS 6.1 (unter Verwendung von Jasmine 2) scheint für mich ziemlich gut zu funktionieren.__defineGetter__
hat bei Jasmine 2.4.1 und Node 6.8.1 nicht funktioniert, aber dies hat perfekt funktioniert.Für diejenigen, die versuchen, dasselbe in TypeScript zu tun, ist hier die Lösung:
(<any>navigator)['__defineGetter__']('userAgent', function(){ return 'foo'; }); navigator.userAgent; // 'foo'
Oder dasselbe für die Sprache:
(<any>navigator)['__defineGetter__']('language', function(){ return 'de-DE'; });
quelle
Ich denke, ich würde einen Ansatz zur Abhängigkeitsinjektion wählen. Anstatt:
function myFunction() { var userAgent = navigator.userAgent; // do stuff with userAgent }
Vielleicht machen Sie so etwas wie:
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); }
Dann können Sie "verspotten",
getUserAgent()
indem Sie Folgendes tun:function getUserAgentReal() { // formerly not 'Real' // ... } function getUserAgent() { // formerly 'Mock' // ... }
Dieses Design ist immer noch nicht vollständig automatisiert (Sie müssen den Getter manuell umbenennen, um Ihre Tests durchzuführen), und es fügt etwas so Einfachem wie der Bedienung eine Menge Komplexität hinzu
navigator.userAgent
, und ich bin mir nicht sicher, wie Sie tatsächlich eines identifizieren würden FehlermyFunction
, aber ich dachte nur, ich würde es da rauswerfen, um Ihnen einige Ideen zu geben, wie damit umgegangen werden könnte.Vielleicht kann die hier vorgestellte Idee der "Abhängigkeitsinjektion" irgendwie in FireUnit integriert werden.
quelle
Die obigen Antworten funktionierten nicht für PhantomJS + TypeScript. Der folgende Code hat bei mir funktioniert:
var __originalNavigator = navigator; (window as any).navigator = new Object(); navigator["__proto__"] = __originalNavigator["__proto__"]; navigator["__defineGetter__"]('userAgent', function () { return 'Custom'; });
quelle
Versuchen Sie dies, es hat bei mir ohne Flusenprobleme funktioniert
Object.defineProperty(global.navigator, 'userAgent', { get: () => 'iPhone' });
quelle
navigator.userAgent
ist eine schreibgeschützte Zeichenfolgeeigenschaft, daher kann sie nicht bearbeitet werdenquelle
Spät zu diesem Thema, aber für Karma + Jasmin und Typescript und wenn Sie die userAgent-Eigenschaft festlegen möchten, wird dies Folgendes tun:
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 });
Dieser Artikel hat geholfen: https://www.codeproject.com/Tips/1036762/Mocking-userAgent-with-JavaScript
quelle
Ändern Sie navigator.userAgent in Firefox und Opera über defineGetter
navigator.__defineGetter__('userAgent', function(){ return( "iPhone 5" ); }); alert( navigator.userAgent ); //iPhone 5
Ändern Sie navigator.userAgent in IE und Opera über die Objektinstanz
var navigator = new Object; navigator.userAgent = 'iPhone 5'; alert( navigator.userAgent ); //iPhone5
Gut ist, wenn Sie an der IE-Webbrowser-Steuerung arbeiten, können Sie sowohl die HTTP-Anforderung als auch den JavaScript-Navigator.userAgent über execScript doppelt fälschen
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
quelle
Nein, ich bezweifle, dass Sie dies in Javascript tun können. Mit dem User Agent Switcher von Firefox können Sie jedoch jeden gewünschten Useragent testen. Warum also nicht einfach diesen verwenden?
quelle