자바스크립트에서 사용자 에이전트를 조롱하시나요?
-
19-09-2019 - |
문제
저는 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.userAgent
Getter는 Safari 5.0.5에서 작동하지 않는 것 같습니다 (Windows 7 & Mac OS x 10.6.7).
상속하는 새 개체를 만들어야합니다. navigator
새로운 것을 반대하고 정의합니다 userAgent
원본을 숨기려고합니다 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');
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+, 크롬 6+, 오페라 10.5+ 그리고 IE9+. 불행히도 모든 플랫폼의 Safari는 UserAgent를 변경할 수 없습니다.
편집 : Safari는 사용자 에이전트를 변경할 수 없지만 전체를 대체 할 수 있습니다. 항해자 위의 다른 솔루션에서 지적한 대상.
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에서 작동하지 않습니다. 그러나 나는 이것이 Jasmine의 Navigator.useragent의 getter를 수정할 수 있음을 발견했습니다.
navigator = {
get userAgent() {
return 'agent';
}
}
console.log(navigator.userAgent); // returns 'agent'
자스민에서 테스트를 마치면 네비게이터 개체를 재설정하는 것을 기억하십시오.
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'
// ...
}
이 디자인은 아직 완전히 자동화되지 않았으며(테스트를 수행하려면 getter의 이름을 수동으로 변경해야 함) 작업처럼 간단한 것에 많은 복잡성을 추가합니다. navigator.userAgent
, 실제로 버그를 어떻게 식별할지 잘 모르겠습니다. myFunction
, 하지만 저는 이 문제를 어떻게 처리할 수 있는지 몇 가지 아이디어를 제공하기 위해 그것을 거기에 던져야겠다고 생각했습니다.
어쩌면 여기에 제시된 "의존성 주입" 아이디어가 어떻게든 FireUnit과 통합될 수 있을 것입니다.
단위 테스트에서 사용자 가건 값을 변경해야하므로 Tyler Long의 솔루션은 작동하지만 초기 사용자 가건을 복원하거나 두 번 이상 변경하려면 속성을 구성 가능한 것으로 설정해야 할 것입니다.
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);
그렇지 않으면 당신은 a TypeError: Cannot redefine property
오류. Chrome Headless에서 나를 위해 일합니다.
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 and 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
DefineGetter를 통해 Firefox 및 Opera에서 Navigator.useragent를 변경하십시오
navigator.__defineGetter__('userAgent', function(){
return( "iPhone 5" );
});
alert( navigator.userAgent ); //iPhone 5
객체 인스턴스를 통해 IE 및 Opera에서 Navigator.useragent를 변경하십시오
var navigator = new Object;
navigator.userAgent = 'iPhone 5';
alert( navigator.userAgent ); //iPhone5
좋은 점은 IE Webbrowser Control에서 작업하면 execscript를 통해 HTTP 요청과 JavaScript Navigator.useragent를 두 배로 스푸핑 할 수 있다는 것입니다.
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
아니요, JavaScript 내에서 할 수 있다고 의심 스럽습니다. 그러나 Firefox의 사용자 에이전트 스위처를 사용하면 원하는 사용자 에이전트를 테스트 할 수 있으므로 왜 사용하지 않겠습니까?