mirror of
				https://github.com/strapi/strapi.git
				synced 2025-10-31 01:47:13 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			432 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			432 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict';
 | |
| 
 | |
| const { createTestBuilder } = require('api-tests/builder');
 | |
| const { createStrapiInstance } = require('api-tests/strapi');
 | |
| const { createAuthRequest } = require('api-tests/request');
 | |
| 
 | |
| let strapi;
 | |
| let rq;
 | |
| 
 | |
| const defaultBody = {
 | |
|   field: [
 | |
|     {
 | |
|       __component: 'default.simple-compo',
 | |
|       name: 'someString',
 | |
|     },
 | |
|     {
 | |
|       __component: 'default.compo-with-other-compo',
 | |
|       compo: {
 | |
|         name: 'someString',
 | |
|       },
 | |
|     },
 | |
|   ],
 | |
| };
 | |
| 
 | |
| const models = {
 | |
|   ct: {
 | |
|     displayName: 'withdynamiczone',
 | |
|     singularName: 'withdynamiczone',
 | |
|     pluralName: 'withdynamiczones',
 | |
|     attributes: {
 | |
|       field: {
 | |
|         type: 'dynamiczone',
 | |
|         components: ['default.compo-with-other-compo', 'default.simple-compo'],
 | |
|         required: false,
 | |
|         min: 2,
 | |
|         max: 5,
 | |
|       },
 | |
|     },
 | |
|   },
 | |
|   simpleCompo: {
 | |
|     displayName: 'simple-compo',
 | |
|     attributes: {
 | |
|       name: {
 | |
|         type: 'string',
 | |
|       },
 | |
|     },
 | |
|   },
 | |
|   otherCompo: {
 | |
|     displayName: 'compo-with-other-compo',
 | |
|     attributes: {
 | |
|       compo: {
 | |
|         type: 'component',
 | |
|         component: 'default.simple-compo',
 | |
|       },
 | |
|     },
 | |
|   },
 | |
| };
 | |
| 
 | |
| const createEntry = () => {
 | |
|   return rq({
 | |
|     method: 'POST',
 | |
|     url: '/',
 | |
|     body: defaultBody,
 | |
|   });
 | |
| };
 | |
| 
 | |
| const createEmpty = () => {
 | |
|   return rq({
 | |
|     method: 'POST',
 | |
|     url: '/',
 | |
|     body: {
 | |
|       field: [],
 | |
|     },
 | |
|   });
 | |
| };
 | |
| 
 | |
