Mock useragent in javascript?

I am looking for a way to programmatically change navigator.userAgent on the fly. In my unsuccessful attempt to get an automatic javascript block tester, I gave up and tried to start using fireunit. Immediately, I crashed into one of the walls using the actual browser to test javascript.

In particular, I need to modify navigator.userAgent to simulate several hundred UserAgent strings to ensure proper detection and coverage of this function. navigator.userAgent is read-only, so I seem to be stuck! How can I mock navigator.userAgent? User Agent Switcher (plugin) can toggle Fag useragent, but can I do this in javascript?

+51
javascript unit-testing user-agent
Aug 20 '09 at 15:34
source share
12 answers

Try:

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

Tried it in FF2 and FF3.

+84
Aug 20 '09 at 15:46
source share

Adding Crescent Fresh to solutions , overriding the navigator.userAgent tag does not seem to work in Safari 5.0.5 (on Windows 7 and Mac OS X 10.6 0.7).

You need to create a new object that inherits the navigator object and define a new userAgent getter to hide the original userAgent getter in the navigator :

 var __originalNavigator = navigator; navigator = new Object(); navigator.__proto__ = __originalNavigator; navigator.__defineGetter__('userAgent', function () { return 'Custom'; }); 
+21
May 10 '11 at 12:29
source share

The following solution works in Chrome, Firefox, Safari, IE9 +, as well as 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 }); } } } 

Examples:

 setUserAgent(window, 'new user agent'); setUserAgent(document.querySelector('iframe').contentWindow, 'new user agent'); 
+18
Nov 12 '14 at 13:36 on
source share

Using Object.defineProperty should add a few more browsers to the mix:

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

This code should work (and has been tested) in Firefox 1.5+ , Chrome 6+ , Opera 10.5+, and IE9 + . Unfortunately, Safari does not allow changing userAgent on any platform.

Edit: Safari does not allow userAgent to be modified, but you can replace the entire navigator object, as indicated in another solution above.

+5
Mar 24 '14 at 16:40
source share

To update this thread, defineGetter no longer works in Jasmine, as it is deprecated. However, I found that this allows me to modify the getter for navigator.userAgent in jasmine:

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

Just remember how to reset the navigator object as soon as you finish testing in jasmine

+3
Jun 23 '15 at 15:43
source share

Crescent Fresh answer is correct. But there is a problem: __defineGetter__ deprecated:

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

Deprecated This feature has been removed from web standards. Although some browsers may still support it, it is in the process of being reset. Do not use it in old or new projects. Pages or web applications may be interrupted at any time.

Instead, use defineProperty :

 Object.defineProperty(navigator, "userAgent", { get: function () { return "foo"; // customized user agent } }); navigator.userAgent; // 'foo' 
+2
Jan 30 '15 at 11:43
source share

I think I would take an approach to dependency injection. Instead:

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

Maybe something like:

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

Then you can “mock” getUserAgent() by doing:

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

This design is still not fully automated (you need to manually rename the getter to do your testing), and it adds a ton of complexity to something as simple as working on navigator.userAgent , and I'm not sure how you would actually identify errors in myFunction , but I just thought that I would throw it there to give you some ideas how this can be solved.

Maybe the idea of ​​“dependency injection” presented here can somehow be integrated with FireUnit.

+1
Aug 20 '09 at 16:43
source share

For those trying to do the same in TypeScript here, the solution is:

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

The same for language:

 (<any>navigator)['__defineGetter__']('language', function(){ return 'de-DE'; }); 
+1
Oct 20 '16 at 11:32
source share

navigator.userAgent is a read-only string property, so it cannot be edited

0
Aug 20 '09 at 15:39
source share

Above answers did not work for PhantomJS + TypeScript. Below code worked for me:

 var __originalNavigator = navigator; (window as any).navigator = new Object(); navigator["__proto__"] = __originalNavigator["__proto__"]; navigator["__defineGetter__"]('userAgent', function () { return 'Custom'; }); 
0
Aug 22 '17 at 13:29 on
source share

No, I doubt you can do this in javascript. But with the Firefox User Agent Switcher, you can test any user address you want, so why not just use this?

-one
Aug 20 '09 at 15:38
source share

Change navigator.userAgent on Firefox and Opera with defineGetter

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

Change navigator.userAgent to IE and Opera through an instance of an object

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

Well, if you are working on IE webbrowser control, you can double the spoofing of both HTTP request and JavaScript navigator.userAgent via 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 
-one
May 6 '14 at 10:45
source share



All Articles