Jsdom: لا يعمل localstorage داخل jsdom

تم إنشاؤها على ٢٨ مايو ٢٠١٥  ·  29تعليقات  ·  مصدر: jsdom/jsdom

مرحبا يا اصدقاء،

هل يعمل شخص ما على تنفيذ واجهات برمجة تطبيقات localStorage / sessionStorage في jsdom؟

يعتبر،
ألفارو

best-fixed-by-webidl2js feature html living standard

التعليق الأكثر فائدة

حل justinmchase رائع للاختبار. قد ترغب في إضافة sessionStorage أيضًا.

    var jsdom = require('jsdom').jsdom;
    document = jsdom('hello world');
    window = document.defaultView;
    navigator = window.navigator;
    window.localStorage = window.sessionStorage = {
        getItem: function (key) {
            return this[key];
        },
        setItem: function (key, value) {
            this[key] = value;
        }
    };

FAIK هذا يسخر جيدا. يصلح بعض اختباراتي. شكرا.

ال 29 كومينتر

هذه للأسف صعبة للغاية بدون وكلاء ES2015 :(. يمكننا الحصول على عمل getItem / setItem / إلخ ، ولكن تطبيق تعديلات الخاصية بشكل صحيح ليس ممكنًا حقًا.

سيكون من الجيد أن يكون لديك على الأقل تجربة في الذاكرة ، على سبيل المثال ، LocalStorage لها سلوك مشابه لـ sessionStorage
يجب أن يكون أقل تعقيدًا أليس كذلك؟

لا ، لأننا لا نستطيع محاكاة API بشكل كافٍ. بالنسبة لحالات الاستخدام البسيطة (أي استخدام getItem / setItem فقط) ، فقد ينجح الأمر ، ولكن بمجرد الوصول إلى الخصائص مباشرةً ، سيتعطل تنفيذنا.

Sebmaster : لقد كتبت

https://github.com/mnahkies/node-storage-shim

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

يسمح Real localStorage بإعداد هذه المفاتيح باستخدام setItem ، لكن استخدام الوصول إلى الخاصية يفقد تعريفات الوظائف ، وبمجرد التعيين لا يمكنك الوصول إلى هذه المفاتيح باستخدام خاصية الوصول أيضًا.

ولكن بصرف النظر عن هذه القيود ، أعتقد أنه تطبيق مخلص للغاية:
https://github.com/mnahkies/node-storage-shim/blob/master/test.js

هل يمكنك توضيح جوانب واجهة برمجة التطبيقات التي لا يمكن محاكاتها بشكل جيد بما فيه الكفاية؟

بقدر ما أستطيع أن أقول إن الشيء الرئيسي الذي لا يمكن محاكاته حاليًا هو إطلاق حدث التخزين استجابة لإعداد الخاصية.

سأكون سعيدًا لدمجها مع jsdom إذا كنت تعتقد أنها كاملة بما فيه الكفاية مع التحذيرات المذكورة.

هل يمكنك توضيح جوانب واجهة برمجة التطبيقات التي لا يمكن محاكاتها بشكل جيد بما فيه الكفاية؟

يدعم localStorage تعيين أي اسم خاصية مباشرة على الواجهة كما في

localStorage.myKey = "myVal";
localStorage.getItem('myKey') // 'myVal'

localStorage.setItem('otherKey', 'val')
localStorage.otherKey // 'val'

التي يمكننا محاكاتها إلى حد ما من خلال إنشاء أداة getter دائمًا إذا تم استدعاء setItem ، لكننا لن نكون قادرين على دعم الطريقة الأخرى (تعيين الخصائص التعسفية على الكائن) بدون وكلاء.

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

نعم ، هذا جانب مهم جدًا للتخزين المحلي. نحتاج إلى ES6 Proxy لهذا الغرض ، v8 لم ينفذه بعد (Microsoft و mozilla يمتلكانه بالفعل!)

لقد ضربنا هذا الحاجز نفسه في مواقع متعددة في منطقة jsdom

لا أفهم سبب عدم نجاح ذلك:

var localStorage = {
  getItem: function (key) {
    return this[key];
  },
  setItem: function (key, value) {
    this[key] = value;
  }
};

localStorage.setItem('foo', 'bar');
localStorage.bar = 'foo'
assert(localStorage.foo === 'bar')
assert(localStorage.getItem('bar') === 'foo')

ماذا ينقصني؟

عندما تقوم بتعيين العناصر باستخدام الوصول إلى الخاصية ، فإن التخزين المحلي الحقيقي يقوم دائمًا بإجبار القيمة على سلسلة.

على سبيل المثال:

localStorage.foo = 35
assert(typeof localStorage.foo === "string")

localStorage.foo = {my: 'object'}
assert(localStorage.foo === "[object Object]")

هذا غير ممكن بدون وكيل ES6 ، وهو تعبير هام للتخزين المحلي

أرى. على الرغم من أنك تفعل هذا العار عليك ؛)

