824 lines
26 KiB
TypeScript
824 lines
26 KiB
TypeScript
import { v4 } from 'uuid';
|
|
import { describe, it } from 'mocha';
|
|
import { EntityDict, storageSchema } from 'oak-domain/lib/base-app-domain';
|
|
import { generateNewId } from 'oak-domain/lib/utils/uuid';
|
|
import assert from 'assert';
|
|
import TreeStore from '../src/store';
|
|
import { FrontendRuntimeContext, FrontendStore } from './Context';
|
|
|
|
describe('基础测试', function () {
|
|
this.timeout(1000000);
|
|
|
|
it('[1.0]简单查询', () => {
|
|
const store = new FrontendStore(storageSchema);
|
|
const context = new FrontendRuntimeContext(store);
|
|
context.begin();
|
|
const created = store.operate('modiEntity', {
|
|
id: generateNewId(),
|
|
action: 'create',
|
|
data: [{
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
modi: {
|
|
action: 'create',
|
|
data: {
|
|
id: generateNewId(),
|
|
targetEntity: 'ddd',
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
action: 'create',
|
|
data: {},
|
|
}
|
|
}
|
|
}, {
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
modi: {
|
|
action: 'create',
|
|
data: {
|
|
id: generateNewId(),
|
|
targetEntity: 'ddd',
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
action: 'update',
|
|
data: {},
|
|
}
|
|
}
|
|
}]
|
|
}, context, {});
|
|
|
|
// console.log(created);
|
|
|
|
const modiEntities = store.select('modiEntity', {
|
|
data: {
|
|
id: 1,
|
|
entity: 1,
|
|
entityId: 1,
|
|
modi: {
|
|
id: 1,
|
|
targetEntity: 1,
|
|
entity: 1,
|
|
entityId: 1,
|
|
action: 1,
|
|
data: 1,
|
|
}
|
|
},
|
|
sorter: [
|
|
{
|
|
$attr: {
|
|
modi: {
|
|
id: 1,
|
|
}
|
|
},
|
|
$direction: 'asc',
|
|
}
|
|
]
|
|
}, context, {});
|
|
// console.log(modiEntities);
|
|
|
|
context.commit();
|
|
});
|
|
|
|
it('[1.1]子查询', () => {
|
|
const store = new FrontendStore(storageSchema);
|
|
const context = new FrontendRuntimeContext(store);
|
|
context.begin();
|
|
|
|
const created = store.operate('modiEntity', {
|
|
id: generateNewId(),
|
|
action: 'create',
|
|
data: [{
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
modi: {
|
|
action: 'create',
|
|
data: {
|
|
id: generateNewId(),
|
|
targetEntity: 'ddd',
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
action: 'create',
|
|
data: {},
|
|
}
|
|
}
|
|
}, {
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
modi: {
|
|
action: 'create',
|
|
data: {
|
|
id: generateNewId(),
|
|
targetEntity: 'ddd',
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
action: 'update',
|
|
data: {},
|
|
}
|
|
}
|
|
}]
|
|
}, context, {});
|
|
|
|
/**
|
|
* 这个子查询没有跨结点的表达式,所以应该可以提前计算子查询的值
|
|
* 这个可以跟一下store.ts中translateAttribute函数里$in的分支代码
|
|
* by Xc
|
|
*/
|
|
const rows = store.select('modi', {
|
|
data: {
|
|
id: 1,
|
|
targetEntity: 1,
|
|
entity: 1,
|
|
},
|
|
filter: {
|
|
id: {
|
|
$in: {
|
|
entity: 'modiEntity',
|
|
data: {
|
|
modiId: 1,
|
|
},
|
|
filter: {
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
}
|
|
},
|
|
}
|
|
},
|
|
}, context, {});
|
|
// console.log(rows);
|
|
assert(rows.length === 2);
|
|
context.commit();
|
|
});
|
|
|
|
it('[1.2]行内属性上的表达式', () => {
|
|
const store = new FrontendStore(storageSchema);
|
|
const context = new FrontendRuntimeContext(store);
|
|
context.begin();
|
|
|
|
const created = store.operate('modiEntity', {
|
|
id: generateNewId(),
|
|
action: 'create',
|
|
data: [{
|
|
id: generateNewId(),
|
|
entity: 'user-id-1',
|
|
entityId: 'user-id-1',
|
|
modi: {
|
|
action: 'create',
|
|
data: {
|
|
id: generateNewId(),
|
|
targetEntity: 'ddd',
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
action: 'create',
|
|
data: {},
|
|
}
|
|
}
|
|
}, {
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
modi: {
|
|
action: 'create',
|
|
data: {
|
|
id: generateNewId(),
|
|
targetEntity: 'ddd',
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
action: 'update',
|
|
data: {},
|
|
}
|
|
}
|
|
}]
|
|
}, context, {});
|
|
|
|
const modiEntities = store.select('modiEntity', {
|
|
data: {
|
|
id: 1,
|
|
entity: 1,
|
|
entityId: 1,
|
|
},
|
|
filter: {
|
|
// '#id': 'node-123',
|
|
$expr: {
|
|
$ne: [{
|
|
'#attr': 'entity',
|
|
}, {
|
|
"#attr": 'entityId',
|
|
}]
|
|
}
|
|
},
|
|
}, context, {});
|
|
|
|
// console.log(modiEntities);
|
|
assert(modiEntities.length === 1);
|
|
context.commit();
|
|
});
|
|
|
|
it('[1.3]跨filter结点的表达式', () => {
|
|
const store = new FrontendStore(storageSchema);
|
|
const context = new FrontendRuntimeContext(store);
|
|
context.begin();
|
|
|
|
const created = store.operate('modiEntity', {
|
|
id: generateNewId(),
|
|
action: 'create',
|
|
data: [{
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
modi: {
|
|
action: 'create',
|
|
data: {
|
|
id: generateNewId(),
|
|
targetEntity: 'ddd',
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
action: 'create',
|
|
data: {},
|
|
}
|
|
}
|
|
}, {
|
|
id: generateNewId(),
|
|
entity: 'user3',
|
|
entityId: 'user3-id-1',
|
|
modi: {
|
|
action: 'create',
|
|
data: {
|
|
id: generateNewId(),
|
|
targetEntity: 'ddd',
|
|
entity: 'user2',
|
|
entityId: 'user2-id-1',
|
|
action: 'update',
|
|
data: {},
|
|
}
|
|
}
|
|
}]
|
|
}, context, {});
|
|
|
|
|
|
const applications = store.select('modiEntity', {
|
|
data: {
|
|
id: 1,
|
|
entity: 1,
|
|
entityId: 1,
|
|
},
|
|
filter: {
|
|
$expr: {
|
|
$startsWith: [
|
|
{
|
|
"#refAttr": 'entityId',
|
|
"#refId": 'node-1',
|
|
},
|
|
{
|
|
"#attr": 'entity',
|
|
}
|
|
]
|
|
},
|
|
modi: {
|
|
"#id": 'node-1',
|
|
}
|
|
},
|
|
sorter: [
|
|
{
|
|
$attr: {
|
|
modi: {
|
|
entity: 1,
|
|
}
|
|
},
|
|
$direction: 'asc',
|
|
}
|
|
]
|
|
}, context, {});
|
|
// console.log(applications);
|
|
assert(applications.length === 1);
|
|
|
|
context.commit();
|
|
});
|
|
|
|
|
|
it('[1.4]跨filter子查询的表达式', () => {
|
|
const store = new FrontendStore(storageSchema);
|
|
const context = new FrontendRuntimeContext(store);
|
|
context.begin();
|
|
|
|
const created = store.operate('modiEntity', {
|
|
id: generateNewId(),
|
|
action: 'create',
|
|
data: [{
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
modi: {
|
|
action: 'create',
|
|
data: {
|
|
id: generateNewId(),
|
|
targetEntity: 'ddd',
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
action: 'create',
|
|
data: {},
|
|
}
|
|
}
|
|
}, {
|
|
id: generateNewId(),
|
|
entity: 'user3',
|
|
entityId: 'user3-id-1',
|
|
modi: {
|
|
action: 'create',
|
|
data: {
|
|
id: generateNewId(),
|
|
targetEntity: 'ddd',
|
|
entity: 'user2',
|
|
entityId: 'user2-id-1',
|
|
action: 'update',
|
|
data: {},
|
|
}
|
|
}
|
|
}]
|
|
}, context, {});
|
|
|
|
let modies = store.select('modi', {
|
|
data: {
|
|
id: 1,
|
|
targetEntity: 1,
|
|
},
|
|
filter: {
|
|
"#id": 'node-1',
|
|
id: {
|
|
$nin: {
|
|
entity: 'modiEntity',
|
|
data: {
|
|
modiId: 1,
|
|
},
|
|
filter: {
|
|
$expr: {
|
|
$eq: [
|
|
{
|
|
"#attr": 'entity',
|
|
},
|
|
{
|
|
'#refId': 'node-1',
|
|
"#refAttr": 'entity',
|
|
}
|
|
]
|
|
},
|
|
'#id': 'node-2',
|
|
}
|
|
},
|
|
}
|
|
},
|
|
sorter: [
|
|
{
|
|
$attr: {
|
|
entity: 1,
|
|
},
|
|
$direction: 'asc',
|
|
}
|
|
]
|
|
}, context, {});
|
|
assert(modies.length === 1);
|
|
// console.log(modies);
|
|
context.commit();
|
|
});
|
|
|
|
it('[1.5]projection中的跨结点表达式', () => {
|
|
const store = new FrontendStore(storageSchema);
|
|
const context = new FrontendRuntimeContext(store);
|
|
context.begin();
|
|
|
|
const created = store.operate('modiEntity', {
|
|
id: generateNewId(),
|
|
action: 'create',
|
|
data: [{
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
modi: {
|
|
action: 'create',
|
|
data: {
|
|
id: generateNewId(),
|
|
targetEntity: 'ddd',
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
action: 'create',
|
|
data: {},
|
|
}
|
|
}
|
|
}, {
|
|
id: generateNewId(),
|
|
entity: 'user3',
|
|
entityId: 'user3-id-1',
|
|
modi: {
|
|
action: 'create',
|
|
data: {
|
|
id: generateNewId(),
|
|
targetEntity: 'ddd',
|
|
entity: 'user2',
|
|
entityId: 'user2-id-1',
|
|
action: 'update',
|
|
data: {},
|
|
}
|
|
}
|
|
}]
|
|
}, context, {});
|
|
|
|
let modiEntities = store.select('modiEntity', {
|
|
data: {
|
|
"#id": 'node-1',
|
|
id: 1,
|
|
entity: 1,
|
|
modi: {
|
|
id: 1,
|
|
$expr: {
|
|
$eq: [
|
|
{
|
|
"#attr": 'entity',
|
|
},
|
|
{
|
|
'#refId': 'node-1',
|
|
"#refAttr": 'entity',
|
|
}
|
|
]
|
|
},
|
|
}
|
|
},
|
|
}, context, {});
|
|
// console.log(modiEntities);
|
|
assert(modiEntities.length === 2);
|
|
modiEntities.forEach(
|
|
(me) => {
|
|
assert(me.entity === 'user' && me?.modi?.$expr === true ||
|
|
me.entity === 'user3' && me?.modi?.$expr === false);
|
|
}
|
|
)
|
|
|
|
const modiEntities2 = store.select('modiEntity', {
|
|
data: {
|
|
$expr: {
|
|
$eq: [
|
|
{
|
|
"#attr": 'entity',
|
|
},
|
|
{
|
|
'#refId': 'node-1',
|
|
"#refAttr": 'entity',
|
|
}
|
|
]
|
|
},
|
|
id: 1,
|
|
entity: 1,
|
|
modi: {
|
|
"#id": 'node-1',
|
|
id: 1,
|
|
targetEntity: 1,
|
|
entity: 1,
|
|
}
|
|
},
|
|
}, context, {});
|
|
// console.log(modiEntities2);
|
|
assert(modiEntities2.length === 2);
|
|
modiEntities2.forEach(
|
|
(me) => assert(me.entity === 'user' && me.$expr === true ||
|
|
me.entity === 'user3' && me.$expr === false)
|
|
);
|
|
context.commit();
|
|
});
|
|
|
|
it('[1.6]projection中的一对多跨结点表达式', () => {
|
|
const store = new FrontendStore(storageSchema);
|
|
const context = new FrontendRuntimeContext(store);
|
|
context.begin();
|
|
|
|
const created = store.operate('modiEntity', {
|
|
id: generateNewId(),
|
|
action: 'create',
|
|
data: [{
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
modi: {
|
|
action: 'create',
|
|
data: {
|
|
id: generateNewId(),
|
|
targetEntity: 'ddd',
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
action: 'create',
|
|
data: {},
|
|
}
|
|
}
|
|
}]
|
|
}, context, {});
|
|
|
|
const modies = store.select('modi', {
|
|
data: {
|
|
"#id": 'node-1',
|
|
id: 1,
|
|
targetEntity: 1,
|
|
entity: 1,
|
|
modiEntity$modi: {
|
|
$entity: 'modiEntity',
|
|
data: {
|
|
id: 1,
|
|
entity: 1,
|
|
// modiId: 1,
|
|
$expr: {
|
|
$eq: [
|
|
{
|
|
"#attr": 'entity',
|
|
},
|
|
{
|
|
'#refId': 'node-1',
|
|
"#refAttr": 'entity',
|
|
}
|
|
]
|
|
},
|
|
$expr2: {
|
|
'#refId': 'node-1',
|
|
"#refAttr": 'id',
|
|
}
|
|
}
|
|
},
|
|
},
|
|
}, context, {});
|
|
// console.log(JSON.stringify(modies));
|
|
assert(modies.length === 1);
|
|
const [modi] = modies;
|
|
const { modiEntity$modi: modiEntities } = modi;
|
|
assert(modiEntities!.length === 1 && modiEntities![0]?.$expr === true && modiEntities![0]?.$expr2 === modi.id);
|
|
context.commit();
|
|
});
|
|
|
|
it('[1.7]事务性测试', () => {
|
|
const store = new FrontendStore(storageSchema);
|
|
const context = new FrontendRuntimeContext(store);
|
|
context.begin();
|
|
|
|
const created = store.operate('modiEntity', {
|
|
id: generateNewId(),
|
|
action: 'create',
|
|
data: [{
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
modi: {
|
|
action: 'create',
|
|
data: {
|
|
id: generateNewId(),
|
|
targetEntity: 'ddd',
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
action: 'create',
|
|
data: {},
|
|
}
|
|
}
|
|
}, {
|
|
id: generateNewId(),
|
|
entity: 'user3',
|
|
entityId: 'user3-id-1',
|
|
modi: {
|
|
action: 'create',
|
|
data: {
|
|
id: generateNewId(),
|
|
targetEntity: 'ddd',
|
|
entity: 'user2',
|
|
entityId: 'user2-id-1',
|
|
action: 'update',
|
|
data: {},
|
|
}
|
|
}
|
|
}]
|
|
}, context, {});
|
|
context.commit();
|
|
|
|
context.begin();
|
|
const modies = store.select('modi', {
|
|
data: {
|
|
id: 1,
|
|
entity: 1,
|
|
modiEntity$modi: {
|
|
$entity: 'modiEntity',
|
|
data: {
|
|
id: 1,
|
|
entity: 1,
|
|
modiId: 1,
|
|
}
|
|
},
|
|
},
|
|
}, context, {});
|
|
assert(modies.length === 2 && modies[0].modiEntity$modi!.length === 1);
|
|
|
|
store.operate('modiEntity', {
|
|
action: 'remove',
|
|
data: {},
|
|
filter: {
|
|
modiId: modies[0]!.id,
|
|
}
|
|
}, context, {});
|
|
|
|
const me2 = store.select('modiEntity', {
|
|
data: {
|
|
id: 1,
|
|
entity: 1,
|
|
},
|
|
}, context, {});
|
|
assert(me2.length === 1 && !me2.find(ele => !!ele.$$deleteAt$$));
|
|
context.rollback();
|
|
|
|
context.begin();
|
|
|
|
const me3 = store.select('modiEntity', {
|
|
data: {
|
|
id: 1,
|
|
entity: 1,
|
|
},
|
|
}, context, {});
|
|
assert(me3.length === 2 && !me3.find(ele => !!ele.$$deleteAt$$));
|
|
|
|
context.commit();
|
|
});
|
|
|
|
it('[1.8]aggregate', () => {
|
|
const store = new FrontendStore(storageSchema);
|
|
const context = new FrontendRuntimeContext(store);
|
|
context.begin();
|
|
store.operate('modi', {
|
|
id: generateNewId(),
|
|
action: 'create',
|
|
data: [{
|
|
id: generateNewId(),
|
|
targetEntity: 'ddd',
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
action: 'create',
|
|
data: {},
|
|
modiEntity$modi: {
|
|
action: 'create',
|
|
data: [{
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
}, {
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
}, {
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
}, {
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
}]
|
|
}
|
|
}, {
|
|
id: generateNewId(),
|
|
targetEntity: 'ddd2',
|
|
entity: 'user',
|
|
entityId: 'user-id-2',
|
|
action: 'create',
|
|
data: {},
|
|
modiEntity$modi: {
|
|
action: 'create',
|
|
data: [
|
|
{
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-2',
|
|
},
|
|
{
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-2',
|
|
},
|
|
{
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-2',
|
|
}
|
|
],
|
|
},
|
|
}],
|
|
}, context, {});
|
|
context.commit();
|
|
|
|
context.begin();
|
|
const result = store.aggregate('modiEntity', {
|
|
data: {
|
|
'$count-1': {
|
|
id: 1,
|
|
},
|
|
'$avg-1': {
|
|
$$createAt$$: 1,
|
|
},
|
|
$aggr: {
|
|
modi: {
|
|
targetEntity: 1,
|
|
}
|
|
}
|
|
},
|
|
}, context, {});
|
|
// console.log(result);
|
|
context.commit();
|
|
});
|
|
|
|
it('[1.9]selection+aggregate', () => {
|
|
const store = new FrontendStore(storageSchema);
|
|
const context = new FrontendRuntimeContext(store);
|
|
context.begin();
|
|
store.operate('modi', {
|
|
id: generateNewId(),
|
|
action: 'create',
|
|
data: [{
|
|
id: generateNewId(),
|
|
targetEntity: 'ddd',
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
action: 'create',
|
|
data: {},
|
|
modiEntity$modi: {
|
|
action: 'create',
|
|
data: [{
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
}, {
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
}, {
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
}, {
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-1',
|
|
}]
|
|
}
|
|
}, {
|
|
id: generateNewId(),
|
|
targetEntity: 'ddd2',
|
|
entity: 'user',
|
|
entityId: 'user-id-2',
|
|
action: 'create',
|
|
data: {},
|
|
modiEntity$modi: {
|
|
action: 'create',
|
|
data: [
|
|
{
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-2',
|
|
},
|
|
{
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-2',
|
|
},
|
|
{
|
|
id: generateNewId(),
|
|
entity: 'user',
|
|
entityId: 'user-id-2',
|
|
}
|
|
],
|
|
},
|
|
}],
|
|
}, context, {});
|
|
context.commit();
|
|
|
|
context.begin();
|
|
const result = store.select('modi', {
|
|
data: {
|
|
id: 1,
|
|
modiEntity$modi$$aggr: {
|
|
$entity: 'modiEntity',
|
|
data: {
|
|
'$count-1': {
|
|
id: 1,
|
|
},
|
|
'$avg-1': {
|
|
$$createAt$$: 1,
|
|
},
|
|
$aggr: {
|
|
modi: {
|
|
targetEntity: 1,
|
|
}
|
|
}
|
|
},
|
|
filter: {
|
|
entity: 'user',
|
|
},
|
|
}
|
|
}
|
|
}, context, {});
|
|
console.log(result);
|
|
context.commit();
|
|
})
|
|
});
|
|
|