diff --git a/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/__tests__/belongs-to-array-field.test.ts b/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/__tests__/belongs-to-array-field.test.ts index c36c401d01..5d0f9feee1 100644 --- a/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/__tests__/belongs-to-array-field.test.ts +++ b/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/__tests__/belongs-to-array-field.test.ts @@ -78,8 +78,8 @@ describe('belongs to array field', () => { describe('association keys check', async () => { it('targetKey is required', async () => { - try { - await db.sequelize.transaction(async (transaction) => { + await expect( + db.sequelize.transaction(async (transaction) => { const field = await fieldRepo.create({ values: { interface: 'mbm', @@ -92,15 +92,13 @@ describe('belongs to array field', () => { transaction, }); await field.load({ transaction }); - }); - } catch (error) { - expect(error.message).toContain('Target key is required'); - } + }), + ).rejects.toThrow(/Target key is required/); }); it('foreign field must be an array or set field', async () => { - try { - await db.sequelize.transaction(async (transaction) => { + await expect( + db.sequelize.transaction(async (transaction) => { const field = await fieldRepo.create({ values: { interface: 'mbm', @@ -114,20 +112,16 @@ describe('belongs to array field', () => { transaction, }); await field.load({ transaction }); - }); - } catch (error) { - expect(error.message).toContain( - 'The type of foreign key "username" in collection "users" must be ARRAY, JSON or JSONB', - ); - } + }), + ).rejects.toThrow(/The type of foreign key "username" in collection "users" must be ARRAY, JSON or JSONB/); }); it('element type of foreign field must be match the type of target field', async () => { if (db.sequelize.getDialect() !== 'postgres') { return; } - try { - await db.sequelize.transaction(async (transaction) => { + await expect( + db.sequelize.transaction(async (transaction) => { const field = await fieldRepo.create({ values: { interface: 'mbm', @@ -141,14 +135,12 @@ describe('belongs to array field', () => { transaction, }); await field.load({ transaction }); - }); - } catch (error) { - expect(error.message).toContain( - 'The element type "STRING" of foreign key "tag_ids" does not match the type "BIGINT" of target key "id" in collection "tags"', - ); - } + }), + ).rejects.toThrow( + /The element type "STRING" of foreign key "tag_ids" does not match the type "BIGINT" of target key "id" in collection "tags"/, + ); - expect( + await expect( db.sequelize.transaction(async (transaction) => { const field = await fieldRepo.create({ values: { @@ -166,5 +158,25 @@ describe('belongs to array field', () => { }), ).resolves.not.toThrow(); }); + + it('the name of foreign key must not be the same as the name of the field', async () => { + await expect( + db.sequelize.transaction(async (transaction) => { + const field = await fieldRepo.create({ + values: { + interface: 'mbm', + collectionName: 'users', + name: 'tag_ids_same', + type: 'belongsToArray', + foreignKey: 'tag_ids_same', + target: 'tags', + targetKey: 'stringCode', + }, + transaction, + }); + await field.load({ transaction }); + }), + ).rejects.toThrow(/Naming collision/); + }); }); }); diff --git a/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/hooks/create-foreign-key.ts b/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/hooks/create-foreign-key.ts index aac1330d2a..049cfada75 100644 --- a/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/hooks/create-foreign-key.ts +++ b/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/hooks/create-foreign-key.ts @@ -12,10 +12,15 @@ import { elementTypeMap } from '../belongs-to-array-field'; export const createForeignKey = (db: Database) => { return async (model: Model, { transaction }) => { - const { type, collectionName, target, targetKey, foreignKey } = model.get(); + const { type, collectionName, target, targetKey, foreignKey, name } = model.get(); if (type !== 'belongsToArray') { return; } + if (name === foreignKey) { + throw new Error( + `Naming collision between attribute '${foreignKey}' and association '${name}' on model ${collectionName}. To remedy this, change either foreignKey or as in your association definition`, + ); + } const r = db.getRepository('fields'); const instance = await r.findOne({ filter: {