在JavaScript中嘲笑useragent?
我正在寻找一种方法来编程方式更改navigator.userAgent上飞。 在我失败的尝试获得一个自动化的JavaScriptunit testing,我放弃了,并试图开始使用fireunit。 马上,我抨击了使用真正的浏览器进行javascripttesting的一面墙壁。
具体来说,我需要更改navigator.userAgent来模拟几百个userAgentstring,以确保对给定函数进行正确的检测和覆盖。 navigator.userAgent是只读的,所以我似乎卡住了! 我怎样才能模拟navigator.userAgent? 用户代理切换器(插件)可以切换FF的useragent,但我可以在JavaScript内做到这一点?
尝试:
navigator.__defineGetter__('userAgent', function(){ return 'foo' // customized user agent }); navigator.userAgent; // 'foo'
尝试在FF2和FF3。
添加到Crescent Fresh的解决scheme中 ,重新定义navigator.userAgent
getter似乎在Safari 5.0.5(在Windows 7和Mac OS X 10.6.7)上不起作用。
需要创build一个从navigator
对象inheritance的新对象,并定义一个新的userAgent
getter来隐藏navigator
的原始userAgent
getter:
var __originalNavigator = navigator; navigator = new Object(); navigator.__proto__ = __originalNavigator; navigator.__defineGetter__('userAgent', function () { return 'Custom'; });
以下解决scheme适用于Chrome,Firefox,Safari,IE9 +以及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 }); } } }
例子:
setUserAgent(window, 'new user agent'); setUserAgent(document.querySelector('iframe').contentWindow, 'new user agent');
使用Object.defineProperty应该添加更多的浏览器混合:
if (navigator.__defineGetter__) { navigator.__defineGetter__("userAgent", function () { return "ua"; }); } else if (Object.defineProperty) { Object.defineProperty(navigator, "userAgent", { get: function () { return "ua"; } }); }
这个代码应该在Firefox 1.5 + , Chrome 6+ , Opera 10.5+和IE9 +上运行 (并经过testing)。 不幸的是,Safari在任何平台上都不允许更改userAgent。
编辑:Safari不允许更改userAgent,但可以replace整个导航器对象,如上面的另一个解决scheme中指出的那样。
为了更新这个线程,defineGetter在Jasmine中不再起作用,因为它已经被弃用了。 但是,我发现这使我可以修改茉莉花的navigator.userAgent getter:
navigator = { get userAgent() { return 'agent'; } } console.log(navigator.userAgent); // returns 'agent'
只要记得在茉莉花testing完成后重置导航器对象
Crescent Fresh的答案是正确的。 但有一个问题: __defineGetter__
已弃用:
已弃用此function已从Web标准中删除。 尽pipe一些浏览器可能仍然支持它,但它正在被丢弃。 不要在旧的或新的项目中使用它。 使用它的页面或Web应用程序可能会随时中断。
你应该使用defineProperty
来代替:
Object.defineProperty(navigator, "userAgent", { get: function () { return "foo"; // customized user agent } }); navigator.userAgent; // 'foo'
我想我会采取dependency injection的方法。 代替:
function myFunction() { var userAgent = navigator.userAgent; // do stuff with userAgent }
也许做一些事情:
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); }
然后你可以通过下面的方法“模拟” getUserAgent()
function getUserAgentReal() { // formerly not 'Real' // ... } function getUserAgent() { // formerly 'Mock' // ... }
这个devise仍然不是完全自动化的(你必须手动重命名getter来执行你的testing),而且它增加了一些复杂性,就像在navigator.userAgent
操作一样简单,我不知道你是怎么做的实际上找出了myFunction
任何错误,但是我只是想把它扔到那里给你一些想法如何处理。
也许这里介绍的“dependency injection”的概念可以以某种方式与FireUnit集成。
对于那些试图在TypeScript中做同样的事情的解决scheme:
(<any>navigator)['__defineGetter__']('userAgent', function(){ return 'foo'; }); navigator.userAgent; // 'foo'
或者语言同样的东西:
(<any>navigator)['__defineGetter__']('language', function(){ return 'de-DE'; });
navigator.userAgent
是一个只读的string属性,所以不能编辑它
以上的答案不适用于PhantomJS + TypeScript。 下面的代码为我工作:
var __originalNavigator = navigator; (window as any).navigator = new Object(); navigator["__proto__"] = __originalNavigator["__proto__"]; navigator["__defineGetter__"]('userAgent', function () { return 'Custom'; });
不,我怀疑你可以在JavaScript内做到这一点。 但是使用Firefox的用户代理切换器,你可以testing你想要的任何useragent,那么为什么不使用它呢?
通过defineGetter在Firefox和Opera上更改navigator.userAgent
navigator.__defineGetter__('userAgent', function(){ return( "iPhone 5" ); }); alert( navigator.userAgent ); //iPhone 5
在IE和Opera上通过对象实例更改navigator.userAgent
var navigator = new Object; navigator.userAgent = 'iPhone 5'; alert( navigator.userAgent ); //iPhone5
好的是,如果你使用IE浏览器控制,你可以通过execScript双重欺骗HTTP请求和JavaScript navigator.userAgent
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