mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-05 13:39:24 +08:00
fix(plugin-field-sort): fix field registering for external data source (#6212)
This commit is contained in:
parent
dd7c7f641c
commit
7b715c847d
@ -7,329 +7,375 @@
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import { Database } from '@nocobase/database';
|
||||
import { Database, mockDatabase } from '@nocobase/database';
|
||||
import { createMockServer, MockServer } from '@nocobase/test';
|
||||
|
||||
import Plugin from '..';
|
||||
import { SequelizeCollectionManager, SequelizeDataSource } from '@nocobase/data-source-manager';
|
||||
import { uid } from '@nocobase/utils';
|
||||
|
||||
describe('sort field', () => {
|
||||
let app: MockServer;
|
||||
let db: Database;
|
||||
let another: SequelizeDataSource;
|
||||
let anotherDB: Database;
|
||||
|
||||
beforeEach(async () => {
|
||||
app = await createMockServer({
|
||||
plugins: [Plugin, 'data-source-main', 'error-handler'],
|
||||
});
|
||||
db = app.db;
|
||||
|
||||
await app.dataSourceManager.add(
|
||||
new SequelizeDataSource({
|
||||
name: 'another',
|
||||
collectionManager: {
|
||||
database: mockDatabase({
|
||||
tablePrefix: `t${uid(5)}`,
|
||||
}),
|
||||
},
|
||||
resourceManager: {},
|
||||
}),
|
||||
);
|
||||
another = app.dataSourceManager.dataSources.get('another') as SequelizeDataSource;
|
||||
|
||||
anotherDB = (another.collectionManager as SequelizeCollectionManager).db;
|
||||
|
||||
another.acl.allow('*', '*', 'loggedIn');
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.destroy();
|
||||
});
|
||||
|
||||
it('should init with camelCase scope key', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'name',
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'someField',
|
||||
},
|
||||
],
|
||||
});
|
||||
describe('main data source', () => {
|
||||
it('should init with camelCase scope key', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'name',
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'someField',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await db.sync();
|
||||
|
||||
await Test.repository.create({
|
||||
values: [
|
||||
{
|
||||
name: 't1',
|
||||
someField: 'a',
|
||||
},
|
||||
{
|
||||
name: 't2',
|
||||
someField: 'b',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
Test.setField('scopeKeySort', { type: 'sort', scopeKey: 'someField' });
|
||||
await db.sync();
|
||||
});
|
||||
|
||||
it('should init sorted value with thousand records', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'name',
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'group',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await db.sync();
|
||||
|
||||
await Test.model.bulkCreate(
|
||||
(() => {
|
||||
const values = [];
|
||||
for (let i = 0; i < 100000; i++) {
|
||||
values.push({
|
||||
group: 'a',
|
||||
name: `r${i}`,
|
||||
});
|
||||
|
||||
values.push({
|
||||
group: 'b',
|
||||
name: `r${i}`,
|
||||
});
|
||||
}
|
||||
return values;
|
||||
})(),
|
||||
);
|
||||
|
||||
Test.setField('sort', { type: 'sort', scopeKey: 'group' });
|
||||
|
||||
const begin = Date.now();
|
||||
await db.sync();
|
||||
const end = Date.now();
|
||||
// log time cost as milliseconds
|
||||
console.log(end - begin);
|
||||
});
|
||||
|
||||
it('should init sorted value with null scopeValue', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'name',
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'group',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await db.sync();
|
||||
|
||||
await Test.repository.create({
|
||||
values: [
|
||||
{
|
||||
group: null,
|
||||
name: 'r5',
|
||||
},
|
||||
{
|
||||
group: null,
|
||||
name: 'r6',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
Test.setField('sort', { type: 'sort', scopeKey: 'group' });
|
||||
|
||||
await db.sync();
|
||||
});
|
||||
|
||||
it('should init sorted value with scopeKey', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'name',
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'group',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await db.sync();
|
||||
await Test.repository.create({
|
||||
values: [
|
||||
{
|
||||
group: 'a',
|
||||
name: 'r1',
|
||||
},
|
||||
{
|
||||
group: 'b',
|
||||
name: 'r2',
|
||||
},
|
||||
{
|
||||
group: 'a',
|
||||
name: 'r3',
|
||||
},
|
||||
{
|
||||
group: 'b',
|
||||
name: 'r4',
|
||||
},
|
||||
{
|
||||
group: null,
|
||||
name: 'r5',
|
||||
},
|
||||
{
|
||||
group: null,
|
||||
name: 'r6',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
Test.setField('sort', { type: 'sort', scopeKey: 'group' });
|
||||
|
||||
await db.sync();
|
||||
|
||||
const records = await Test.repository.find({});
|
||||
const r3 = records.find((r) => r.get('name') === 'r3');
|
||||
expect(r3.get('sort')).toBe(2);
|
||||
const r5 = records.find((r) => r.get('name') === 'r5');
|
||||
expect(r5.get('sort')).toBe(1);
|
||||
});
|
||||
|
||||
it('should init sorted value by createdAt when primaryKey not exists', async () => {
|
||||
const Test = db.collection({
|
||||
autoGenId: false,
|
||||
name: 'tests',
|
||||
});
|
||||
|
||||
await db.sync();
|
||||
await Test.repository.create({
|
||||
values: [{}, {}, {}],
|
||||
});
|
||||
|
||||
// add sort field
|
||||
Test.setField('sort', { type: 'sort' });
|
||||
|
||||
let err;
|
||||
try {
|
||||
await db.sync();
|
||||
} catch (e) {
|
||||
err = e;
|
||||
}
|
||||
expect(err).toBeFalsy();
|
||||
});
|
||||
|
||||
it('sort', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
fields: [{ type: 'sort', name: 'sort' }],
|
||||
await Test.repository.create({
|
||||
values: [
|
||||
{
|
||||
name: 't1',
|
||||
someField: 'a',
|
||||
},
|
||||
{
|
||||
name: 't2',
|
||||
someField: 'b',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
Test.setField('scopeKeySort', { type: 'sort', scopeKey: 'someField' });
|
||||
await db.sync();
|
||||
});
|
||||
await db.sync();
|
||||
|
||||
const test1 = await Test.model.create<any>();
|
||||
expect(test1.sort).toBe(1);
|
||||
const test2 = await Test.model.create<any>();
|
||||
expect(test2.sort).toBe(2);
|
||||
const test3 = await Test.model.create<any>();
|
||||
expect(test3.sort).toBe(3);
|
||||
});
|
||||
it('should init sorted value with thousand records', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'name',
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'group',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
it('should init sort value on data already exits', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'name',
|
||||
await db.sync();
|
||||
|
||||
await Test.model.bulkCreate(
|
||||
(() => {
|
||||
const values = [];
|
||||
for (let i = 0; i < 100000; i++) {
|
||||
values.push({
|
||||
group: 'a',
|
||||
name: `r${i}`,
|
||||
});
|
||||
|
||||
values.push({
|
||||
group: 'b',
|
||||
name: `r${i}`,
|
||||
});
|
||||
}
|
||||
return values;
|
||||
})(),
|
||||
);
|
||||
|
||||
Test.setField('sort', { type: 'sort', scopeKey: 'group' });
|
||||
|
||||
const begin = Date.now();
|
||||
await db.sync();
|
||||
const end = Date.now();
|
||||
// log time cost as milliseconds
|
||||
console.log(end - begin);
|
||||
});
|
||||
|
||||
it('should init sorted value with null scopeValue', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'name',
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'group',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await db.sync();
|
||||
|
||||
await Test.repository.create({
|
||||
values: [
|
||||
{
|
||||
group: null,
|
||||
name: 'r5',
|
||||
},
|
||||
{
|
||||
group: null,
|
||||
name: 'r6',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
Test.setField('sort', { type: 'sort', scopeKey: 'group' });
|
||||
|
||||
await db.sync();
|
||||
});
|
||||
|
||||
it('should init sorted value with scopeKey', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'name',
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'group',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await db.sync();
|
||||
await Test.repository.create({
|
||||
values: [
|
||||
{
|
||||
group: 'a',
|
||||
name: 'r1',
|
||||
},
|
||||
{
|
||||
group: 'b',
|
||||
name: 'r2',
|
||||
},
|
||||
{
|
||||
group: 'a',
|
||||
name: 'r3',
|
||||
},
|
||||
{
|
||||
group: 'b',
|
||||
name: 'r4',
|
||||
},
|
||||
{
|
||||
group: null,
|
||||
name: 'r5',
|
||||
},
|
||||
{
|
||||
group: null,
|
||||
name: 'r6',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
Test.setField('sort', { type: 'sort', scopeKey: 'group' });
|
||||
|
||||
await db.sync();
|
||||
|
||||
const records = await Test.repository.find({});
|
||||
const r3 = records.find((r) => r.get('name') === 'r3');
|
||||
expect(r3.get('sort')).toBe(2);
|
||||
const r5 = records.find((r) => r.get('name') === 'r5');
|
||||
expect(r5.get('sort')).toBe(1);
|
||||
});
|
||||
|
||||
it('should init sorted value by createdAt when primaryKey not exists', async () => {
|
||||
const Test = db.collection({
|
||||
autoGenId: false,
|
||||
name: 'tests',
|
||||
});
|
||||
|
||||
await db.sync();
|
||||
await Test.repository.create({
|
||||
values: [{}, {}, {}],
|
||||
});
|
||||
|
||||
// add sort field
|
||||
Test.setField('sort', { type: 'sort' });
|
||||
|
||||
let err;
|
||||
try {
|
||||
await db.sync();
|
||||
} catch (e) {
|
||||
err = e;
|
||||
}
|
||||
expect(err).toBeFalsy();
|
||||
});
|
||||
|
||||
it('sort', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
fields: [{ type: 'sort', name: 'sort' }],
|
||||
});
|
||||
await db.sync();
|
||||
|
||||
const test1 = await Test.model.create<any>();
|
||||
expect(test1.sort).toBe(1);
|
||||
const test2 = await Test.model.create<any>();
|
||||
expect(test2.sort).toBe(2);
|
||||
const test3 = await Test.model.create<any>();
|
||||
expect(test3.sort).toBe(3);
|
||||
});
|
||||
|
||||
it('should init sort value on data already exits', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'name',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await db.sync();
|
||||
|
||||
await db.getRepository('tests').create({
|
||||
values: {
|
||||
name: 't1',
|
||||
},
|
||||
],
|
||||
});
|
||||
await db.getRepository('tests').create({
|
||||
values: {
|
||||
name: 't2',
|
||||
},
|
||||
});
|
||||
await db.getRepository('tests').create({
|
||||
values: {
|
||||
name: 't3',
|
||||
},
|
||||
});
|
||||
|
||||
const field = Test.addField('sort', { type: 'sort' });
|
||||
|
||||
await field.sync({});
|
||||
|
||||
const items = await db.getRepository('tests').find({
|
||||
order: ['id'],
|
||||
});
|
||||
expect(items.map((item) => item.get('sort'))).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
await db.sync();
|
||||
test.skip('simultaneously create ', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
fields: [{ type: 'sort', name: 'sort' }],
|
||||
});
|
||||
|
||||
await db.getRepository('tests').create({
|
||||
values: {
|
||||
name: 't1',
|
||||
},
|
||||
});
|
||||
await db.getRepository('tests').create({
|
||||
values: {
|
||||
name: 't2',
|
||||
},
|
||||
});
|
||||
await db.getRepository('tests').create({
|
||||
values: {
|
||||
name: 't3',
|
||||
},
|
||||
await db.sync();
|
||||
|
||||
const promise = [];
|
||||
for (let i = 0; i < 3; i++) {
|
||||
promise.push(Test.model.create());
|
||||
}
|
||||
|
||||
await Promise.all(promise);
|
||||
const tests = await Test.model.findAll();
|
||||
const sortValues = tests.map((t) => t.get('sort')).sort();
|
||||
expect(sortValues).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
const field = Test.addField('sort', { type: 'sort' });
|
||||
|
||||
await field.sync({});
|
||||
|
||||
const items = await db.getRepository('tests').find({
|
||||
order: ['id'],
|
||||
it('skip if sort value not empty', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
fields: [{ type: 'sort', name: 'sort' }],
|
||||
});
|
||||
await db.sync();
|
||||
const test1 = await Test.model.create<any>({ sort: 3 });
|
||||
expect(test1.sort).toBe(3);
|
||||
const test2 = await Test.model.create<any>();
|
||||
expect(test2.sort).toBe(4);
|
||||
const test3 = await Test.model.create<any>();
|
||||
expect(test3.sort).toBe(5);
|
||||
});
|
||||
|
||||
it('scopeKey', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
fields: [
|
||||
{ type: 'sort', name: 'sort', scopeKey: 'status' },
|
||||
{ type: 'string', name: 'status' },
|
||||
],
|
||||
});
|
||||
await db.sync();
|
||||
|
||||
const t1 = await Test.model.create({ status: 'publish' });
|
||||
const t2 = await Test.model.create({ status: 'publish' });
|
||||
const t3 = await Test.model.create({ status: 'draft' });
|
||||
const t4 = await Test.model.create({ status: 'draft' });
|
||||
|
||||
expect(t1.get('sort')).toBe(1);
|
||||
expect(t2.get('sort')).toBe(2);
|
||||
expect(t3.get('sort')).toBe(1);
|
||||
expect(t4.get('sort')).toBe(2);
|
||||
|
||||
t1.set('status', 'draft');
|
||||
await t1.save();
|
||||
|
||||
await t1.reload();
|
||||
expect(t1.get('sort')).toBe(3);
|
||||
});
|
||||
expect(items.map((item) => item.get('sort'))).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
test.skip('simultaneously create ', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
fields: [{ type: 'sort', name: 'sort' }],
|
||||
describe('external data source', () => {
|
||||
it('create record', async () => {
|
||||
anotherDB.collection({
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{ type: 'string', name: 'title' },
|
||||
{ type: 'sort', name: 'sort' },
|
||||
],
|
||||
});
|
||||
|
||||
await anotherDB.sync();
|
||||
|
||||
const p1 = await anotherDB.getRepository('posts').create({
|
||||
values: { title: 'p1' },
|
||||
});
|
||||
const p2 = await anotherDB.getRepository('posts').create({
|
||||
values: { title: 'p2' },
|
||||
});
|
||||
expect(p1.sort).toBe(1);
|
||||
expect(p2.sort).toBe(2);
|
||||
});
|
||||
|
||||
await db.sync();
|
||||
|
||||
const promise = [];
|
||||
for (let i = 0; i < 3; i++) {
|
||||
promise.push(Test.model.create());
|
||||
}
|
||||
|
||||
await Promise.all(promise);
|
||||
const tests = await Test.model.findAll();
|
||||
const sortValues = tests.map((t) => t.get('sort')).sort();
|
||||
expect(sortValues).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
it('skip if sort value not empty', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
fields: [{ type: 'sort', name: 'sort' }],
|
||||
});
|
||||
await db.sync();
|
||||
const test1 = await Test.model.create<any>({ sort: 3 });
|
||||
expect(test1.sort).toBe(3);
|
||||
const test2 = await Test.model.create<any>();
|
||||
expect(test2.sort).toBe(4);
|
||||
const test3 = await Test.model.create<any>();
|
||||
expect(test3.sort).toBe(5);
|
||||
});
|
||||
|
||||
it('scopeKey', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
fields: [
|
||||
{ type: 'sort', name: 'sort', scopeKey: 'status' },
|
||||
{ type: 'string', name: 'status' },
|
||||
],
|
||||
});
|
||||
await db.sync();
|
||||
|
||||
const t1 = await Test.model.create({ status: 'publish' });
|
||||
const t2 = await Test.model.create({ status: 'publish' });
|
||||
const t3 = await Test.model.create({ status: 'draft' });
|
||||
const t4 = await Test.model.create({ status: 'draft' });
|
||||
|
||||
expect(t1.get('sort')).toBe(1);
|
||||
expect(t2.get('sort')).toBe(2);
|
||||
expect(t3.get('sort')).toBe(1);
|
||||
expect(t4.get('sort')).toBe(2);
|
||||
|
||||
t1.set('status', 'draft');
|
||||
await t1.save();
|
||||
|
||||
await t1.reload();
|
||||
expect(t1.get('sort')).toBe(3);
|
||||
});
|
||||
});
|
||||
|
@ -20,12 +20,12 @@ export class PluginFieldSortServer extends Plugin {
|
||||
const { lockManager } = this.app;
|
||||
class SortFieldClass extends SortField {}
|
||||
SortFieldClass.lockManager = lockManager;
|
||||
this.app.db.registerFieldTypes({
|
||||
sort: SortFieldClass,
|
||||
});
|
||||
|
||||
this.app.dataSourceManager.beforeAddDataSource((dataSource: DataSource) => {
|
||||
if (dataSource.collectionManager instanceof SequelizeCollectionManager) {
|
||||
dataSource.collectionManager.db.registerFieldTypes({
|
||||
sort: SortFieldClass,
|
||||
});
|
||||
dataSource.resourceManager.registerActionHandlers({ move });
|
||||
}
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user