Jsdom: penyimpanan lokal tidak berfungsi dalam jsdom

Dibuat pada 28 Mei 2015  ·  29Komentar  ·  Sumber: jsdom/jsdom

Hai semuanya,

Apakah seseorang bekerja untuk mengimplementasikan API localStorage/sessionStorage di jsdom?

Salam,
Alvaro

best-fixed-by-webidl2js feature html living standard

Komentar yang paling membantu

Solusi @justinmchase sangat bagus untuk pengujian. Mungkin ingin menambahkan sessionStorage juga.

    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 ini mengolok-olok dengan baik. Memperbaiki beberapa pengujian saya. Terima kasih.

Semua 29 komentar

Sayangnya, ini cukup sulit tanpa proksi ES2015 :(. Kita bisa membuat getItem/setItem/etc. berfungsi, tetapi menerapkan modifikasi properti dengan benar sebenarnya tidak mungkin.

Akan menyenangkan untuk memiliki setidaknya pengalaman dalam memori yaitu localStorage yang memiliki perilaku yang mirip dengan sessionStorage
itu seharusnya tidak terlalu rumit bukan?

Tidak, karena kami tidak dapat meniru API dengan cukup baik. Untuk kasus penggunaan sederhana (yaitu hanya menggunakan getItem/setItem) mungkin berhasil, tetapi segera setelah properti diakses secara langsung, implementasi kita akan rusak.

@Sebmaster : Saya menulis shim sederhana untuk antarmuka penyimpanan untuk digunakan dalam pengujian unit saya untuk paket terpisah.

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

Saat ini merupakan solusi sementara, dan melarang pengaturan kunci yang berbenturan dengan nama metode antarmuka penyimpanan. Itu juga saat ini tidak mengimplementasikan bagian pengaktifan peristiwa dari spesifikasi.

Penyimpanan lokal nyata memungkinkan pengaturan kunci ini menggunakan setItem, tetapi menggunakan akses properti tidak menerbangkan definisi fungsi, dan setelah disetel, Anda juga tidak dapat mengakses kunci tersebut menggunakan akses properti.

Namun selain dari batasan ini, saya pikir ini adalah implementasi yang cukup setia:
https://github.com/mnahkies/node-storage-shim/blob/master/test.js

Bisakah Anda menguraikan aspek API apa yang tidak dapat ditiru dengan cukup baik?

Sejauh yang saya tahu hal utama yang saat ini tidak mungkin untuk ditiru adalah peristiwa penyimpanan yang diaktifkan sebagai respons terhadap pengaturan properti.

Saya akan senang untuk mencoba mengintegrasikannya dengan jsdom jika Anda pikir itu cukup lengkap dengan peringatan yang disebutkan.

Bisakah Anda menguraikan aspek API apa yang tidak dapat ditiru dengan cukup baik?

localStorage mendukung pengaturan nama properti apa pun secara langsung pada antarmuka seperti pada

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

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

yang dapat kami tiru dengan selalu membuat pengambil jika setItem dipanggil, tetapi kami tidak akan dapat mendukung sebaliknya (menyetel properti arbiter pada objek) tanpa proxy.

Benar, saya kira masalah utama sehubungan dengan pengaturan kunci dengan akses properti adalah bahwa kita tidak dapat memaksa nilai ke string dengan benar, seperti yang dilakukan antarmuka sebenarnya.

Ya itu adalah aspek yang sangat penting dari penyimpanan lokal. Kami membutuhkan ES6 Proxy untuk ini, v8 belum mengimplementasikannya (microsoft dan mozilla sudah memilikinya!)

Kami mencapai blok jalan yang sama ini di beberapa lokasi di jsdom

Saya tidak mengerti mengapa ini tidak berhasil:

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

Apa yang saya lewatkan?

Saat Anda menyetel item menggunakan akses properti, penyimpanan lokal yang sebenarnya selalu memaksa nilai menjadi string.

Misalnya:

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

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

Ini tidak mungkin tanpa proxy ES6, dan merupakan karakteristik penting dari Penyimpanan lokal

Jadi begitu. Meskipun jika Anda melakukan itu memalukan;)

Saya pikir yang lebih penting jika Anda melakukannya dengan objek, itu mungkin bug yang akan ditutupi oleh jsdom dan kemudian terjadi di browser

+1

+1

mungkin sesuatu seperti ini akan berfungsi https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage ?

Saya pikir Anda akan menemukan bahwa Anda masih kehilangan beberapa perilaku yang dimiliki penyimpanan lokal yang sebenarnya seperti yang dijelaskan di atas.

Solusi tertaut membuat polyfill yang baik tetapi saya tidak berpikir itu akan menjadi implementasi yang cukup setia untuk jsdom

@mnahkies Sejujurnya, polyfill lebih baik daripada tidak sama sekali (yang Anda miliki sekarang). Anda hanya harus memasukkannya dan menambahkan beberapa dokumentasi tentang batasan yang 99% orang tidak akan pernah capai.

