سؤال

أنا أبحث عن طريقة لتغيير Navigatriatically.useragent على الطاير. في محاولتي الفاشلة للحصول على اختبار وحدة JavaScript الآلي، استسلمت ومحاولة البدء في استخدام FIRTUNIT. على الفور، انتقدت واحدة من جدران استخدام متصفح فعلي لاختبار JavaScript.

على وجه التحديد، أحتاج إلى تغيير Navigator.useragent لمحاكاة بضع مئات من سلاسل UserAgent لضمان الكشف والتغطية السليم على وظيفة معينة. Navigator.useragent هو Readonly، لذلك أبدو عالقا! كيف يمكنني وهمية Navigator.useragent؟ يمكن أن يقوم مستخدمو وكيل المستخدم (البرنامج المساعد) بتبديل UserAgent FF، ولكن هل يمكنني القيام بذلك داخل JavaScript؟

هل كانت مفيدة؟

المحلول

محاولة:

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

navigator.userAgent; // 'foo'

حاول ذلك في FF2 و FF3.

نصائح أخرى

إضافة إلى حل الهلال الطازج, ، إعادة تحديد navigator.userAgent لا يبدو أن Getter يعمل في Safari 5.0.5 (على نظام التشغيل Windows 7 & Mac OS X 10.6.7).

بحاجة إلى إنشاء كائن جديد يرث من navigator كائن وتحديد جديد userAgent الحصول على إخفاء الأصل userAgent getter في 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 بتغيير UserAgent، ولكن يمكن للمرء أن يحل محل الكل الملاح كائن، كما هو مذكور في حل آخر أعلاه.

إجابة الهلال الطازجة صحيحة. ولكن هناك مشكلة: __defineGetter__ تم إهمالها:

https:/developer.mozilla.org/en-us/docs/web/javascript/reeference/global_objects/object/التراجع

إهمال تمت إزالة هذه الميزة من معايير الويب. على الرغم من أن بعض المتصفحات قد لا تزال تدعمها، إلا أنها تعمل في طورتها. لا تستخدمه في مشاريع قديمة أو جديدة. الصفحات أو تطبيقات الويب باستخدامها قد تنكسر في أي وقت.

يجب عليك استخدامها defineProperty في حين أن:

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

navigator.userAgent; // 'foo'

لتحديث هذا الموضوع، لا يعمل التراجع بعد الآن في الياسمين كما تم إهماله. ومع ذلك، وجدت أن هذا يسمح لي بتعديل Getter for Navigator.useragent في الياسمين:

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

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

فقط تذكر إعادة ضبط كائن المستكشف بمجرد الانتهاء من الاختبار في الياسمين

بالنسبة لأولئك الذين يحاولون فعل نفس الشيء في المحول هنا هو الحل:

(<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, ، لكنني احسب أنا فقط رميها هناك لإعطائك بعض الأفكار كيف يمكن التعامل مع هذا.

ربما يمكن أن تكون فكرة "حقن التبعية" المقدمة هنا بطريقة أو بأخرى مع جنبا إلى جنب.

بالنسبة لأولئك هنا لأنهم يحتاجون إلى تغيير قيمة UserAgent في اختبارات الوحدة، يعمل حل Tyler Long's Solution، ولكن إذا كنت ترغب في استعادة UserAgent الأولي أو تغييره أكثر من مرة، فربما تحتاج إلى تعيين الخاصية كقابلتك:

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

خلاف ذلك قد تعمل في TypeError: Cannot redefine property خطأ. يعمل بالنسبة لي على الكروم مقر الرئيسي.

navigator.userAgent هي خاصية سلسلة للقراءة فقط، لذلك ليس من الممكن تحريره

الأجوبة المذكورة أعلاه لم تكن تعمل من أجل phantomjs + didescript. أدنى رمز عملت بالنسبة لي:

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

في وقت متأخر من هذا الموضوع ولكن بالنسبة إلى Karma + Jasmin و Cydycript وترغب في تعيين خاصية 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.

تغيير navigator.useragent على فايرفوكس والأوبرا عبر الترتيب

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

alert( navigator.userAgent ); //iPhone 5

تغيير Navigator.useragent على IE والأوبرا عبر مثيل الكائن

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

alert( navigator.userAgent ); //iPhone5

شيء جيد هو، إذا كنت تعمل على عنصر التحكم IE WebBrowser، فيمكنك مضاعفة محاكاة ساخرة كلا من طلب HTTP و JavaScript Navigator.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

لا، أشك في أنك تستطيع القيام بذلك داخل جافا سكريبت. ولكن مع مفاد تشغيل وكيل مستخدم Firefox، يمكنك اختبار أي مستخدم تريده، فلماذا لا تستخدم ذلك؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top