98 lines
3.4 KiB
TypeScript
98 lines
3.4 KiB
TypeScript
|
import {type TestContext, setup} from '@holllo/test';
|
||
|
import {type Value} from '@holllo/webextension-storage';
|
||
|
import browser from 'webextension-polyfill';
|
||
|
|
||
|
import {type Item, createItem, nextItem, nextItemId, storage} from './item.js';
|
||
|
|
||
|
const testText = 'Test Item';
|
||
|
const testUrl = 'https://example.org/';
|
||
|
|
||
|
/**
|
||
|
* Check all properties of an {@link Item}.
|
||
|
*
|
||
|
* @param item The {@link Item} to assert.
|
||
|
* @param test The {@link TestContext} for the assertions.
|
||
|
*/
|
||
|
function assertItem(item: Value<Item>, test: TestContext): void {
|
||
|
// Assert that itemKeyPrefix is used.
|
||
|
test.true(/^item-\d+$/.test(item.key), 'item key regex');
|
||
|
|
||
|
// Assert that deserialization instantiates any classes.
|
||
|
test.true(item.value.dateAdded instanceof Date, 'dateAdded is a Date');
|
||
|
|
||
|
// Assert that the expected values are indeed present.
|
||
|
test.true(item.value.id > 0, 'id is set');
|
||
|
test.equals(item.value.text, testText, 'text is set');
|
||
|
test.equals(item.value.url, testUrl, 'url is set');
|
||
|
}
|
||
|
|
||
|
await setup(
|
||
|
'Item',
|
||
|
async (group) => {
|
||
|
group.beforeAll(async () => {
|
||
|
// If we're in production and testing, clear item storage.
|
||
|
if (!$dev && $test) {
|
||
|
await storage.clear();
|
||
|
}
|
||
|
});
|
||
|
|
||
|
group.test('create & nextItem', async (test) => {
|
||
|
const testItem = await createItem(testText, testUrl);
|
||
|
assertItem(testItem, test);
|
||
|
await testItem.save();
|
||
|
|
||
|
// Make sure `nextItem()` returns an item.
|
||
|
let storedNext = await nextItem();
|
||
|
if (storedNext === undefined) {
|
||
|
throw new Error('Expected an item');
|
||
|
}
|
||
|
|
||
|
// Assert that our first test item and the stored one are identical.
|
||
|
test.equals(storedNext.key, testItem.key, 'id check');
|
||
|
assertItem(storedNext, test);
|
||
|
|
||
|
// Store all test items we create so we can remove them later on.
|
||
|
const items = [testItem];
|
||
|
|
||
|
// Create a bunch of test items and assert them all.
|
||
|
for (let index = 1; index < 10; index++) {
|
||
|
const next = await createItem(testText, testUrl);
|
||
|
test.equals(testItem.value.id + index, next.value.id, 'id check');
|
||
|
assertItem(next, test);
|
||
|
items.push(next);
|
||
|
await next.save();
|
||
|
}
|
||
|
|
||
|
// Remove all test items.
|
||
|
await Promise.all(items.map(async (item) => item.remove()));
|
||
|
|
||
|
// After all items have been removed test that `nextItem` returns nothing.
|
||
|
// This test will fail if an item is left from development, to clear
|
||
|
// storage automatically run in production and have test enabled.
|
||
|
// ie. `NODE_ENV=production TEST=true makers dev`
|
||
|
// TODO: Temporarily store existing storage and run the tests, and then
|
||
|
// restore it again.
|
||
|
storedNext = await nextItem();
|
||
|
test.equals(storedNext, undefined, 'next item is undefined');
|
||
|
});
|
||
|
|
||
|
group.test('nextItemId', async (test) => {
|
||
|
const testItem = await createItem(testText, testUrl);
|
||
|
assertItem(testItem, test);
|
||
|
await testItem.save();
|
||
|
|
||
|
const id = await nextItemId();
|
||
|
test.equals(typeof id, 'number', 'id is a number');
|
||
|
test.false(Number.isNaN(id), 'id is not NaN');
|
||
|
test.true(id > 0, 'id larger than 0');
|
||
|
test.equals(await nextItemId(), testItem.value.id + 1, 'id check');
|
||
|
await testItem.remove();
|
||
|
});
|
||
|
},
|
||
|
{
|
||
|
// Run tests in series since we're using WebExtension storage to test stuff
|
||
|
// and don't want the ID checks to interfere with one another.
|
||
|
parallel: false,
|
||
|
},
|
||
|
);
|