mirror of
				https://github.com/strapi/strapi.git
				synced 2025-11-04 11:54:10 +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),
 | 
						|
            }),
 | 
						|
          ]),
 | 
						|
        })
 | 
						|
      );
 | 
						|
    });
 | 
						|
  });
 | 
						|
});
 |