mirror of
				https://github.com/strapi/strapi.git
				synced 2025-11-04 03:43:34 +00:00 
			
		
		
		
	add e2e tests for CTB singularNames + better handle names containing numbers
This commit is contained in:
		
							parent
							
								
									64940edbae
								
							
						
					
					
						commit
						7f0877b73f
					
				@ -64,11 +64,13 @@ describe('Content type validator', () => {
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Prevents use of names without plural form', () => {
 | 
			
		||||
    test('Throws when using name without plural form', async () => {
 | 
			
		||||
  describe('Prevents use of same singularName and pluralName', () => {
 | 
			
		||||
    test('Throws when using same singularName and pluralName', async () => {
 | 
			
		||||
      const data = {
 | 
			
		||||
        contentType: {
 | 
			
		||||
          name: 'news',
 | 
			
		||||
          displayName: 'news',
 | 
			
		||||
          singularName: 'news',
 | 
			
		||||
          pluralName: 'news',
 | 
			
		||||
          attributes: {
 | 
			
		||||
            title: {
 | 
			
		||||
              type: 'string',
 | 
			
		||||
@ -79,7 +81,7 @@ describe('Content type validator', () => {
 | 
			
		||||
 | 
			
		||||
      await validateContentTypeInput(data).catch(err => {
 | 
			
		||||
        expect(err).toMatchObject({
 | 
			
		||||
          'contentType.name': [expect.stringMatching('cannot be pluralized')],
 | 
			
		||||
          contentType: [expect.stringMatching('singularName and pluralName should be different')],
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
@ -89,7 +91,9 @@ describe('Content type validator', () => {
 | 
			
		||||
    test('Can use custom keys', async () => {
 | 
			
		||||
      const input = {
 | 
			
		||||
        contentType: {
 | 
			
		||||
          name: 'test',
 | 
			
		||||
          displayName: 'test',
 | 
			
		||||
          singularName: 'test',
 | 
			
		||||
          pluralName: 'tests',
 | 
			
		||||
          attributes: {
 | 
			
		||||
            views: {
 | 
			
		||||
              type: 'integer',
 | 
			
		||||
@ -115,7 +119,9 @@ describe('Content type validator', () => {
 | 
			
		||||
    test('Deletes empty defaults', async () => {
 | 
			
		||||
      const data = {
 | 
			
		||||
        contentType: {
 | 
			
		||||
          name: 'test',
 | 
			
		||||
          displayName: 'test',
 | 
			
		||||
          singularName: 'test',
 | 
			
		||||
          pluralName: 'tests',
 | 
			
		||||
          attributes: {
 | 
			
		||||
            slug: {
 | 
			
		||||
              type: 'string',
 | 
			
		||||
@ -161,7 +167,9 @@ describe('Content type validator', () => {
 | 
			
		||||
    test('Deleted UID target fields are removed from input data', async () => {
 | 
			
		||||
      const data = {
 | 
			
		||||
        contentType: {
 | 
			
		||||
          name: 'test',
 | 
			
		||||
          displayName: 'test',
 | 
			
		||||
          singularName: 'test',
 | 
			
		||||
          pluralName: 'tests',
 | 
			
		||||
          attributes: {
 | 
			
		||||
            slug: {
 | 
			
		||||
              type: 'uid',
 | 
			
		||||
@ -181,7 +189,9 @@ describe('Content type validator', () => {
 | 
			
		||||
    test('Can use custom keys', async () => {
 | 
			
		||||
      const input = {
 | 
			
		||||
        contentType: {
 | 
			
		||||
          name: 'test',
 | 
			
		||||
          displayName: 'test',
 | 
			
		||||
          singularName: 'test',
 | 
			
		||||
          pluralName: 'tests',
 | 
			
		||||
          attributes: {
 | 
			
		||||
            views: {
 | 
			
		||||
              type: 'integer',
 | 
			
		||||
 | 
			
		||||
@ -46,26 +46,32 @@ const createContentTypeSchema = (data, { isEdition = false } = {}) => {
 | 
			
		||||
  const kind = _.get(data, 'contentType.kind', typeKinds.COLLECTION_TYPE);
 | 
			
		||||
  const contentTypeSchema = createSchema(VALID_TYPES, VALID_RELATIONS[kind] || [], {
 | 
			
		||||
    modelType: modelTypes.CONTENT_TYPE,
 | 
			
		||||
  }).shape({
 | 
			
		||||
    displayName: yup
 | 
			
		||||
      .string()
 | 
			
		||||
      .min(1)
 | 
			
		||||
      .required(),
 | 
			
		||||
    singularName: yup
 | 
			
		||||
      .string()
 | 
			
		||||
      .min(1)
 | 
			
		||||
      .test(alreadyUsedContentTypeName(isEdition))
 | 
			
		||||
      .test(forbiddenContentTypeNameValidator())
 | 
			
		||||
      .isKebabCase()
 | 
			
		||||
      .required(),
 | 
			
		||||
    pluralName: yup
 | 
			
		||||
      .string()
 | 
			
		||||
      .min(1)
 | 
			
		||||
      .test(alreadyUsedContentTypeName(isEdition))
 | 
			
		||||
      .test(forbiddenContentTypeNameValidator())
 | 
			
		||||
      .isKebabCase()
 | 
			
		||||
      .required(),
 | 
			
		||||
  });
 | 
			
		||||
  })
 | 
			
		||||
    .shape({
 | 
			
		||||
      displayName: yup
 | 
			
		||||
        .string()
 | 
			
		||||
        .min(1)
 | 
			
		||||
        .required(),
 | 
			
		||||
      singularName: yup
 | 
			
		||||
        .string()
 | 
			
		||||
        .min(1)
 | 
			
		||||
        .test(alreadyUsedContentTypeName(isEdition))
 | 
			
		||||
        .test(forbiddenContentTypeNameValidator())
 | 
			
		||||
        .isKebabCase()
 | 
			
		||||
        .required(),
 | 
			
		||||
      pluralName: yup
 | 
			
		||||
        .string()
 | 
			
		||||
        .min(1)
 | 
			
		||||
        .test(alreadyUsedContentTypeName(isEdition))
 | 
			
		||||
        .test(forbiddenContentTypeNameValidator())
 | 
			
		||||
        .isKebabCase()
 | 
			
		||||
        .required(),
 | 
			
		||||
    })
 | 
			
		||||
    .test(
 | 
			
		||||
      'singularName-not-equal-pluralName',
 | 
			
		||||
      '${path}: singularName and pluralName should be different',
 | 
			
		||||
      value => value.singularName !== value.pluralName
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
  return yup
 | 
			
		||||
    .object({
 | 
			
		||||
 | 
			
		||||
@ -12,15 +12,17 @@ Object {
 | 
			
		||||
    },
 | 
			
		||||
    "collectionName": "tests",
 | 
			
		||||
    "description": "My description",
 | 
			
		||||
    "displayName": "My name",
 | 
			
		||||
    "draftAndPublish": false,
 | 
			
		||||
    "kind": "singleType",
 | 
			
		||||
    "name": "My name",
 | 
			
		||||
    "pluginOptions": Object {
 | 
			
		||||
      "content-manager": Object {
 | 
			
		||||
        "visible": true,
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    "pluralName": "my-names",
 | 
			
		||||
    "restrictRelationsTo": null,
 | 
			
		||||
    "singularName": "my-name",
 | 
			
		||||
    "visible": true,
 | 
			
		||||
  },
 | 
			
		||||
  "uid": "test-uid",
 | 
			
		||||
 | 
			
		||||
@ -12,6 +12,8 @@ describe('Content types service', () => {
 | 
			
		||||
      collectionName: 'tests',
 | 
			
		||||
      info: {
 | 
			
		||||
        displayName: 'My name',
 | 
			
		||||
        singularName: 'my-name',
 | 
			
		||||
        pluralName: 'my-names',
 | 
			
		||||
        description: 'My description',
 | 
			
		||||
      },
 | 
			
		||||
      options: {
 | 
			
		||||
 | 
			
		||||
@ -59,38 +59,3 @@ Object {
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
exports[`Content Type Builder - Content types Single Types Get single type returns full schema and information 1`] = `
 | 
			
		||||
Object {
 | 
			
		||||
  "data": Object {
 | 
			
		||||
    "apiID": "test-single-type",
 | 
			
		||||
    "schema": Object {
 | 
			
		||||
      "attributes": Object {
 | 
			
		||||
        "title": Object {
 | 
			
		||||
          "pluginOptions": Object {
 | 
			
		||||
            "i18n": Object {
 | 
			
		||||
              "localized": true,
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
          "type": "string",
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
      "collectionName": "test_single_types",
 | 
			
		||||
      "description": "",
 | 
			
		||||
      "displayName": "Test Single Type",
 | 
			
		||||
      "draftAndPublish": false,
 | 
			
		||||
      "kind": "singleType",
 | 
			
		||||
      "pluginOptions": Object {
 | 
			
		||||
        "i18n": Object {
 | 
			
		||||
          "localized": true,
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
      "pluralName": "test-single-types",
 | 
			
		||||
      "restrictRelationsTo": null,
 | 
			
		||||
      "singularName": "test-single-type",
 | 
			
		||||
      "visible": true,
 | 
			
		||||
    },
 | 
			
		||||
    "uid": "api::test-single-type.test-single-type",
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
`;
 | 
			
		||||
@ -0,0 +1,36 @@
 | 
			
		||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
 | 
			
		||||
 | 
			
		||||
exports[`Content Type Builder - Content types Single Types Get single type returns full schema and information 1`] = `
 | 
			
		||||
Object {
 | 
			
		||||
  "data": Object {
 | 
			
		||||
    "apiID": "test-single-type",
 | 
			
		||||
    "schema": Object {
 | 
			
		||||
      "attributes": Object {
 | 
			
		||||
        "title": Object {
 | 
			
		||||
          "pluginOptions": Object {
 | 
			
		||||
            "i18n": Object {
 | 
			
		||||
              "localized": true,
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
          "type": "string",
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
      "collectionName": "test_single_types",
 | 
			
		||||
      "description": "",
 | 
			
		||||
      "displayName": "Test Single Type",
 | 
			
		||||
      "draftAndPublish": false,
 | 
			
		||||
      "kind": "singleType",
 | 
			
		||||
      "pluginOptions": Object {
 | 
			
		||||
        "i18n": Object {
 | 
			
		||||
          "localized": true,
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
      "pluralName": "test-single-types",
 | 
			
		||||
      "restrictRelationsTo": null,
 | 
			
		||||
      "singularName": "test-single-type",
 | 
			
		||||
      "visible": true,
 | 
			
		||||
    },
 | 
			
		||||
    "uid": "api::test-single-type.test-single-type",
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
`;
 | 
			
		||||
@ -0,0 +1,277 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Integration test for the content-type-builder content types management apis
 | 
			
		||||
 */
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
const { createStrapiInstance } = require('../../../../test/helpers/strapi');
 | 
			
		||||
const { createAuthRequest } = require('../../../../test/helpers/request');
 | 
			
		||||
const modelsUtils = require('../../../../test/helpers/models');
 | 
			
		||||
 | 
			
		||||
let strapi;
 | 
			
		||||
let rq;
 | 
			
		||||
 | 
			
		||||
const restart = async () => {
 | 
			
		||||
  await strapi.destroy();
 | 
			
		||||
  strapi = await createStrapiInstance();
 | 
			
		||||
  rq = await createAuthRequest({ strapi });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
describe('Content Type Builder - Content types', () => {
 | 
			
		||||
  beforeAll(async () => {
 | 
			
		||||
    strapi = await createStrapiInstance();
 | 
			
		||||
    rq = await createAuthRequest({ strapi });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  afterEach(async () => {
 | 
			
		||||
    await restart();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  afterAll(async () => {
 | 
			
		||||
    const modelsUIDs = [
 | 
			
		||||
      'api::test-collection-type.test-collection-type',
 | 
			
		||||
      'api::ct-with-dp.ct-with-dp',
 | 
			
		||||
      'api::kebab-case.kebab-case',
 | 
			
		||||
      'api::my2space.my2space',
 | 
			
		||||
      'api::my-3-space.my-3-space',
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    await modelsUtils.cleanupModels(modelsUIDs, { strapi });
 | 
			
		||||
    await modelsUtils.deleteContentTypes(modelsUIDs, { strapi });
 | 
			
		||||
 | 
			
		||||
    await strapi.destroy();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Collection Types', () => {
 | 
			
		||||
    const testCollectionTypeUID = 'api::test-collection-type.test-collection-type';
 | 
			
		||||
    const ctWithDpUID = 'api::ct-with-dp.ct-with-dp';
 | 
			
		||||
 | 
			
		||||
    test('Successful creation of a collection type', async () => {
 | 
			
		||||
      const res = await rq({
 | 
			
		||||
        method: 'POST',
 | 
			
		||||
        url: '/content-type-builder/content-types',
 | 
			
		||||
        body: {
 | 
			
		||||
          contentType: {
 | 
			
		||||
            displayName: 'Test Collection Type',
 | 
			
		||||
            singularName: 'test-collection-type',
 | 
			
		||||
            pluralName: 'test-collection-types',
 | 
			
		||||
            pluginOptions: {
 | 
			
		||||
              i18n: {
 | 
			
		||||
                localized: true,
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            attributes: {
 | 
			
		||||
              title: {
 | 
			
		||||
                type: 'string',
 | 
			
		||||
                pluginOptions: {
 | 
			
		||||
                  i18n: {
 | 
			
		||||
                    localized: true,
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.statusCode).toBe(201);
 | 
			
		||||
      expect(res.body).toEqual({
 | 
			
		||||
        data: {
 | 
			
		||||
          uid: testCollectionTypeUID,
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Get collection type returns full schema and information', async () => {
 | 
			
		||||
      const res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: `/content-type-builder/content-types/${testCollectionTypeUID}`,
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.statusCode).toBe(200);
 | 
			
		||||
      expect(res.body).toMatchSnapshot();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Successfull creation of a collection type with draftAndPublish enabled', async () => {
 | 
			
		||||
      const res = await rq({
 | 
			
		||||
        method: 'POST',
 | 
			
		||||
        url: '/content-type-builder/content-types',
 | 
			
		||||
        body: {
 | 
			
		||||
          contentType: {
 | 
			
		||||
            displayName: 'CT with DP',
 | 
			
		||||
            singularName: 'ct-with-dp',
 | 
			
		||||
            pluralName: 'ct-with-dps',
 | 
			
		||||
            draftAndPublish: true,
 | 
			
		||||
            attributes: {
 | 
			
		||||
              title: {
 | 
			
		||||
                type: 'string',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.statusCode).toBe(201);
 | 
			
		||||
      expect(res.body).toEqual({
 | 
			
		||||
        data: {
 | 
			
		||||
          uid: ctWithDpUID,
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Get collection type returns full schema and informations with draftAndPublish', async () => {
 | 
			
		||||
      const res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: `/content-type-builder/content-types/${ctWithDpUID}`,
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.statusCode).toBe(200);
 | 
			
		||||
      expect(res.body).toMatchSnapshot();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Cannot use same string for singularName and pluralName', async () => {
 | 
			
		||||
      const res = await rq({
 | 
			
		||||
        method: 'POST',
 | 
			
		||||
        url: '/content-type-builder/content-types',
 | 
			
		||||
        body: {
 | 
			
		||||
          contentType: {
 | 
			
		||||
            displayName: 'same string',
 | 
			
		||||
            singularName: 'same-string',
 | 
			
		||||
            pluralName: 'same-string',
 | 
			
		||||
            draftAndPublish: true,
 | 
			
		||||
            attributes: {
 | 
			
		||||
              title: {
 | 
			
		||||
                type: 'string',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.statusCode).toBe(400);
 | 
			
		||||
      expect(res.body).toEqual({
 | 
			
		||||
        error: {
 | 
			
		||||
          contentType: ['contentType: singularName and pluralName should be different'],
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('displayNamen singularName and pluralName are required', async () => {
 | 
			
		||||
      const res = await rq({
 | 
			
		||||
        method: 'POST',
 | 
			
		||||
        url: '/content-type-builder/content-types',
 | 
			
		||||
        body: {
 | 
			
		||||
          contentType: {
 | 
			
		||||
            draftAndPublish: true,
 | 
			
		||||
            attributes: {
 | 
			
		||||
              title: {
 | 
			
		||||
                type: 'string',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.statusCode).toBe(400);
 | 
			
		||||
      expect(res.body).toEqual({
 | 
			
		||||
        error: {
 | 
			
		||||
          contentType: ['contentType: singularName and pluralName should be different'],
 | 
			
		||||
          'contentType.displayName': ['contentType.displayName is a required field'],
 | 
			
		||||
          'contentType.singularName': ['contentType.singularName is a required field'],
 | 
			
		||||
          'contentType.pluralName': ['contentType.pluralName is a required field'],
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Can edit displayName but singularName and pluralName are ignored', async () => {
 | 
			
		||||
      const uid = 'api::ct-with-dp.ct-with-dp';
 | 
			
		||||
      let res = await rq({
 | 
			
		||||
        method: 'PUT',
 | 
			
		||||
        url: `/content-type-builder/content-types/${uid}`,
 | 
			
		||||
        body: {
 | 
			
		||||
          contentType: {
 | 
			
		||||
            displayName: 'new displayName',
 | 
			
		||||
            singularName: 'ct-with-dp-new',
 | 
			
		||||
            pluralName: 'ct-with-dps-new',
 | 
			
		||||
            draftAndPublish: true,
 | 
			
		||||
            attributes: {
 | 
			
		||||
              title: {
 | 
			
		||||
                type: 'string',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
      expect(res.statusCode).toBe(201);
 | 
			
		||||
 | 
			
		||||
      await restart();
 | 
			
		||||
 | 
			
		||||
      res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: `/content-type-builder/content-types/${uid}`,
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.statusCode).toBe(200);
 | 
			
		||||
      expect(res.body).toMatchObject({
 | 
			
		||||
        data: {
 | 
			
		||||
          uid,
 | 
			
		||||
          schema: {
 | 
			
		||||
            displayName: 'new displayName',
 | 
			
		||||
            singularName: 'ct-with-dp', // no change
 | 
			
		||||
            pluralName: 'ct-with-dps',
 | 
			
		||||
            draftAndPublish: true,
 | 
			
		||||
            attributes: {
 | 
			
		||||
              title: {
 | 
			
		||||
                type: 'string',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test.each([
 | 
			
		||||
      ['kebab-case', 'kebab-cases', true],
 | 
			
		||||
      ['Kebab-case', 'Kebab-cases', false],
 | 
			
		||||
      ['kebab case', 'kebab cases', false],
 | 
			
		||||
      ['kebabCase', 'kebabCases', false],
 | 
			
		||||
      ['kebab@case', 'kebab@cases', false],
 | 
			
		||||
      ['my2space', 'my2spaces', true],
 | 
			
		||||
      ['2myspace', '2myspaces', false],
 | 
			
		||||
      ['my-3-space', 'my-3-spaces', true],
 | 
			
		||||
    ])('Are "%s" and "%s" valid: %s', async (singularName, pluralName, isExpectedValid) => {
 | 
			
		||||
      const res = await rq({
 | 
			
		||||
        method: 'POST',
 | 
			
		||||
        url: '/content-type-builder/content-types',
 | 
			
		||||
        body: {
 | 
			
		||||
          contentType: {
 | 
			
		||||
            displayName: 'same string',
 | 
			
		||||
            singularName,
 | 
			
		||||
            pluralName,
 | 
			
		||||
            draftAndPublish: true,
 | 
			
		||||
            attributes: {
 | 
			
		||||
              title: {
 | 
			
		||||
                type: 'string',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      if (isExpectedValid) {
 | 
			
		||||
        expect(res.statusCode).toBe(201);
 | 
			
		||||
      } else {
 | 
			
		||||
        expect(res.statusCode).toBe(400);
 | 
			
		||||
        expect(res.body).toEqual({
 | 
			
		||||
          error: {
 | 
			
		||||
            'contentType.pluralName': [
 | 
			
		||||
              'contentType.pluralName is not in kebab case (an-example-of-kebab-case)',
 | 
			
		||||
            ],
 | 
			
		||||
            'contentType.singularName': [
 | 
			
		||||
              'contentType.singularName is not in kebab case (an-example-of-kebab-case)',
 | 
			
		||||
            ],
 | 
			
		||||
          },
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@ -28,10 +28,8 @@ describe('Content Type Builder - Content types', () => {
 | 
			
		||||
 | 
			
		||||
  afterAll(async () => {
 | 
			
		||||
    const modelsUIDs = [
 | 
			
		||||
      'api::test-collection-type.test-collection-type',
 | 
			
		||||
      'api::test-collection.test-collection',
 | 
			
		||||
      'api::test-single-type.test-single-type',
 | 
			
		||||
      'api::ct-with-dp.ct-with-dp',
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    await modelsUtils.cleanupModels(modelsUIDs, { strapi });
 | 
			
		||||
@ -40,94 +38,6 @@ describe('Content Type Builder - Content types', () => {
 | 
			
		||||
    await strapi.destroy();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Collection Types', () => {
 | 
			
		||||
    const testCollectionTypeUID = 'api::test-collection-type.test-collection-type';
 | 
			
		||||
    const ctWithDpUID = 'api::ct-with-dp.ct-with-dp';
 | 
			
		||||
 | 
			
		||||
    test('Successful creation of a collection type', async () => {
 | 
			
		||||
      const res = await rq({
 | 
			
		||||
        method: 'POST',
 | 
			
		||||
        url: '/content-type-builder/content-types',
 | 
			
		||||
        body: {
 | 
			
		||||
          contentType: {
 | 
			
		||||
            displayName: 'Test Collection Type',
 | 
			
		||||
            singularName: 'test-collection-type',
 | 
			
		||||
            pluralName: 'test-collection-types',
 | 
			
		||||
            pluginOptions: {
 | 
			
		||||
              i18n: {
 | 
			
		||||
                localized: true,
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            attributes: {
 | 
			
		||||
              title: {
 | 
			
		||||
                type: 'string',
 | 
			
		||||
                pluginOptions: {
 | 
			
		||||
                  i18n: {
 | 
			
		||||
                    localized: true,
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.statusCode).toBe(201);
 | 
			
		||||
      expect(res.body).toEqual({
 | 
			
		||||
        data: {
 | 
			
		||||
          uid: testCollectionTypeUID,
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Get collection type returns full schema and information', async () => {
 | 
			
		||||
      const res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: `/content-type-builder/content-types/${testCollectionTypeUID}`,
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.statusCode).toBe(200);
 | 
			
		||||
      expect(res.body).toMatchSnapshot();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Successfull creation of a collection type with draftAndPublish enabled', async () => {
 | 
			
		||||
      const res = await rq({
 | 
			
		||||
        method: 'POST',
 | 
			
		||||
        url: '/content-type-builder/content-types',
 | 
			
		||||
        body: {
 | 
			
		||||
          contentType: {
 | 
			
		||||
            displayName: 'CT with DP',
 | 
			
		||||
            singularName: 'ct-with-dp',
 | 
			
		||||
            pluralName: 'ct-with-dps',
 | 
			
		||||
            draftAndPublish: true,
 | 
			
		||||
            attributes: {
 | 
			
		||||
              title: {
 | 
			
		||||
                type: 'string',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.statusCode).toBe(201);
 | 
			
		||||
      expect(res.body).toEqual({
 | 
			
		||||
        data: {
 | 
			
		||||
          uid: ctWithDpUID,
 | 
			
		||||
        },
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Get collection type returns full schema and informations with draftAndPublish', async () => {
 | 
			
		||||
      const res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: `/content-type-builder/content-types/${ctWithDpUID}`,
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      expect(res.statusCode).toBe(200);
 | 
			
		||||
      expect(res.body).toMatchSnapshot();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Single Types', () => {
 | 
			
		||||
    const singleTypeUID = 'api::test-single-type.test-single-type';
 | 
			
		||||
 | 
			
		||||
@ -259,12 +169,8 @@ describe('Content Type Builder - Content types', () => {
 | 
			
		||||
      expect(updateRes.statusCode).toBe(400);
 | 
			
		||||
      expect(updateRes.body.error).toMatch('multiple entries in DB');
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Private relation field', () => {
 | 
			
		||||
    const singleTypeUID = 'api::test-single-type.test-single-type';
 | 
			
		||||
 | 
			
		||||
    test('should add a relation field', async () => {
 | 
			
		||||
    test('Should add a relation field', async () => {
 | 
			
		||||
      const res = await rq({
 | 
			
		||||
        method: 'PUT',
 | 
			
		||||
        url: `/content-type-builder/content-types/${singleTypeUID}`,
 | 
			
		||||
@ -294,7 +200,7 @@ describe('Content Type Builder - Content types', () => {
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('should contain a private relation field', async () => {
 | 
			
		||||
    test('Should contain a private relation field', async () => {
 | 
			
		||||
      const res = await rq({
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        url: `/content-type-builder/content-types/${singleTypeUID}`,
 | 
			
		||||
@ -4,8 +4,10 @@ const { join, extname, basename } = require('path');
 | 
			
		||||
const { existsSync } = require('fs-extra');
 | 
			
		||||
const _ = require('lodash');
 | 
			
		||||
const fse = require('fs-extra');
 | 
			
		||||
const { isKebabCase } = require('@strapi/utils');
 | 
			
		||||
 | 
			
		||||
const normalizeName = _.kebabCase;
 | 
			
		||||
// to handle names with numbers in it we first check is it is already in kebabCase
 | 
			
		||||
const normalizeName = name => (isKebabCase(name) ? name : _.kebabCase(name));
 | 
			
		||||
 | 
			
		||||
const DEFAULT_CONTENT_TYPE = {
 | 
			
		||||
  schema: {},
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user