Compare commits
No commits in common. "786bcce6b4f727342c0ade6a8cac1249b7e51c71" and "1c2397b8f605a20bc570aa23fc016159a5876277" have entirely different histories.
786bcce6b4
...
1c2397b8f6
|
@ -2,7 +2,7 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@holllo/migration-helper": "^0.1.4",
|
"@holllo/migration-helper": "^0.1.3",
|
||||||
"@holllo/preact-components": "^0.2.3",
|
"@holllo/preact-components": "^0.2.3",
|
||||||
"@holllo/test": "^0.2.1",
|
"@holllo/test": "^0.2.1",
|
||||||
"@holllo/webextension-storage": "^0.2.0",
|
"@holllo/webextension-storage": "^0.2.0",
|
||||||
|
|
1038
pnpm-lock.yaml
1038
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 988 B After Width: | Height: | Size: 1.8 KiB |
|
@ -1,5 +1,5 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" viewBox="0 0 100 100">
|
<svg xmlns="http://www.w3.org/2000/svg" width="128" viewBox="0 0 100 100">
|
||||||
<rect fill="#eff1f5" width="100" height="100" />
|
<rect fill="#E6DEFF" width="100" height="100" />
|
||||||
|
|
||||||
<!-- Alignment grid. -->
|
<!-- Alignment grid. -->
|
||||||
<g display="none">
|
<g display="none">
|
||||||
|
@ -13,19 +13,16 @@
|
||||||
<rect fill="#f0f" x="86" width="1" height="100" />
|
<rect fill="#f0f" x="86" width="1" height="100" />
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<g fill="#4c4f69">
|
<text
|
||||||
<path transform="translate(14, 46)" d="
|
fill="#1F1731"
|
||||||
M0,0
|
font-family="Iosevka SS01"
|
||||||
l51,0
|
font-size="75"
|
||||||
l-12,-12
|
font-weight="900"
|
||||||
l4,-4
|
x="47.9"
|
||||||
l20,20
|
y="55.6"
|
||||||
l-20,20
|
alignment-baseline="middle"
|
||||||
l-4,-4
|
text-anchor="middle"
|
||||||
l12,-12
|
>
|
||||||
l-51,0
|
⇥
|
||||||
z
|
</text>
|
||||||
" />
|
|
||||||
<rect width="7" height="40" x="78" y="30" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 781 B After Width: | Height: | Size: 730 B |
|
@ -1,8 +1,13 @@
|
||||||
import browser from "webextension-polyfill";
|
|
||||||
import {type TestContext, setup} from "@holllo/test";
|
import {type TestContext, setup} from "@holllo/test";
|
||||||
import {type Value} from "@holllo/webextension-storage";
|
import {type Value} from "@holllo/webextension-storage";
|
||||||
|
|
||||||
import {type Item, createItem, nextItem, nextItemId} from "./item.js";
|
import {
|
||||||
|
type Item,
|
||||||
|
createItem,
|
||||||
|
nextItem,
|
||||||
|
nextItemId,
|
||||||
|
storageForPrefix,
|
||||||
|
} from "./item.js";
|
||||||
|
|
||||||
const testText = "Test Item";
|
const testText = "Test Item";
|
||||||
const testUrl = "https://example.org/";
|
const testUrl = "https://example.org/";
|
||||||
|
@ -29,21 +34,9 @@ function assertItem(item: Value<Item>, test: TestContext): void {
|
||||||
await setup(
|
await setup(
|
||||||
"Item",
|
"Item",
|
||||||
async (group) => {
|
async (group) => {
|
||||||
const existingStorages: Array<Record<string, any>> = [];
|
|
||||||
|
|
||||||
group.beforeAll(async () => {
|
group.beforeAll(async () => {
|
||||||
existingStorages.push(
|
// TODO: Temporarily store existing storage and run the tests, and then
|
||||||
await browser.storage.local.get(),
|
// restore it again.
|
||||||
await browser.storage.sync.get(),
|
|
||||||
);
|
|
||||||
|
|
||||||
await browser.storage.local.clear();
|
|
||||||
await browser.storage.sync.clear();
|
|
||||||
});
|
|
||||||
|
|
||||||
group.afterAll(async () => {
|
|
||||||
await browser.storage.local.set(existingStorages[0]);
|
|
||||||
await browser.storage.sync.set(existingStorages[1]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
group.test("create & nextItem", async (test) => {
|
group.test("create & nextItem", async (test) => {
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
import type {Migration} from '@holllo/migration-helper';
|
||||||
|
|
||||||
|
export const dataMigrations: Array<Migration<string>> = [
|
||||||
|
{
|
||||||
|
version: '0.1.7',
|
||||||
|
async migrate(data: Record<string, any>) {
|
||||||
|
const migrated: Record<string, any> = {
|
||||||
|
version: '0.1.7',
|
||||||
|
};
|
||||||
|
|
||||||
|
const items = (data.queue as Queue.Item[]) ?? [];
|
||||||
|
for (const item of items) {
|
||||||
|
const key = `qi${item.id}`;
|
||||||
|
migrated[key] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return migrated;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: '0.3.0',
|
||||||
|
async migrate(data: Record<string, any>) {
|
||||||
|
const migrated: Record<string, any> = {
|
||||||
|
version: '0.3.0',
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries<Queue.Item>(data)) {
|
||||||
|
if (key.startsWith('qi')) {
|
||||||
|
migrated[key] = value;
|
||||||
|
migrated[key].sortIndex = value.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return migrated;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export function deserializeQueue(data: Record<string, any>): Queue.Item[] {
|
||||||
|
const deserialized: Queue.Item[] = [];
|
||||||
|
|
||||||
|
for (const [key, item] of Object.entries(data)) {
|
||||||
|
if (/^qi\d+$/.test(key)) {
|
||||||
|
item.added = new Date(item.added);
|
||||||
|
deserialized.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return deserialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function serializeQueue(queue: Queue.Item[]): Record<string, any> {
|
||||||
|
const serialized: Record<string, any> = {};
|
||||||
|
|
||||||
|
for (const item of queue) {
|
||||||
|
const key = `qi${item.id}`;
|
||||||
|
serialized[key] = {...item};
|
||||||
|
serialized[key].added = item.added.toISOString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return serialized;
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/// <reference path="../source/types.d.ts" />
|
||||||
|
|
||||||
|
import test from 'ava';
|
||||||
|
|
||||||
|
import {
|
||||||
|
dataMigrations,
|
||||||
|
deserializeQueue,
|
||||||
|
serializeQueue,
|
||||||
|
} from '../source/settings/migrations.js';
|
||||||
|
|
||||||
|
const queueItemSample: Queue.Item = {
|
||||||
|
added: new Date('2022-03-02T16:00:00Z'),
|
||||||
|
id: 1,
|
||||||
|
text: 'Sample',
|
||||||
|
url: 'https://example.org',
|
||||||
|
} as unknown as Queue.Item;
|
||||||
|
|
||||||
|
test('dataMigrations happy path', async (t) => {
|
||||||
|
let data: Record<string, any> = {
|
||||||
|
latestVersion: '0.1.0',
|
||||||
|
queue: [queueItemSample],
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const migration of dataMigrations) {
|
||||||
|
data = (await migration.migrate(data)) as Record<string, any>;
|
||||||
|
t.snapshot(data, `Migration ${migration.version}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('dataMigrations unhappy path', async (t) => {
|
||||||
|
let data: Record<string, any> = {};
|
||||||
|
|
||||||
|
for (const migration of dataMigrations) {
|
||||||
|
data = (await migration.migrate(data)) as Record<string, any>;
|
||||||
|
t.snapshot(data, `Migration ${migration.version}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Serializing & Deserializing Queue', (t) => {
|
||||||
|
const sample: Queue.Item = {
|
||||||
|
added: queueItemSample.added,
|
||||||
|
id: queueItemSample.id,
|
||||||
|
sortIndex: queueItemSample.id,
|
||||||
|
text: queueItemSample.text,
|
||||||
|
url: queueItemSample.url,
|
||||||
|
};
|
||||||
|
const serialized = serializeQueue([sample]);
|
||||||
|
t.snapshot(serialized, 'Serialized');
|
||||||
|
|
||||||
|
serialized.extra = 'Extra';
|
||||||
|
serialized.version = '0.0.0';
|
||||||
|
|
||||||
|
const deserialized = deserializeQueue(serialized);
|
||||||
|
t.snapshot(deserialized, 'Deserialized');
|
||||||
|
});
|
|
@ -0,0 +1,72 @@
|
||||||
|
# Snapshot report for `tests/migrations.test.ts`
|
||||||
|
|
||||||
|
The actual snapshot is saved in `migrations.test.ts.snap`.
|
||||||
|
|
||||||
|
Generated by [AVA](https://avajs.dev).
|
||||||
|
|
||||||
|
## dataMigrations happy path
|
||||||
|
|
||||||
|
> Migration 0.1.7
|
||||||
|
|
||||||
|
{
|
||||||
|
qi1: {
|
||||||
|
added: Date 2022-03-02 16:00:00 UTC {},
|
||||||
|
id: 1,
|
||||||
|
text: 'Sample',
|
||||||
|
url: 'https://example.org',
|
||||||
|
},
|
||||||
|
version: '0.1.7',
|
||||||
|
}
|
||||||
|
|
||||||
|
> Migration 0.3.0
|
||||||
|
|
||||||
|
{
|
||||||
|
qi1: {
|
||||||
|
added: Date 2022-03-02 16:00:00 UTC {},
|
||||||
|
id: 1,
|
||||||
|
sortIndex: 1,
|
||||||
|
text: 'Sample',
|
||||||
|
url: 'https://example.org',
|
||||||
|
},
|
||||||
|
version: '0.3.0',
|
||||||
|
}
|
||||||
|
|
||||||
|
## dataMigrations unhappy path
|
||||||
|
|
||||||
|
> Migration 0.1.7
|
||||||
|
|
||||||
|
{
|
||||||
|
version: '0.1.7',
|
||||||
|
}
|
||||||
|
|
||||||
|
> Migration 0.3.0
|
||||||
|
|
||||||
|
{
|
||||||
|
version: '0.3.0',
|
||||||
|
}
|
||||||
|
|
||||||
|
## Serializing & Deserializing Queue
|
||||||
|
|
||||||
|
> Serialized
|
||||||
|
|
||||||
|
{
|
||||||
|
qi1: {
|
||||||
|
added: '2022-03-02T16:00:00.000Z',
|
||||||
|
id: 1,
|
||||||
|
sortIndex: 1,
|
||||||
|
text: 'Sample',
|
||||||
|
url: 'https://example.org',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
> Deserialized
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
added: Date 2022-03-02 16:00:00 UTC {},
|
||||||
|
id: 1,
|
||||||
|
sortIndex: 1,
|
||||||
|
text: 'Sample',
|
||||||
|
url: 'https://example.org',
|
||||||
|
},
|
||||||
|
]
|
Binary file not shown.
|
@ -9,7 +9,6 @@
|
||||||
],
|
],
|
||||||
"module": "ES2022",
|
"module": "ES2022",
|
||||||
"moduleResolution": "Node",
|
"moduleResolution": "Node",
|
||||||
"resolveJsonModule": true,
|
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"target": "ES2022"
|
"target": "ES2022"
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue