blob: 87e926a576f827efc3597e3b31c5154c3f310c24 [file] [log] [blame]
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';
/**
* @fileoverview Common storage API tests.
*/
/**
* Testsuite for the generic storage API.
*
* Each implementation should call this to verify functionality.
*/
lib.Storage.ApiTest = function() {
/**
* @param {!Object} storage The storage object under test.
* @return {boolean} Whether the storage type supports event testing.
*/
function storageSupportsEventTests(storage) {
// We can't test Local storage directly. sessionStorage never fires events,
// and localStorage doesn't fire in the same page. So there's that.
// https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API
return !(storage instanceof lib.Storage.Local);
}
/**
* Verify single get/set APIs.
*/
it('get-set', async function() {
const storage = this.storage;
// Make sure we can set an item and read it back out.
let value = await storage.getItem('foo');
assert.isUndefined(value);
await storage.setItem('foo', 1);
value = await storage.getItem('foo');
assert.equal(value, 1);
});
/**
* Verify multiple get/set APIs.
*/
it('gets-sets', async function() {
const storage = this.storage;
let value = await storage.getItems(null);
assert.deepEqual(value, {});
value = await storage.getItems(['foo']);
assert.deepEqual(value, {});
await storage.setItems({'foo': 1, 'bar': 2, 'cow': 3});
value = await storage.getItems(['foo']);
assert.deepEqual(value, {'foo': 1});
value = await storage.getItems(['foo', 'bar']);
assert.deepEqual(value, {'foo': 1, 'bar': 2});
value = await storage.getItems(null);
assert.deepEqual(value, {'foo': 1, 'bar': 2, 'cow': 3});
});
/**
* Verify remove API.
*/
it('remove', async function() {
const storage = this.storage;
// Add some items.
await storage.setItems({'foo': 1, 'bar': 2});
// Make sure things are in there.
let value = await storage.getItems(null);
assert.deepEqual(value, {'foo': 1, 'bar': 2});
// Remove the item.
await storage.removeItem('foo');
// Make sure it's gone.
value = await storage.getItems(null);
assert.deepEqual(value, {'bar': 2});
});
/**
* Verify remove API with missing values.
*/
it('remove-missing', async function() {
const storage = this.storage;
// Add some items.
await storage.setItems({'foo': 1, 'bar': 2});
// Make sure things are in there.
let value = await storage.getItems(null);
assert.deepEqual(value, {'foo': 1, 'bar': 2});
// Remove unrelated item.
await storage.removeItem('f00');
// Make sure nothing is changed.
value = await storage.getItems(null);
assert.deepEqual(value, {'foo': 1, 'bar': 2});
});
/**
* Verify removes API.
*/
it('removes', async function() {
const storage = this.storage;
// Add some items.
await storage.setItems({'foo': 1, 'bar': 2, 'cow': 3});
// Make sure things are in there.
let value = await storage.getItems(null);
assert.deepEqual(value, {'foo': 1, 'bar': 2, 'cow': 3});
// Remove some items.
await storage.removeItems(['foo', 'bar', 'blah']);
// Make sure it's gone.
value = await storage.getItems(null);
assert.deepEqual(value, {'cow': 3});
});
/**
* Verify clear API.
*/
it('clear', async function() {
const storage = this.storage;
// Add some items.
await storage.setItems({'foo': 1, 'bar': 2, 'cow': 3});
// Make sure things are in there.
let value = await storage.getItems(null);
assert.deepEqual(value, {'foo': 1, 'bar': 2, 'cow': 3});
// Remove all items.
await storage.clear();
// Make sure it's gone.
value = await storage.getItems(null);
assert.deepEqual(value, {});
});
/**
* Verify add/removing observers.
*/
it('observe-add-remove', async function() {
const storage = this.storage;
if (!storageSupportsEventTests(storage)) {
this.skip();
return;
}
// Unknown or empty should not crash.
storage.removeObserver(() => {});
const seen1 = [];
const ob1 = (e) => seen1.push(e);
const seen2 = [];
const ob2 = (e) => seen2.push(e);
// Neither should see this.
await storage.setItem('empty', '');
storage.addObserver(ob1);
storage.addObserver(ob2);
// Both should see this.
await storage.setItem('k', 'v');
storage.removeObserver(ob1);
// Only ob2 should see this.
await storage.removeItem('k');
storage.removeObserver(ob2);
// Neither should see this.
await storage.setItem('k2', 'v2');
assert.deepEqual(seen1, [
{'k': {newValue: 'v'}},
]);
assert.deepEqual(seen2, [
{'k': {newValue: 'v'}},
{'k': {oldValue: 'v'}},
]);
});
/**
* Verify observer notifications.
*/
it('observe', function(done) {
const storage = this.storage;
if (!storageSupportsEventTests(storage)) {
this.skip();
return;
}
// All the events we should see in order.
const exp = [
{a: {newValue: '1'}},
{a: {oldValue: '1', newValue: '2'}},
];
const events = [];
storage.addObserver((e) => events.push(e));
storage.setItem('a', '1').then(() => {
storage.setItem('a', '2');
});
// Poll to finish asap, but don't give up too soon.
let retry = 200;
const check = () => {
if (events.length >= exp.length) {
assert.deepEqual(events, exp);
done();
} else if (retry-- > 0) {
setTimeout(check, 1);
} else {
assert.fail();
}
};
check();
});
};