Programing

자바 스크립트에서 사용자 에이전트를 조롱합니까?

lottogame 2020. 11. 23. 07:39
반응형

자바 스크립트에서 사용자 에이전트를 조롱합니까?


navigator.userAgent를 즉시 프로그래밍 방식으로 변경하는 방법을 찾고 있습니다. 자동화 된 자바 스크립트 단위 테스터를 얻기위한 실패한 시도에서 포기하고 fireunit 사용을 시작했습니다. 즉시 저는 자바 스크립트 테스트를 위해 실제 브라우저를 사용하는 벽 중 하나에 부딪 혔습니다.

특히, 주어진 함수에 대한 적절한 감지 및 적용을 보장하기 위해 수백 개의 userAgent 문자열을 시뮬레이션하도록 navigator.userAgent를 변경해야합니다. navigator.userAgent는 읽기 전용이므로 멈춘 것 같습니다! navigator.userAgent를 어떻게 모의 할 수 있습니까? User Agent Switcher (플러그인)는 FF의 useragent를 전환 할 수 있지만 javascript 내에서 할 수 있습니까?


시험:

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

navigator.userAgent; // 'foo'

FF2 및 FF3에서 시도했습니다.


Crescent Fresh의 솔루션 에 추가 하여 navigator.userAgentgetter를 재정의하는 것은 Safari 5.0.5 (Windows 7 및 Mac OS X 10.6.7)에서 작동하지 않는 것 같습니다.

객체에서 상속하는 새 객체를 만들고 원래 getter 를 숨기려면 navigatoruserAgentgetter를 정의해야합니다 .userAgentnavigator

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

다음 솔루션은 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');

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 변경을 허용하지 않지만 위의 다른 솔루션에서 지적한 것처럼 전체 탐색기 객체를 대체 할 수 있습니다 .


Crescent Fresh의 대답이 맞습니다. 그러나 문제가 있습니다. __defineGetter__is deprecated :

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에서 더 이상 작동하지 않습니다. 그러나 이것이 jasmine에서 navigator.userAgent의 getter를 수정할 수 있음을 발견했습니다.

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

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.


For those here because they need to change the userAgent value in unit tests, Tyler Long's solution works, but if you want to restore the initial userAgent or change it more than once, you will probably need to set the property as configurable:

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

Otherwise you might run into a TypeError: Cannot redefine property error. Works for me on Chrome Headless.


navigator.userAgent is a read-only string property, so its not possible to edit it


Above answers were not working for PhantomJS + TypeScript. Below code worked for me:

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

Late to this topic but for Karma + Jasmin and Typescript and want to set the userAgent property this will do it:

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

});

This article helped: https://www.codeproject.com/Tips/1036762/Mocking-userAgent-with-JavaScript


Change navigator.userAgent on Firefox and Opera via defineGetter

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

alert( navigator.userAgent ); //iPhone 5

Change navigator.userAgent on IE and Opera via object instance

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

alert( navigator.userAgent ); //iPhone5

Good thing is, if you work on IE webbrowser control, you can double spoof both HTTP request and JavaScript navigator.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

No, i doubt you can do it within javascript. But with Firefox's User Agent Switcher you can test whatever useragent you want, so why not just use that?

참고URL : https://stackoverflow.com/questions/1307013/mocking-a-useragent-in-javascript

반응형