mirror of
				https://github.com/strapi/strapi.git
				synced 2025-11-03 19:36:20 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			678 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			678 lines
		
	
	
		
			14 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 component = {
 | 
						|
  displayName: 'somecomponent',
 | 
						|
  attributes: {
 | 
						|
    name: {
 | 
						|
      type: 'string',
 | 
						|
    },
 | 
						|
  },
 | 
						|
};
 | 
						|
 | 
						|
const ct = {
 | 
						|
  displayName: 'withcomponent',
 | 
						|
  singularName: 'withcomponent',
 | 
						|
  pluralName: 'withcomponents',
 | 
						|
  attributes: {
 | 
						|
    field: {
 | 
						|
      type: 'component',
 | 
						|
      component: 'default.somecomponent',
 | 
						|
      repeatable: true,
 | 
						|
      required: true,
 | 
						|
      min: 1,
 | 
						|
      max: 5,
 | 
						|
    },
 | 
						|
  },
 | 
						|
};
 | 
						|
 | 
						|
describe('Non repeatable and Not required component', () => {
 | 
						|
  const builder = createTestBuilder();
 | 
						|
 | 
						|
  beforeAll(async () => {
 | 
						|
    await builder.addComponent(component).addContentType(ct).build();
 | 
						|
 | 
						|
    strapi = await createStrapiInstance();
 | 
						|
    rq = await createAuthRequest({ strapi });
 | 
						|
    rq.setURLPrefix('/content-manager/collection-types/api::withcomponent.withcomponent');
 | 
						|
  });
 | 
						|
 | 
						|
  afterAll(async () => {
 | 
						|
    await strapi.destroy();
 | 
						|
    await builder.cleanup();
 | 
						|
  });
 | 
						|
 | 
						|
  describe('POST new entry', () => {
 | 
						|
    test('Creating entry with JSON works', async () => {
 | 
						|
      const res = await rq.post('/', {
 | 
						|
        body: {
 | 
						|
          field: [
 | 
						|
            {
 | 
						|
              name: 'someString',
 | 
						|
            },
 | 
						|
          ],
 | 
						|
        },
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(res.statusCode).toBe(200);
 | 
						|
      expect(Array.isArray(res.body.field)).toBe(true);
 | 
						|
      expect(res.body.field).toEqual(
 | 
						|
        expect.arrayContaining([
 | 
						|
          expect.objectContaining({
 | 
						|
            id: expect.anything(),
 | 
						|
            name: 'someString',
 | 
						|
          }),
 | 
						|
        ])
 | 
						|
      );
 | 
						|
    });
 | 
						|
 | 
						|
    test('Creating second entry', async () => {
 | 
						|
      const res = await rq.post('/', {
 | 
						|
        body: {
 | 
						|
          field: [
 | 
						|
            {
 | 
						|
              name: 'someValue',
 | 
						|
            },
 | 
						|
          ],
 | 
						|
        },
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(res.statusCode).toBe(200);
 | 
						|
      expect(Array.isArray(res.body.field)).toBe(true);
 | 
						|
      expect(res.body.field).toEqual(
 | 
						|
        expect.arrayContaining([
 | 
						|
          expect.objectContaining({
 | 
						|
            id: expect.anything(),
 | 
						|
            name: 'someValue',
 | 
						|
          }),
 | 
						|
        ])
 | 
						|
      );
 | 
						|
    });
 | 
						|
 | 
						|
    test.each(['someString', 128219, false, {}, null])(
 | 
						|
      'Throws if the field is not an object %p',
 | 
						|
      async (value) => {
 | 
						|
        const res = await rq.post('/', {
 | 
						|
          body: {
 | 
						|
            field: value,
 | 
						|
          },
 | 
						|
          qs: {
 | 
						|
            populate: ['field'],
 | 
						|
          },
 | 
						|
        });
 | 
						|
 | 
						|
        expect(res.statusCode).toBe(400);
 | 
						|
      }
 | 
						|
    );
 | 
						|
 | 
						|
    test('Throws when sending an empty array or an array with less than the min', async () => {
 | 
						|
      const res = await rq.post('/', {
 | 
						|
        body: {
 | 
						|
          field: [],
 | 
						|
        },
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(res.statusCode).toBe(400);
 | 
						|
    });
 | 
						|
 | 
						|
    test('Throws when sending too many items', async () => {
 | 
						|
      const res = await rq.post('/', {
 | 
						|
        body: {
 | 
						|
          field: [
 | 
						|
            {
 | 
						|
              name: 'one',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              name: 'one',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              name: 'one',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              name: 'one',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              name: 'one',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              name: 'one',
 | 
						|
            },
 | 
						|
          ],
 | 
						|
        },
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(res.statusCode).toBe(400);
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  describe('GET entries', () => {
 | 
						|
    test('Data is orderd in the order sent', async () => {
 | 
						|
      const res = await rq.post('/', {
 | 
						|
        body: {
 | 
						|
          field: [
 | 
						|
            {
 | 
						|
              name: 'firstString',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              name: 'someString',
 | 
						|
            },
 | 
						|
          ],
 | 
						|
        },
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      const getRes = await rq.get(`/${res.body.id}`, {
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
      expect(getRes.statusCode).toBe(200);
 | 
						|
      expect(Array.isArray(getRes.body.field)).toBe(true);
 | 
						|
 | 
						|
      expect(getRes.body.field[0]).toMatchObject({
 | 
						|
        name: 'firstString',
 | 
						|
      });
 | 
						|
      expect(getRes.body.field[1]).toMatchObject({
 | 
						|
        name: 'someString',
 | 
						|
      });
 | 
						|
    });
 | 
						|
 | 
						|
    test('Should return entries with their nested components', async () => {
 | 
						|
      const res = await rq.get('/', {
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(res.statusCode).toBe(200);
 | 
						|
 | 
						|
      expect(res.body.pagination).toBeDefined();
 | 
						|
      expect(Array.isArray(res.body.results)).toBe(true);
 | 
						|
      res.body.results.forEach((entry) => {
 | 
						|
        expect(Array.isArray(entry.field)).toBe(true);
 | 
						|
 | 
						|
        if (entry.field.length === 0) return;
 | 
						|
 | 
						|
        expect(entry.field).toEqual(
 | 
						|
          expect.arrayContaining([
 | 
						|
            expect.objectContaining({
 | 
						|
              name: expect.any(String),
 | 
						|
            }),
 | 
						|
          ])
 | 
						|
        );
 | 
						|
      });
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  describe('PUT entry', () => {
 | 
						|
    test.each(['someString', 128219, false, {}, null])(
 | 
						|
      'Throws when sending invalid updated field %p',
 | 
						|
      async (value) => {
 | 
						|
        const res = await rq.post('/', {
 | 
						|
          body: {
 | 
						|
            field: [
 | 
						|
              {
 | 
						|
                name: 'someString',
 | 
						|
              },
 | 
						|
            ],
 | 
						|
          },
 | 
						|
          qs: {
 | 
						|
            populate: ['field'],
 | 
						|
          },
 | 
						|
        });
 | 
						|
 | 
						|
        const updateRes = await rq.put(`/${res.body.id}`, {
 | 
						|
          body: {
 | 
						|
            field: value,
 | 
						|
          },
 | 
						|
          qs: {
 | 
						|
            populate: ['field'],
 | 
						|
          },
 | 
						|
        });
 | 
						|
 | 
						|
        expect(updateRes.statusCode).toBe(400);
 | 
						|
 | 
						|
        // shouldn't have been updated
 | 
						|
        const getRes = await rq.get(`/${res.body.id}`, {
 | 
						|
          qs: {
 | 
						|
            populate: ['field'],
 | 
						|
          },
 | 
						|
        });
 | 
						|
 | 
						|
        expect(getRes.statusCode).toBe(200);
 | 
						|
        expect(getRes.body).toMatchObject({
 | 
						|
          id: res.body.id,
 | 
						|
          field: res.body.field,
 | 
						|
        });
 | 
						|
      }
 | 
						|
    );
 | 
						|
 | 
						|
    test('Updates order at each request', async () => {
 | 
						|
      const res = await rq.post('/', {
 | 
						|
        body: {
 | 
						|
          field: [
 | 
						|
            {
 | 
						|
              name: 'someString',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              name: 'otherString',
 | 
						|
            },
 | 
						|
          ],
 | 
						|
        },
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(res.body.field[0]).toMatchObject({
 | 
						|
        name: 'someString',
 | 
						|
      });
 | 
						|
      expect(res.body.field[1]).toMatchObject({
 | 
						|
        name: 'otherString',
 | 
						|
      });
 | 
						|
 | 
						|
      const updateRes = await rq.put(`/${res.body.id}`, {
 | 
						|
        body: {
 | 
						|
          field: [
 | 
						|
            {
 | 
						|
              name: 'otherString',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              name: 'someString',
 | 
						|
            },
 | 
						|
          ],
 | 
						|
        },
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(updateRes.statusCode).toBe(200);
 | 
						|
      expect(Array.isArray(updateRes.body.field)).toBe(true);
 | 
						|
 | 
						|
      expect(updateRes.body.field[0]).toMatchObject({
 | 
						|
        name: 'otherString',
 | 
						|
      });
 | 
						|
      expect(updateRes.body.field[1]).toMatchObject({
 | 
						|
        name: 'someString',
 | 
						|
      });
 | 
						|
 | 
						|
      const getRes = await rq.get(`/${res.body.id}`, {
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(getRes.statusCode).toBe(200);
 | 
						|
      expect(Array.isArray(getRes.body.field)).toBe(true);
 | 
						|
 | 
						|
      expect(getRes.body.field[0]).toMatchObject({
 | 
						|
        name: 'otherString',
 | 
						|
      });
 | 
						|
      expect(getRes.body.field[1]).toMatchObject({
 | 
						|
        name: 'someString',
 | 
						|
      });
 | 
						|
    });
 | 
						|
 | 
						|
    test('Keeps the previous value if component not sent', async () => {
 | 
						|
      const res = await rq.post('/', {
 | 
						|
        body: {
 | 
						|
          field: [
 | 
						|
            {
 | 
						|
              name: 'someString',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              name: 'otherString',
 | 
						|
            },
 | 
						|
          ],
 | 
						|
        },
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      const updateRes = await rq.put(`/${res.body.id}`, {
 | 
						|
        body: {},
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(updateRes.statusCode).toBe(200);
 | 
						|
      expect(updateRes.body).toMatchObject({
 | 
						|
        id: res.body.id,
 | 
						|
        field: res.body.field,
 | 
						|
      });
 | 
						|
 | 
						|
      const getRes = await rq.get(`/${res.body.id}`, {
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(getRes.statusCode).toBe(200);
 | 
						|
      expect(getRes.body).toMatchObject({
 | 
						|
        id: res.body.id,
 | 
						|
        field: res.body.field,
 | 
						|
      });
 | 
						|
    });
 | 
						|
 | 
						|
    test('Throws when not enough items', async () => {
 | 
						|
      const res = await rq.post('/', {
 | 
						|
        body: {
 | 
						|
          field: [
 | 
						|
            {
 | 
						|
              name: 'someString',
 | 
						|
            },
 | 
						|
          ],
 | 
						|
        },
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      const updateRes = await rq.put(`/${res.body.id}`, {
 | 
						|
        body: {
 | 
						|
          field: [],
 | 
						|
        },
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(updateRes.statusCode).toBe(400);
 | 
						|
 | 
						|
      const getRes = await rq.get(`/${res.body.id}`, {
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(getRes.statusCode).toBe(200);
 | 
						|
      expect(getRes.body).toMatchObject(res.body);
 | 
						|
    });
 | 
						|
 | 
						|
    test('Throws when too many items', async () => {
 | 
						|
      const res = await rq.post('/', {
 | 
						|
        body: {
 | 
						|
          field: [
 | 
						|
            {
 | 
						|
              name: 'someString',
 | 
						|
            },
 | 
						|
          ],
 | 
						|
        },
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      const updateRes = await rq.put(`/${res.body.id}`, {
 | 
						|
        body: {
 | 
						|
          field: [
 | 
						|
            {
 | 
						|
              name: 'someString',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              name: 'someString',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              name: 'someString',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              name: 'someString',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              name: 'someString',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              name: 'someString',
 | 
						|
            },
 | 
						|
          ],
 | 
						|
        },
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(updateRes.statusCode).toBe(400);
 | 
						|
 | 
						|
      const getRes = await rq.get(`/${res.body.id}`, {
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(getRes.statusCode).toBe(200);
 | 
						|
      expect(getRes.body).toMatchObject(res.body);
 | 
						|
    });
 | 
						|
 | 
						|
    test('Replaces the previous components if sent without id', async () => {
 | 
						|
      const res = await rq.post('/', {
 | 
						|
        body: {
 | 
						|
          field: [
 | 
						|
            {
 | 
						|
              name: 'someString',
 | 
						|
            },
 | 
						|
          ],
 | 
						|
        },
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      const updateRes = await rq.put(`/${res.body.id}`, {
 | 
						|
        body: {
 | 
						|
          field: [
 | 
						|
            {
 | 
						|
              name: 'new String',
 | 
						|
            },
 | 
						|
          ],
 | 
						|
        },
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(updateRes.statusCode).toBe(200);
 | 
						|
 | 
						|
      const oldIds = res.body.field.map((val) => val.id);
 | 
						|
      updateRes.body.field.forEach((val) => {
 | 
						|
        expect(oldIds.includes(val.id)).toBe(false);
 | 
						|
      });
 | 
						|
 | 
						|
      expect(updateRes.body).toMatchObject({
 | 
						|
        id: res.body.id,
 | 
						|
        field: [
 | 
						|
          {
 | 
						|
            name: 'new String',
 | 
						|
          },
 | 
						|
        ],
 | 
						|
      });
 | 
						|
 | 
						|
      const getRes = await rq.get(`/${res.body.id}`, {
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(getRes.statusCode).toBe(200);
 | 
						|
      expect(getRes.body).toMatchObject({
 | 
						|
        id: res.body.id,
 | 
						|
        field: [
 | 
						|
          {
 | 
						|
            name: 'new String',
 | 
						|
          },
 | 
						|
        ],
 | 
						|
      });
 | 
						|
    });
 | 
						|
 | 
						|
    test('Throws on invalid id in component', async () => {
 | 
						|
      const res = await rq.post('/', {
 | 
						|
        body: {
 | 
						|
          field: [
 | 
						|
            {
 | 
						|
              name: 'someString',
 | 
						|
            },
 | 
						|
          ],
 | 
						|
        },
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      const updateRes = await rq.put(`/${res.body.id}`, {
 | 
						|
        body: {
 | 
						|
          field: [
 | 
						|
            {
 | 
						|
              id: 'invalid_id',
 | 
						|
              name: 'new String',
 | 
						|
            },
 | 
						|
          ],
 | 
						|
        },
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(updateRes.statusCode).toBe(400);
 | 
						|
    });
 | 
						|
 | 
						|
    test('Updates component with ids, create new ones and removes old ones', async () => {
 | 
						|
      const res = await rq.post('/', {
 | 
						|
        body: {
 | 
						|
          field: [
 | 
						|
            {
 | 
						|
              name: 'one',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              name: 'two',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              name: 'three',
 | 
						|
            },
 | 
						|
          ],
 | 
						|
        },
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      const updateRes = await rq.put(`/${res.body.id}`, {
 | 
						|
        body: {
 | 
						|
          field: [
 | 
						|
            {
 | 
						|
              id: res.body.field[0].id, // send old id to update the previous component
 | 
						|
              name: 'newOne',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              name: 'newTwo',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              id: res.body.field[2].id,
 | 
						|
              name: 'three',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              name: 'four',
 | 
						|
            },
 | 
						|
          ],
 | 
						|
        },
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      const expectedResult = {
 | 
						|
        id: res.body.id,
 | 
						|
        field: [
 | 
						|
          {
 | 
						|
            id: res.body.field[0].id,
 | 
						|
            name: 'newOne',
 | 
						|
          },
 | 
						|
          {
 | 
						|
            name: 'newTwo',
 | 
						|
          },
 | 
						|
          {
 | 
						|
            id: res.body.field[2].id,
 | 
						|
            name: 'three',
 | 
						|
          },
 | 
						|
          {
 | 
						|
            name: 'four',
 | 
						|
          },
 | 
						|
        ],
 | 
						|
      };
 | 
						|
 | 
						|
      expect(updateRes.statusCode).toBe(200);
 | 
						|
      expect(updateRes.body).toMatchObject(expectedResult);
 | 
						|
 | 
						|
      const getRes = await rq.get(`/${res.body.id}`, {
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(getRes.statusCode).toBe(200);
 | 
						|
      expect(getRes.body).toMatchObject(expectedResult);
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  describe('DELETE entry', () => {
 | 
						|
    test('Returns entry with components', async () => {
 | 
						|
      const res = await rq.post('/', {
 | 
						|
        body: {
 | 
						|
          field: [
 | 
						|
            {
 | 
						|
              name: 'someString',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              name: 'someOtherString',
 | 
						|
            },
 | 
						|
            {
 | 
						|
              name: 'otherSomeString',
 | 
						|
            },
 | 
						|
          ],
 | 
						|
        },
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      const deleteRes = await rq.delete(`/${res.body.id}`, {
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(deleteRes.statusCode).toBe(200);
 | 
						|
      expect(deleteRes.body).toMatchObject(res.body);
 | 
						|
 | 
						|
      const getRes = await rq.get(`/${res.body.id}`, {
 | 
						|
        qs: {
 | 
						|
          populate: ['field'],
 | 
						|
        },
 | 
						|
      });
 | 
						|
 | 
						|
      expect(getRes.statusCode).toBe(404);
 | 
						|
    });
 | 
						|
  });
 | 
						|
});
 |