أعتقد أن الأهم من ذلك ، إذا كنت تفعل ذلك باستخدام الكائنات ، فمن المحتمل أن يكون خطأ قد يتم إخفاءه بواسطة jsdom ثم يحدث في المتصفح

+1

+1

ربما يعمل شيء من هذا القبيل https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage ؟

أعتقد أنك ستجد أنك لا تزال تفتقد بعض السلوكيات التي يمتلكها التخزين المحلي الحقيقي كما هو موضح أعلاه.

الحل المرتبط يجعل polyfill جيدًا ولكني لا أعتقد أنه سيكون تنفيذًا مخلصًا بدرجة كافية لـ jsdom

mnahkies بصراحة ، إن

+1 إلى التعليق الأخير ، مثال على MDN يستخدم setItem و getItem كوصلات للتخزين. لذلك يمكن اعتبارها حالة استخدام شائعة أننا نفتقدها حقًا.

في الوقت الحالي ، أقوم بحلها بـ jasmine.createSpy (لأنني أعمل مع Jasmine ، يمكن لمقاتلي التجسس الآخرين أيضًا القيام بذلك)

حل justinmchase رائع للاختبار. قد ترغب في إضافة sessionStorage أيضًا.

    var jsdom = require('jsdom').jsdom;
    document = jsdom('hello world');
    window = document.defaultView;
    navigator = window.navigator;
    window.localStorage = window.sessionStorage = {
        getItem: function (key) {
            return this[key];
        },
        setItem: function (key, value) {
            this[key] = value;
        }
    };

FAIK هذا يسخر جيدا. يصلح بعض اختباراتي. شكرا.

يعمل على إصلاح الاختبارات الخاصة بك حتى يكتب شخص ما عن طريق الخطأ كائنًا إلى التخزين المحلي باستخدام الوصول إلى الخاصية ويخلق خطأً خفيًا.

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

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

حان الوقت!!!

Node.js v6 خرج ومعه ... الوكلاء.

Sebmaster ، هل ستكون مستعدًا لتحديث webidl2js لتتمكن من إنشاء وكلاء عند وجود حروف / محددات / محذوفات مسماة؟ أعتقد أننا يجب أن نستهدف هذا الطلب أولاً ، قبل القلق بشأن أشياء أخرى مثل NamedNodeMap أو NodeList أو أي شيء آخر. هذا لطيف وقائم بذاته ولن يؤثر على أداء الأساسيات الأساسية.

https://html.spec.whatwg.org/multipage/webstorage.html#storage -2 لديه IDL الذي نحتاج إلى دعمه. أعتقد أن الطريقة التي يجب اتباعها هي جعل الوكيل يحصل على سلوك مفوض إلى getItem الضمني ، وما إلى ذلك.

+1

يمكنك استخدام node-localstorage