Memberi +1 pada komentar terakhir, contoh pada MDN menggunakan setItem dan getItem sebagai pengakses penyimpanan. Jadi itu bisa dianggap sebagai kasus penggunaan umum yang benar-benar kita lewatkan.

Untuk saat ini, saya menyelesaikannya dengan jasmine.createSpy (karena saya bekerja dengan Jasmine, lib mata-mata lain juga dapat melakukannya)

Solusi @justinmchase sangat bagus untuk pengujian. Mungkin ingin menambahkan sessionStorage juga.

    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 ini mengolok-olok dengan baik. Memperbaiki beberapa pengujian saya. Terima kasih.

Ini memperbaiki pengujian Anda sampai seseorang secara tidak sengaja menulis objek ke penyimpanan lokal menggunakan akses properti dan membuat bug halus.

Menurut pendapat saya, Anda akan lebih baik memiliki objek yang mengabstraksi penyimpanan dengan backend penyimpanan yang dapat ditukar yang dapat Anda operasikan dengan solusi memori dalam pengujian Anda.

Ini juga memudahkan untuk melakukan hal-hal yang lebih kompleks seperti enkripsi, kompresi, menulis melalui caching dll jika Anda memerlukannya di kemudian hari.

Saatnya!!!

Node.js v6 keluar, dan dengan itu... PROXIES.

@Sebmaster , apakah Anda siap memperbarui webidl2js untuk dapat menghasilkan proxy ketika ada getter/setter/penghapus bernama? Saya pikir kita harus menargetkan permintaan ini terlebih dahulu, sebelum mengkhawatirkan hal-hal lain seperti NamedNodeMap atau NodeList atau apa pun. Ini bagus dan mandiri dan tidak akan memengaruhi kinerja primitif inti.

https://html.spec.whatwg.org/multipage/webstorage.html#storage -2 memiliki IDL yang perlu kami dukung. Saya pikir cara untuk melakukannya adalah dengan membuat proxy mendapatkan delegasi perilaku ke getItem impl, dll.

+1

Anda dapat menggunakan 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;

@adjavaherian @justinmchase Saya bermain-main dengan jsdom yang saya gunakan untuk pengujian di react-jwt-auth dan react-jwt-auth-redux dan itu berfungsi dengan baik. Namun, saya juga telah mengerjakan pemeriksaan kebalikan - lingkungan untuk pengembangan isomorfik. Salah satu cek adalah localStorage dan sessionStorage . Saya telah menjalankan masalah yang sama persis tentang cara mengujinya dengan benar dan polyfil Anda berfungsi dengan baik. Terima kasih kawan! Akan lebih bagus jika dilengkapi dengan jsdom secara default.

dukungan webidl2js untuk ini sekarang ada. Jika orang ingin mengambil ini, saya sarankan mempelajari implementasi DOMStringList (untuk dataset) yang baru saja mendarat.

Untuk saat ini kami dapat menyimpan semuanya di memori, meskipun pada akhirnya kami harus menyediakan cara penyimpanan ke disk jika orang menginginkannya. (Apakah orang menginginkan itu?)

Saya ingin bekerja untuk mengimplementasikan ini. Anda dapat menetapkan masalah ini kepada saya.

tiruan ini berfungsi lebih baik karena ketika kunci tidak disimpan, localStorage.getItem() seharusnya mengembalikan null , bukan 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;

Mengapa relevan? Baris di bawah ini berfungsi dengan baik di lingkungan browser. json.parse() gagal jika melewati undefined sebagai argumen, tetapi berfungsi dengan baik dengan null sebagai parameter:

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

@simoami Hati- hati dengan win.localStorage = win.sessionStorage = { ... } . Ini adalah referensi objek yang sama yang ditetapkan untuk kedua variabel sehingga memanggil fungsi get/set akan mengakses objek dasar yang sama. Misalnya memanggil localStorage.set('foo', 'bar') berarti sessionStorage.get('foo') akan berfungsi -- ini mungkin baik-baik saja untuk pengujian sederhana, tetapi akan mengacaukan apa pun yang memerlukan penyimpanan terpisah.

https://Gist.github.com/rkurbatov/17468b2ade459a7498c8209800287a03 - kami menggunakan polyfill ini untuk penyimpanan lokal/sesi. Ini didasarkan pada https://github.com/capaj/localstorage-polyfill oleh @capaj

Mereka yang tersandung ke utas ini nanti, setelah peningkatan jsdom baru-baru ini, Anda perlu mengatur window._localStorage ke penyimpanan tiruan Anda sendiri

Sebagai umpan balik, saya tidak dapat menemukan acara localStorage asli yang disebutkan sebagai solusi untuk masalah ini

Dan sebagai peringatan bagi siapa saja yang menggunakan jsdom secara paralel dan banyak menggunakan localStorage, node-localstorage dll. hampir tidak berguna, Anda mungkin juga menemukan kembali roda, mereka tidak dirancang untuk penggunaan paralel, juga hal-hal dasar seperti for(var key in localStorage) atau Object.keys(localStorage) dll. juga tidak berfungsi

Apakah halaman ini membantu?
0 / 5 - 0 peringkat