mirror of
https://github.com/irislib/iris-messenger.git
synced 2024-10-18 06:03:22 +00:00
test
This commit is contained in:
parent
ad9a3158c4
commit
74a4e1261b
@ -21,11 +21,11 @@ export default class LocalForageAdapter extends Adapter {
|
||||
return unsub;
|
||||
}
|
||||
|
||||
set(path: string, data: NodeValue) {
|
||||
async set(path: string, data: NodeValue) {
|
||||
if (data === undefined) {
|
||||
localForage.removeItem(path);
|
||||
await localForage.removeItem(path);
|
||||
} else {
|
||||
localForage.setItem(path, data);
|
||||
await localForage.setItem(path, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,8 @@ export default class MemoryAdapter extends Adapter {
|
||||
return () => {};
|
||||
}
|
||||
|
||||
set(path: string, value: NodeValue): void {
|
||||
if (!value.updatedAt || !value.value) {
|
||||
async set(path: string, value: NodeValue) {
|
||||
if (value.updatedAt === undefined) {
|
||||
throw new Error(`Invalid value: ${JSON.stringify(value)}`);
|
||||
}
|
||||
if (value === undefined) {
|
||||
|
@ -67,7 +67,7 @@ describe('Node', () => {
|
||||
expect(mockCallback).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should trigger list callbacks when children are present', async () => {
|
||||
it('should trigger map callbacks when children are present', async () => {
|
||||
const node = new Node({ id: 'test', adapters: [new MemoryAdapter()] });
|
||||
const mockCallback: Callback = vi.fn();
|
||||
|
||||
@ -99,4 +99,36 @@ describe('Node', () => {
|
||||
// Should still have been called only twice
|
||||
expect(mockCallback).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('should return children when on() is called on a branch node', async () => {
|
||||
const node = new Node({ id: 'settings', adapters: [new MemoryAdapter()] });
|
||||
const mockCallback: Callback = vi.fn();
|
||||
|
||||
// save settings object
|
||||
await node.put({
|
||||
theme: 'dark',
|
||||
fontSize: 14,
|
||||
});
|
||||
|
||||
node.on(mockCallback);
|
||||
|
||||
expect(mockCallback).toHaveBeenCalledWith(
|
||||
{
|
||||
theme: 'dark',
|
||||
fontSize: 14,
|
||||
},
|
||||
'settings',
|
||||
expect.any(Number),
|
||||
expect.any(Function),
|
||||
);
|
||||
|
||||
node.get('theme').on(mockCallback);
|
||||
|
||||
expect(mockCallback).toHaveBeenCalledWith(
|
||||
'dark',
|
||||
'settings/theme',
|
||||
expect.any(Number),
|
||||
expect.any(Function),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -43,26 +43,38 @@ export default class Node {
|
||||
return new_node;
|
||||
}
|
||||
|
||||
private async putLeaf(value: any, updatedAt: number) {
|
||||
this.children = new Map();
|
||||
const nodeValue: NodeValue = {
|
||||
updatedAt,
|
||||
value,
|
||||
};
|
||||
const promises = this.adapters.map((adapter) => adapter.set(this.id, nodeValue));
|
||||
this.on_subscriptions.forEach((callback) => {
|
||||
callback(value, this.id, updatedAt, () => {});
|
||||
});
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
private async putBranch(value: Record<string, any>, updatedAt: number) {
|
||||
const promises = this.adapters.map((adapter) =>
|
||||
adapter.set(this.id, { value: '__DIR__', updatedAt }),
|
||||
);
|
||||
const children = Object.keys(value);
|
||||
const childPromises = children.map((key) => this.get(key).put(value[key], updatedAt));
|
||||
await Promise.all([...promises, ...childPromises]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value to the node. If the value is an object, it will be converted to child nodes.
|
||||
* @param value
|
||||
* @example node.get('users').get('alice').put({name: 'Alice'})
|
||||
*/
|
||||
async put(value, updatedAt = Date.now()) {
|
||||
async put(value: any, updatedAt = Date.now()) {
|
||||
if (typeof value === 'object' && value !== null) {
|
||||
this.adapters.forEach((adapter) => adapter.set(this.id, { value: '__DIR__', updatedAt }));
|
||||
const children = Object.keys(value);
|
||||
children.map((key) => this.get(key).put(value[key], updatedAt));
|
||||
await this.putBranch(value, updatedAt);
|
||||
} else {
|
||||
this.children = new Map();
|
||||
const nodeValue: NodeValue = {
|
||||
updatedAt,
|
||||
value,
|
||||
};
|
||||
this.adapters.forEach((adapter) => adapter.set(this.id, nodeValue));
|
||||
this.on_subscriptions.forEach((callback) => {
|
||||
callback(value, this.id, updatedAt, () => {});
|
||||
});
|
||||
await this.putLeaf(value, updatedAt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,7 +84,11 @@ export default class Node {
|
||||
*/
|
||||
on(callback: Callback): Unsubscribe {
|
||||
let latest: NodeValue | null = null;
|
||||
// TODO handle case where it's a branch node
|
||||
if (this.children.size > 0) {
|
||||
// TODO handle branch node
|
||||
} else {
|
||||
// TODO handle leaf node
|
||||
}
|
||||
const cb = (value, path, updatedAt, unsubscribe) => {
|
||||
if (latest === null || latest.updatedAt < value.updatedAt) {
|
||||
latest = { value, updatedAt };
|
||||
|
@ -11,5 +11,5 @@ export type Callback = (
|
||||
) => void;
|
||||
export abstract class Adapter {
|
||||
abstract get(path: string, callback: Callback): Unsubscribe;
|
||||
abstract set(path: string, data: NodeValue): void;
|
||||
abstract set(path: string, data: NodeValue): Promise<void>;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user