test: filter nested association (#1802)
* test: filter nested association * chore: log * fix: tree instance to json * ci: test case * chore: test * chore: log --------- Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
parent
d0edc6ce3f
commit
b8c85c91b4
1
.github/workflows/nocobase-test-lite.yml
vendored
1
.github/workflows/nocobase-test-lite.yml
vendored
@ -68,7 +68,6 @@ jobs:
|
||||
node-version: ${{ matrix.node_version }}
|
||||
cache: 'yarn'
|
||||
- run: yarn install
|
||||
# - run: yarn build
|
||||
- name: Test with postgres
|
||||
run: yarn nocobase install -f && yarn test
|
||||
env:
|
||||
|
@ -43,12 +43,20 @@ async function listWithPagination(ctx: Context) {
|
||||
|
||||
const repository = getRepositoryFromParams(ctx);
|
||||
|
||||
const [rows, count] = await repository.findAndCount({
|
||||
const options = {
|
||||
context: ctx,
|
||||
...findArgs(ctx),
|
||||
...pageArgsToLimitArgs(parseInt(String(page)), parseInt(String(pageSize))),
|
||||
};
|
||||
|
||||
Object.keys(options).forEach((key) => {
|
||||
if (options[key] === undefined) {
|
||||
delete options[key];
|
||||
}
|
||||
});
|
||||
|
||||
const [rows, count] = await repository.findAndCount(options);
|
||||
|
||||
ctx.body = {
|
||||
count,
|
||||
rows,
|
||||
|
@ -1,7 +1,101 @@
|
||||
import { mockDatabase } from '../index';
|
||||
import Database from '@nocobase/database';
|
||||
import { Collection } from '../../collection';
|
||||
import { OptionsParser } from '../../options-parser';
|
||||
|
||||
describe('find with associations', () => {
|
||||
let db: Database;
|
||||
beforeEach(async () => {
|
||||
db = mockDatabase({
|
||||
tablePrefix: '',
|
||||
});
|
||||
|
||||
await db.clean({ drop: true });
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await db.close();
|
||||
});
|
||||
|
||||
it('should filter by association field', async () => {
|
||||
const User = db.collection({
|
||||
name: 'users',
|
||||
tree: 'adjacency-list',
|
||||
fields: [
|
||||
{ type: 'string', name: 'name' },
|
||||
{ type: 'hasMany', name: 'posts', target: 'posts', foreignKey: 'user_id' },
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'parent',
|
||||
foreignKey: 'parent_id',
|
||||
treeParent: true,
|
||||
},
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'children',
|
||||
foreignKey: 'parent_id',
|
||||
treeChildren: true,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const Post = db.collection({
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{ type: 'string', name: 'title' },
|
||||
{ type: 'belongsTo', name: 'user', target: 'users', foreignKey: 'user_id' },
|
||||
],
|
||||
});
|
||||
|
||||
await db.sync();
|
||||
|
||||
expect(User.options.tree).toBeTruthy();
|
||||
|
||||
await User.repository.create({
|
||||
values: [
|
||||
{
|
||||
name: 'u1',
|
||||
posts: [
|
||||
{
|
||||
title: 'u1p1',
|
||||
},
|
||||
],
|
||||
children: [
|
||||
{
|
||||
name: 'u2',
|
||||
posts: [
|
||||
{
|
||||
title: '标题2',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const filter = {
|
||||
$and: [
|
||||
{
|
||||
children: {
|
||||
posts: {
|
||||
title: {
|
||||
$eq: '标题2',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const [findResult, count] = await User.repository.findAndCount({
|
||||
filter,
|
||||
offset: 0,
|
||||
limit: 20,
|
||||
});
|
||||
|
||||
expect(findResult[0].get('name')).toEqual('u1');
|
||||
});
|
||||
});
|
||||
|
||||
describe('repository find', () => {
|
||||
let db: Database;
|
||||
|
@ -351,10 +351,9 @@ export class Repository<TModelAttributes extends {} = any, TCreationAttributes e
|
||||
* @param options
|
||||
*/
|
||||
async findAndCount(options?: FindAndCountOptions): Promise<[Model[], number]> {
|
||||
const transaction = await this.getTransaction(options);
|
||||
options = {
|
||||
...options,
|
||||
transaction,
|
||||
transaction: await this.getTransaction(options),
|
||||
};
|
||||
|
||||
const count = await this.count(options);
|
||||
|
@ -44,9 +44,7 @@ export class AdjacencyListRepository extends Repository {
|
||||
});
|
||||
}
|
||||
|
||||
const childInstances = (await super.find(findChildrenOptions)).map((r) => {
|
||||
return r.toJSON();
|
||||
});
|
||||
const childInstances = await super.find(findChildrenOptions);
|
||||
|
||||
const nodeMap = {};
|
||||
|
||||
@ -64,10 +62,10 @@ export class AdjacencyListRepository extends Repository {
|
||||
return [];
|
||||
}
|
||||
|
||||
return children.map((child) => ({
|
||||
...child,
|
||||
[childrenKey]: buildTree(child.id),
|
||||
}));
|
||||
return children.map((child) => {
|
||||
child.setDataValue(childrenKey, buildTree(child.id));
|
||||
return child;
|
||||
});
|
||||
}
|
||||
|
||||
for (const parent of parentNodes) {
|
||||
|
@ -0,0 +1,128 @@
|
||||
import { Database } from '@nocobase/database';
|
||||
import { MockServer } from '@nocobase/test';
|
||||
import { createApp } from '../index';
|
||||
|
||||
describe('find with association', () => {
|
||||
let app: MockServer;
|
||||
let agent;
|
||||
|
||||
let db: Database;
|
||||
beforeEach(async () => {
|
||||
app = await createApp();
|
||||
|
||||
agent = app.agent();
|
||||
db = app.db;
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.destroy();
|
||||
});
|
||||
|
||||
it('should filter by association field', async () => {
|
||||
await db.getRepository('collections').create({
|
||||
values: {
|
||||
name: 'users',
|
||||
tree: 'adjacency-list',
|
||||
fields: [
|
||||
{ type: 'string', name: 'name' },
|
||||
{ type: 'hasMany', name: 'posts', target: 'posts', foreignKey: 'user_id' },
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'parent',
|
||||
foreignKey: 'parent_id',
|
||||
treeParent: true,
|
||||
target: 'users',
|
||||
},
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'children',
|
||||
foreignKey: 'parent_id',
|
||||
treeChildren: true,
|
||||
target: 'users',
|
||||
},
|
||||
],
|
||||
},
|
||||
context: {},
|
||||
});
|
||||
|
||||
await db.getRepository('collections').create({
|
||||
values: {
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{ type: 'string', name: 'title' },
|
||||
{ type: 'belongsTo', name: 'user', target: 'users', foreignKey: 'user_id' },
|
||||
],
|
||||
},
|
||||
context: {},
|
||||
});
|
||||
|
||||
const UserCollection = db.getCollection('users');
|
||||
|
||||
expect(UserCollection.options.tree).toBeTruthy();
|
||||
|
||||
await db.getRepository('users').create({
|
||||
values: [
|
||||
{
|
||||
name: 'u1',
|
||||
posts: [
|
||||
{
|
||||
title: 'u1p1',
|
||||
},
|
||||
],
|
||||
children: [
|
||||
{
|
||||
name: 'u2',
|
||||
posts: [
|
||||
{
|
||||
title: '标题2',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'u3',
|
||||
children: [
|
||||
{
|
||||
name: 'u4',
|
||||
posts: [
|
||||
{
|
||||
title: '标题五',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const filter = {
|
||||
$and: [
|
||||
{
|
||||
children: {
|
||||
posts: {
|
||||
title: {
|
||||
$eq: '标题五',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const items = await db.getRepository('users').find({
|
||||
filter,
|
||||
appends: ['children'],
|
||||
});
|
||||
|
||||
expect(items[0].name).toEqual('u3');
|
||||
|
||||
const response2 = await agent.resource('users').list({
|
||||
filter,
|
||||
appends: ['children'],
|
||||
});
|
||||
|
||||
expect(response2.statusCode).toEqual(200);
|
||||
expect(response2.body.data[0].name).toEqual('u3');
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user