603 lines
18 KiB
TypeScript
603 lines
18 KiB
TypeScript
import { v4 } from 'uuid';
|
|
import { describe, it } from 'mocha';
|
|
import TreeStore from '../src/store';
|
|
import EntityDict from './app-domain/EntityDict';
|
|
import { Context } from '../src/context';
|
|
import { storageSchema } from './app-domain/Storage';
|
|
import assert from 'assert';
|
|
|
|
describe('基础测试', function () {
|
|
this.timeout(1000000);
|
|
|
|
it('[1.0]简单查询', async () => {
|
|
const store = new TreeStore<keyof EntityDict, EntityDict>(storageSchema);
|
|
const context = new Context(store);
|
|
await store.operate('application', {
|
|
action: 'create',
|
|
data: [{
|
|
id: 'aaa',
|
|
name: 'test',
|
|
description: 'ttttt',
|
|
type: 'web',
|
|
system: {
|
|
action: 'create',
|
|
data: {
|
|
id: 'bbb',
|
|
name: 'systest',
|
|
description: 'aaaaa',
|
|
config: {},
|
|
}
|
|
}
|
|
}, {
|
|
id: 'aaa2',
|
|
name: 'test2',
|
|
description: 'ttttt2',
|
|
type: 'web',
|
|
system: {
|
|
action: 'create',
|
|
data: {
|
|
id: 'ccc',
|
|
name: 'systest2',
|
|
description: 'aaaaa2',
|
|
config: {},
|
|
}
|
|
}
|
|
}]
|
|
}, context);
|
|
|
|
const applications = await store.select('application', {
|
|
data: {
|
|
id: 1,
|
|
name: 1,
|
|
systemId: 1,
|
|
system: {
|
|
id: 1,
|
|
name: 1,
|
|
}
|
|
},
|
|
sorter: [
|
|
{
|
|
$attr: {
|
|
system: {
|
|
name: 1,
|
|
}
|
|
},
|
|
$direction: 'asc',
|
|
}
|
|
]
|
|
}, context);
|
|
console.log(applications);
|
|
});
|
|
|
|
it('[1.1]子查询', async () => {
|
|
const store = new TreeStore<keyof EntityDict, EntityDict>(storageSchema);
|
|
const context = new Context(store);
|
|
|
|
await store.operate('user', {
|
|
action: 'create',
|
|
data: {
|
|
id: v4(),
|
|
name: 'xc',
|
|
nickname: 'xc',
|
|
}
|
|
}, context);
|
|
|
|
/**
|
|
* 这个子查询没有跨结点的表达式,所以应该可以提前计算子查询的值
|
|
* 这个可以跟一下store.ts中translateAttribute函数里$in的分支代码
|
|
* by Xc
|
|
*/
|
|
const rows = await store.select('user', {
|
|
data: {
|
|
id: 1,
|
|
name: 1,
|
|
nickname: 1,
|
|
},
|
|
filter: {
|
|
id: {
|
|
$in: {
|
|
entity: 'token',
|
|
data: {
|
|
userId: 1,
|
|
},
|
|
filter: {
|
|
entity: 'mobile',
|
|
}
|
|
},
|
|
}
|
|
},
|
|
}, context);
|
|
// console.log(rows);
|
|
assert(rows.length === 0);
|
|
});
|
|
|
|
it('[1.2]行内属性上的表达式', async () => {
|
|
const store = new TreeStore<keyof EntityDict, EntityDict>(storageSchema);
|
|
const context = new Context(store);
|
|
|
|
await store.operate('user', {
|
|
action: 'create',
|
|
data: {
|
|
id: v4(),
|
|
name: 'xc',
|
|
nickname: 'xc',
|
|
}
|
|
}, context);
|
|
|
|
const users = await store.select('user', {
|
|
data: {
|
|
id: 1,
|
|
name: 1,
|
|
nickname: 1,
|
|
},
|
|
filter: {
|
|
// '#id': 'node-123',
|
|
$expr: {
|
|
$ne: [{
|
|
'#attr': 'name',
|
|
}, {
|
|
"#attr": 'nickname',
|
|
}]
|
|
}
|
|
},
|
|
}, context);
|
|
|
|
console.log(users);
|
|
});
|
|
|
|
it('[1.3]跨filter结点的表达式', async () => {
|
|
const store = new TreeStore<keyof EntityDict, EntityDict>(storageSchema);
|
|
const context = new Context(store);
|
|
|
|
await store.operate('application', {
|
|
action: 'create',
|
|
data: [{
|
|
id: 'aaa',
|
|
name: 'test',
|
|
description: 'ttttt',
|
|
type: 'web',
|
|
system: {
|
|
action: 'create',
|
|
data: {
|
|
id: 'bbb',
|
|
name: 'systest',
|
|
description: 'aaaaa',
|
|
config: {},
|
|
}
|
|
}
|
|
}, {
|
|
id: 'aaa2',
|
|
name: 'test2',
|
|
description: 'ttttt2',
|
|
type: 'web',
|
|
system: {
|
|
action: 'create',
|
|
data: {
|
|
id: 'ccc',
|
|
name: 'test2',
|
|
description: 'aaaaa2',
|
|
config: {},
|
|
}
|
|
}
|
|
}]
|
|
}, context);
|
|
|
|
const applications = await store.select('application', {
|
|
data: {
|
|
id: 1,
|
|
name: 1,
|
|
systemId: 1,
|
|
system: {
|
|
id: 1,
|
|
name: 1,
|
|
}
|
|
},
|
|
filter: {
|
|
$expr: {
|
|
$startsWith: [
|
|
{
|
|
"#refAttr": 'name',
|
|
"#refId": 'node-1',
|
|
},
|
|
{
|
|
"#attr": 'name',
|
|
}
|
|
]
|
|
},
|
|
system: {
|
|
"#id": 'node-1',
|
|
}
|
|
},
|
|
sorter: [
|
|
{
|
|
$attr: {
|
|
system: {
|
|
name: 1,
|
|
}
|
|
},
|
|
$direction: 'asc',
|
|
}
|
|
]
|
|
}, context);
|
|
console.log(applications);
|
|
});
|
|
|
|
|
|
it('[1.4]跨filter子查询的表达式', async () => {
|
|
const store = new TreeStore<keyof EntityDict, EntityDict>(storageSchema);
|
|
const context = new Context(store);
|
|
|
|
await store.operate('application', {
|
|
action: 'create',
|
|
data: [{
|
|
id: 'aaa',
|
|
name: 'test',
|
|
description: 'ttttt',
|
|
type: 'web',
|
|
system: {
|
|
action: 'create',
|
|
data: {
|
|
id: 'bbb',
|
|
name: 'systest',
|
|
description: 'aaaaa',
|
|
config: {},
|
|
}
|
|
}
|
|
}, {
|
|
id: 'aaa2',
|
|
name: 'test2',
|
|
description: 'ttttt2',
|
|
type: 'web',
|
|
system: {
|
|
action: 'create',
|
|
data: {
|
|
id: 'ccc',
|
|
name: 'test2',
|
|
description: 'aaaaa2',
|
|
config: {},
|
|
}
|
|
}
|
|
}]
|
|
}, context);
|
|
|
|
let systems = await store.select('system', {
|
|
data: {
|
|
id: 1,
|
|
name: 1,
|
|
},
|
|
filter: {
|
|
"#id": 'node-1',
|
|
id: {
|
|
$nin: {
|
|
entity: 'application',
|
|
data: {
|
|
systemId: 1,
|
|
},
|
|
filter: {
|
|
$expr: {
|
|
$eq: [
|
|
{
|
|
"#attr": 'name',
|
|
},
|
|
{
|
|
'#refId': 'node-1',
|
|
"#refAttr": 'name',
|
|
}
|
|
]
|
|
},
|
|
'#id': 'node-2',
|
|
}
|
|
},
|
|
}
|
|
},
|
|
sorter: [
|
|
{
|
|
$attr: {
|
|
name: 1,
|
|
},
|
|
$direction: 'asc',
|
|
}
|
|
]
|
|
}, context);
|
|
assert(systems.length === 1 && systems[0].id === 'bbb');
|
|
systems = await store.select('system', {
|
|
data: {
|
|
id: 1,
|
|
name: 1,
|
|
},
|
|
filter: {
|
|
"#id": 'node-1',
|
|
id: {
|
|
$in: {
|
|
entity: 'application',
|
|
data: {
|
|
systemId: 1,
|
|
},
|
|
filter: {
|
|
$expr: {
|
|
$eq: [
|
|
{
|
|
"#attr": 'name',
|
|
},
|
|
{
|
|
'#refId': 'node-1',
|
|
"#refAttr": 'name',
|
|
}
|
|
]
|
|
},
|
|
}
|
|
},
|
|
}
|
|
},
|
|
sorter: [
|
|
{
|
|
$attr: {
|
|
name: 1,
|
|
},
|
|
$direction: 'asc',
|
|
}
|
|
]
|
|
}, context);
|
|
assert(systems.length === 1 && systems[0].id === 'ccc');
|
|
});
|
|
|
|
it('[1.5]projection中的跨结点表达式', async () => {
|
|
const store = new TreeStore<keyof EntityDict, EntityDict>(storageSchema);
|
|
const context = new Context(store);
|
|
|
|
await store.operate('application', {
|
|
action: 'create',
|
|
data: [{
|
|
id: 'aaa',
|
|
name: 'test',
|
|
description: 'ttttt',
|
|
type: 'web',
|
|
system: {
|
|
action: 'create',
|
|
data: {
|
|
id: 'bbb',
|
|
name: 'systest',
|
|
description: 'aaaaa',
|
|
config: {},
|
|
}
|
|
}
|
|
}, {
|
|
id: 'aaa2',
|
|
name: 'test2',
|
|
description: 'ttttt2',
|
|
type: 'web',
|
|
system: {
|
|
action: 'create',
|
|
data: {
|
|
id: 'ccc',
|
|
name: 'test2',
|
|
description: 'aaaaa2',
|
|
config: {},
|
|
}
|
|
}
|
|
}]
|
|
}, context);
|
|
|
|
let applications = await store.select('application', {
|
|
data: {
|
|
"#id": 'node-1',
|
|
id: 1,
|
|
name: 1,
|
|
system: {
|
|
id: 1,
|
|
name: 1,
|
|
$expr: {
|
|
$eq: [
|
|
{
|
|
"#attr": 'name',
|
|
},
|
|
{
|
|
'#refId': 'node-1',
|
|
"#refAttr": 'name',
|
|
}
|
|
]
|
|
},
|
|
}
|
|
},
|
|
}, context);
|
|
// console.log(applications);
|
|
assert(applications.length === 2);
|
|
applications.forEach(
|
|
(app) => {
|
|
assert(app.id === 'aaa' && app.system!.$expr === false
|
|
|| app.id === 'aaa2' && app.system!.$expr === true);
|
|
}
|
|
);
|
|
|
|
applications = await store.select('application', {
|
|
data: {
|
|
$expr: {
|
|
$eq: [
|
|
{
|
|
"#attr": 'name',
|
|
},
|
|
{
|
|
'#refId': 'node-1',
|
|
"#refAttr": 'name',
|
|
}
|
|
]
|
|
},
|
|
id: 1,
|
|
name: 1,
|
|
system: {
|
|
"#id": 'node-1',
|
|
id: 1,
|
|
name: 1,
|
|
}
|
|
},
|
|
}, context);
|
|
console.log(applications);
|
|
// assert(applications.length === 2);
|
|
applications.forEach(
|
|
(app) => {
|
|
assert(app.id === 'aaa' && app.$expr === false
|
|
|| app.id === 'aaa2' && app.$expr === true);
|
|
}
|
|
);
|
|
});
|
|
|
|
it('[1.6]projection中的一对多跨结点表达式', async () => {
|
|
const store = new TreeStore<keyof EntityDict, EntityDict>(storageSchema);
|
|
const context = new Context(store);
|
|
|
|
await store.operate('system', {
|
|
action: 'create',
|
|
data: {
|
|
id: 'bbb',
|
|
name: 'test2',
|
|
description: 'aaaaa',
|
|
config: {},
|
|
application$system: {
|
|
action: 'create',
|
|
data: [
|
|
{
|
|
id: 'aaa',
|
|
name: 'test',
|
|
description: 'ttttt',
|
|
type: 'web',
|
|
},
|
|
{
|
|
|
|
id: 'aaa2',
|
|
name: 'test2',
|
|
description: 'ttttt2',
|
|
type: 'weChatMp',
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}, context);
|
|
|
|
const systems = await store.select('system', {
|
|
data: {
|
|
"#id": 'node-1',
|
|
id: 1,
|
|
name: 1,
|
|
application$system: {
|
|
data: {
|
|
id: 1,
|
|
name: 1,
|
|
$expr: {
|
|
$eq: [
|
|
{
|
|
"#attr": 'name',
|
|
},
|
|
{
|
|
'#refId': 'node-1',
|
|
"#refAttr": 'name',
|
|
}
|
|
]
|
|
},
|
|
$expr2: {
|
|
'#refId': 'node-1',
|
|
"#refAttr": 'id',
|
|
}
|
|
}
|
|
},
|
|
},
|
|
}, context);
|
|
// console.log(systems);
|
|
assert(systems.length === 1);
|
|
const [ system ] = systems;
|
|
const { application$system: applications } = system;
|
|
assert(applications!.length === 2);
|
|
applications!.forEach(
|
|
(ele) => {
|
|
assert(ele.id === 'aaa' && ele.$expr === false && ele.$expr2 === 'bbb'
|
|
|| ele.id === 'aaa2' && ele.$expr === true && ele.$expr2 === 'bbb');
|
|
}
|
|
);
|
|
});
|
|
|
|
it('[1.7]事务性测试', async () => {
|
|
const store = new TreeStore<keyof EntityDict, EntityDict>(storageSchema);
|
|
const context = new Context(store);
|
|
|
|
await store.operate('system', {
|
|
action: 'create',
|
|
data: {
|
|
id: 'bbb',
|
|
name: 'test2',
|
|
description: 'aaaaa',
|
|
config: {},
|
|
application$system: {
|
|
action: 'create',
|
|
data: [
|
|
{
|
|
id: 'aaa',
|
|
name: 'test',
|
|
description: 'ttttt',
|
|
type: 'web',
|
|
},
|
|
{
|
|
|
|
id: 'aaa2',
|
|
name: 'test2',
|
|
description: 'ttttt2',
|
|
type: 'weChatMp',
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}, context);
|
|
|
|
await context.begin();
|
|
const systems = await store.select('system', {
|
|
data: {
|
|
id: 1,
|
|
name: 1,
|
|
application$system: {
|
|
data: {
|
|
id: 1,
|
|
name: 1,
|
|
}
|
|
},
|
|
},
|
|
}, context);
|
|
assert(systems.length === 1 && systems[0].application$system!.length === 2);
|
|
|
|
await store.operate('application', {
|
|
action: 'remove',
|
|
data: {},
|
|
filter: {
|
|
id: 'aaa',
|
|
}
|
|
}, context);
|
|
|
|
const systems2 = await store.select('system', {
|
|
data: {
|
|
id: 1,
|
|
name: 1,
|
|
application$system: {
|
|
data: {
|
|
id: 1,
|
|
name: 1,
|
|
}
|
|
},
|
|
},
|
|
}, context);
|
|
assert(systems2.length === 1 && systems2[0].application$system!.length === 1);
|
|
await context.rollback();
|
|
|
|
const systems3 = await store.select('system', {
|
|
data: {
|
|
id: 1,
|
|
name: 1,
|
|
application$system: {
|
|
data: {
|
|
id: 1,
|
|
name: 1,
|
|
}
|
|
},
|
|
},
|
|
}, context);
|
|
assert(systems3.length === 1 && systems3[0].application$system!.length === 2);
|
|
});
|
|
});
|
|
|