78

プログラムでnavigator.userAgentをその場で変更する方法を探しています。自動化されたjavascriptユニットテスターを取得しようとして失敗したので、私はあきらめて、fireunitの使用を開始しようとしました。すぐに、JavaScriptのテストに実際のブラウザーを使用する際の壁の1つにぶつかりました。

具体的には、navigator.userAgentを変更して、数百のuserAgent文字列をシミュレートし、特定の関数で適切な検出とカバレッジを確保する必要があります。navigator.userAgentは読み取り専用なので、スタックしているようです。navigator.userAgentをモックするにはどうすればよいですか?User Agent Switcher(プラグイン)はFFのuseragentを切り替えることができますが、javascript内で切り替えることはできますか?

4

15 に答える 15

120

試す:

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

navigator.userAgent; // 'foo'

FF2とFF3でやってみた。

于 2009-08-20T15:46:04.407 に答える
25

Crescent Fresh のソリューションに追加すると、getter の再定義はnavigator.userAgentSafari 5.0.5 (Windows 7 および Mac OS X 10.6.7) では機能しないようです。

オブジェクトから継承する新しいオブジェクトを作成し、元のゲッターを非表示にする新しいゲッターをnavigator定義する必要があります。userAgentuserAgentnavigator

var __originalNavigator = navigator;
navigator = new Object();
navigator.__proto__ = __originalNavigator;
navigator.__defineGetter__('userAgent', function () { return 'Custom'; });
于 2011-05-10T12:29:34.410 に答える
24

次のソリューションは、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');
于 2014-11-12T13:36:51.127 に答える
9

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以降で動作するはずです (テスト済み) 。残念ながら、どのプラットフォームの Safari でも userAgent を変更することはできません。

編集: Safari では userAgent を変更することはできませんが、上記の別のソリューションで指摘されているように、ナビゲーターオブジェクト全体を置き換えることができます。

于 2014-03-24T16:40:44.410 に答える
4

Crescent Fresh の答えは正しいです。しかし、問題があります:__defineGetter__非推奨です:

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

非推奨 この機能は Web 標準から削除されました。一部のブラウザーはまだサポートしている可能性がありますが、廃止される過程にあります。古いプロジェクトや新しいプロジェクトでは使用しないでください。それを使用しているページまたは Web アプリは、いつでも壊れる可能性があります。

defineProperty代わりに次を使用する必要があります。

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

navigator.userAgent; // 'foo'
于 2015-01-30T11:43:37.143 に答える
4

このスレッドを更新するために、defineGetter は廃止されたため、Jasmine では機能しなくなりました。ただし、これにより、jasmine の navigator.userAgent のゲッターを変更できることがわかりました。

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

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

ジャスミンでのテストが完了したら、ナビゲーター オブジェクトをリセットすることを覚えておいてください。

于 2015-06-23T15:43:41.647 に答える
2

I guess I'd take a dependency injection approach. Instead of:

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

Maybe do 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 out" getUserAgent() by doing:

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

function getUserAgent() { // formerly 'Mock'
    // ...
}

This design still isn't completely automated (you have to manually rename the getter to perform your testing), and it adds a bunch of complexity to something as simple as operating on navigator.userAgent, and I'm not sure how you'd actually identify any bugs in myFunction, but I just figured I'd throw it out there to give you some ideas how this might be dealt with.

Maybe the idea of "dependency injection" presented here can somehow be integrated with FireUnit.

于 2009-08-20T16:43:43.590 に答える
0

navigator.userAgentは読み取り専用の文字列プロパティであるため、編集することはできません

于 2009-08-20T15:39:23.343 に答える
-3

いいえ、javascript 内で実行できるとは思えません。しかし、Firefox のユーザー エージェント スイッチャーを使用すると、必要なユーザー エージェントをテストできます。

于 2009-08-20T15:38:09.447 に答える