在javascript中嘲笑一个useragent?

Ste*_*all 63 javascript user-agent unit-testing

我正在寻找一种以编程方式动态更改navigator.userAgent的方法.在我尝试获得自动javascript单元测试器失败的尝试中,我放弃并试图开始使用fireunit.我立即猛烈抨击了使用实际浏览器进行javascript测试的一面墙.

具体来说,我需要更改navigator.userAgent来模拟几百个userAgent字符串,以确保对给定函数的正确检测和覆盖.navigator.userAgent只读,所以我好像卡住了!我怎么能模拟navigator.userAgent?用户代理切换器(插件)可以切换FF的useragent,但我可以在javascript中执行吗?

Cre*_*esh 105

尝试:

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

navigator.userAgent; // 'foo'
Run Code Online (Sandbox Code Playgroud)

在FF2和FF3中尝试过.

  • 这个解决方案可以用来设置iframe的用户代理吗? (4认同)
  • 不推荐使用`__defineGetter__`,而是使用`defineProperty`.检查我的答案如下. (3认同)

max*_*yfc 24

添加到Crescent Fresh的解决方案,重新定义navigator.userAgentgetter似乎在Safari 5.0.5中不起作用(在Windows 7和Mac OS X 10.6.7上).

需要创建一个从对象继承的新对象,navigator并定义一个新的userAgentgetter来隐藏原始的userAgentgetter navigator:

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

  • 这也适用于phantomjs ...需要新的Object.我猜它是一个webkit的东西. (6认同)

Joe*_*ard 23

以下解决方案适用于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
            });
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

例子:

setUserAgent(window, 'new user agent');
setUserAgent(document.querySelector('iframe').contentWindow, 'new user agent');
Run Code Online (Sandbox Code Playgroud)


So6*_*So6 9

对于这里的人,因为他们需要在单元测试中更改 userAgent 值,Tyler Long 的解决方案有效,但是如果您想恢复初始 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);
Run Code Online (Sandbox Code Playgroud)

否则,您可能会遇到TypeError: Cannot redefine property错误。在 Chrome Headless 上对我有用。

  • 经过反复试验,我得出了同样的结论,希望我先阅读这个答案。 (2认同)

Bun*_*dyo 7

使用Object.defineProperty应该添加几个浏览器:

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

此代码应该工作(和测试)的火狐1.5 +,Chrome浏览器6+,歌剧10.5+IE9 +.不幸的是,任何平台上的Safari都不允许更改userAgent.

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


Tyl*_*ong 5

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

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

已弃用 此功能已从 Web 标准中删除。尽管某些浏览器可能仍然支持它,但它正在被删除。不要在旧项目或新项目中使用它。使用它的页面或网络应用程序可能随时中断。

你应该使用defineProperty

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

navigator.userAgent; // 'foo'
Run Code Online (Sandbox Code Playgroud)