mirror of
				https://github.com/strapi/strapi.git
				synced 2025-10-31 18:08:11 +00:00 
			
		
		
		
	
		
			
	
	
		
			238 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			238 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|   | 'use strict'; | ||
|  | 
 | ||
|  | const { createTestBuilder } = require('api-tests/builder'); | ||
|  | const { createStrapiInstance } = require('api-tests/strapi'); | ||
|  | const { createAuthRequest } = require('api-tests/request'); | ||
|  | const modelsUtils = require('api-tests/models'); | ||
|  | 
 | ||
|  | let strapi; | ||
|  | let rq; | ||
|  | const data = { | ||
|  |   products: [], | ||
|  |   shops: [], | ||
|  | }; | ||
|  | let id1; | ||
|  | let id2; | ||
|  | let id3; | ||
|  | const populateShop = [ | ||
|  |   'products_ow', | ||
|  |   'products_oo', | ||
|  |   'products_mo', | ||
|  |   'products_om', | ||
|  |   'products_mm', | ||
|  |   'products_mw', | ||
|  |   'myCompo.compo_products_ow', | ||
|  |   'myCompo.compo_products_mw', | ||
|  | ]; | ||
|  | 
 | ||
|  | const compo = (withRelations = false) => ({ | ||
|  |   displayName: 'compo', | ||
|  |   category: 'default', | ||
|  |   attributes: { | ||
|  |     name: { | ||
|  |       type: 'string', | ||
|  |     }, | ||
|  |     ...(!withRelations | ||
|  |       ? {} | ||
|  |       : { | ||
|  |           compo_products_ow: { | ||
|  |             type: 'relation', | ||
|  |             relation: 'oneToOne', | ||
|  |             target: 'api::product.product', | ||
|  |           }, | ||
|  |           compo_products_mw: { | ||
|  |             type: 'relation', | ||
|  |             relation: 'oneToMany', | ||
|  |             target: 'api::product.product', | ||
|  |           }, | ||
|  |         }), | ||
|  |   }, | ||
|  | }); | ||
|  | 
 | ||
|  | const productModel = { | ||
|  |   attributes: { | ||
|  |     name: { | ||
|  |       type: 'string', | ||
|  |     }, | ||
|  |   }, | ||
|  |   displayName: 'Product', | ||
|  |   singularName: 'product', | ||
|  |   pluralName: 'products', | ||
|  |   description: '', | ||
|  |   collectionName: '', | ||
|  | }; | ||
|  | 
 | ||
|  | const shopModel = { | ||
|  |   attributes: { | ||
|  |     name: { | ||
|  |       type: 'string', | ||
|  |     }, | ||
|  |     products_ow: { | ||
|  |       type: 'relation', | ||
|  |       relation: 'oneToOne', | ||
|  |       target: 'api::product.product', | ||
|  |     }, | ||
|  |     products_oo: { | ||
|  |       type: 'relation', | ||
|  |       relation: 'oneToOne', | ||
|  |       target: 'api::product.product', | ||
|  |       targetAttribute: 'shop', | ||
|  |     }, | ||
|  |     products_mo: { | ||
|  |       type: 'relation', | ||
|  |       relation: 'manyToOne', | ||
|  |       target: 'api::product.product', | ||
|  |       targetAttribute: 'shops_mo', | ||
|  |     }, | ||
|  |     products_om: { | ||
|  |       type: 'relation', | ||
|  |       relation: 'oneToMany', | ||
|  |       target: 'api::product.product', | ||
|  |       targetAttribute: 'shop_om', | ||
|  |     }, | ||
|  |     products_mm: { | ||
|  |       type: 'relation', | ||
|  |       relation: 'manyToMany', | ||
|  |       target: 'api::product.product', | ||
|  |       targetAttribute: 'shops', | ||
|  |     }, | ||
|  |     products_mw: { | ||
|  |       type: 'relation', | ||
|  |       relation: 'oneToMany', | ||
|  |       target: 'api::product.product', | ||
|  |     }, | ||
|  |     myCompo: { | ||
|  |       type: 'component', | ||
|  |       repeatable: false, | ||
|  |       component: 'default.compo', | ||
|  |     }, | ||
|  |   }, | ||
|  |   displayName: 'Shop', | ||
|  |   singularName: 'shop', | ||
|  |   pluralName: 'shops', | ||
|  | }; | ||
|  | 
 | ||
|  | const createEntry = async (singularName, data, populate) => { | ||
|  |   const { body } = await rq({ | ||
|  |     method: 'POST', | ||
|  |     url: `/content-manager/collection-types/api::${singularName}.${singularName}`, | ||
|  |     body: data, | ||
|  |     qs: { populate }, | ||
|  |   }); | ||
|  |   return body; | ||
|  | }; | ||
|  | 
 | ||
|  | const updateEntry = async (singularName, id, data, populate) => { | ||
|  |   const { body } = await rq({ | ||
|  |     method: 'PUT', | ||
|  |     url: `/content-manager/collection-types/api::${singularName}.${singularName}/${id}`, | ||
|  |     body: data, | ||
|  |     qs: { populate }, | ||
|  |   }); | ||
|  |   return body; | ||
|  | }; | ||
|  | 
 | ||
