import { DataEvent, newSystemClient, ResourceInstance, ResourceSpecials, ServiceError, SpecialEvent, ValueEvent } from '../node'; import {Universe} from '../node'; import {newServiceClient} from '../node'; import {Id, Obj} from '../node'; import {ListMapping, PrimitiveMapping} from '../node'; import {ResourceOrder, ResourceSchema} from '../node'; import {newSystemStreamClient} from '../node'; import {firstValueFrom} from 'rxjs'; import {globalApiUrl, globalSystemUrl, globalUniverse, layerProfile} from './config'; const globalSystemStreamUrl = 'ws://localhost:9131'; async function loadUniverseFromApi(name: string, url: string): Promise { const client = newServiceClient(url); const id = await client.resolveUniverse(name); if (id instanceof ServiceError) { return undefined; } return await client.loadUniverse(id); } function sortIds(ids: Id[]): Id[] { return ids.sort((id1, id2) => id1 < id2 ? -1 : 1); } function sleep(time: number): Promise { return new Promise(resolve => { setTimeout(() => resolve(), time); }) } test('newClient returns instance', async () => { const streamClient = newSystemStreamClient(globalSystemStreamUrl); expect(streamClient).toBeTruthy(); }); test('getInfo returns info object', async () => { const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); const info = await streamClient.getInfo(); expect(info['apiVersion']).toEqual('1.0'); expect(info['session']['created']).toBeTruthy(); await streamClient.disconnect(); }); test('registerSpaceToken works', async () => { const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const spaceTokens = await streamClient.getLayerTokens(); expect(spaceTokens).toHaveLength(1); await streamClient.disconnect(); }); test('getName works', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obj = await client.createObject(universe.resolve('base.object/')!, 'name1') as Obj; const nameObs = streamClient.getName(obj.id, {instant: true, payload: true}); const name = await firstValueFrom(nameObs); let name2: string | undefined; streamClient.getName(obj.id, {instant: false, payload: true}).subscribe(evt => { name2 = evt.new; }); await client.setName(obj.id, 'name2'); await streamClient.unsubscribe(nameObs); await client.setName(obj.id, 'name3'); await streamClient.disconnect(); expect(name.new).toEqual('name1'); expect(name2).toEqual('name3'); expect(nameObs.value).toEqual('name2'); }); test('getData works', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obj = await client.createObject(universe.resolve('base.object/')!, 'name1') as Obj; await client.setData(obj.id, 'str123', 'string'); const dataRcv1: DataEvent[] = []; const dataRcv2: DataEvent[] = []; streamClient.getData(obj.id, 'string', {instant: true, payload: true}).subscribe(update => { dataRcv1.push(update); }); streamClient.getData(obj.id, 'string', {instant: false, payload: true}).subscribe(update => { dataRcv2.push(update); }); await client.setData(obj.id, 'str456', 'string'); await streamClient.disconnect(); await sleep(500); expect(dataRcv1).toHaveLength(2); expect(dataRcv2).toHaveLength(1); expect(dataRcv1[0].old).toBeFalsy(); expect(dataRcv1[0].new).toEqual('str123'); expect(dataRcv1[1].old).toEqual('str123'); expect(dataRcv1[1].new).toEqual('str456'); expect(dataRcv2[0].old).toEqual('str123'); expect(dataRcv2[0].new).toEqual('str456'); }); test('getSpecials works', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obj = await client.createObject(universe.resolve('base.object/')!, 'obj') as Obj; await client.createObject(obj.id, 'obj1') as Obj; await client.createObject(obj.id, 'obj2') as Obj; const dataRcv1: SpecialEvent[] = []; const dataRcv2: SpecialEvent[] = []; const dataRcv3: SpecialEvent[] = []; const dataRcv4: SpecialEvent[] = []; streamClient.getSpecials(obj.id, false, true, false, {instant: true, payload: true, specials: true}).subscribe(update => { dataRcv1.push(update); }); streamClient.getSpecials(obj.id, false, true, false, {instant: false, payload: true, specials: true}).subscribe(update => { dataRcv2.push(update); }); streamClient.getSpecials(obj.id, false, true, false, {instant: false, payload: true, specials: false}).subscribe(update => { dataRcv3.push(update); }); streamClient.getSpecials(obj.id, false, true, true, {instant: false, payload: true, specials: false}).subscribe(update => { dataRcv4.push(update); }); const obj3 = await client.createObject(obj.id, 'obj3') as Obj; await client.createObject(obj3.id, 'obj4') as Obj; await streamClient.disconnect(); expect(dataRcv1).toHaveLength(4); expect(dataRcv2).toHaveLength(2); expect(dataRcv3).toHaveLength(1); expect(dataRcv4).toHaveLength(2); }); test('getSpecials works with direct and indirect including specials', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obj = await client.createObject(universe.resolve('base.object/')!, 'obj') as Obj; const dataRcvDirect: SpecialEvent[] = []; const dataRcvIndirect: SpecialEvent[] = []; const dataRcvDirectIndirect: SpecialEvent[] = []; const dataRcvSpecialsDirect: SpecialEvent[] = []; const dataRcvSpecialsIndirect: SpecialEvent[] = []; const dataRcvSpecialsDirectIndirect: SpecialEvent[] = []; streamClient.getSpecials(obj.id, false, true, false, {instant: true, payload: true, specials: false}).subscribe(update => { dataRcvDirect.push(update); }); streamClient.getSpecials(obj.id, false, false, true, {instant: true, payload: true, specials: false}).subscribe(update => { dataRcvIndirect.push(update); }); streamClient.getSpecials(obj.id, false, true, true, {instant: true, payload: true, specials: false}).subscribe(update => { dataRcvDirectIndirect.push(update); }); streamClient.getSpecials(obj.id, false, true, false, {instant: true, payload: true, specials: true}).subscribe(update => { dataRcvSpecialsDirect.push(update); }); streamClient.getSpecials(obj.id, false, false, true, {instant: true, payload: true, specials: true}).subscribe(update => { dataRcvSpecialsIndirect.push(update); }); streamClient.getSpecials(obj.id, false, true, true, {instant: true, payload: true, specials: true}).subscribe(update => { dataRcvSpecialsDirectIndirect.push(update); }); await sleep(100); expect(dataRcvDirect).toHaveLength(0); expect(dataRcvIndirect).toHaveLength(0); expect(dataRcvDirectIndirect).toHaveLength(0); expect(dataRcvSpecialsDirect).toHaveLength(0); expect(dataRcvSpecialsIndirect).toHaveLength(0); expect(dataRcvSpecialsDirectIndirect).toHaveLength(0); const obj1 = await client.createObject(obj.id, 'obj.1') as Obj; await sleep(100); expect(dataRcvDirect).toHaveLength(1); expect(dataRcvDirect[0].added).toContain(obj1.id); expect(dataRcvIndirect).toHaveLength(0); expect(dataRcvDirectIndirect).toHaveLength(1); expect(dataRcvSpecialsDirect).toHaveLength(1 + 0); expect(dataRcvSpecialsIndirect).toHaveLength(0 + 0); expect(dataRcvSpecialsDirectIndirect).toHaveLength(1 + 0); const obj11 = await client.createObject(obj1.id, 'obj.1.1') as Obj; await sleep(100); expect(dataRcvDirect).toHaveLength(1); expect(dataRcvIndirect).toHaveLength(1); expect(dataRcvDirectIndirect).toHaveLength(2); expect(dataRcvSpecialsDirect).toHaveLength(2); expect(dataRcvSpecialsIndirect).toHaveLength(1); expect(dataRcvSpecialsDirectIndirect).toHaveLength(3); const obj111 = await client.createObject(obj11.id, 'obj.1.1.1') as Obj; await sleep(100); expect(dataRcvDirect).toHaveLength(1); expect(dataRcvIndirect).toHaveLength(2); expect(dataRcvDirectIndirect).toHaveLength(3); expect(dataRcvSpecialsDirect).toHaveLength(3); expect(dataRcvSpecialsIndirect).toHaveLength(3); expect(dataRcvSpecialsDirectIndirect).toHaveLength(6); const obj1111 = await client.createObject(obj111.id, 'obj.1.1.1.1') as Obj; const obj1112 = await client.createObject(obj111.id, 'obj.1.1.1.2') as Obj; await sleep(100); expect(dataRcvDirect).toHaveLength(1); expect(dataRcvIndirect).toHaveLength(4); expect(dataRcvDirectIndirect).toHaveLength(5); expect(dataRcvSpecialsDirect).toHaveLength(5); expect(dataRcvSpecialsIndirect).toHaveLength(9); expect(dataRcvSpecialsDirectIndirect).toHaveLength(14); await streamClient.disconnect(); }); test('getSpecials works with self', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obj = await client.createObject(universe.resolve('base.object/')!, 'obj') as Obj; const dataRcvSelf: SpecialEvent[] = []; const dataRcvSelfDirect: SpecialEvent[] = []; const dataRcvSelfIndirect: SpecialEvent[] = []; const dataRcvSelfDirectIndirect: SpecialEvent[] = []; streamClient.getSpecials(obj.id, true, false, false, {instant: true, payload: true, specials: false}).subscribe(update => { dataRcvSelf.push(update); }); streamClient.getSpecials(obj.id, true, true, false, {instant: true, payload: true, specials: false}).subscribe(update => { dataRcvSelfDirect.push(update); }); streamClient.getSpecials(obj.id, true, false, true, {instant: true, payload: true, specials: false}).subscribe(update => { dataRcvSelfIndirect.push(update); }); streamClient.getSpecials(obj.id, true, true, true, {instant: true, payload: true, specials: false}).subscribe(update => { dataRcvSelfDirectIndirect.push(update); }); await sleep(100); expect(dataRcvSelf).toHaveLength(1); expect(dataRcvSelfDirect).toHaveLength(1); expect(dataRcvSelfIndirect).toHaveLength(1); expect(dataRcvSelfDirectIndirect).toHaveLength(1); const obj1 = await client.createObject(obj.id, 'obj.1') as Obj; await sleep(100); expect(dataRcvSelf).toHaveLength(1); expect(dataRcvSelfDirect).toHaveLength(2); expect(dataRcvSelfIndirect).toHaveLength(1); expect(dataRcvSelfDirectIndirect).toHaveLength(2); const obj11 = await client.createObject(obj1.id, 'obj.1.1') as Obj; await sleep(100); expect(dataRcvSelf).toHaveLength(1); expect(dataRcvSelfDirect).toHaveLength(2); expect(dataRcvSelfIndirect).toHaveLength(2); expect(dataRcvSelfDirectIndirect).toHaveLength(3); const obj111 = await client.createObject(obj11.id, 'obj.1.1.1') as Obj; await sleep(100); expect(dataRcvSelf).toHaveLength(1); expect(dataRcvSelfDirect).toHaveLength(2); expect(dataRcvSelfIndirect).toHaveLength(3); expect(dataRcvSelfDirectIndirect).toHaveLength(4); const obj1111 = await client.createObject(obj111.id, 'obj.1.1.1.1') as Obj; const obj1112 = await client.createObject(obj111.id, 'obj.1.1.1.2') as Obj; await sleep(100); expect(dataRcvSelf).toHaveLength(1); expect(dataRcvSelfDirect).toHaveLength(2); expect(dataRcvSelfIndirect).toHaveLength(5); expect(dataRcvSelfDirectIndirect).toHaveLength(6); await streamClient.disconnect(); }); test('getSpecials works with deleted specials', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obj = await client.createObject(universe.resolve('base.object/')!, 'obj') as Obj; await client.createObject(obj.id, 'obj1') as Obj; await client.createObject(obj.id, 'obj2') as Obj; const dataRcv1: SpecialEvent[] = []; const dataRcv2: SpecialEvent[] = []; const dataRcv3: SpecialEvent[] = []; const dataRcv4: SpecialEvent[] = []; streamClient.getSpecials(obj.id, false, true, false, {instant: true, payload: true, specials: true}).subscribe(update => { dataRcv1.push(update); }); streamClient.getSpecials(obj.id, false, true, false, {instant: false, payload: true, specials: true}).subscribe(update => { dataRcv2.push(update); }); streamClient.getSpecials(obj.id, false, true, false, {instant: false, payload: true, specials: false}).subscribe(update => { dataRcv3.push(update); }); streamClient.getSpecials(obj.id, false, true, true, {instant: false, payload: true, specials: false}).subscribe(update => { dataRcv4.push(update); }); const obj3 = await client.createObject(obj.id, 'obj3') as Obj; const obj4 = await client.createObject(obj3.id, 'obj4') as Obj; await sleep(100); expect(dataRcv1).toHaveLength(4); expect(dataRcv2).toHaveLength(2); expect(dataRcv3).toHaveLength(1); expect(dataRcv4).toHaveLength(2); await client.deleteObject(obj4.id); await sleep(100); expect(dataRcv1).toHaveLength(5); expect(dataRcv2).toHaveLength(3); expect(dataRcv3).toHaveLength(1); expect(dataRcv4).toHaveLength(3); await streamClient.disconnect(); }); test('getSpecials value works', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obj = await client.createObject(universe.resolve('base.object/')!, 'obj') as Obj; const specObs = streamClient.getSpecials(obj.id, false, true, true, {payload: true}); const obj1 = await client.createObject(obj.id) as Obj; const obj2 = await client.createObject(obj.id) as Obj; const obj3 = await client.createObject(obj.id) as Obj; await sleep(100); expect(sortIds(specObs.value!)).toEqual(sortIds([obj1.id, obj2.id, obj3.id])); const nsSpecials = await client.getSpecials(obj.id, false, true, true) as Id[]; expect(sortIds(specObs.value!)).toEqual(sortIds(nsSpecials)); await client.deleteObject(obj2.id); await sleep(100); expect(sortIds(specObs.value!)).toEqual(sortIds([obj1.id, obj3.id])); expect(sortIds(specObs.value!)).toEqual(sortIds(await client.getSpecials(obj.id, false, true, true) as Id[])); await streamClient.disconnect(); }); test('getValue for primitive id works', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerProfile(layerProfile); const obja = await client.createObject(universe.resolve('base.object/')!, 'obja') as Obj; const objb = await client.createObject(universe.resolve('base.object/')!, 'objb') as Obj; const rel1 = await client.createRelation(obja.id, objb.id, universe.resolve('base.object#relation/')!) as Obj; const rel2 = await client.createRelation(obja.id, objb.id, universe.resolve('base.object#relation/')!) as Obj; const rel3 = await client.createRelation(obja.id, objb.id, universe.resolve('base.object#relation/')!) as Obj; const objb1 = await client.createObject(objb.id, 'objb1') as Obj; const objb2 = await client.createObject(objb.id, 'objb2') as Obj; const objb3 = await client.createObject(objb.id, 'objb3') as Obj; const objb4 = await client.createObject(objb.id, 'objb4') as Obj; const dataRcv1: ValueEvent[] = []; const dataRcv2: ValueEvent[] = []; const dataRcv3: ValueEvent[] = []; await client.putValue(obja.id, rel2.id, objb1.id, 'id', 'hex', new PrimitiveMapping()); const obs1 = streamClient.getValue(obja.id, rel1.id, 'id', 'hex', new PrimitiveMapping(), {specials: true, payload: true, instant: true}); obs1.subscribe(update => { dataRcv1.push(update); }) const obs2 = streamClient.getValue(obja.id, rel2.id, 'id', 'hex', new PrimitiveMapping(), {specials: true, payload: true, instant: true}); obs2.subscribe(update => { dataRcv2.push(update); }); const obs3 = streamClient.getValue(obja.id, rel3.id, 'id', 'hex', new PrimitiveMapping(), {specials: true, payload: true, instant: true}); obs3.subscribe(update => { dataRcv3.push(update); }); await client.putValue(obja.id, rel1.id, objb2.id, 'id', 'hex', new PrimitiveMapping()); await client.putValue(obja.id, rel1.id, objb3.id, 'id', 'hex', new PrimitiveMapping().change('set')); await client.putValue(obja.id, rel3.id, objb4.id, 'id', 'hex', new PrimitiveMapping()); await sleep(100); expect(dataRcv1).toHaveLength(3); expect(dataRcv1[0].new).toEqual(objb2.id); expect(dataRcv1[1].old).toEqual(objb2.id); expect(dataRcv1[2].new).toEqual(objb3.id); expect(dataRcv2).toHaveLength(1); expect(dataRcv2[0].new).toEqual(objb1.id); expect(dataRcv3).toHaveLength(1); expect(dataRcv3[0].new).toEqual(objb4.id); expect(obs1.value).toEqual(objb3.id); expect(obs2.value).toEqual(objb1.id); expect(obs3.value).toEqual(objb4.id); await streamClient.disconnect(); }); test('getValue for primitive name works', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obja = await client.createObject(universe.resolve('base.object/')!, 'obja') as Obj; const objb = await client.createObject(universe.resolve('base.object/')!, 'objb') as Obj; const rel1 = await client.createRelation(obja.id, objb.id, universe.resolve('base.object#relation/')!) as Obj; const rel2 = await client.createRelation(obja.id, objb.id, universe.resolve('base.object#relation/')!) as Obj; const rel3 = await client.createRelation(obja.id, objb.id, universe.resolve('base.object#relation/')!) as Obj; const objb1 = await client.createObject(objb.id, 'objb1') as Obj; const objb2 = await client.createObject(objb.id, 'objb2') as Obj; const objb3 = await client.createObject(objb.id, 'objb3') as Obj; const objb4 = await client.createObject(objb.id, 'objb4') as Obj; const dataRcv1: ValueEvent[] = []; const dataRcv2: ValueEvent[] = []; const dataRcv3: ValueEvent[] = []; await client.putValue(obja.id, rel2.id, objb1.id, 'id', 'hex', new PrimitiveMapping()); const obs1 = streamClient.getValue(obja.id, rel1.id, 'name', 'string', new PrimitiveMapping(), {specials: true, payload: true, instant: true}); obs1.subscribe(update => { dataRcv1.push(update); }); const obs2 = streamClient.getValue(obja.id, rel2.id, 'name', 'string', new PrimitiveMapping(), {specials: true, payload: true, instant: true}); obs2.subscribe(update => { dataRcv2.push(update); }); const obs3 = streamClient.getValue(obja.id, rel3.id, 'name', 'string', new PrimitiveMapping(), {specials: true, payload: true, instant: true}); obs3.subscribe(update => { dataRcv3.push(update); }); await client.putValue(obja.id, rel1.id, objb2.id, 'id', 'hex', new PrimitiveMapping()); await client.putValue(obja.id, rel1.id, objb3.id, 'id', 'hex', new PrimitiveMapping().change('set')); await client.putValue(obja.id, rel3.id, objb4.id, 'id', 'hex', new PrimitiveMapping()); await client.setName(objb4.id, 'newName'); await sleep(100); expect(dataRcv1).toHaveLength(3); expect(dataRcv1[0].new).toEqual('objb2'); expect(dataRcv1[1].old).toEqual('objb2'); expect(dataRcv1[2].new).toEqual('objb3'); expect(dataRcv2).toHaveLength(1); expect(dataRcv2[0].new).toEqual('objb1'); expect(dataRcv3).toHaveLength(3); expect(dataRcv3[0].new).toEqual('objb4'); expect(dataRcv3[1].old).toEqual('objb4'); expect(dataRcv3[2].new).toEqual('newName'); expect(obs1.value).toEqual('objb3'); expect(obs2.value).toEqual('objb1'); expect(obs3.value).toEqual('newName'); await streamClient.disconnect(); }); test('getValue for primitive data works', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obj = await client.createObject(universe.resolve('base.object/')!, 'obj') as Obj; const objb = await client.createObject(universe.resolve('base.object/')!, 'objb') as Obj; const rel1 = await client.createRelation(obj.id, objb.id, universe.resolve('base.object#relation/')!) as Obj; const rel2 = await client.createRelation(obj.id, objb.id, universe.resolve('base.object#relation/')!) as Obj; const rel3 = await client.createRelation(obj.id, objb.id, universe.resolve('base.object#relation/')!) as Obj; const dataRcv1: ValueEvent[] = []; const dataRcv2: ValueEvent[] = []; const dataRcv3: ValueEvent[] = []; await client.putValue(obj.id, rel2.id, 5, 'data', 'integer', new PrimitiveMapping().change('set')); streamClient.getValue(obj.id, rel1.id, 'data', 'string', new PrimitiveMapping(), {specials: true, payload: true, instant: true}).subscribe(update => { dataRcv1.push(update); }); streamClient.getValue(obj.id, rel2.id, 'data', 'integer', new PrimitiveMapping(), {specials: true, payload: true, instant: true}).subscribe(update => { dataRcv2.push(update); }); streamClient.getValue(obj.id, rel3.id, 'data', 'boolean', new PrimitiveMapping(), {specials: true, payload: true, instant: true}).subscribe(update => { dataRcv3.push(update); }); await client.putValue(obj.id, rel1.id, 'test321', 'data', 'string', new PrimitiveMapping()); await client.putValue(obj.id, rel1.id, 'test123', 'data', 'string', new PrimitiveMapping().change('set')); await client.putValue(obj.id, rel3.id, true, 'data', 'boolean', new PrimitiveMapping()); await sleep(100); expect(dataRcv1).toHaveLength(3); expect(dataRcv1[0].new).toEqual('test321'); expect(dataRcv1[1].old).toEqual('test321'); expect(dataRcv1[2].new).toEqual('test123'); expect(dataRcv2).toHaveLength(1); expect(dataRcv2[0].new).toEqual(5); expect(dataRcv3).toHaveLength(1); expect(dataRcv3[0].new).toEqual(true); await streamClient.disconnect(); }); test('getValue for list data works', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obj = await client.createObject(universe.resolve('base.object/')!, 'obj') as Obj; const objb = await client.createObject(universe.resolve('base.object/')!, 'objb') as Obj; const rel1 = await client.createRelation(obj.id, objb.id, universe.resolve('base.object#relation/')!) as Obj; const rel2 = await client.createRelation(obj.id, objb.id, universe.resolve('base.object#relation/')!) as Obj; const rel3 = await client.createRelation(obj.id, objb.id, universe.resolve('base.object#relation/')!) as Obj; const dataRcv1: ValueEvent[] = []; const dataRcv2: ValueEvent[] = []; const dataRcv3: ValueEvent[] = []; await client.putValue(obj.id, rel2.id, 5, 'data', 'integer', new PrimitiveMapping().change('set')); const obs1 = streamClient.getValue(obj.id, rel1.id, 'data', 'string', new ListMapping(), {specials: true, payload: true, instant: true}); obs1.subscribe(update => { dataRcv1.push(update); }); const obs2 = streamClient.getValue(obj.id, rel2.id, 'data', 'integer', new ListMapping(), {specials: true, payload: true, instant: true}); obs2.subscribe(update => { dataRcv2.push(update); }); const obs3 = streamClient.getValue(obj.id, rel3.id, 'data', 'boolean', new ListMapping(), {specials: true, payload: true, instant: true}); obs3.subscribe(update => { dataRcv3.push(update); }); await sleep(100); await client.putValue(obj.id, rel1.id, ['test321'], 'data', 'string', new ListMapping().change('add')); await client.putValue(obj.id, rel1.id, ['test123'], 'data', 'string', new ListMapping().change('set')); await client.putValue(obj.id, rel3.id, [true, true], 'data', 'boolean', new ListMapping().change('add')); await client.putValue(obj.id, rel3.id, [false], 'data', 'boolean', new ListMapping().change('set')); await client.putValue(obj.id, rel3.id, [false, true], 'data', 'boolean', new ListMapping().change('add')); await sleep(100); expect(dataRcv1).toHaveLength(3); expect(dataRcv1[0].new).toEqual(['test321']); expect(dataRcv1[1].old).toEqual(['test321']); expect(dataRcv1[2].new).toEqual(['test123']); expect(obs1.value).toEqual(['test123']); expect(dataRcv2).toHaveLength(1); expect(dataRcv2[0].new).toEqual([5]); expect(obs2.value).toEqual([5]); expect(dataRcv3).toHaveLength(7); expect(obs3.value).toEqual([false, false, true]); await streamClient.disconnect(); }); test('getResource for instance object fields works', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obj = await client.createObject(universe.resolve('base.object/')!, 'obj') as Obj; const schema = new ResourceSchema() .addField('id', 'id', 'hex') .addField('name', 'name', 'string') .addField('created', 'created', 'integer') .addField('user', 'user', 'hex') .addField('value', 'data', 'integer'); await client.setData(obj.id, 321, 'integer'); const objs = streamClient.getResourceInstance(new ResourceInstance(obj.id, schema), {instant: true}); const subObj: any = {}; objs.subscribe((evt) => { // console.log(evt); if (evt.added) { Object.assign(subObj, evt.added); } }); await client.setName(obj.id, 'newName'); await client.setData(obj.id, 123, 'integer'); await sleep(1000); expect(subObj.id).toEqual(obj.id); expect(subObj.created).toEqual(obj.created); expect(subObj.user).toEqual(obj.user); expect(subObj.name).toEqual('newName'); expect(subObj.value).toEqual(123); expect(objs.value).toEqual({ 'id': obj.id, 'created': obj.created, 'user': obj.user, 'name': 'newName', 'value': 123, }); await client.deleteObject(obj.id); await sleep(100); expect(objs.value).toBeFalsy(); await streamClient.disconnect(); }); test('getResource for instance relation primitive fields (except data) works (instant)', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obj1 = await client.createObject(universe.resolve('base.object/')!, 'obj1') as Obj; const obj2 = await client.createObject(universe.resolve('base.object/')!, 'obj2') as Obj; const obj11 = await client.createObject(obj1.id, 'obj11') as Obj; const rel1 = await client.createRelation(obj1.id, obj2.id, universe.resolve('base.object#relation/')!) as Obj; const schema = new ResourceSchema() .addField('obj2ID', 'id', 'hex', rel1.id, new PrimitiveMapping) .addField('obj2Created', 'created', 'integer', rel1.id, new PrimitiveMapping) .addField('obj2Name', 'name', 'string', rel1.id, new PrimitiveMapping) .addField('obj2User', 'user', 'hex', rel1.id, new PrimitiveMapping); const obj21 = await client.createObject(obj2.id, 'obj21') as Obj; await client.putValue(obj11.id, rel1.id, obj21.id, 'id', 'hex', new PrimitiveMapping()); const newObj: any = {}; const obs = streamClient.getResourceInstance(new ResourceInstance(obj11.id, schema), {instant: true}); obs.subscribe((evt) => { if (evt.added) { Object.assign(newObj, evt.added); } }); await sleep(100); await streamClient.disconnect(); expect(newObj.obj2ID).toEqual(obj21.id); expect(newObj.obj2Created).toEqual(obj21.created); expect(newObj.obj2Name).toEqual(obj21.name); expect(newObj.obj2User).toEqual(obj21.user); expect(obs.value).toEqual({ 'obj2ID': obj21.id, 'obj2Created': obj21.created, 'obj2Name': obj21.name, 'obj2User': obj21.user, }) }); test('getResource for instance relation primitive fields (except data) works', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obj1 = await client.createObject(universe.resolve('base.object/')!, 'obj1') as Obj; const obj2 = await client.createObject(universe.resolve('base.object/')!, 'obj2') as Obj; const obj11 = await client.createObject(obj1.id, 'obj11') as Obj; const rel1 = await client.createRelation(obj1.id, obj2.id, universe.resolve('base.object#relation/')!) as Obj; const schema = new ResourceSchema() .addField('obj2ID', 'id', 'hex', rel1.id, new PrimitiveMapping()) .addField('obj2Created', 'created', 'integer', rel1.id, new PrimitiveMapping()) .addField('obj2Name', 'name', 'string', rel1.id, new PrimitiveMapping()) .addField('obj2User', 'user', 'hex', rel1.id, new PrimitiveMapping()); const newObj: any = {}; const objs = streamClient.getResourceInstance(new ResourceInstance(obj11.id, schema), {instant: true}); objs.subscribe((evt) => { if (evt.added) { Object.assign(newObj, evt.added); } }); const obj21 = await client.createObject(obj2.id, 'obj21') as Obj; await client.putValue(obj11.id, rel1.id, obj21.id, 'id', 'hex', new PrimitiveMapping()); await client.setName(obj21.id, 'newName123'); await sleep(100); await streamClient.disconnect(); expect(newObj.obj2ID).toEqual(obj21.id); expect(newObj.obj2Created).toEqual(obj21.created); expect(newObj.obj2Name).toEqual('newName123'); expect(newObj.obj2User).toEqual(obj21.user); expect(objs.value).toEqual({ 'obj2ID': obj21.id, 'obj2Created': obj21.created, 'obj2Name': 'newName123', 'obj2User': obj21.user, }); }); test('getResource for instance relation data primitive fields works', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obj1 = await client.createObject(universe.resolve('base.object/')!, 'obj1') as Obj; const obj2 = await client.createObject(universe.resolve('base.object/')!, 'obj2') as Obj; const obj11 = await client.createObject(obj1.id, 'obj11') as Obj; const rel1 = await client.createRelation(obj1.id, obj2.id, universe.resolve('base.object#relation/')!) as Obj; await client.putValue(obj11.id, rel1.id, -12, 'data', 'integer', new PrimitiveMapping()); const schema = new ResourceSchema() .addField('val', 'data', 'integer', rel1.id, new PrimitiveMapping()); const newValsRcv: any[] = []; const objs = streamClient.getResourceInstance(new ResourceInstance(obj11.id, schema), {instant: true}); objs.subscribe((evt) => { if (evt.added) { newValsRcv.push(evt.added['val']); } }); await sleep(100); expect(objs.value).toEqual({'val': -12}); expect(newValsRcv).toEqual([-12]); await client.putValue(obj11.id, rel1.id, 1, 'data', 'integer', new PrimitiveMapping()); await sleep(100); expect(objs.value).toEqual({'val': 1}); await client.putValue(obj11.id, rel1.id, 2, 'data', 'integer', new PrimitiveMapping()); await sleep(100); expect(objs.value).toEqual({'val': 2}); await client.putValue(obj11.id, rel1.id, 3, 'data', 'integer', new PrimitiveMapping()); await sleep(100); expect(objs.value).toEqual({'val': 3}); await streamClient.disconnect(); expect(newValsRcv).toEqual([-12, 1, 2, 3]); }); test('getResource for instance relation list fields (except data) works', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obj1 = await client.createObject(universe.resolve('base.object/')!, 'obj1') as Obj; const obj2 = await client.createObject(universe.resolve('base.object/')!, 'obj2') as Obj; const obj11 = await client.createObject(obj1.id, 'obj11') as Obj; const rel1 = await client.createRelation(obj1.id, obj2.id, universe.resolve('base.object#relation/')!) as Obj; const schema = new ResourceSchema() .addField('obj2ID', 'id', 'hex', rel1.id, new ListMapping()) .addField('obj2Created', 'created', 'integer', rel1.id, new ListMapping()) .addField('obj2Name', 'name', 'string', rel1.id, new ListMapping()) .addField('obj2User', 'user', 'hex', rel1.id, new ListMapping()); const newObj: any = {}; const obs = streamClient.getResourceInstance(new ResourceInstance(obj11.id, schema), { instant: true, interval: 2 }); obs.subscribe((evt) => { if (evt.added) { Object.assign(newObj, evt.added); } }); const obj21 = await client.createObject(obj2.id, 'obj21') as Obj; await client.putValue(obj11.id, rel1.id, obj21.id, 'id', 'hex', new PrimitiveMapping()); await client.setName(obj21.id, 'newName123'); await sleep(100); await streamClient.disconnect(); expect(newObj.obj2ID).toEqual([obj21.id]); expect(newObj.obj2Created).toEqual([obj21.created]); expect(newObj.obj2Name).toEqual(['newName123']); expect(newObj.obj2User).toEqual([obj21.user]); expect(obs.value).toEqual({ 'obj2ID': [obj21.id], 'obj2Created': [obj21.created], 'obj2Name': ['newName123'], 'obj2User': [obj21.user], }); }); test('getResource for special object primitive fields works', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obj1 = await client.createObject(universe.resolve('base.object/')!, 'obj1') as Obj; const schema = new ResourceSchema() .addField('id', 'id', 'hex') .addField('name', 'name', 'string') .addField('created', 'created', 'integer') .addField('user', 'user', 'hex') .addField('value', 'data', 'integer'); const idRcv = new Map(); const nameRcv = new Map(); const createdRcv = new Map(); const userRcv = new Map(); const valueRcv = new Map(); const obj11 = await client.createObject(obj1.id, 'obj11') as Obj; await client.setData(obj11.id, 1, 'integer'); const obj12 = await client.createObject(obj1.id, 'obj12') as Obj; const objs = streamClient.getResourceSpecials(new ResourceSpecials(obj1.id, schema), { instant: true, interval: 0 }); objs.subscribe((evt) => { if (evt.added) { if (evt.added['id']) { idRcv.set(evt.id, evt.added['id'] as Id); } if (evt.added['name']) { nameRcv.set(evt.id, evt.added['name'] as string); } if (evt.added['created']) { createdRcv.set(evt.id, evt.added['created'] as number); } if (evt.added['user']) { userRcv.set(evt.id, evt.added['user'] as string); } if (evt.added['value']) { valueRcv.set(evt.id, evt.added['value'] as number); } } }); await sleep(100); await client.setData(obj12.id, 2, 'integer'); const obj13 = await client.createObject(obj1.id, 'obj13') as Obj; await client.setData(obj13.id, 3, 'integer'); await sleep(100); expect(nameRcv.get(obj11.id)).toEqual(obj11.name); expect(nameRcv.get(obj12.id)).toEqual(obj12.name); expect(nameRcv.get(obj13.id)).toEqual(obj13.name); expect(idRcv.get(obj11.id)).toEqual(obj11.id); expect(idRcv.get(obj12.id)).toEqual(obj12.id); expect(idRcv.get(obj13.id)).toEqual(obj13.id); expect(createdRcv.get(obj11.id)).toEqual(obj11.created); expect(createdRcv.get(obj12.id)).toEqual(obj12.created); expect(createdRcv.get(obj13.id)).toEqual(obj13.created); expect(userRcv.get(obj11.id)).toEqual(obj11.user); expect(userRcv.get(obj12.id)).toEqual(obj12.user); expect(userRcv.get(obj13.id)).toEqual(obj13.user); expect(valueRcv.get(obj11.id)).toEqual(1); expect(valueRcv.get(obj12.id)).toEqual(2); expect(valueRcv.get(obj13.id)).toEqual(3); expect(objs.values).toHaveLength(3); expect(objs.values.find(v => v.id === obj11.id)).toEqual({ 'id': obj11.id, 'name': obj11.name, 'created': obj11.created, 'user': obj11.user, 'value': 1 }); expect(objs.values.find(v => v.id === obj12.id)).toEqual({ 'id': obj12.id, 'name': obj12.name, 'created': obj12.created, 'user': obj12.user, 'value': 2 }); expect(objs.values.find(v => v.id === obj13.id)).toEqual({ 'id': obj13.id, 'name': obj13.name, 'created': obj13.created, 'user': obj13.user, 'value': 3 }); await client.deleteObject(obj11.id); await sleep(100); expect(objs.values).toHaveLength(2); expect(objs.values.find(v => v.id === obj11.id)).toBeFalsy(); await streamClient.disconnect(); }); test('getResource for special relation primitive fields (except data) works (instant)', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obj1 = await client.createObject(universe.resolve('base.object/')!, 'obj1') as Obj; const obj2 = await client.createObject(universe.resolve('base.object/')!, 'obj2') as Obj; const rel1 = await client.createRelation(obj1.id, obj2.id, universe.resolve('base.object#relation/')!) as Obj; const obj11 = await client.createObject(obj1.id, 'obj11') as Obj; const obj21 = await client.createObject(obj2.id, 'obj21') as Obj; await client.putValue(obj11.id, rel1.id, obj21.id, 'id', 'hex', new PrimitiveMapping()); const schema = new ResourceSchema() .addField('obj2ID', 'id', 'hex', rel1.id, new PrimitiveMapping) .addField('obj2Created', 'created', 'integer', rel1.id, new PrimitiveMapping) .addField('obj2Name', 'name', 'string', rel1.id, new PrimitiveMapping) .addField('obj2User', 'user', 'hex', rel1.id, new PrimitiveMapping); const objs = streamClient.getResourceSpecials(new ResourceSpecials(obj1.id, schema), {instant: true}); let newId: Id | undefined; let newCreated: number | undefined; let newName: string | undefined; let newUser: Id | undefined; objs.subscribe((evt) => { newId = (evt.added?.obj2ID as Id | undefined ?? newId); newCreated = (evt.added?.obj2Created as number | undefined ?? newCreated); newName = (evt.added?.obj2Name as string | undefined ?? newName); newUser = (evt.added?.obj2User as Id | undefined ?? newUser); }); await sleep(100); await streamClient.disconnect(); expect(newId).toEqual(obj21.id); expect(newCreated).toEqual(obj21.created); expect(newName).toEqual(obj21.name); expect(newUser).toEqual(obj21.user); }); test('getResource for special relation primitive fields (except data) works', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obj1 = await client.createObject(universe.resolve('base.object/')!, 'obj1') as Obj; const obj2 = await client.createObject(universe.resolve('base.object/')!, 'obj2') as Obj; const rel1 = await client.createRelation(obj1.id, obj2.id, universe.resolve('base.object#relation/')!) as Obj; const schema = new ResourceSchema() .addField('obj2ID', 'id', 'hex', rel1.id, new PrimitiveMapping) .addField('obj2Created', 'created', 'integer', rel1.id, new PrimitiveMapping) .addField('obj2Name', 'name', 'string', rel1.id, new PrimitiveMapping) .addField('obj2User', 'user', 'hex', rel1.id, new PrimitiveMapping); const objs = streamClient.getResourceSpecials(new ResourceSpecials(obj1.id, schema), {instant: false}); let newId: Id | undefined; let newCreated: number | undefined; let newName: string | undefined; let newUser: Id | undefined; objs.subscribe((evt) => { newId = (evt.added?.obj2ID as Id | undefined ?? newId); newCreated = (evt.added?.obj2Created as number | undefined ?? newCreated); newName = (evt.added?.obj2Name as string | undefined ?? newName); newUser = (evt.added?.obj2User as Id | undefined ?? newUser); }); const obj11 = await client.createObject(obj1.id, 'obj11') as Obj; const obj21 = await client.createObject(obj2.id, 'obj21') as Obj; await client.putValue(obj11.id, rel1.id, obj21.id, 'id', 'hex', new PrimitiveMapping()); await client.setName(obj21.id, 'newName123'); await sleep(200); await streamClient.disconnect(); expect(newId).toEqual(obj21.id); expect(newCreated).toEqual(obj21.created); expect(newName).toEqual('newName123'); expect(newUser).toEqual(obj21.user); }); test('getResource for special relation list fields works', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obj1 = await client.createObject(universe.resolve('base.object/')!, 'obj1') as Obj; const obj2 = await client.createObject(universe.resolve('base.object/')!, 'obj2') as Obj; const obj3 = await client.createObject(universe.resolve('base.object/')!, 'obj2') as Obj; const obj4 = await client.createObject(universe.resolve('base.object/')!, 'obj2') as Obj; const obj5 = await client.createObject(universe.resolve('base.object/')!, 'obj2') as Obj; const rel1 = await client.createRelation(obj1.id, obj2.id, universe.resolve('base.object#relation/')!) as Obj; const rel2 = await client.createRelation(obj1.id, obj3.id, universe.resolve('base.object#relation/')!) as Obj; const rel3 = await client.createRelation(obj1.id, obj4.id, universe.resolve('base.object#relation/')!) as Obj; const rel4 = await client.createRelation(obj1.id, obj5.id, universe.resolve('base.object#relation/')!) as Obj; const schema = new ResourceSchema() .addField('id', 'id', 'hex') .addField('intVals', 'data', 'integer', rel1.id, new ListMapping().change('set')) .addField('strVal', 'data', 'string', rel2.id, new PrimitiveMapping()) .addField('ids', 'id', 'hex', rel3.id, new ListMapping()) .addField('id2', 'id', 'hex', rel4.id, new PrimitiveMapping()); const res = new ResourceSpecials(obj1.id, schema); const objs = streamClient.getResourceSpecials(res, {instant: false}); const val1: any = { intVals: [1, 2, 3], strVal: 'test' }; await client.putResourceSpecials(res, [val1]); await sleep(100); expect(objs.values[0]['intVals']).toEqual(val1['intVals']); val1.id = objs.values[0].id; val1.intVals = [6, 7, 8]; await client.putResourceSpecials(res, [val1]); await sleep(100); expect(objs.values).toEqual([val1]); const val2: any = { strVal: 'test2' }; await client.putResourceSpecials(res, [val2]); await sleep(100); expect(objs.values).toHaveLength(2); await client.deleteObject(objs.values[0].id as Id); await sleep(100); expect(objs.values).toHaveLength(1); await streamClient.disconnect(); }); test('getResource filtering and ordering works', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obj1 = await client.createObject(universe.resolve('base.object/')!, 'obj1') as Obj; const obj2 = await client.createObject(universe.resolve('base.object/')!, 'obj2') as Obj; const rel1 = await client.createRelation(obj1.id, obj2.id, universe.resolve('base.object#relation/')!) as Obj; const schema = new ResourceSchema() .addField('id', 'id', 'hex') .addField('intVal', 'data', 'integer', rel1.id, new PrimitiveMapping().change('set')); const res = new ResourceSpecials(obj1.id, schema); for (let i = 0; i < 10; i++) { await client.putResourceSpecials(res, [{'intVal': i}]); } await sleep(100); const obs = streamClient.getResourceSpecials(res .addFilter('intVal', 2, 'gt') .addOrder('intVal', true), {instant: true}, ); for (let i = 0; i < 10; i++) { await client.putResourceSpecials(res, [{'intVal': i}]); } await sleep(200); expect(obs.values).toHaveLength(14); expect(obs.values.map(v => v['intVal'])).toEqual([3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9]); res.order = new ResourceOrder().order('intVal', false); obs.reorder(); expect(obs.values.map(v => v['intVal'])).toEqual([3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9].reverse()); await streamClient.disconnect(); }, 15000); test('getResource interval works', async () => { const universe = (await loadUniverseFromApi(globalUniverse, globalApiUrl))!; const client = newSystemClient(globalSystemUrl); client.layerProfile = layerProfile; const streamClient = newSystemStreamClient(globalSystemStreamUrl); await streamClient.connect(); await streamClient.registerLayerToken(layerProfile.getAccessGroup('main_full')!.tokens[0]); const obj1 = await client.createObject(universe.resolve('base.object/')!, 'obj1') as Obj; const obj2 = await client.createObject(universe.resolve('base.object/')!, 'obj2') as Obj; const rel1 = await client.createRelation(obj1.id, obj2.id, universe.resolve('base.object#relation/')!) as Obj; const rel2 = await client.createRelation(obj1.id, obj2.id, universe.resolve('base.object#relation/')!) as Obj; const schema = new ResourceSchema() .addField('id', 'id', 'hex') .addField('intVal', 'data', 'integer', rel1.id, new PrimitiveMapping().change('set')) .addField('intVals', 'data', 'integer', rel2.id, new ListMapping().change('set')); const res = new ResourceSpecials(obj1.id, schema); for (let i = 0; i < 1; i++) { await client.putResourceSpecials(res, [{'intVal': -1, 'intVals': [-1, -2, -3]}]); } await sleep(100); const interval = 100; const obs = streamClient.getResourceSpecials(res, {instant: true, interval}, ); const objRes = new Map(); const updates: any[] = []; obs.subscribe(ud => { if (!objRes.has(ud.id)) { objRes.set(ud.id, new ResourceInstance(ud.id, schema)); } updates.push(ud); }); await sleep(interval + 1000); for (const or of Array.from(objRes.values())) { await client.putResourceInstance(or, {'intVal': 1, 'intVals': [1]}); console.log(new Date()); } for (const or of Array.from(objRes.values())) { await client.putResourceInstance(or, {'intVal': 2, 'intVals': [2]}); console.log(new Date()); } for (const or of Array.from(objRes.values())) { await client.putResourceInstance(or, {'intVal': 4, 'intVals': [3, 4]}); console.log(new Date()); } await sleep(3000); await streamClient.disconnect(); console.log(updates); expect(objRes.size).toEqual(1); expect(obs.values[0].intVal).toEqual(4); expect(obs.values[0].intVals).toEqual([3, 4]); expect(obs.values).toHaveLength(1); }, 15000);