mirror of
				https://github.com/strapi/strapi.git
				synced 2025-11-03 19:36:20 +00:00 
			
		
		
		
	add e2e tests
This commit is contained in:
		
							parent
							
								
									7f521c9348
								
							
						
					
					
						commit
						8dfa1c70d1
					
				@ -1,238 +0,0 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
const createContext = require('../../../../../../test/helpers/create-context');
 | 
			
		||||
const relations = require('../relations');
 | 
			
		||||
 | 
			
		||||
describe('Relations', () => {
 | 
			
		||||
  describe('find', () => {
 | 
			
		||||
    test('Fails on model not found', async () => {
 | 
			
		||||
      const notFound = jest.fn();
 | 
			
		||||
      const ctx = createContext(
 | 
			
		||||
        {
 | 
			
		||||
          params: { model: 'test', targetField: 'field' },
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          notFound,
 | 
			
		||||
        }
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      const getModel = jest.fn();
 | 
			
		||||
      global.strapi = {
 | 
			
		||||
        getModel,
 | 
			
		||||
        plugins: {
 | 
			
		||||
          'content-manager': {
 | 
			
		||||
            services: {},
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      await relations.find(ctx);
 | 
			
		||||
 | 
			
		||||
      expect(notFound).toHaveBeenCalledWith('model.notFound');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Fails on invalid target field', async () => {
 | 
			
		||||
      const badRequest = jest.fn();
 | 
			
		||||
      const ctx = createContext(
 | 
			
		||||
        {
 | 
			
		||||
          params: { model: 'test', targetField: 'field' },
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          badRequest,
 | 
			
		||||
        }
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      const getModel = jest.fn(() => ({
 | 
			
		||||
        attributes: {},
 | 
			
		||||
      }));
 | 
			
		||||
 | 
			
		||||
      global.strapi = {
 | 
			
		||||
        getModel,
 | 
			
		||||
        plugins: {
 | 
			
		||||
          'content-manager': {
 | 
			
		||||
            services: {},
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      await relations.find(ctx);
 | 
			
		||||
 | 
			
		||||
      expect(badRequest).toHaveBeenCalledWith('targetField.invalid');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Fails on model not found', async () => {
 | 
			
		||||
      const notFound = jest.fn();
 | 
			
		||||
      const ctx = createContext(
 | 
			
		||||
        {
 | 
			
		||||
          params: { model: 'test', targetField: 'target' },
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          notFound,
 | 
			
		||||
        }
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      const getModel = jest
 | 
			
		||||
        .fn()
 | 
			
		||||
        .mockReturnValueOnce({
 | 
			
		||||
          attributes: { target: { type: 'relation', target: 'test' } },
 | 
			
		||||
        })
 | 
			
		||||
        .mockReturnValueOnce(null);
 | 
			
		||||
 | 
			
		||||
      global.strapi = {
 | 
			
		||||
        getModel,
 | 
			
		||||
        plugins: {
 | 
			
		||||
          'content-manager': {
 | 
			
		||||
            services: {},
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      await relations.find(ctx);
 | 
			
		||||
 | 
			
		||||
      expect(notFound).toHaveBeenCalledWith('target.notFound');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Picks the mainField and id only', async () => {
 | 
			
		||||
      const notFound = jest.fn();
 | 
			
		||||
      const ctx = createContext(
 | 
			
		||||
        {
 | 
			
		||||
          params: { model: 'test', targetField: 'target' },
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          notFound,
 | 
			
		||||
        }
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      const getModel = jest.fn(() => ({
 | 
			
		||||
        attributes: { target: { type: 'relation', target: 'test' } },
 | 
			
		||||
      }));
 | 
			
		||||
 | 
			
		||||
      global.strapi = {
 | 
			
		||||
        getModel,
 | 
			
		||||
        plugins: {
 | 
			
		||||
          'content-manager': {
 | 
			
		||||
            services: {
 | 
			
		||||
              'content-types': {
 | 
			
		||||
                findConfiguration() {
 | 
			
		||||
                  return {
 | 
			
		||||
                    metadatas: {
 | 
			
		||||
                      target: {
 | 
			
		||||
                        edit: {
 | 
			
		||||
                          mainField: 'title',
 | 
			
		||||
                        },
 | 
			
		||||
                      },
 | 
			
		||||
                    },
 | 
			
		||||
                  };
 | 
			
		||||
                },
 | 
			
		||||
              },
 | 
			
		||||
              'entity-manager': {
 | 
			
		||||
                find() {
 | 
			
		||||
                  return [
 | 
			
		||||
                    {
 | 
			
		||||
                      id: 1,
 | 
			
		||||
                      title: 'title1',
 | 
			
		||||
                      secret: 'some secret',
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                      id: 2,
 | 
			
		||||
                      title: 'title2',
 | 
			
		||||
                      secret: 'some secret 2',
 | 
			
		||||
                    },
 | 
			
		||||
                  ];
 | 
			
		||||
                },
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      await relations.find(ctx);
 | 
			
		||||
 | 
			
		||||
      expect(ctx.body).toEqual([
 | 
			
		||||
        {
 | 
			
		||||
          id: 1,
 | 
			
		||||
          title: 'title1',
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          id: 2,
 | 
			
		||||
          title: 'title2',
 | 
			
		||||
        },
 | 
			
		||||
      ]);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Omit somes ids', async () => {
 | 
			
		||||
      const result = [
 | 
			
		||||
        {
 | 
			
		||||
          id: 1,
 | 
			
		||||
          title: 'title1',
 | 
			
		||||
          secret: 'some secret',
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          id: 2,
 | 
			
		||||
          title: 'title2',
 | 
			
		||||
          secret: 'some secret 2',
 | 
			
		||||
        },
 | 
			
		||||
      ];
 | 
			
		||||
      const configuration = {
 | 
			
		||||
        metadatas: {
 | 
			
		||||
          target: {
 | 
			
		||||
            edit: {
 | 
			
		||||
              mainField: 'title',
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      };
 | 
			
		||||
      const assocModel = { uid: 'api::test.test', attributes: {} };
 | 
			
		||||
      const notFound = jest.fn();
 | 
			
		||||
      const find = jest.fn(() => Promise.resolve(result));
 | 
			
		||||
      const findConfiguration = jest.fn(() => Promise.resolve(configuration));
 | 
			
		||||
 | 
			
		||||
      const getModel = jest
 | 
			
		||||
        .fn()
 | 
			
		||||
        .mockImplementationOnce(() => ({
 | 
			
		||||
          attributes: { target: { type: 'relation', target: 'test' } },
 | 
			
		||||
        }))
 | 
			
		||||
        .mockImplementationOnce(() => assocModel);
 | 
			
		||||
 | 
			
		||||
      global.strapi = {
 | 
			
		||||
        getModel,
 | 
			
		||||
        plugins: {
 | 
			
		||||
          'content-manager': {
 | 
			
		||||
            services: {
 | 
			
		||||
              'content-types': { findConfiguration },
 | 
			
		||||
              'entity-manager': { find },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      const ctx = createContext(
 | 
			
		||||
        {
 | 
			
		||||
          params: { model: 'test', targetField: 'target' },
 | 
			
		||||
          body: { idsToOmit: [3, 4] },
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          notFound,
 | 
			
		||||
        }
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      await relations.find(ctx);
 | 
			
		||||
 | 
			
		||||
      expect(find).toHaveBeenCalledWith(
 | 
			
		||||
        { filters: { $and: [{ id: { $notIn: [3, 4] } }] } },
 | 
			
		||||
        assocModel.uid,
 | 
			
		||||
        []
 | 
			
		||||
      );
 | 
			
		||||
      expect(ctx.body).toEqual([
 | 
			
		||||
        {
 | 
			
		||||
          id: 1,
 | 
			
		||||
          title: 'title1',
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          id: 2,
 | 
			
		||||
          title: 'title2',
 | 
			
		||||
        },
 | 
			
		||||
      ]);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
const { prop, isEmpty } = require('lodash/fp');
 | 
			
		||||
const { hasDraftAndPublish } = require('@strapi/utils').contentTypes;
 | 
			
		||||
const { PUBLISHED_AT_ATTRIBUTE } = require('@strapi/utils').contentTypes.constants;
 | 
			
		||||
 | 
			
		||||
const { getService } = require('../utils');
 | 
			
		||||
@ -14,14 +15,14 @@ module.exports = {
 | 
			
		||||
 | 
			
		||||
    const { component, entityId, idsToOmit, page = 1, pageSize = 10, q } = ctx.request.query;
 | 
			
		||||
 | 
			
		||||
    const sourceModel = component || model;
 | 
			
		||||
    const sourceModelUid = component || model;
 | 
			
		||||
 | 
			
		||||
    const modelDef = strapi.getModel(sourceModel);
 | 
			
		||||
    if (!modelDef) {
 | 
			
		||||
    const sourceModel = strapi.getModel(sourceModelUid);
 | 
			
		||||
    if (!sourceModel) {
 | 
			
		||||
      return ctx.badRequest("The model doesn't exist");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const attribute = modelDef.attributes[targetField];
 | 
			
		||||
    const attribute = sourceModel.attributes[targetField];
 | 
			
		||||
    if (!attribute || attribute.type !== 'relation') {
 | 
			
		||||
      return ctx.badRequest("This relational field doesn't exist");
 | 
			
		||||
    }
 | 
			
		||||
@ -32,8 +33,8 @@ module.exports = {
 | 
			
		||||
    const limit = Number(pageSize);
 | 
			
		||||
 | 
			
		||||
    const modelConfig = component
 | 
			
		||||
      ? await getService('components').findConfiguration(modelDef)
 | 
			
		||||
      : await getService('content-types').findConfiguration(modelDef);
 | 
			
		||||
      ? await getService('components').findConfiguration(sourceModel)
 | 
			
		||||
      : await getService('content-types').findConfiguration(sourceModel);
 | 
			
		||||
    const mainField = prop(`metadatas.${targetField}.edit.mainField`, modelConfig) || 'id';
 | 
			
		||||
 | 
			
		||||
    const query = strapi.db.queryBuilder(targetedModel.uid);
 | 
			
		||||
@ -47,7 +48,7 @@ module.exports = {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (entityId) {
 | 
			
		||||
      const joinTable = strapi.db.metadata.get(sourceModel).attributes[targetField].joinTable;
 | 
			
		||||
      const joinTable = strapi.db.metadata.get(sourceModelUid).attributes[targetField].joinTable;
 | 
			
		||||
      const sourceColumn = component ? joinTable.joinColumn.name : joinTable.inverseJoinColumn.name;
 | 
			
		||||
      const targetColumn = component ? joinTable.inverseJoinColumn.name : joinTable.joinColumn.name;
 | 
			
		||||
 | 
			
		||||
@ -66,8 +67,13 @@ module.exports = {
 | 
			
		||||
      .count()
 | 
			
		||||
      .first()
 | 
			
		||||
      .execute();
 | 
			
		||||
 | 
			
		||||
    const fieldsToSelect = ['id', mainField];
 | 
			
		||||
    if (hasDraftAndPublish(targetedModel)) {
 | 
			
		||||
      fieldsToSelect.push(PUBLISHED_AT_ATTRIBUTE);
 | 
			
		||||
    }
 | 
			
		||||
    const entities = await query
 | 
			
		||||
      .select([mainField, 'id', PUBLISHED_AT_ATTRIBUTE])
 | 
			
		||||
      .select(fieldsToSelect)
 | 
			
		||||
      .orderBy(mainField)
 | 
			
		||||
      .offset(offset)
 | 
			
		||||
      .limit(limit)
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,7 @@ const validateFindNewSchema = yup
 | 
			
		||||
    component: yup.string(),
 | 
			
		||||
    entityId: yup.strapiID(),
 | 
			
		||||
    q: yup.string(),
 | 
			
		||||
    omitIds: yup.array().of(yup.strapiID()),
 | 
			
		||||
    idsToOmit: yup.array().of(yup.strapiID()),
 | 
			
		||||
    page: yup
 | 
			
		||||
      .number()
 | 
			
		||||
      .integer()
 | 
			
		||||
 | 
			
		||||
@ -1,196 +0,0 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
// Test a simple default API with no relations
 | 
			
		||||
 | 
			
		||||
const { omit, pick } = require('lodash/fp');
 | 
			
		||||
 | 
			
		||||
const { createTestBuilder } = require('../../../../../test/helpers/builder');
 | 
			
		||||
const { createStrapiInstance } = require('../../../../../test/helpers/strapi');
 | 
			
		||||
const { createAuthRequest } = require('../../../../../test/helpers/request');
 | 
			
		||||
 | 
			
		||||
let strapi;
 | 
			
		||||
let rq;
 | 
			
		||||
const data = {
 | 
			
		||||
  products: [],
 | 
			
		||||
  shops: [],
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const productModel = {
 | 
			
		||||
  attributes: {
 | 
			
		||||
    name: {
 | 
			
		||||
      type: 'string',
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  displayName: 'Product',
 | 
			
		||||
  singularName: 'product',
 | 
			
		||||
  pluralName: 'products',
 | 
			
		||||
  description: '',
 | 
			
		||||
  collectionName: '',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const productWithDPModel = {
 | 
			
		||||
  attributes: {
 | 
			
		||||
    name: {
 | 
			
		||||
      type: 'string',
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  displayName: 'Product',
 | 
			
		||||
  singularName: 'product',
 | 
			
		||||
  pluralName: 'products',
 | 
			
		||||
  draftAndPublish: true,
 | 
			
		||||
  description: '',
 | 
			
		||||
  collectionName: '',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const shopModel = {
 | 
			
		||||
  attributes: {
 | 
			
		||||
    name: {
 | 
			
		||||
      type: 'string',
 | 
			
		||||
    },
 | 
			
		||||
    products: {
 | 
			
		||||
      type: 'relation',
 | 
			
		||||
      relation: 'manyToMany',
 | 
			
		||||
      target: 'api::product.product',
 | 
			
		||||
      targetAttribute: 'shops',
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  displayName: 'Shop',
 | 
			
		||||
  singularName: 'shop',
 | 
			
		||||
  pluralName: 'shops',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const shops = [
 | 
			
		||||
  {
 | 
			
		||||
    name: 'market',
 | 
			
		||||
  },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const products =
 | 
			
		||||
  ({ withPublished = false }) =>
 | 
			
		||||
  ({ shop }) => {
 | 
			
		||||
    const shops = [shop[0].id];
 | 
			
		||||
 | 
			
		||||
    const entries = [
 | 
			
		||||
      {
 | 
			
		||||
        name: 'tomato',
 | 
			
		||||
        shops,
 | 
			
		||||
        publishedAt: new Date(),
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        name: 'apple',
 | 
			
		||||
        shops,
 | 
			
		||||
        publishedAt: null,
 | 
			
		||||
      },
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    if (withPublished) {
 | 
			
		||||
      return entries;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return entries.map(omit('publishedAt'));
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
describe('Relation-list route', () => {
 | 
			
		||||
  describe('without draftAndPublish', () => {
 | 
			
		||||
    const builder = createTestBuilder();
 | 
			
		||||
 | 
			
		||||
    beforeAll(async () => {
 | 
			
		||||
      await builder
 | 
			
		||||
        .addContentTypes([productModel, shopModel])
 | 
			
		||||
        .addFixtures(shopModel.singularName, shops)
 | 
			
		||||
        .addFixtures(productModel.singularName, products({ withPublished: false }))
 | 
			
		||||
        .build();
 | 
			
		||||
 | 
			
		||||
      strapi = await createStrapiInstance();
 | 
			
		||||
      rq = await createAuthRequest({ strapi });
 | 
			
		||||
 | 
			
		||||
      data.shops = await builder.sanitizedFixturesFor(shopModel.singularName, strapi);
 | 
			
		||||
      data.products = await builder.sanitizedFixturesFor(productModel.singularName, strapi);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    afterAll(async () => {
 | 
			
		||||
      await strapi.destroy();
 | 
			
		||||
      await builder.cleanup();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Can get relation-list for products of a shop', async () => {
 | 
			
		||||
      const res = await rq({
 | 
			
		||||
        method: 'POST',
 | 
			
		||||
        url: '/content-manager/relations/api::shop.shop/products',
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.body).toHaveLength(data.products.length);
 | 
			
		||||
      data.products.forEach((product, index) => {
 | 
			
		||||
        expect(res.body[index]).toStrictEqual(pick(['_id', 'id', 'name'], product));
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Can get relation-list for products of a shop and omit some results', async () => {
 | 
			
		||||
      const res = await rq({
 | 
			
		||||
        method: 'POST',
 | 
			
		||||
        url: '/content-manager/relations/api::shop.shop/products',
 | 
			
		||||
        body: {
 | 
			
		||||
          idsToOmit: [data.products[0].id],
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.body).toHaveLength(1);
 | 
			
		||||
      expect(res.body[0]).toStrictEqual(pick(['_id', 'id', 'name'], data.products[1]));
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('with draftAndPublish', () => {
 | 
			
		||||
    const builder = createTestBuilder();
 | 
			
		||||
 | 
			
		||||
    beforeAll(async () => {
 | 
			
		||||
      await builder
 | 
			
		||||
        .addContentTypes([productWithDPModel, shopModel])
 | 
			
		||||
        .addFixtures(shopModel.singularName, shops)
 | 
			
		||||
        .addFixtures(productWithDPModel.singularName, products({ withPublished: true }))
 | 
			
		||||
        .build();
 | 
			
		||||
 | 
			
		||||
      strapi = await createStrapiInstance();
 | 
			
		||||
      rq = await createAuthRequest({ strapi });
 | 
			
		||||
 | 
			
		||||
      data.shops = await builder.sanitizedFixturesFor(shopModel.singularName, strapi);
 | 
			
		||||
      data.products = await builder.sanitizedFixturesFor(productWithDPModel.singularName, strapi);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    afterAll(async () => {
 | 
			
		||||
      await strapi.destroy();
 | 
			
		||||
      await builder.cleanup();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Can get relation-list for products of a shop', async () => {
 | 
			
		||||
      const res = await rq({
 | 
			
		||||
        method: 'POST',
 | 
			
		||||
        url: '/content-manager/relations/api::shop.shop/products',
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.body).toHaveLength(data.products.length);
 | 
			
		||||
 | 
			
		||||
      const tomatoProductRes = res.body.find((p) => p.name === 'tomato');
 | 
			
		||||
      const appleProductRes = res.body.find((p) => p.name === 'apple');
 | 
			
		||||
 | 
			
		||||
      expect(tomatoProductRes).toMatchObject(pick(['_id', 'id', 'name'], data.products[0]));
 | 
			
		||||
      expect(tomatoProductRes.publishedAt).toBeISODate();
 | 
			
		||||
      expect(appleProductRes).toStrictEqual({
 | 
			
		||||
        ...pick(['_id', 'id', 'name'], data.products[1]),
 | 
			
		||||
        publishedAt: null,
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Can get relation-list for products of a shop and omit some results', async () => {
 | 
			
		||||
      const res = await rq({
 | 
			
		||||
        method: 'POST',
 | 
			
		||||
        url: '/content-manager/relations/api::shop.shop/products',
 | 
			
		||||
        body: {
 | 
			
		||||
          idsToOmit: [data.products[1].id],
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.body).toHaveLength(1);
 | 
			
		||||
      expect(res.body[0]).toMatchObject(pick(['_id', 'id', 'name'], data.products[0]));
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@ -0,0 +1,260 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
const { createTestBuilder } = require('../../../../../test/helpers/builder');
 | 
			
		||||
const { createStrapiInstance } = require('../../../../../test/helpers/strapi');
 | 
			
		||||
const { createAuthRequest } = require('../../../../../test/helpers/request');
 | 
			
		||||
 | 
			
		||||
let strapi;
 | 
			
		||||
let rq;
 | 
			
		||||
let data = {
 | 
			
		||||
  products: [],
 | 
			
		||||
  shops: [],
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const compo = {
 | 
			
		||||
  displayName: 'compo',
 | 
			
		||||
  attributes: {
 | 
			
		||||
    name: {
 | 
			
		||||
      type: 'string',
 | 
			
		||||
    },
 | 
			
		||||
    compoProducts: {
 | 
			
		||||
      type: 'relation',
 | 
			
		||||
      relation: 'manyToMany',
 | 
			
		||||
      target: 'api::product.product',
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const productModel = {
 | 
			
		||||
  draftAndPublish: true,
 | 
			
		||||
  attributes: {
 | 
			
		||||
    name: {
 | 
			
		||||
      type: 'string',
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  displayName: 'Product',
 | 
			
		||||
  singularName: 'product',
 | 
			
		||||
  pluralName: 'products',
 | 
			
		||||
  description: '',
 | 
			
		||||
  collectionName: '',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const shopModel = {
 | 
			
		||||
  draftAndPublish: true,
 | 
			
		||||
  attributes: {
 | 
			
		||||
    name: {
 | 
			
		||||
      type: 'string',
 | 
			
		||||
    },
 | 
			
		||||
    products: {
 | 
			
		||||
      type: 'relation',
 | 
			
		||||
      relation: 'manyToMany',
 | 
			
		||||
      target: 'api::product.product',
 | 
			
		||||
      targetAttribute: 'shops',
 | 
			
		||||
      inversedBy: 'shops',
 | 
			
		||||
    },
 | 
			
		||||
    myCompo: {
 | 
			
		||||
      type: 'component',
 | 
			
		||||
      repeatable: false,
 | 
			
		||||
      component: 'default.compo',
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  displayName: 'Shop',
 | 
			
		||||
  singularName: 'shop',
 | 
			
		||||
  pluralName: 'shops',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
describe('Relations with Draft & Publish', () => {
 | 
			
		||||
  const builder = createTestBuilder();
 | 
			
		||||
 | 
			
		||||
  beforeAll(async () => {
 | 
			
		||||
    await builder
 | 
			
		||||
      .addContentTypes([productModel])
 | 
			
		||||
      .addComponent(compo)
 | 
			
		||||
      .addContentTypes([shopModel])
 | 
			
		||||
      .build();
 | 
			
		||||
 | 
			
		||||
    strapi = await createStrapiInstance();
 | 
			
		||||
    rq = await createAuthRequest({ strapi });
 | 
			
		||||
 | 
			
		||||
    const { body: createdProduct1 } = await rq({
 | 
			
		||||
      method: 'POST',
 | 
			
		||||
      url: '/content-manager/collection-types/api::product.product',
 | 
			
		||||
      body: { name: 'Skate' },
 | 
			
		||||
    });
 | 
			
		||||
    await rq({
 | 
			
		||||
      url: `/content-manager/collection-types/api::product.product/${createdProduct1.id}/actions/publish`,
 | 
			
		||||
      method: 'POST',
 | 
			
		||||
    });
 | 
			
		||||
    const { body: createdProduct2 } = await rq({
 | 
			
		||||
      method: 'POST',
 | 
			
		||||
      url: '/content-manager/collection-types/api::product.product',
 | 
			
		||||
      body: { name: 'Candle' },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    data.products.push(createdProduct1);
 | 
			
		||||
    data.products.push(createdProduct2);
 | 
			
		||||
 | 
			
		||||
    const { body: createdShop } = await rq({
 | 
			
		||||
      method: 'POST',
 | 
			
		||||
      url: '/content-manager/collection-types/api::shop.shop',
 | 
			
		||||
      body: {
 | 
			
		||||
        name: 'Cazotte Shop',
 | 
			
		||||
        products: [createdProduct1.id],
 | 
			
		||||
        myCompo: { compoProducts: [createdProduct2.id] },
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    data.shops.push(createdShop);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  afterAll(async () => {
 | 
			
		||||
    await strapi.destroy();
 | 
			
		||||
    await builder.cleanup();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('findNew', () => {
 | 
			
		||||
    test('relation not in a component && no entity', async () => {
 | 
			
		||||
      let res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: '/content-manager/relations/api::shop.shop/products',
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.status).toBe(200);
 | 
			
		||||
      expect(res.body.results).toMatchObject([
 | 
			
		||||
        {
 | 
			
		||||
          id: expect.any(Number),
 | 
			
		||||
          name: 'Candle',
 | 
			
		||||
          publishedAt: null,
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          id: expect.any(Number),
 | 
			
		||||
          name: 'Skate',
 | 
			
		||||
          publishedAt: expect.any(String),
 | 
			
		||||
        },
 | 
			
		||||
      ]);
 | 
			
		||||
 | 
			
		||||
      // can omitIds
 | 
			
		||||
      res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: '/content-manager/relations/api::shop.shop/products',
 | 
			
		||||
        qs: {
 | 
			
		||||
          idsToOmit: [data.products[0].id],
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.body.results).toMatchObject([
 | 
			
		||||
        {
 | 
			
		||||
          id: expect.any(Number),
 | 
			
		||||
          name: 'Candle',
 | 
			
		||||
          publishedAt: null,
 | 
			
		||||
        },
 | 
			
		||||
      ]);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('relation not in a component && on an entity', async () => {
 | 
			
		||||
      let res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: '/content-manager/relations/api::shop.shop/products',
 | 
			
		||||
        qs: {
 | 
			
		||||
          entityId: data.shops[0].id,
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.status).toBe(200);
 | 
			
		||||
      expect(res.body.results).toMatchObject([
 | 
			
		||||
        {
 | 
			
		||||
          id: expect.any(Number),
 | 
			
		||||
          name: 'Candle',
 | 
			
		||||
          publishedAt: null,
 | 
			
		||||
        },
 | 
			
		||||
      ]);
 | 
			
		||||
 | 
			
		||||
      // can omitIds
 | 
			
		||||
      res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: '/content-manager/relations/api::shop.shop/products',
 | 
			
		||||
        qs: {
 | 
			
		||||
          entityId: data.shops[0].id,
 | 
			
		||||
          idsToOmit: [data.products[1].id],
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.body.results).toHaveLength(0);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('relation in a component && no entity', async () => {
 | 
			
		||||
      let res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: '/content-manager/relations/api::shop.shop/compoProducts',
 | 
			
		||||
        qs: {
 | 
			
		||||
          component: 'default.compo',
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.status).toBe(200);
 | 
			
		||||
      expect(res.body.results).toMatchObject([
 | 
			
		||||
        {
 | 
			
		||||
          id: expect.any(Number),
 | 
			
		||||
          name: 'Candle',
 | 
			
		||||
          publishedAt: null,
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          id: expect.any(Number),
 | 
			
		||||
          name: 'Skate',
 | 
			
		||||
          publishedAt: expect.any(String),
 | 
			
		||||
        },
 | 
			
		||||
      ]);
 | 
			
		||||
 | 
			
		||||
      // can omitIds
 | 
			
		||||
      res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: '/content-manager/relations/api::shop.shop/compoProducts',
 | 
			
		||||
        qs: {
 | 
			
		||||
          component: 'default.compo',
 | 
			
		||||
          idsToOmit: [data.products[0].id],
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.body.results).toMatchObject([
 | 
			
		||||
        {
 | 
			
		||||
          id: expect.any(Number),
 | 
			
		||||
          name: 'Candle',
 | 
			
		||||
          publishedAt: null,
 | 
			
		||||
        },
 | 
			
		||||
      ]);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('relation in a component && on an entity', async () => {
 | 
			
		||||
      let res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: '/content-manager/relations/api::shop.shop/compoProducts',
 | 
			
		||||
        qs: {
 | 
			
		||||
          entityId: data.shops[0].myCompo.id,
 | 
			
		||||
          component: 'default.compo',
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.status).toBe(200);
 | 
			
		||||
      expect(res.body.results).toMatchObject([
 | 
			
		||||
        {
 | 
			
		||||
          id: expect.any(Number),
 | 
			
		||||
          name: 'Skate',
 | 
			
		||||
          publishedAt: expect.any(String),
 | 
			
		||||
        },
 | 
			
		||||
      ]);
 | 
			
		||||
 | 
			
		||||
      // can omitIds
 | 
			
		||||
      res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: '/content-manager/relations/api::shop.shop/compoProducts',
 | 
			
		||||
        qs: {
 | 
			
		||||
          entityId: data.shops[0].myCompo.id,
 | 
			
		||||
          component: 'default.compo',
 | 
			
		||||
          idsToOmit: [data.products[0].id],
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.body.results).toHaveLength(0);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										246
									
								
								packages/core/content-manager/server/tests/relations.test.e2e.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										246
									
								
								packages/core/content-manager/server/tests/relations.test.e2e.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,246 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
const { createTestBuilder } = require('../../../../../test/helpers/builder');
 | 
			
		||||
const { createStrapiInstance } = require('../../../../../test/helpers/strapi');
 | 
			
		||||
const { createAuthRequest } = require('../../../../../test/helpers/request');
 | 
			
		||||
 | 
			
		||||
let strapi;
 | 
			
		||||
let rq;
 | 
			
		||||
let data = {
 | 
			
		||||
  products: [],
 | 
			
		||||
  shops: [],
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const compo = {
 | 
			
		||||
  displayName: 'compo',
 | 
			
		||||
  attributes: {
 | 
			
		||||
    name: {
 | 
			
		||||
      type: 'string',
 | 
			
		||||
    },
 | 
			
		||||
    compoProducts: {
 | 
			
		||||
      type: 'relation',
 | 
			
		||||
      relation: 'manyToMany',
 | 
			
		||||
      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: {
 | 
			
		||||
      type: 'relation',
 | 
			
		||||
      relation: 'manyToMany',
 | 
			
		||||
      target: 'api::product.product',
 | 
			
		||||
      targetAttribute: 'shops',
 | 
			
		||||
      inversedBy: 'shops',
 | 
			
		||||
    },
 | 
			
		||||
    myCompo: {
 | 
			
		||||
      type: 'component',
 | 
			
		||||
      repeatable: false,
 | 
			
		||||
      component: 'default.compo',
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  displayName: 'Shop',
 | 
			
		||||
  singularName: 'shop',
 | 
			
		||||
  pluralName: 'shops',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
describe('Relations', () => {
 | 
			
		||||
  const builder = createTestBuilder();
 | 
			
		||||
 | 
			
		||||
  beforeAll(async () => {
 | 
			
		||||
    await builder
 | 
			
		||||
      .addContentTypes([productModel])
 | 
			
		||||
      .addComponent(compo)
 | 
			
		||||
      .addContentTypes([shopModel])
 | 
			
		||||
      .build();
 | 
			
		||||
 | 
			
		||||
    strapi = await createStrapiInstance();
 | 
			
		||||
    rq = await createAuthRequest({ strapi });
 | 
			
		||||
 | 
			
		||||
    const { body: createdProduct1 } = await rq({
 | 
			
		||||
      method: 'POST',
 | 
			
		||||
      url: '/content-manager/collection-types/api::product.product',
 | 
			
		||||
      body: { name: 'Skate' },
 | 
			
		||||
    });
 | 
			
		||||
    const { body: createdProduct2 } = await rq({
 | 
			
		||||
      method: 'POST',
 | 
			
		||||
      url: '/content-manager/collection-types/api::product.product',
 | 
			
		||||
      body: { name: 'Candle' },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    data.products.push(createdProduct1);
 | 
			
		||||
    data.products.push(createdProduct2);
 | 
			
		||||
 | 
			
		||||
    const { body: createdShop } = await rq({
 | 
			
		||||
      method: 'POST',
 | 
			
		||||
      url: '/content-manager/collection-types/api::shop.shop',
 | 
			
		||||
      body: {
 | 
			
		||||
        name: 'Cazotte Shop',
 | 
			
		||||
        products: [createdProduct1.id],
 | 
			
		||||
        myCompo: { compoProducts: [createdProduct2.id] },
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    data.shops.push(createdShop);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  afterAll(async () => {
 | 
			
		||||
    await strapi.destroy();
 | 
			
		||||
    await builder.cleanup();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('findNew', () => {
 | 
			
		||||
    test('relation not in a component && no entity', async () => {
 | 
			
		||||
      let res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: '/content-manager/relations/api::shop.shop/products',
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.status).toBe(200);
 | 
			
		||||
      expect(res.body.results).toMatchObject([
 | 
			
		||||
        {
 | 
			
		||||
          id: expect.any(Number),
 | 
			
		||||
          name: 'Candle',
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          id: expect.any(Number),
 | 
			
		||||
          name: 'Skate',
 | 
			
		||||
        },
 | 
			
		||||
      ]);
 | 
			
		||||
 | 
			
		||||
      // can omitIds
 | 
			
		||||
      res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: '/content-manager/relations/api::shop.shop/products',
 | 
			
		||||
        qs: {
 | 
			
		||||
          idsToOmit: [data.products[0].id],
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.body.results).toMatchObject([
 | 
			
		||||
        {
 | 
			
		||||
          id: expect.any(Number),
 | 
			
		||||
          name: 'Candle',
 | 
			
		||||
        },
 | 
			
		||||
      ]);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('relation not in a component && on an entity', async () => {
 | 
			
		||||
      let res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: '/content-manager/relations/api::shop.shop/products',
 | 
			
		||||
        qs: {
 | 
			
		||||
          entityId: data.shops[0].id,
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.status).toBe(200);
 | 
			
		||||
      expect(res.body.results).toMatchObject([
 | 
			
		||||
        {
 | 
			
		||||
          id: expect.any(Number),
 | 
			
		||||
          name: 'Candle',
 | 
			
		||||
        },
 | 
			
		||||
      ]);
 | 
			
		||||
 | 
			
		||||
      // can omitIds
 | 
			
		||||
      res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: '/content-manager/relations/api::shop.shop/products',
 | 
			
		||||
        qs: {
 | 
			
		||||
          entityId: data.shops[0].id,
 | 
			
		||||
          idsToOmit: [data.products[1].id],
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.body.results).toHaveLength(0);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('relation in a component && no entity', async () => {
 | 
			
		||||
      let res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: '/content-manager/relations/api::shop.shop/compoProducts',
 | 
			
		||||
        qs: {
 | 
			
		||||
          component: 'default.compo',
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.status).toBe(200);
 | 
			
		||||
      expect(res.body.results).toMatchObject([
 | 
			
		||||
        {
 | 
			
		||||
          id: expect.any(Number),
 | 
			
		||||
          name: 'Candle',
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          id: expect.any(Number),
 | 
			
		||||
          name: 'Skate',
 | 
			
		||||
        },
 | 
			
		||||
      ]);
 | 
			
		||||
 | 
			
		||||
      // can omitIds
 | 
			
		||||
      res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: '/content-manager/relations/api::shop.shop/compoProducts',
 | 
			
		||||
        qs: {
 | 
			
		||||
          component: 'default.compo',
 | 
			
		||||
          idsToOmit: [data.products[0].id],
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.body.results).toMatchObject([
 | 
			
		||||
        {
 | 
			
		||||
          id: expect.any(Number),
 | 
			
		||||
          name: 'Candle',
 | 
			
		||||
        },
 | 
			
		||||
      ]);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('relation in a component && on an entity', async () => {
 | 
			
		||||
      let res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: '/content-manager/relations/api::shop.shop/compoProducts',
 | 
			
		||||
        qs: {
 | 
			
		||||
          entityId: data.shops[0].myCompo.id,
 | 
			
		||||
          component: 'default.compo',
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.status).toBe(200);
 | 
			
		||||
      expect(res.body.results).toMatchObject([
 | 
			
		||||
        {
 | 
			
		||||
          id: expect.any(Number),
 | 
			
		||||
          name: 'Skate',
 | 
			
		||||
        },
 | 
			
		||||
      ]);
 | 
			
		||||
 | 
			
		||||
      // can omitIds
 | 
			
		||||
      res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: '/content-manager/relations/api::shop.shop/compoProducts',
 | 
			
		||||
        qs: {
 | 
			
		||||
          entityId: data.shops[0].myCompo.id,
 | 
			
		||||
          component: 'default.compo',
 | 
			
		||||
          idsToOmit: [data.products[0].id],
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.body.results).toHaveLength(0);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user