Se moquer d'un agent utilisateur en javascript?

je cherche un moyen de changer programmatiquement le navigateur.userAgent à la volée. Dans ma tentative ratée d'obtenir un testeur automatique d'unité javascript, j'ai abandonné et essayé de commencer à utiliser fireunit. Immédiatement, j'ai claqué dans l'un des murs de l'aide d'un navigateur pour le test javascript.

en particulier, je dois changer de navigateur.userAgent pour simuler quelques centaines de chaînes userAgent pour assurer une détection et une couverture adéquates sur une fonction donnée. Navigator.userAgent est en lecture seule, alors il me semble coincé! Comment puis-je me moquer de navigator?userAgent? User Agent Switcher (plugin) peut commuter L'useragent de FF, mais puis-je le faire dans javascript?

53
demandé sur Stefan Kendall 2009-08-20 19:34:05

13 réponses

, Essayez:

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

navigator.userAgent; // 'foo'

a essayé en FF2 et FF3.

92
répondu Crescent Fresh 2009-08-20 15:54:34

ajouté à solution de Crescent Fresh , redéfinissant le navigator.userAgent getter ne semble pas fonctionner dans Safari 5.0.5 (sur Windows 7 & Mac OS X 10.6.7).

besoin de créer un nouvel objet qui hérite de l'objet navigator et de définir un nouveau userAgent getter pour cacher l'original userAgent getter dans navigator :

var __originalNavigator = navigator;
navigator = new Object();
navigator.__proto__ = __originalNavigator;
navigator.__defineGetter__('userAgent', function () { return 'Custom'; });
22
répondu maxyfc 2017-05-23 11:54:05

la solution suivante fonctionne en Chrome, Firefox, Safari, IE9+ et aussi avec 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
            });
        }
    }
}

exemples:

setUserAgent(window, 'new user agent');
setUserAgent(document.querySelector('iframe').contentWindow, 'new user agent');
19
répondu Joel Richard 2015-03-01 12:38:09

Utilisant L'Objet.defineProperty devrait ajouter plusieurs navigateurs supplémentaires à la composition:

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

ce code devrait fonctionner (et a été testé) dans Firefox 1.5+ , Chrome 6+ , Opera 10.5+ et IE9+ . Malheureusement Safari sur n'importe quelle plate-forme ne permet pas de changer l'agent utilisateur.

Edit: Safari ne permet pas de changer l'userAgent, mais on peut remplacer le objet navigator entier, comme indiqué dans une autre solution ci-dessus.

6
répondu Bundyo 2015-02-09 16:31:05

la réponse de Crescent Fresh est correcte. Mais il y a un problème: __defineGetter__ est déprécié:

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

déprécié Cette fonctionnalité a été retirée des normes Web. Bien que certains navigateurs peuvent encore soutenir, il est dans le processus de être tomber. Ne l'utilisez pas dans des projets anciens ou nouveaux. Pages ou applications Web à l'aide, elle peut se briser à tout moment.

vous devez utiliser defineProperty à la place:

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

navigator.userAgent; // 'foo'
3
répondu Tyler Long 2015-01-30 11:43:37

pour mettre à jour ce fil, defineGetter ne fonctionne plus dans Jasmine car il a été déprécié. Cependant, j'ai trouvé que cela me permet de modifier le getter pour navigator.userAgent à jasmine:

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

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

n'oubliez pas de réinitialiser l'objet navigator une fois que vous avez terminé les tests dans jasmine

3
répondu fdvj 2015-06-23 15:43:41

pour ceux qui essaient de faire la même chose à la typographie voici la solution:

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

navigator.userAgent; // 'foo'

ou même chose pour la langue:

(<any>navigator)['__defineGetter__']('language', function(){
    return 'de-DE';
});
2
répondu Miroslav Jonas 2016-10-20 11:32:26

je suppose que j'ai une approche d'injection de dépendance. Au lieu de:

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

peut-être faire quelque chose comme:

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

alors vous pouvez "mock out " getUserAgent() en faisant:

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

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

cette conception n'est toujours pas complètement automatisée (vous devez renommer manuellement le getter pour effectuer vos tests), et il ajoute un tas de complexité à quelque chose d'aussi simple que l'exploitation sur navigator.userAgent , et je ne suis pas sûr comment vous avez en fait identifié tous les bogues dans myFunction , mais j'ai juste pensé que je voudrais le jeter là-bas pour vous donner quelques idées comment cela pourrait être traité.

peut-être que l'idée de "dependency injection" présentée ici peut être intégrée à FireUnit.

1
répondu Grant Wagner 2009-08-20 16:43:43

navigator.userAgent est une propriété de chaîne de caractères en lecture seule, il n'est donc pas possible de l'éditer

0
répondu Lil'Monkey 2011-03-20 07:02:33

ci-dessus les réponses ne fonctionnaient pas pour PhantomJS + TypeScript. Ci-dessous code travaillé pour moi:

var __originalNavigator = navigator;
(window as any).navigator = new Object();
navigator["__proto__"] = __originalNavigator["__proto__"];
navigator["__defineGetter__"]('userAgent', function () { return 'Custom'; });
0
répondu blackspacer 2017-08-22 13:29:49

en retard à ce sujet mais pour Karma + Jasmin et dactylographier et si vous voulez définir la propriété userAgent cela le fera:

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

});

cet article a aidé: https://www.codeproject.com/Tips/1036762/Mocking-userAgent-with-JavaScript

0
répondu Avram Virgil 2018-08-06 14:15:49

Non, Je doute que vous puissiez le faire avec javascript. Mais avec L'Agent utilisateur de Firefox Switcher vous pouvez tester n'importe quel agent utilisateur que vous voulez, alors pourquoi ne pas simplement utiliser cela?

-1
répondu Marius 2009-08-20 15:38:09

Changer de navigateur.userAgent sur Firefox et Opera via defineGetter

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

alert( navigator.userAgent ); //iPhone 5

Changer de navigateur.userAgent sur IE et Opera via l'instance de l'objet

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

alert( navigator.userAgent ); //iPhone5

bonne chose est, si vous travaillez sur IE webbrowser contrôle, vous pouvez double spoof demande HTTP et JavaScript navigateur.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
-1
répondu Priince paul Gates 2014-05-06 22:45:28