| describe('Not required dynamiczone', () => {
 | |
|   const builder = createTestBuilder();
 | |
| 
 | |
|   beforeAll(async () => {
 | |
|     await builder
 | |
|       .addComponent(models.simpleCompo)
 | |
|       .addComponent(models.otherCompo)
 | |
|       .addContentType(models.ct)
 | |
|       .build();
 | |
| 
 | |
|     strapi = await createStrapiInstance();
 | |
|     rq = await createAuthRequest({ strapi });
 | |
|     rq.setURLPrefix('/content-manager/collection-types/api::withdynamiczone.withdynamiczone');
 | |
|   });
 | |
| 
 | |
|   afterAll(async () => {
 | |
|     await strapi.destroy();
 | |
|     await builder.cleanup();
 | |
|   });
 | |
| 
 | |
|   describe('Creation', () => {
 | |
|     test('Can create an entry with a dynamic zone and a nested compo', async () => {
 | |
|       const res = await rq({
 | |
|         method: 'POST',
 | |
|         url: '/',
 | |
|         body: {
 | |
|           field: [
 | |
|             {
 | |
|               __component: 'default.simple-compo',
 | |
|               name: 'someString',
 | |
|             },
 | |
|             {
 | |
|               __component: 'default.compo-with-other-compo',
 | |
|               compo: {
 | |
|                 name: 'someString',
 | |
|               },
 | |
|             },
 | |
|           ],
 | |
|         },
 | |
|         qs: {
 | |
|           populate: ['field'],
 | |
|         },
 | |
|       });
 | |
| 
 | |
|       expect(res.statusCode).toBe(200);
 | |
|       expect(Array.isArray(res.body.field)).toBe(true);
 | |
|       expect(res.body).toMatchObject({
 | |
|         field: [
 | |
|           {
 | |
|             id: expect.anything(),
 | |
|             __component: 'default.simple-compo',
 | |
|             name: 'someString',
 | |
|           },
 | |
|           {
 | |
|             id: expect.anything(),
 | |
|             __component: 'default.compo-with-other-compo',
 | |
|             compo: {
 | |
|               id: expect.anything(),
 | |
|               name: 'someString',
 | |
|             },
 | |
|           },
 | |
|         ],
 | |
|       });
 | |
|     });
 | |
| 
 | |
|     test('Can create entry with empty dynamiczone if it is not required', async () => {
 | |
|       const res = await rq({
 | |
|         method: 'POST',
 | |
|         url: '/',
 | |
|         body: {
 | |
|           field: [],
 | |
|         },
 | |
|         qs: {
 | |
|           populate: ['field'],
 | |
|         },
 | |
|       });
 | |
| 
 | |
|       expect(res.statusCode).toBe(200);
 | |
|       expect(Array.isArray(res.body.field)).toBe(true);
 | |
|       expect(res.body.field.length).toBe(0);
 | |
|     });
 | |
| 
 | |
|     test('Throw if min items is not respected', async () => {
 | |
|       const res = await rq({
 | |
|         method: 'POST',
 | |
|         url: '/',
 | |
|         body: {
 | |
|           field: [
 | |
|             {
 | |
|               __component: 'default.simple-compo',
 | |
|               name: 'someString',
 | |
|             },
 | |
|           ],
 | |
|         },
 | |
|       });
 | |
| 
 | |
|       expect(res.statusCode).toBe(400);
 | |
|     });
 | |
| 
 | |
|     test('Throws if max items is not respected', async () => {
 | |
|       const res = await rq({
 | |
|         method: 'POST',
 | |
|         url: '/',
 | |
|         body: {
 | |
|           field: Array(10).fill({
 | |
|             __component: 'default.simple-compo',
 | |
|             name: 'someString',
 | |
|           }),
 | |
|         },
 | |
|       });
 | |
| 
 | |
|       expect(res.statusCode).toBe(400);
 | |
|     });
 | |
|   });
 | |
| 
 | |
|   describe('Getting one entry', () => {
 | |
|     test('The entry has its dynamic zone populated', async () => {
 | |
|       const createRes = await createEntry();
 | |
|       const entryId = createRes.body.id;
 | |
| 
 | |
|       const res = await rq({
 | |
|         method: 'GET',
 | |
|         url: `/${entryId}`,
 | |
|         qs: {
 | |
|           populate: ['field'],
 | |
|         },
 | |
|       });
 | |
| 
 | |
|       expect(res.statusCode).toBe(200);
 | |
|       expect(Array.isArray(res.body.field)).toBe(true);
 | |
|       expect(res.body).toMatchObject({
 | |
|         field: [
 | |
|           {
 | |
|             id: expect.anything(),
 | |
|             __component: 'default.simple-compo',
 | |
|             name: 'someString',
 | |
|           },
 | |
|           {
 | |
|             id: expect.anything(),
 | |
|             __component: 'default.compo-with-other-compo',
 | |
|             compo: {
 | |
|               id: expect.anything(),
 | |
|               name: 'someString',
 | |
|             },
 | |
|           },
 | |
|         ],
 | |
|       });
 | |
|     });
 | |
|   });
 | |
| 
 | |
|   describe('Listing entries', () => {
 | |
|     test('The entries have their dynamic zones populated', async () => {
 | |
|       const res = await rq({
 | |
|         method: 'GET',
 | |
|         url: '/',
 | |
|         qs: {
 | |
|           populate: ['field'],
 | |
|         },
 | |
|       });
 | |
| 
 | |
|       expect(res.statusCode).toBe(200);
 | |
| 
 | |
|       expect(res.body.pagination).toBeDefined();
 | |
|       expect(Array.isArray(res.body.results)).toBe(true);
 | |
|       expect(res.body.results).toEqual(
 | |
|         expect.arrayContaining([
 | |
|           expect.objectContaining({
 | |
|             field: expect.arrayContaining([
 | |
|               expect.objectContaining({
 | |
|                 id: expect.anything(),
 | |
|                 __component: expect.any(String),
 | |
|               }),
 | |
|             ]),
 | |
|           }),
 | |
|         ])
 | |
|       );
 | |
|     });
 | |
|   });
 | |
| 
 | |
|   describe('Edition', () => {
 | |
|     test('Can empty non required dynamic zone', async () => {
 | |
|       const createRes = await createEntry();
 | |
| 
 | |
|       expect(createRes.statusCode).toBe(200);
 | |
|       const entryId = createRes.body.id;
 | |
| 
 | |
|       const res = await rq({
 | |
|         method: 'PUT',
 | |
|         url: `/${entryId}`,
 | |
|         body: {
 | |
|           field: [],
 | |
|         },
 | |
|         qs: {
 | |
|           populate: ['field'],
 | |
|         },
 | |
|       });
 | |
| 
 | |
|       expect(res.statusCode).toBe(200);
 | |
|       expect(Array.isArray(res.body.field)).toBe(true);
 | |
|       expect(res.body.field).toEqual([]);
 | |
|     });
 | |
| 
 | |
|     test('Can add items to empty dynamic zone', async () => {
 | |
|       const createRes = await createEmpty();
 | |
| 
 | |
|       expect(createRes.statusCode).toBe(200);
 | |
|       const entryId = createRes.body.id;
 | |
| 
 | |
|       const res = await rq({
 | |
|         method: 'PUT',
 | |
|         url: `/${entryId}`,
 | |
|         body: defaultBody,
 | |
|         qs: {
 | |
|           populate: ['field'],
 | |
|         },
 | |
|       });
 | |
| 
 | |
|       expect(res.statusCode).toBe(200);
 | |
|       expect(Array.isArray(res.body.field)).toBe(true);
 | |
|       expect(res.body).toMatchObject({
 | |
|         field: [
 | |
|           {
 | |
|             id: expect.anything(),
 | |
|             __component: 'default.simple-compo',
 | |
|             name: 'someString',
 | |
|           },
 | |
|           {
 | |
|             id: expect.anything(),
 | |
|             __component: 'default.compo-with-other-compo',
 | |
|             compo: {
 | |
|               id: expect.anything(),
 | |
|               name: 'someString',
 | |
|             },
 | |
|           },
 | |
|         ],
 | |
|       });
 | |
|     });
 | |
| 
 | |
|     test('Can remove items from dynamic zone', async () => {
 | |
|       const createRes = await createEntry();
 | |
| 
 | |
|       expect(createRes.statusCode).toBe(200);
 | |
|       const entryId = createRes.body.id;
 | |
| 
 | |
|       const res = await rq({
 | |
|         method: 'PUT',
 | |
|         url: `/${entryId}`,
 | |
|         body: {
 | |
|           field: [
 | |
|             {
 | |
|               __component: 'default.simple-compo',
 | |
|               name: 'otherString',
 | |
|             },
 | |
|             {
 | |
|               __component: 'default.simple-compo',
 | |
|               name: 'secondString',
 | |
|             },
 | |
|           ],
 | |
|         },
 | |
|         qs: {
 | |
|           populate: ['field'],
 | |
|         },
 | |
|       });
 | |
| 
 | |
|       expect(res.statusCode).toBe(200);
 | |
|       expect(Array.isArray(res.body.field)).toBe(true);
 | |
|       expect(res.body).toMatchObject({
 | |
|         field: [
 | |
|           {
 | |
|             id: expect.anything(),
 | |
|             __component: 'default.simple-compo',
 | |
|             name: 'otherString',
 | |
|           },
 | |
|           {
 | |
|             id: expect.anything(),
 | |
|             __component: 'default.simple-compo',
 | |
|             name: 'secondString',
 | |
|           },
 | |
|         ],
 | |
|       });
 | |
|     });
 | |
| 
 | |
|     test('Respects min items', async () => {
 | |
|       const createRes = await createEntry();
 | |
| 
 | |
|       expect(createRes.statusCode).toBe(200);
 | |
|       const entryId = createRes.body.id;
 | |
| 
 | |
|       const res = await rq({
 | |
|         method: 'PUT',
 | |
|         url: `/${entryId}`,
 | |
|         body: {
 | |
|           field: [
 | |
|             {
 | |
|               __component: 'default.simple-compo',
 | |
|               name: 'otherString',
 | |
|             },
 | |
|           ],
 | |
|         },
 | |
|       });
 | |
| 
 | |
|       expect(res.statusCode).toBe(400);
 | |
|     });
 | |
| 
 | |
|     test('Respects max items', async () => {
 | |
|       const createRes = await createEntry();
 | |
| 
 | |
|       expect(createRes.statusCode).toBe(200);
 | |
|       const entryId = createRes.body.id;
 | |
| 
 | |
|       const res = await rq({
 | |
|         method: 'PUT',
 | |
|         url: `/${entryId}`,
 | |
|         body: {
 | |
|           field: Array(10).fill({
 | |
|             __component: 'default.simple-compo',
 | |
|             name: 'otherString',
 | |
|           }),
 | |
|         },
 | |
|       });
 | |
| 
 | |
|       expect(res.statusCode).toBe(400);
 | |
|     });
 | |
|   });
 | |
| 
 | |
|   describe('Deletion', () => {
 | |
|     test('Returns the entry with its paths populated', async () => {
 | |
|       const createRes = await createEntry();
 | |
| 
 | |
|       expect(createRes.statusCode).toBe(200);
 | |
|       const entryId = createRes.body.id;
 | |
| 
 | |
|       const res = await rq({
 | |
|         method: 'DELETE',
 | |
|         url: `/${entryId}`,
 | |
|         qs: {
 | |
|           populate: ['field'],
 | |
|         },
 | |
|       });
 | |
| 
 | |
|       expect(res.statusCode).toBe(200);
 | |
|       expect(Array.isArray(res.body.field)).toBe(true);
 | |
|       expect(res.body).toEqual(
 | |
|         expect.objectContaining({
 | |
|           field: expect.arrayContaining([
 | |
|             expect.objectContaining({
 | |
|               id: expect.anything(),
 | |
|               __component: expect.any(String),
 | |
|             }),
 | |
|           ]),
 | |
|         })
 | |
|       );
 | |
|     });
 | |
|   });
 | |
| });
 | 
