Издеваясь над useragent в javascript?



Я ищу способ программно изменить навигатора.userAgent на лету. В моей неудачной попытке получить автоматический модульный тестер javascript я сдался и попытался начать использовать fireunit. Сразу же я врезался в одну из стен использования фактического браузера для тестирования javascript.



в частности, мне нужно менять навигатор.userAgent для имитации нескольких сотен строк userAgent для обеспечения правильного обнаружения и покрытия данной функции. навигатор.userAgent только для чтения, так что я, кажется, застрял! Как я могу издеваться над навигатором.userAgent? User Agent Switcher (плагин) может переключать useragent FF, но могу ли я сделать это в javascript?

1077   13  

13 ответов:

попробуй:

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

navigator.userAgent; // 'foo'

пробовал в FF2 и FF3.

на решение Crescent Fresh, переиначивая navigator.userAgent getter, похоже, не работает в Safari 5.0.5 (на Windows 7 и Mac OS X 10.6.7).

нужно создать новый объект, который наследует от navigator "объект" и определить новый userAgent getter, чтобы скрыть оригинал userAgent getter in navigator:

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

следующее решение работает в Chrome, Firefox, Safari, IE9+ , а также с 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
            });
        }
    }
}

примеры:

setUserAgent(window, 'new user agent');
setUserAgent(document.querySelector('iframe').contentWindow, 'new user agent');

Использование Объекта.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.

Edit: Safari не позволяет изменить userAgent, но можно заменить весь навигатор объект, как указано в другом решение выше.

Crescent Fresh ответ правильный. Но есть проблема: __defineGetter__ осуждается:

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

устаревший Эта функция была удалена из веб-стандартов. Хотя некоторые браузеры все еще могут поддерживать его, он находится в процессе быть сняты. Не используйте его в старых или новых проектах. Страницы или веб-приложения использование его может сломаться в любое время.

вы должны использовать defineProperty вместо:

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

navigator.userAgent; // 'foo'

чтобы обновить этот поток, defineGetter больше не работает в Jasmine, поскольку он был устаревшим. Однако я обнаружил, что это позволяет мне изменить геттер для навигатора.userAgent в жасмин:

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

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

просто помните, сброс объекта навигатора, как только вы закончите тестирование в jasmine

для тех, кто пытается сделать то же самое в TypeScript вот решение:

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

этот дизайн все еще не полностью автоматизирован (вам нужно вручную переименовать геттер для выполнения вашего тестирования), и он добавляет кучу сложности к чему-то столь же простому, как работа с navigator.userAgent, и я не уверен, как бы вы на самом деле определить какие-либо ошибки в myFunction, но я просто я решил выбросить его туда, чтобы дать вам некоторые идеи, как с этим можно справиться.

возможно, идея" инъекции зависимости", представленная здесь, может быть каким-то образом интегрирована с FireUnit.

navigator.userAgent является строковым свойством только для чтения, поэтому его невозможно редактировать

выше ответы не работали для PhantomJS + TypeScript. Ниже код работал для меня:

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

поздно к этой теме, но для Karma + Jasmin и Typescript и хотите установить свойство 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/Tips/1036762/Mocking-userAgent-with-JavaScript

Нет, я сомневаюсь, что вы можете сделать это в JavaScript. Но с помощью переключателя агента пользователя Firefox вы можете проверить любой useragent, который вы хотите, так почему бы просто не использовать его?

сменить навигатор.userAgent на Firefox и Opera через defineGetter

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

alert( navigator.userAgent ); //iPhone 5

сменить навигатор.userAgent на IE и Opera через экземпляр объекта

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

alert( navigator.userAgent ); //iPhone5

хорошо, что если вы работаете над управлением IE webbrowser, вы можете дважды подделать как HTTP-запрос, так и JavaScript-навигатор.userAgent через 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

Comments

    Ничего не найдено.