|  | const cloneEntry = async (singularName, id, data, populate) => { | ||
|  |   const { body } = await rq({ | ||
|  |     method: 'POST', | ||
|  |     url: `/content-manager/collection-types/api::${singularName}.${singularName}/clone/${id}`, | ||
|  |     body: data, | ||
|  |     qs: { populate }, | ||
|  |   }); | ||
|  |   return body; | ||
|  | }; | ||
|  | 
 | ||
|  | const getRelations = async (uid, field, id) => { | ||
|  |   const res = await rq({ | ||
|  |     method: 'GET', | ||
|  |     url: `/content-manager/relations/${uid}/${id}/${field}`, | ||
|  |   }); | ||
|  | 
 | ||
|  |   return res.body; | ||
|  | }; | ||
|  | 
 | ||
|  | describe('Relations', () => { | ||
|  |   const builder = createTestBuilder(); | ||
|  | 
 | ||
|  |   beforeAll(async () => { | ||
|  |     await builder.addComponent(compo(false)).addContentTypes([productModel, shopModel]).build(); | ||
|  | 
 | ||
|  |     await modelsUtils.modifyComponent(compo(true)); | ||
|  | 
 | ||
|  |     strapi = await createStrapiInstance(); | ||
|  |     rq = await createAuthRequest({ strapi }); | ||
|  | 
 | ||
|  |     const createdProduct1 = await createEntry('product', { name: 'Skate' }); | ||
|  |     const createdProduct2 = await createEntry('product', { name: 'Candle' }); | ||
|  |     const createdProduct3 = await createEntry('product', { name: 'Mug' }); | ||
|  | 
 | ||
|  |     data.products.push(createdProduct1); | ||
|  |     data.products.push(createdProduct2); | ||
|  |     data.products.push(createdProduct3); | ||
|  | 
 | ||
|  |     id1 = data.products[0].id; | ||
|  |     id2 = data.products[1].id; | ||
|  |     id3 = data.products[2].id; | ||
|  |   }); | ||
|  | 
 | ||
|  |   afterAll(async () => { | ||
|  |     await strapi.destroy(); | ||
|  |     await builder.cleanup(); | ||
|  |   }); | ||
|  | 
 | ||
|  |   describe('Update entity relations does not break other relations', () => { | ||
|  |     test('Update and disconnect relation does not break other relations', async () => { | ||
|  |       // Create 2 entries connected to the same relations
 | ||
|  |       const shops = []; | ||
|  | 
 | ||
|  |       for (let i = 0; i < 2; i++) { | ||
|  |         const createdShop = await createEntry( | ||
|  |           'shop', | ||
|  |           { | ||
|  |             name: 'Cazotte Shop', | ||
|  |             products_ow: { connect: [id1] }, | ||
|  |             products_oo: { connect: [id1] }, | ||
|  |             products_mo: { connect: [id1] }, | ||
|  |             products_om: { connect: [id1, id2] }, | ||
|  |             products_mm: { connect: [id1, id2] }, | ||
|  |             products_mw: { connect: [id1, id2] }, | ||
|  |             myCompo: { | ||
|  |               compo_products_ow: { connect: [id1] }, | ||
|  |               compo_products_mw: { connect: [id1, id2] }, | ||
|  |             }, | ||
|  |           }, | ||
|  |           ['myCompo'] | ||
|  |         ); | ||
|  |         shops.push(createdShop); | ||
|  |       } | ||
|  | 
 | ||
|  |       // Update shop 1 relation order
 | ||
|  |       await updateEntry( | ||
|  |         'shop', | ||
|  |         shops[0].id, | ||
|  |         { | ||
|  |           name: 'Cazotte Shop', | ||
|  |           products_om: { disconnect: [id2] }, | ||
|  |           products_mm: { disconnect: [id2] }, | ||
|  |           products_mw: { disconnect: [id2] }, | ||
|  |           myCompo: { | ||
|  |             id: shops[0].myCompo.id, | ||
|  |             compo_products_mw: { disconnect: [id2] }, | ||
|  |           }, | ||
|  |         }, | ||
|  |         [] | ||
|  |       ); | ||
|  | 
 | ||
|  |       const updatedShop2 = await strapi.entityService.findOne('api::shop.shop', shops[1].id, { | ||
|  |         populate: populateShop, | ||
|  |       }); | ||
|  | 
 | ||
|  |       // shop2 relations should be unchanged
 | ||
|  |       expect(updatedShop2.products_om).toMatchObject([{ id: id1 }, { id: id2 }]); | ||
|  |       expect(updatedShop2.products_mm).toMatchObject([{ id: id1 }, { id: id2 }]); | ||
|  |       expect(updatedShop2.products_mw).toMatchObject([{ id: id1 }, { id: id2 }]); | ||
|  |       expect(updatedShop2.myCompo.compo_products_mw).toMatchObject([{ id: id1 }, { id: id2 }]); | ||
|  |     }); | ||
|  |   }); | ||
|  | }); |