我正在寻找一种方法以编程方式动态更改navigator.userAgent的。在我失败的尝试得到一个自动的JavaScript单元测试,我放弃了,并试图开始使用fireunit。随即,我已经撞上使用实际的浏览器为JavaScript测试的壁中的一个。

具体来说,我需要改变的navigator.userAgent模拟几百的userAgent字符串,以确保在一个给定函数正确检测和覆盖范围。 navigator.userAgent的是只读的,所以我似乎卡住了!我怎么能嘲笑navigator.userAgent的?用户代理切换器(插件)可以切换FF的用户代理,但我可以做到这一点的JavaScript内?

有帮助吗?

解决方案

尝试:

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

navigator.userAgent; // 'foo'

试图在FF2和FF3。

其他提示

添加到新月新鲜的溶液时,重新定义navigator.userAgent吸气剂似乎不工作在Safari 5.0.5(在Windows 7和Mac OS X 10.6.7)。

需要创建一个新对象从navigator对象继承并定义一个新userAgent吸气隐藏在userAgent原始navigator吸气剂:

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

下面的解决方案适用于浏览器,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";
        }
    });
}

此代码,就可以(和测试)中的火狐1.5 + ,<强>铬6 + 下,的歌剧10.5 + 和<强> IE9 + 即可。不幸的是Safari浏览器在任何平台上不允许更改的userAgent。

编辑:Safari浏览器不允许更改的userAgent,但可以替换整个的导航对象,如在上述的另一解决方案指出

新月新鲜的答案是正确的。但有一个问题:__defineGetter__被弃用:

HTTPS://developer.mozilla。组织/ EN-US /文档/网络/的JavaScript /参考/ Global_Objects /对象/ defineGetter

  

<强>已过时   此功能已被从Web标准中删除。   尽管一些浏览器可能仍然支持它,它是在过程   被丢弃。不要在旧的或新的项目中使用它。网页或Web应用程序   使用它可以在任何时间中断。

您应该使用defineProperty代替:

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

navigator.userAgent; // 'foo'

要更新这个帖子,defineGetter不会再在茉莉花,因为它是不推荐使用。然而,我发现这个允许我修改吸气为navigator.userAgent的在茉莉:

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

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

只要记住重置导航对象一旦你完成在茉莉测试

对于那些试图做同样的事情在打字稿这里的解决方案:

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

navigator.userAgent; // 'foo'

或者语言一样的东西:

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

我想我需要依赖注入的方法。代替:

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'
    // ...
}

此设计还没有完全自动化(您必须手动重命名为您进行测试的getter),并增加了一堆复杂的,以作为navigator.userAgent操作简单的东西,我不知道你怎么” ð实际上识别myFunction任何错误,但我只是想我会扔在那里给你一些想法如何,这可能与处理。

也许“依赖注入”这里提出的思想可以以某种方式与FireUnit集成。

对于那些在这里,因为他们需要改变在单元测试中的userAgent值,泰勒长期的解决方案的工作,但如果你想恢复到初始的userAgent或改变不止一次,你可能需要的属性设置为配置:

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

否则,你可能会遇到一个TypeError: Cannot redefine property错误。 适用于我在Chrome无头。

navigator.userAgent是只读字符串属性,所以它无法修改它

以上答案没有工作PhantomJS +打字稿。下面的代码为我工作:

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

下旬到这个话题但噶+茉莉和打字稿,并要设置userAgent属性,这将做到这一点:

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

});

此文章帮助: https://www.codeproject.com /提示/ 1036762 /嘲讽-的userAgent-与JavaScript的

更改navigator.userAgent的上Firefox和Opera经由defineGetter

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

alert( navigator.userAgent ); //iPhone 5

更改navigator.userAgent的上IE和Opera经由对象实例

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

alert( navigator.userAgent ); //iPhone5

的好处是,如果在IE浏览器控件,则可以增加一倍欺骗两者的HTTP请求,并经由EXECSCRIPT的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

没有,我怀疑你可以在JavaScript中做到这一点。但随着Firefox的用户代理切换器可以测试任何你想要的用户代理,所以为什么不使用呢?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top