var LocalStorage = require('node-localstorage').LocalStorage;
global.localStorage = new LocalStorage('./build/localStorageTemp');

global.document = jsdom('');

global.window = document.defaultView;
global.window.localStorage = global.localStorage;

justinmchaseadjavaherian كنت ألعب مع حولها jsdom التي يمكنني استخدام لاختبار في كل من رد فعل-JWT-المصادقة و تتفاعل-JWT-المصادقة-مسترجع ويعمل كبيرة. ومع ذلك ، فقد كنت أعمل أيضًا على فحوصات البيئة localStorage و sessionStorage . لقد واجهت نفس المشكلة تمامًا وهي كيفية اختبارها بشكل صحيح ويعمل ملفك البولي بشكل رائع. شكرا يا رفاق! سيكون من الرائع أن يأتي مع jsdom افتراضيًا.

يتوفر دعم webidl2js لهذا الآن في مكانه. إذا كان الناس يريدون أخذ هذا الأمر ، أقترح دراسة تطبيق DOMStringList (لمجموعة البيانات) التي وصلت مؤخرًا.

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

أود العمل على تنفيذ هذا. يمكنك تعيين المشكلة لي.

يعمل هذا الوهمي بشكل أفضل لأنه عندما لا يتم تخزين المفتاح ، من المفترض أن يُرجع localStorage.getItem() null ، وليس undefined :

const jsdom = require('jsdom');
// setup the simplest document possible
const doc = jsdom.jsdom('<!doctype html><html><body></body></html>');;

// get the window object out of the document
const win = doc.defaultView;

win.localStorage = win.sessionStorage = {
  getItem: function(key) {
    const value = this[key];
    return typeof value === 'undefined' ? null : value;
  },
  setItem: function (key, value) {
    this[key] = value;
  },
  removeItem: function(key) {
    return delete this[key]
  }
};

// set globals for mocha that make access to document and window feel
// natural in the test environment
global.document = doc;
global.window = win;

لماذا هو مناسب؟ السطر أدناه يعمل بشكل جيد في بيئة المتصفح. فشل json.parse() إذا تجاوز undefined كوسيطة ، لكنه يعمل بشكل جيد مع null كمعامل:

let users = JSON.parse(localStorage.getItem('users')) || [];

simoami فقط احترس من تسلسل win.localStorage = win.sessionStorage = { ... } . إنه نفس مرجع الكائن المعين لكلا المتغيرين ، لذا فإن استدعاء وظائف get / set لأي منهما سيصل إلى نفس الكائن الأساسي. على سبيل المثال ، استدعاء localStorage.set('foo', 'bar') يعني أن sessionStorage.get('foo') سيعمل - قد يكون هذا مناسبًا للاختبارات البسيطة ، لكنه سيؤدي إلى إفساد أي شيء يتطلب مساحة تخزين منفصلة.

https://gist.github.com/rkurbatov/17468b2ade459a7498c8209800287a03 - نستخدم هذا polyfill لكل من المخازن المحلية / الجلسة. يعتمد على https://github.com/capaj/localstorage-polyfill بواسطةcapaj

أولئك الذين يتعثرون في هذا الموضوع لاحقًا ، بعد التحسينات الأخيرة في jsdom ، تحتاج إلى تعيين window._localStorage لتخزينك الساخر

كتعليقات ، لم أتمكن من العثور على أحداث التخزين المحلية الأصلية المذكورة كحل لهذه المشكلة

وكتنبيه لأي شخص يستخدم jsdom بالتوازي ويستخدم localStorage بكثافة ، فإن node-localstorage وما إلى ذلك غير مجدية إلى حد كبير ، يمكنك أيضًا إعادة اختراع العجلة ، فهي ليست مصممة للاستخدام الموازي ، أيضًا الأشياء الأساسية مثل for(var key in localStorage) أو Object.keys(localStorage) وما إلى ذلك لا تعمل أيضًا

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات