@platform/cell.typesystem
Version:
The 'strongly typed sheets' system of the CellOS.
195 lines (194 loc) • 8.87 kB
JavaScript
import { SheetPool } from '.';
import { TypeSystem } from '../..';
import { expect, Subject, testInstanceFetch, TYPE_DEFS, Uri } from '../../test';
describe('SheetPool', () => {
describe('lifecycle', () => {
it('create', () => {
const pool = SheetPool.create();
expect(pool).to.be.an.instanceof(SheetPool);
});
it('dispose', async () => {
const { sheet } = await testMySheet();
const pool = SheetPool.create();
let fired = 0;
pool.dispose$.subscribe(() => fired++);
pool.add(sheet);
expect(pool.count).to.eql(1);
expect(pool.isDisposed).to.eql(false);
pool.dispose();
pool.dispose();
pool.dispose();
expect(fired).to.eql(1);
expect(pool.isDisposed).to.eql(true);
expect(pool.count).to.eql(0);
expect(pool.sheets).to.eql({});
});
});
describe('add/remove/sheet/children (caching)', () => {
it('add', async () => {
const { sheet } = await testMySheet();
const pool = SheetPool.create();
expect(pool.count).to.eql(0);
expect(pool.sheets[sheet.toString()]).to.eql(undefined);
pool.add(sheet).add(sheet);
expect(pool.count).to.eql(1);
expect(pool.exists(sheet)).to.eql(true);
expect(pool.exists(sheet.uri)).to.eql(true);
expect(pool.exists(sheet.uri.toString())).to.eql(true);
expect(pool.sheets[sheet.toString()]).to.eql(sheet);
});
it('remove', async () => {
const { sheet } = await testMySheet();
const pool = SheetPool.create();
pool.add(sheet);
expect(pool.exists(sheet)).to.eql(true);
pool.remove(sheet).remove(sheet);
expect(pool.count).to.eql(0);
expect(pool.exists(sheet)).to.eql(false);
expect(pool.exists(sheet.uri)).to.eql(false);
expect(pool.exists(sheet.uri.toString())).to.eql(false);
});
it('sheet', async () => {
const { sheet } = await testMySheet();
const pool = SheetPool.create();
expect(pool.sheet(sheet)).to.eql(undefined);
expect(pool.sheet(sheet.uri)).to.eql(undefined);
expect(pool.sheet(sheet.toString())).to.eql(undefined);
pool.add(sheet);
expect(pool.sheet(sheet)).to.eql(sheet);
expect(pool.sheet(sheet.uri)).to.eql(sheet);
expect(pool.sheet(sheet.toString())).to.eql(sheet);
});
it('children', async () => {
const { sheet } = await testMySheet();
const pool = SheetPool.create();
const cursor = await sheet.data('MyRow').load();
const child = (await cursor.row(0).props.messages.load()).sheet;
expect(pool.children(sheet)).to.eql([]);
pool
.add(sheet)
.add(child, { parent: sheet })
.add(child, { parent: sheet });
const children = pool.children(sheet);
expect(children.length).to.eql(1);
expect(children[0]).to.equal(child);
});
it('string params (without the "ns:" prefix)', async () => {
const { sheet } = await testMySheet();
const pool = SheetPool.create();
const cursor = await sheet.data('MyRow').load();
const child = (await cursor.row(0).props.messages.load()).sheet;
pool.add(sheet).add(child, { parent: sheet });
const strip = (sheet) => Uri.strip.ns(sheet.uri.toString());
expect(pool.exists(strip(sheet))).to.eql(true);
expect(pool.exists(strip(child))).to.eql(true);
expect(pool.sheet(strip(sheet))).to.equal(sheet);
pool.remove(strip(sheet));
expect(pool.sheet(strip(sheet))).to.equal(undefined);
expect(pool.sheet(strip(child))).to.equal(undefined);
});
});
describe('auto-removal', () => {
it('removes child sheet when parent sheet removed', async () => {
const { sheet } = await testMySheet();
const pool = SheetPool.create();
const cursor = await sheet.data('MyRow').load();
const child = (await cursor.row(0).props.messages.load()).sheet;
pool.add(sheet).add(child, { parent: sheet });
expect(pool.count).to.eql(2);
expect(pool.exists(sheet)).to.eql(true);
expect(pool.exists(child)).to.eql(true);
pool.remove(sheet);
expect(pool.count).to.eql(0);
});
it('removes child sheet when parent sheet disposed', async () => {
const { sheet } = await testMySheet();
const pool = SheetPool.create();
const cursor = await sheet.data('MyRow').load();
const child = (await cursor.row(0).props.messages.load()).sheet;
pool.add(sheet).add(child, { parent: sheet });
expect(pool.count).to.eql(2);
sheet.dispose();
expect(pool.count).to.eql(0);
});
it('does not remove parent when child removed', async () => {
const { sheet } = await testMySheet();
const pool = SheetPool.create();
const cursor = await sheet.data('MyRow').load();
const child = (await cursor.row(0).props.messages.load()).sheet;
pool.add(sheet).add(child, { parent: sheet });
expect(pool.count).to.eql(2);
child.dispose();
expect(pool.count).to.eql(1);
expect(pool.exists(sheet)).to.eql(true);
expect(pool.exists(child)).to.eql(false);
});
});
describe('auto pooling with sheet/refs', () => {
describe('generates new pool instances', () => {
it('sheet.load()', async () => {
const ns = 'ns:foo.mySheet';
const fetch = await testFetchMySheet(ns);
const sheet = await TypeSystem.Sheet.load({ fetch, ns });
expect(sheet.pool).to.be.an.instanceof(SheetPool);
});
it('sheet.create()', async () => {
const fetch = await testFetchMySheet('ns:foo.mySheet');
const sheet = await TypeSystem.Sheet.create({ fetch, implements: 'ns:foo' });
expect(sheet.pool).to.be.an.instanceof(SheetPool);
});
});
describe('uses given pool', () => {
it('sheet.load()', async () => {
const ns = 'ns:foo.mySheet';
const fetch = await testFetchMySheet(ns);
const pool = SheetPool.create();
const sheet1 = await TypeSystem.Sheet.load({ fetch, ns, pool });
expect(sheet1.pool).to.equal(pool);
const sheet2 = await TypeSystem.Sheet.load({ fetch, ns, pool });
expect(sheet1).to.equal(sheet2);
});
it('sheet.create()', async () => {
const fetch = await testFetchMySheet('ns:foo.mySheet');
const pool = SheetPool.create();
const args = { fetch, implements: 'ns:foo', ns: 'ns:foo.mySheet', pool };
const sheet1 = await TypeSystem.Sheet.create(args);
expect(sheet1.pool).to.equal(pool);
const sheet2 = await TypeSystem.Sheet.create(args);
expect(sheet1).to.equal(sheet2);
});
});
it('inserts sheet into pool', async () => {
const { sheet } = await testMySheet();
expect(sheet.pool.exists(sheet)).to.eql(true);
sheet.dispose();
expect(sheet.pool.exists(sheet)).to.eql(false);
});
it('uses pool on child ref', async () => {
const ns = 'ns:foo.mySheet';
const fetch = await testFetchMySheet(ns);
const pool = SheetPool.create();
const sheet = await TypeSystem.Sheet.load({ fetch, ns, pool });
expect(sheet.pool.exists(sheet)).to.eql(true);
const cursor = await sheet.data('MyRow').load();
const child = (await cursor.row(0).props.messages.load()).sheet;
expect(sheet.pool).to.equal(child.pool);
expect(sheet.pool.exists(child)).to.eql(true);
});
});
});
const testFetchMySheet = (ns, cells) => {
return testInstanceFetch({
instance: ns,
implements: 'ns:foo',
defs: TYPE_DEFS,
cells,
});
};
const testMySheet = async (cells) => {
const ns = 'ns:foo.mySheet';
const event$ = new Subject();
const fetch = await testFetchMySheet(ns, cells);
const sheet = await TypeSystem.Sheet.load({ fetch, ns, event$ });
return { ns, fetch, sheet, event$ };
};