write tests for AsyncMappedList

This commit is contained in:
Bruno Windels 2021-06-21 17:26:08 +02:00
parent 1fc1d2c79b
commit 81f06f565e
3 changed files with 76 additions and 43 deletions

View file

@ -16,67 +16,46 @@ limitations under the License.
export class ListObserver { export class ListObserver {
constructor() { constructor() {
this._queuesPerType = new Map(); this._queue = [];
this._backlog = [];
} }
_nextEvent(type) { next() {
let queue = this._queuesPerType.get(type); if (this._backlog.length) {
if (!queue) { return Promise.resolve(this._backlog.shift());
queue = []; } else {
this._queuesPerType.set(type, queue);
}
return new Promise(resolve => { return new Promise(resolve => {
queue.push(resolve); this._queue.push(resolve);
}); });
} }
nextAdd() {
return this._nextEvent("add");
} }
nextUpdate() { _fullfillNext(value) {
return this._nextEvent("update"); if (this._queue.length) {
const resolve = this._queue.shift();
resolve(value);
} else {
this._backlog.push(value);
} }
nextRemove() {
return this._nextEvent("remove");
}
nextMove() {
return this._nextEvent("move");
}
nextReset() {
return this._nextEvent("reset");
}
_popQueue(type) {
const queue = this._queuesPerType.get(type);
return queue?.unshift();
} }
onReset() { onReset() {
const resolve = this._popQueue("reset"); this._fullfillNext({type: "reset"});
resolve && resolve();
} }
onAdd(index, value) { onAdd(index, value) {
const resolve = this._popQueue("add"); this._fullfillNext({type: "add", index, value});
resolve && resolve({index, value});
} }
onUpdate(index, value, params) { onUpdate(index, value, params) {
const resolve = this._popQueue("update"); this._fullfillNext({type: "update", index, value, params});
resolve && resolve({index, value, params});
} }
onRemove(index, value) { onRemove(index, value) {
const resolve = this._popQueue("remove"); this._fullfillNext({type: "remove", index, value});
resolve && resolve({index, value});
} }
onMove(fromIdx, toIdx, value) { onMove(fromIdx, toIdx, value) {
const resolve = this._popQueue("move"); this._fullfillNext({type: "move", fromIdx, toIdx, value});
resolve && resolve({fromIdx, toIdx, value});
} }
} }

View file

@ -143,8 +143,55 @@ class ResetEvent {
} }
} }
import {ObservableArray} from "./ObservableArray.js";
import {ListObserver} from "../../mocks/ListObserver.js";
export function tests() { export function tests() {
return { return {
"events are emitted in order": async assert => {
const double = n => n * n;
const source = new ObservableArray();
const mapper = new AsyncMappedList(source, async n => {
await new Promise(r => setTimeout(r, n));
return {n: double(n)};
}, (o, params, n) => {
o.n = double(n);
});
const observer = new ListObserver();
mapper.subscribe(observer);
source.append(2); // will sleep this amount, so second append would take less time
source.append(1);
source.update(0, 7, "lucky seven")
source.remove(0);
{
const {type, index, value} = await observer.next();
assert.equal(mapper.length, 1);
assert.equal(type, "add");
assert.equal(index, 0);
assert.equal(value.n, 4);
}
{
const {type, index, value} = await observer.next();
assert.equal(mapper.length, 2);
assert.equal(type, "add");
assert.equal(index, 1);
assert.equal(value.n, 1);
}
{
const {type, index, value, params} = await observer.next();
assert.equal(mapper.length, 2);
assert.equal(type, "update");
assert.equal(index, 0);
assert.equal(value.n, 49);
assert.equal(params, "lucky seven");
}
{
const {type, index, value} = await observer.next();
assert.equal(mapper.length, 1);
assert.equal(type, "remove");
assert.equal(index, 0);
assert.equal(value.n, 49);
}
}
} }
} }

View file

@ -44,6 +44,13 @@ export class ObservableArray extends BaseObservableList {
this.emitAdd(idx, item); this.emitAdd(idx, item);
} }
update(idx, item, params = null) {
if (idx < this._items.length) {
this._items[idx] = item;
this.emitUpdate(idx, item, params);
}
}
get array() { get array() {
return this._items; return this._items;
} }