Fix/recreate association field (#1789)
* chore: test * fix: recreate association with same name as field
This commit is contained in:
		
							parent
							
								
									cba7de55d8
								
							
						
					
					
						commit
						d4636311e8
					
				@ -17,6 +17,25 @@ describe('collection', () => {
 | 
				
			|||||||
    await db.close();
 | 
					    await db.close();
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should remove sequelize model prototype methods after field remove', async () => {
 | 
				
			||||||
 | 
					    db.collection({
 | 
				
			||||||
 | 
					      name: 'tags',
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const UserCollection = db.collection({
 | 
				
			||||||
 | 
					      name: 'users',
 | 
				
			||||||
 | 
					      fields: [{ type: 'belongsToMany', name: 'tags' }],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    console.log(Object.getOwnPropertyNames(UserCollection.model.prototype));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await UserCollection.removeField('tags');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    console.log(Object.getOwnPropertyNames(UserCollection.model.prototype));
 | 
				
			||||||
 | 
					    // @ts-ignore
 | 
				
			||||||
 | 
					    expect(UserCollection.model.prototype.getTags).toBeUndefined();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  it('should not throw error when create empty collection in sqlite and mysql', async () => {
 | 
					  it('should not throw error when create empty collection in sqlite and mysql', async () => {
 | 
				
			||||||
    if (!db.inDialect('sqlite', 'mysql')) {
 | 
					    if (!db.inDialect('sqlite', 'mysql')) {
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
 | 
				
			|||||||
@ -217,6 +217,7 @@ export abstract class Field {
 | 
				
			|||||||
  bind() {
 | 
					  bind() {
 | 
				
			||||||
    const { model } = this.context.collection;
 | 
					    const { model } = this.context.collection;
 | 
				
			||||||
    model.rawAttributes[this.name] = this.toSequelize();
 | 
					    model.rawAttributes[this.name] = this.toSequelize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // @ts-ignore
 | 
					    // @ts-ignore
 | 
				
			||||||
    model.refreshAttributes();
 | 
					    model.refreshAttributes();
 | 
				
			||||||
    if (this.options.index) {
 | 
					    if (this.options.index) {
 | 
				
			||||||
@ -226,6 +227,9 @@ export abstract class Field {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  unbind() {
 | 
					  unbind() {
 | 
				
			||||||
    const { model } = this.context.collection;
 | 
					    const { model } = this.context.collection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    delete model.prototype[this.name];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    model.removeAttribute(this.name);
 | 
					    model.removeAttribute(this.name);
 | 
				
			||||||
    if (this.options.index || this.options.unique) {
 | 
					    if (this.options.index || this.options.unique) {
 | 
				
			||||||
      this.context.collection.removeIndex([this.name]);
 | 
					      this.context.collection.removeIndex([this.name]);
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,95 @@ import Database, { Collection as DBCollection, StringFieldOptions } from '@nocob
 | 
				
			|||||||
import Application from '@nocobase/server';
 | 
					import Application from '@nocobase/server';
 | 
				
			||||||
import { createApp } from '.';
 | 
					import { createApp } from '.';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('recreate field', () => {
 | 
				
			||||||
 | 
					  let db: Database;
 | 
				
			||||||
 | 
					  let app: Application;
 | 
				
			||||||
 | 
					  let Collection: DBCollection;
 | 
				
			||||||
 | 
					  let Field: DBCollection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  beforeEach(async () => {
 | 
				
			||||||
 | 
					    app = await createApp();
 | 
				
			||||||
 | 
					    db = app.db;
 | 
				
			||||||
 | 
					    Collection = db.getCollection('collections');
 | 
				
			||||||
 | 
					    Field = db.getCollection('fields');
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  afterEach(async () => {
 | 
				
			||||||
 | 
					    await app.destroy();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should recreate field', async () => {
 | 
				
			||||||
 | 
					    await Collection.repository.create({
 | 
				
			||||||
 | 
					      values: {
 | 
				
			||||||
 | 
					        name: 'a1',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      context: {},
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await Collection.repository.create({
 | 
				
			||||||
 | 
					      values: {
 | 
				
			||||||
 | 
					        name: 'a2',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      context: {},
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await Field.repository.create({
 | 
				
			||||||
 | 
					      values: {
 | 
				
			||||||
 | 
					        name: 'a',
 | 
				
			||||||
 | 
					        type: 'string',
 | 
				
			||||||
 | 
					        collectionName: 'a1',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      context: {},
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await db.getRepository('a1').create({
 | 
				
			||||||
 | 
					      values: {
 | 
				
			||||||
 | 
					        a: 'a',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await Field.repository.destroy({
 | 
				
			||||||
 | 
					      filter: {
 | 
				
			||||||
 | 
					        name: 'a',
 | 
				
			||||||
 | 
					        collectionName: 'a1',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      context: {},
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await Field.repository.create({
 | 
				
			||||||
 | 
					      values: {
 | 
				
			||||||
 | 
					        name: 'a',
 | 
				
			||||||
 | 
					        type: 'hasOne',
 | 
				
			||||||
 | 
					        collectionName: 'a1',
 | 
				
			||||||
 | 
					        target: 'a2',
 | 
				
			||||||
 | 
					        foreignKey: 'a_id',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      context: {},
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const a1Model = db.getRepository('a1').model;
 | 
				
			||||||
 | 
					    const results = await a1Model.findAll({
 | 
				
			||||||
 | 
					      include: [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          association: 'a',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    expect(Object.getOwnPropertyNames(db.getCollection('a1').model.prototype)).toContain('getA');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await Field.repository.destroy({
 | 
				
			||||||
 | 
					      filter: {
 | 
				
			||||||
 | 
					        name: 'a',
 | 
				
			||||||
 | 
					        collectionName: 'a1',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    expect(Object.getOwnPropertyNames(db.getCollection('a1').model.prototype)).not.toContain('getA');
 | 
				
			||||||
 | 
					    expect(Object.getOwnPropertyNames(db.getCollection('a1').model.prototype)).not.toContain('a');
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('collections repository', () => {
 | 
					describe('collections repository', () => {
 | 
				
			||||||
  let db: Database;
 | 
					  let db: Database;
 | 
				
			||||||
  let app: Application;
 | 
					  let app: Application;
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,66 @@
 | 
				
			|||||||
 | 
					import { MockServer } from '@nocobase/test';
 | 
				
			||||||
 | 
					import { createApp } from '../index';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('recreate field', () => {
 | 
				
			||||||
 | 
					  let app: MockServer;
 | 
				
			||||||
 | 
					  let agent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  beforeEach(async () => {
 | 
				
			||||||
 | 
					    app = await createApp();
 | 
				
			||||||
 | 
					    agent = app.agent();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  afterEach(async () => {
 | 
				
			||||||
 | 
					    await app.destroy();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should recreate field', async () => {
 | 
				
			||||||
 | 
					    await agent.resource('collections').create({
 | 
				
			||||||
 | 
					      values: {
 | 
				
			||||||
 | 
					        name: 'a1',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await agent.resource('collections').create({
 | 
				
			||||||
 | 
					      values: {
 | 
				
			||||||
 | 
					        name: 'a2',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await agent.resource('fields').create({
 | 
				
			||||||
 | 
					      values: {
 | 
				
			||||||
 | 
					        name: 'a',
 | 
				
			||||||
 | 
					        type: 'string',
 | 
				
			||||||
 | 
					        collectionName: 'a1',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await agent.resource('a1').create({
 | 
				
			||||||
 | 
					      values: {
 | 
				
			||||||
 | 
					        a: 'a-value',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await agent.resource('fields').destroy({
 | 
				
			||||||
 | 
					      filter: {
 | 
				
			||||||
 | 
					        name: 'a',
 | 
				
			||||||
 | 
					        collectionName: 'a1',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await agent.resource('fields').create({
 | 
				
			||||||
 | 
					      values: {
 | 
				
			||||||
 | 
					        name: 'a',
 | 
				
			||||||
 | 
					        type: 'belongsToMany',
 | 
				
			||||||
 | 
					        collectionName: 'a1',
 | 
				
			||||||
 | 
					        target: 'a2',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const response = await agent.resource('a1').list({
 | 
				
			||||||
 | 
					      appends: ['a'],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    expect(response.statusCode).toBe(200);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user